При генерации интерфейсного модуля с помощью 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
файла составляет около 16 КБ, из которых 95% - это стандартный шаблон, а размер конечного исполняемого файла примерно равен сумме этих значений, около 39 КБ. Если каждый компилирует каждый интерфейсный файл с -ffunction-sections
и связывает с -Wl,--icf=safe
, размер конечного исполняемого файла составляет 34 КБ, но все еще явно много дублирования (при использовании nm
в исполняемом файле можно увидеть множество определенных функций Несколько раз, и, глядя на их источник, становится ясно, что для большинства из них было бы хорошо использовать одно глобальное определение.