使用gcc从静态链接的文件中查找可选符号

Find an optional symbol from statically linked file with gcc?

本文关键字:查找 符号 文件 gcc 静态 链接 使用      更新时间:2023-10-16

我想支持一些加速的AVX/SSE功能,但我希望能够选择性地包含它。我可以将dlsym((与共享对象一起使用,但为了更便携的二进制文件,我尽可能避免共享链接。

如果静态符号成功地链接进来,我是否可以使用一种机制来使用它,否则就回到泛型函数?

您可以使用弱符号,标记为__attribute__ ((weak)),声明如下:

void avx_function (void) __attribute__ ((weak));

然后在调用函数之前检查NULL

if (avx_function != NULL)
avx_function ();
else
fallback_implementation ();

但这并不适用于替代实现,只适用于通过其他方式链接的可选功能:您需要一种机制来实际引入avx_function,因为弱符号无法做到这一点。

但编译时或链接时功能选择不会让您获得可移植二进制文件。如果您需要可移植的二进制文件,您可能会更好地使用运行时检查和通过函数指针的间接操作(用于复杂的功能选择(。

如果理解正确,您有一些链接,例如:

gcc -o prog main.o ...

其中调用了一些avx_func,并且您希望它是这样的如果CCD_ 5不静态链接CCD_ 6的真实定义,则它将静态链接通用代理。

如果这是正确的,您可以简单地利用链接器将解析的事实它在链接序列中找到的第一个定义的符号,并且不会链接任何其他定义,除非它被强制(在这种情况下是多重定义错误是通常的结果(。因此,例如

main.cpp

extern void avx_func();
int main()
{
avx_func();
return 0;
}

avx_or_not.cpp

#ifdef HAVE_REAL_AVX
#include <iostream>
void avx_func()
{
std::cout << "The real " << __PRETTY_FUNCTION__ << std::endl;
}
#endif

avx_fallback.cpp

#include <iostream>
void avx_func()
{
std::cout << "The fallback " << __PRETTY_FUNCTION__ << std::endl;
}

制作静态库libavxfallback.a:

$ g++ -Wall -Wextra -c avx_fallback.cpp
$ ar rcs libavxfallback.a avx_fallback.o

编译另一个源,假设真实的AVX:

$ g++ -Wall -Wextra -DHAVE_REAL_AVX -c avx_or_not.cpp  main.cpp

链接程序:

$ g++ -o prog main.o avx_or_not.o -L. -lavxfallback

运行:

$ ./prog
The real void avx_func()

再次编译另一个源,这次假设没有真正的AVX:

$ g++ -Wall -Wextra -c avx_or_not.cpp  main.cpp

重新链接并重新运行:

$ g++ -o prog main.o avx_or_not.o -L. -lavxfallback
$ ./prog
The fallback void avx_func()

在链接时,您不需要知道调用avx_func()或定义avx_func()-lavxfallback之前的链接:您仍然知道,如果调用它,链接中的第一个定义将被链接,如果没有更早的,它将是libavxfallback中的那个。