使用 SWIG 生成接口模块时,生成的 C/C++ 文件包含大量静态样板函数。因此,如果想通过在同一个应用程序中使用许多单独编译的小接口来模块化 SWIG 生成的接口的使用,那么由于这些重复的功能,最终会导致很多臃肿。
使用 gcc 的-ffunction-sections
选项和 GNU 链接器的--icf=safe
选项(-Wl,--icf=safe
对编译器),可以删除一些重复,但绝不是全部(我认为它不会合并任何有重定位的东西——其中很多功能做)。
我的问题:我想知道是否有办法删除更多这种重复的样板,最好是不依赖于 GNU 特定的编译器/链接器选项。
特别是,是否有 SWIG 选项/标志/某些内容显示“不在每个输出文件中包含样板”?实际上有一个 SWIG 选项,-external-runtime
它告诉它生成一个“仅样板”输出文件,但没有明显的方法来抑制每个正常输出文件中包含的副本。[我认为这种事情在 SWIG 中实现起来应该相当简单,所以我很惊讶它似乎不存在......但我似乎找不到任何记录。]
这是一个小例子:
swg-oink.swg
给定模块的接口文件swt_oink
:
%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
在可执行文件上使用可以看到多次定义的大量函数,并查看它们的源代码,很明显,对它们中的大多数使用单一的全局定义就可以了)。