Linux编译链接选项静态库--whole-archive,--no-whole-archive

文章目录

背景

在使用cmake构建工程时,目标可执行程序可以正常构建,但是运行不符合预期。可执行程序依赖libtool.a静态库,静态库有个全局map,map中存放注册的回调函数。在可执行程序运行时发现map为空,检查代码逻辑,libtool.a中存在注册行为。

定位思路

1、通过nm定位出相关符号表在libtool.a中存在,但是在最终可执行程序中不存在。

2、不采用静态库编译方式,可执行程序中存在相关符号表,由此确认时编译或者链接存在问题。

3、最后排查出是由于--whole-archive链接选项没有加,默认情况下代码中未被调用的符号,因此最终生成的可执行文件中,这些符号被自动优化掉。

静态库链接选项

--whole-archive可以把在其后面出现的静态库包含的函数和变量输出到动态库(可执行程序中)。在代码中定义的符号(如函数名)还未使用到之前,链接器并不会把它加入到连接表中。

"--whole-archive,--no-whole-archive"这是链接器的选项,所以在编译的时候要用-Wl,options来传递给链接器,不然编译器会不认得这个选项。

cpp 复制代码
//a.cpp:
void func(){
    printf("I am in a.cpp.\n");
}

//main.cpp:
extern void func();

int main()
{
    func(); 
    printf("I am in main.cpp"); 
    return 0;
}

首先编译g++ -c a.cpp,再打包ar -r libtool.a a.o

如果这么链接g++ -L. -ltool main.cpp -o main,则链接器会报错,称func()未定义。其实改一下顺序既可以解决g++ main.cpp -L. -ltool -o main

或者使用g++ -Wl,--whole-archive -L. -ltool -Wl,--no-whole-archive main.cpp -o main,将libtool.a中的所有.o中的符号都链接进来。

对于C++中使用的Register机制,即动态对象创建会遇到这样的问题。

在cmake中添加链接选项

cmake 复制代码
TARGET_LINK_LIBRARIES(app
-Wl,--whole-archive
tool
-Wl,--no-whole-archive
)

参考

http://stackoverflow.com/questions/805555/ld-linker-question-the-whole-archive-option

相关推荐
AlfredZhao16 分钟前
OCI 明明分配了 200G 系统盘,为什么 df 只看到 30G?
linux·oci
AlfredZhao15 小时前
vi 删除指定范围的行,不用再反复按 dd
linux·vi
用户97183563346621 小时前
银河麒麟 KY10 申威(SW64) 安装 nginx-1.16.1-2.p01.ky10.sw_64.rpm 详细步骤
linux
猪脚踏浪1 天前
linux 拷贝文件或目录到指定的位置
linux
摇滚侠2 天前
Linux CentOS7 rpm 安装 MySQL 5.7
linux·运维·mysql
bush42 天前
嵌入式linux学习记录十四、术语
linux·嵌入式
载数而行5202 天前
Linux 11 动态监控指令top
linux
不会C语言的男孩2 天前
Linux 系统编程 · 第 8 章:进程基础
linux·c语言
古城小栈2 天前
Unix 与 Linux 异同小叙
linux·服务器·unix
凡人叶枫2 天前
Effective C++ 条款42:了解 typename 的双重意义
java·linux·服务器·c++