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

时间:2022-08-14 02:14:59

I have a C++ project that due to its directory structure is set up as a static library A, which is linked into shared library B, which is linked into executable C. (This is a cross-platform project using CMake, so on Windows we get A.lib, B.dll, and C.exe, and on Linux we get libA.a, libB.so, and C.) Library A has an init function (A_init, defined in A/initA.cpp), that is called from library B's init function (B_init, defined in B/initB.cpp), which is called from C's main. Thus, when linking B, A_init (and all symbols defined in initA.cpp) is linked into B (which is our desired behavior).

我有一个c++项目,由于它的目录结构,它被设置为静态库a,它被链接到共享库B,它被链接到可执行的C(这是一个使用CMake的跨平台项目,所以在Windows上我们得到a。*,B。dll,C。在Linux上我们有libA。libB。所以,和c .)库A有一个init函数(A_init,在A/initA.cpp中定义),它从库B的init函数(B_init,在B/ initb.c .cpp中定义)调用,从C的main中调用。因此,当连接B时,A_init(以及initA.cpp中定义的所有符号)被连接到B中(这是我们期望的行为)。

The problem comes in that the A library also defines a function (Af, defined in A/Afort.f) that is intended to by dynamically loaded (i.e. LoadLibrary/GetProcAddress on Windows and dlopen/dlsym on Linux). Since there are no references to Af from library B, symbols from A/Afort.o are not included into B. On Windows, we can artifically create a reference by using the pragma:

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

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

Since this is a pragma, it only works on Windows (using Visual Studio 2008). To get it working on Linux, we've tried adding the following to A/initA.cpp:

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

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

This does not cause the symbol Af to be included in the final link of B. How can we force the symbol Af to be linked into B?

这并不会导致符号Af被包含在B的最终链接中,我们如何强制符号Af被链接到B中呢?

6 个解决方案

#1


12  

It turns out my original attempt was mostly there. The following works:

原来我最初的尝试大部分都在那里。以下工作:

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

For those that want a self-contained preprocessor macro to encapsulate this:

对于那些需要一个自包含的预处理器宏来封装它的人:

#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

Which is used thusly:

因而使用:

FORCE_UNDEFINED_SYMBOL(Af)

#2


6  

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

MSVC # pragma评论(链接器,“/包括:__mySymbol”)

gcc -u symbol

gcc - u标志

#3


3  

You can use the --undefined option when you build B:

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

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

#4


2  

There is a better way to write that FORCE_UNDEFINED_SYMBOL macro. Just cast that function pointer to a void*. Then it works with any function - or data for that matter. Also, why bother with MSVC pragmas when the gcc part of your macro will work for MSVC as well. So my simplified version would be:

有一种更好的方法来编写FORCE_UNDEFINED_SYMBOL宏。只需将函数指针转换为void*。然后它可以处理任何函数或数据。此外,当您的宏的gcc部分也适用于MSVC时,为什么还要使用MSVC实用程序呢?我的简化版本是:

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

Which is used thusly:

因而使用:

FORCE_UNDEFINED_SYMBOL(Af)

But it must be used in the program that includes the library that is having its symbols stripped.

但是,它必须在程序中使用,程序中包括正在删除其符号的库。

#5


0  

Try putting those lines into B/initB.cpp so that they're (hopefully) forced into the libB.so library at link time.

试着把这些线放到B/initB中。cpp所以他们(希望)*进入libB。链接时间的库。

But why do you have to do it in this way at all? Can't you set it up so that the executable references that function (or a caller of it), causing the linker to do the right thing automatically?

但是你为什么一定要这样做呢?您难道不能设置它,以便可执行文件引用该函数(或它的调用者),从而导致链接器自动执行正确的操作吗?

#6


0  

If you can use C++0x features of gcc (-std=c++0x), then the function default template arguments may do the trick. As of the current c++ standard, default arguments are not allowed for function templates. With these enabled in c++0x, you can do something like :-

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

In some header file of static library ...

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

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

Then in its corresponding cpp file use explicit template instantiation...

然后在相应的cpp文件中使用显式模板实例化…

template void Af();

This will generate the symbols for the function Af though it is not yet called/referenced. This won't affect the callers due to the fact that because of the default template argument, you need not specify a type. Just add the template <class T = int > before the function declaration and explicitly instantiate it in its implementation file.

这将为函数Af生成符号,尽管它还没有被调用/引用。这不会影响调用者,因为由于默认模板参数,您不需要指定类型。只需在函数声明之前添加模板 ,并在其实现文件中显式实例化模板。

HTH,

HTH,

#1


12  

It turns out my original attempt was mostly there. The following works:

原来我最初的尝试大部分都在那里。以下工作:

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

For those that want a self-contained preprocessor macro to encapsulate this:

对于那些需要一个自包含的预处理器宏来封装它的人:

#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

Which is used thusly:

因而使用:

FORCE_UNDEFINED_SYMBOL(Af)

#2


6  

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

MSVC # pragma评论(链接器,“/包括:__mySymbol”)

gcc -u symbol

gcc - u标志

#3


3  

You can use the --undefined option when you build B:

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

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

#4


2  

There is a better way to write that FORCE_UNDEFINED_SYMBOL macro. Just cast that function pointer to a void*. Then it works with any function - or data for that matter. Also, why bother with MSVC pragmas when the gcc part of your macro will work for MSVC as well. So my simplified version would be:

有一种更好的方法来编写FORCE_UNDEFINED_SYMBOL宏。只需将函数指针转换为void*。然后它可以处理任何函数或数据。此外,当您的宏的gcc部分也适用于MSVC时,为什么还要使用MSVC实用程序呢?我的简化版本是:

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

Which is used thusly:

因而使用:

FORCE_UNDEFINED_SYMBOL(Af)

But it must be used in the program that includes the library that is having its symbols stripped.

但是,它必须在程序中使用,程序中包括正在删除其符号的库。

#5


0  

Try putting those lines into B/initB.cpp so that they're (hopefully) forced into the libB.so library at link time.

试着把这些线放到B/initB中。cpp所以他们(希望)*进入libB。链接时间的库。

But why do you have to do it in this way at all? Can't you set it up so that the executable references that function (or a caller of it), causing the linker to do the right thing automatically?

但是你为什么一定要这样做呢?您难道不能设置它,以便可执行文件引用该函数(或它的调用者),从而导致链接器自动执行正确的操作吗?

#6


0  

If you can use C++0x features of gcc (-std=c++0x), then the function default template arguments may do the trick. As of the current c++ standard, default arguments are not allowed for function templates. With these enabled in c++0x, you can do something like :-

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

In some header file of static library ...

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

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

Then in its corresponding cpp file use explicit template instantiation...

然后在相应的cpp文件中使用显式模板实例化…

template void Af();

This will generate the symbols for the function Af though it is not yet called/referenced. This won't affect the callers due to the fact that because of the default template argument, you need not specify a type. Just add the template <class T = int > before the function declaration and explicitly instantiate it in its implementation file.

这将为函数Af生成符号,尽管它还没有被调用/引用。这不会影响调用者,因为由于默认模板参数,您不需要指定类型。只需在函数声明之前添加模板 ,并在其实现文件中显式实例化模板。

HTH,

HTH,