【发布时间】:2011-11-18 06:14:33
【问题描述】:
使用 SWIG 生成接口模块时,生成的 C/C++ 文件包含大量静态样板函数。因此,如果想要通过在同一个应用程序中使用许多单独编译的小接口来模块化 SWIG 生成的接口的使用,那么由于这些重复的功能,最终会导致很多臃肿。
使用 gcc 的 -ffunction-sections 选项和 GNU 链接器的 --icf=safe 选项(-Wl,--icf=safe 编译器),可以删除一些重复,但绝不是全部(我认为它不会合并任何有重定位的东西——这些函数中的许多都是这样做的)。
我的问题:我想知道是否有办法删除更多这种重复的样板,最好是不依赖于 GNU 特定的编译器/链接器选项。
特别是,是否有 SWIG 选项/标志/某些内容显示“不在每个输出文件中包含样板”?实际上是一个 SWIG 选项,-external-runtime,它告诉它生成一个“仅样板”输出文件,但没有明显的方法来抑制每个正常输出文件中包含的副本。 [我认为这种事情在 SWIG 中实现起来应该相当简单,所以我很惊讶它似乎不存在......但我似乎找不到任何文档记录。]
这是一个小例子:
给定模块swt_oink的接口文件swg-oink.swg:
%module swt_oink
%{ extern int oinker (const char *x); %}
extern int oinker (const char *x);
...和swg-barf.swg 的类似接口swt_barf:
%module swt_barf
%{ extern int barfer (const char *x); %}
extern int barfer (const char *x);
...和一个测试主文件,swt-main.cc:
extern "C"
{
#include "lua.h"
#include "lualib.h"
#include "lauxlib.h"
extern int luaopen_swt_oink (lua_State *);
extern int luaopen_swt_barf (lua_State *);
}
int main ()
{
lua_State *L = lua_open();
luaopen_swt_oink (L);
luaopen_swt_barf (L);
}
int oinker (const char *) { return 7; }
int barfer (const char *) { return 2; }
并像这样编译它们:
swig -lua -c++ swt-oink.swg
g++ -c -I/usr/include/lua5.1 swt-oink_wrap.cxx
swig -lua -c++ swt-barf.swg
g++ -c -I/usr/include/lua5.1 swt-barf_wrap.cxx
g++ -c -I/usr/include/lua5.1 swt-main.cc
g++ -o swt swt-main.o swt-oink_wrap.o swt-barf_wrap.o
那么每个xxx_wrap.o文件的大小约为16KB,其中95%是样板文件,最终可执行文件的大小大致是这些的总和,大约39K。如果用-ffunction-sections编译每个接口文件,用-Wl,--icf=safe链接,最终的可执行文件大小为34KB,但显然还是有很多重复(在可执行文件上使用nm可以看到大量定义的函数多次,并查看它们的来源,很明显对它们中的大多数使用单一的全局定义就可以了)。
【问题讨论】:
标签: optimization gcc lua swig boilerplate