繁体   English   中英

如何在链接到可执行文件时强制将对象文件包含在静态库中?

[英]How to force inclusion of an object file in a static library when linking into executable?

我有一个C ++项目,由于其目录结构被设置为静态库A ,它链接到共享库B ,它链接到可执行文件C (这是一个使用CMake的跨平台项目,所以在Windows上我们得到A.libB.dllC.exe ,在Linux上我们得到libA.alibB.soC )图书馆A有一个init函数( A_init ,在A/initA.cpp定义),从库B的init函数( B_init ,在B/initB.cpp定义)调用,从C的main调用。 因此,在连接时BA_init (和中定义的所有符号initA.cpp )被链接到B (这是我们所希望的行为)。

问题在于A库还定义了一个动态加载的函数( Af ,在A/Afort.f定义)(即Windows上的LoadLibrary / GetProcAddress和Linux上的dlopen / dlsym )。 由于库B中没有对Af引用,因此A/Afort.o中的符号不​​包括在B 在Windows上,我们可以通过使用pragma人工创建引用:

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

由于这是一个pragma,它只适用于Windows(使用Visual Studio 2008)。 为了使它在Linux上运行,我们尝试将以下内容添加到A/initA.cpp

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

这不会导致符号Af包含在B的最后一个链接中。 我们如何强制将符号Af链接到B

事实证明我最初的尝试主要在那里。 以下作品:

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)

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

gcc -u symbol

有一种更好的方法来编写FORCE_UNDEFINED_SYMBOL宏。 只需将该函数指针强制转换为void *即可。 然后它适用于任何功能 - 或者数据。 此外,当宏的gcc部分也适用于MSVC时,为什么还要使用MSVC编译指示。 所以我的简化版本是:

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

因此使用的是:

FORCE_UNDEFINED_SYMBOL(Af)

但它必须在包含其符号被剥离的库的程序中使用。

您可以在构建B时使用--undefined选项:

g++ -Wl,--undefined,Af -o libB.so ...

尝试将这些行放入B/initB.cpp以便它们(希望)在链接时强制进入libB.so库。

但是你为什么要以这种方式去做呢? 你不能设置它,以便可执行文件引用该函数(或它的调用者),导致链接器自动执行正确的操作吗?

如果你可以使用gcc的C ++ 0x特性( -std = c ++ 0x ),那么函数默认模板参数就可以了。 从当前的c ++标准来看,函数模板不允许使用默认参数。 在c ++ 0x中启用这些功能后,您可以执行以下操作: -

在静态库的一些头文件中......

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

然后在其对应的cpp文件中使用显式模板实例化...

template void Af();

这将生成函数Af的符号,尽管它尚未被调用/引用。 这不会影响调用者,因为由于默认模板参数,您无需指定类型。 只需在函数声明之前添加template <class T = int > ,并在其实现文件中显式实例化它。

HTH,

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM