Как принудительно включить объектный файл в статическую библиотеку при компоновке в исполняемый файл? - PullRequest
20 голосов
/ 07 июня 2010

У меня есть проект C ++, который в силу своей структуры каталогов настроен как статическая библиотека A, которая связана с общей библиотекой B, которая связана с исполняемым файлом C. (Это кроссплатформенный проект с использованием CMake, поэтому в Windows мы получаем A.lib, B.dll и C.exe, а в Linux мы получаем libA.a, libB.so и C.) Библиотека A имеет функцию инициализации (A_init, определенную в A/initA.cpp), которая вызывается из библиотеки B Функция инициализации (B_init, определенную в B/initB.cpp), которая вызывается из C ' с основной. Таким образом, при связывании B, A_init (и все символы, определенные в initA.cpp) связываются с B (что является нашим желаемым поведением).

Проблема заключается в том, что библиотека A также определяет функцию (Af, определенную в A/Afort.f), которая предназначена для динамической загрузки (например, LoadLibrary / GetProcAddress в Windows и dlopen / dlsym в Linux). Поскольку в библиотеке B нет ссылок на Af, символы из A/Afort.o не включаются в B. В Windows мы можем искусственно создать ссылку, используя прагму:

#pragma comment (linker, "/export:_Af")

Поскольку это прагма, она работает только в Windows (с использованием Visual Studio 2008). Чтобы заставить его работать в Linux, мы попытались добавить следующее к A/initA.cpp:

extern void Af(void);
static void (*Af_fp)(void) = &Af;

Это не означает, что символ Af будет включен в окончательную ссылку B. Как заставить символ Af быть связан с B?

Ответы [ 6 ]

12 голосов
/ 08 июня 2010

Оказывается, моя первоначальная попытка была в основном там. Следующие работы:

extern "C" void Af(void);
void (*Af_fp)(void) = &Af;

Для тех, кому нужен автономный макрос препроцессора для инкапсуляции:

#if defined(_WIN32)
# if defined(_WIN64)
#  define FORCE_UNDEFINED_SYMBOL(x) __pragma(comment (linker, "/export:" #x))
# else
#  define FORCE_UNDEFINED_SYMBOL(x) __pragma(comment (linker, "/export:_" #x))
# endif
#else
# define FORCE_UNDEFINED_SYMBOL(x) extern "C" void x(void); void (*__ ## x ## _fp)(void)=&x;
#endif

Что используется таким образом:

FORCE_UNDEFINED_SYMBOL(Af)
6 голосов
/ 05 марта 2011

MSVC #pragma comment(linker, "/include:__mySymbol")

ГЦК -u symbol

3 голосов
/ 23 мая 2012

Есть лучший способ написать этот макрос FORCE_UNDEFINED_SYMBOL. Просто приведите указатель этой функции к пустоте *. Тогда это работает с любой функцией - или данными в этом отношении. Кроме того, зачем беспокоиться о прагмах MSVC, если gcc-часть вашего макроса будет работать и для MSVC. Итак, моя упрощенная версия будет:

#define FORCE_UNDEFINED_SYMBOL(x) void* __ ## x ## _fp =(void*)&x;

Который используется таким образом:

FORCE_UNDEFINED_SYMBOL(Af)

Но он должен использоваться в программе, которая включает в себя библиотеку, в которой символы удалены.

3 голосов
/ 07 июня 2010

Вы можете использовать опцию --undefined при сборке B:

g++ -Wl,--undefined,Af -o libB.so ...
0 голосов
/ 07 июня 2010

Если вы можете использовать C ++ 0x функции gcc ( -std = c ++ 0x ), тогда аргументы шаблона функции по умолчанию могут подойти трюк. Начиная с текущего стандарта c ++, аргументы по умолчанию не допускаются для шаблонов функций. Включив их в C ++ 0x, вы можете сделать что-то вроде: -

В каком-то заголовочном файле статической библиотеки ...

template< class T = int >
void Af()
{
}

Затем в соответствующем файле cpp используйте явную реализацию шаблона ...

template void Af();

Это сгенерирует символы для функции Af, хотя она еще не вызывается / не ссылается. Это не повлияет на абонентов из-за того, что из-за аргумента шаблона по умолчанию вам не нужно указывать тип. Просто добавьте template <class T = int > перед объявлением функции и явно создайте его экземпляр в файле реализации.

НТН,

0 голосов
/ 07 июня 2010

Попробуйте поместить эти строки в B/initB.cpp, чтобы (надеюсь) их принудительно поместили в библиотеку libB.so во время ссылки.

Но почему вы вообще должны это делать? Разве вы не можете настроить его так, чтобы исполняемый файл ссылался на эту функцию (или вызывающую ее функцию), заставляя компоновщик автоматически делать правильные вещи?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...