我刚刚将一堆源代码提取到几个静态库中,以使项目更加结构化,并且主可执行文件的二进制大小增加了~150kb。这让我感到困惑,所以我用三个文件制作了小项目:
foo.c:
int foo1(void) { return 1; }
int foo2(void) { return 2; }
...
int foo100(void) { return 3; }
bar.c:
int bar1(void) { return 1; }
int bar2(void) { return 2; }
...
int bar100(void) { return 4; }
main.c:
int main(int argc, const char * argv[]) {
int acc = 0;
acc += foo1();
acc += bar1();
acc += foo2();
acc += bar2();
...
acc += foo100();
acc += bar100();
printf("%dn", acc);
}
在我制作了两个可执行文件和一个静态库之后:
libfoo.a:
foo.o
bar.o
test_no_lib:
main.o
foo.o
bar.o
test_with_lib:
main.o
libfoo.a
它们的大小相差约 2kb(test_no_lib
为 ~31kb,test_with_lib
为 ~33kb,在 macOS 上使用 clang 11 编译,-Os 优化,所有符号都被剥离(。
为什么?静态库不是应该只是对象文件的存档,链接器如果需要一些对象文件,它会获取这些对象文件吗?为什么它也会增加尺寸?它不是很多,但它仍然让我感到惊讶,为什么它不是免费的?
我已经想通了。静态库是使用不同的可见性设置(默认(编译的,因此链接器必须保留重新定位信息,即使所有符号名称都被剥离。