我们知道,在ld链接静态库过程中,通常只有被使用到的符号才回被链接进可执行文件中。
而在某些场景中,我们希望在链接的时候也能把未使用的符号也给链接进来。
在ext/mylib.h文件中声明了一个add函数和一个Register对象
#pragma once
#include
int add(int a, int b);
class Register {
public:
Register() {
std::cout<<"Register constructor : "<<this<<std::endl;
// register
}
~Register() {}
};
在ext/mylib.cc文件中定义了add函数和一个Register静态实例
#include"mylib.h"
int add(int a, int b) {
return a + b;
}
static Register r;
将上述文件编译成静态链接库mylib.a
在hello.cc中我们引入了mylib.h头文件,现在的问题是Register的构造函数会被调用吗?
#include"ext/mylib.h"
int main() {
return 0;
}
第一种情况,我们虽然引入mylib.h文件,但是没有调用任何mylib中的符号。执行的结果是:
什么也没有输出,Register没有被调用,说明Register符号并没有被链接进来。
第二种情况,我们引入mylib.h文件,并且调用add函数:
#include"ext/mylib.h"
int main() {
add(5,23);
return 0;
}
编译运行,结果是:
Register constructor : 0x7ff8e85890e1
Register的构造函数被调用了,说明Register符号被链接进来了。
于是可以得出第一个结论,静态链接以.o文件为单位的。也就是说,在一个.o文件中,只要其中一个符号被链接进来,剩下的符号也会被链接进来(哪怕是没有被使用的)。
如果我们没有引用链接库中的符号,但又想将这些符号链接进来怎么办?
可以使用ld链接器的一个参数:–whole-archive。具体在CMakeList中可以这么写:
target_link_libraries(my_exe -Wl,--whole-archive mylib -Wl,--no-whole-archive)
这里面需要注意的–whole-archive后面是想要全量链接的库名,之后要使用–no-whole-archive避免后面的库也全量链接。
还有一个问题,如果只想链接一个.o文件中被使用的符号,而把其它未被使用的符号删去,应该怎么做?
可以使用-ffunction-sections -fdata-sections参数生成.o文件,链接的时候再加上-Wl,–gc-sections参数。
上述实验仅针对静态链接,动态链接待研究。