我有一个库(Crypto++),编译库时总共有将近 50MB....
是的,静态库包含所有符号。什么都不能丢弃,因为它可能是需要的。
如果您使用了-g,它还会携带调试信息。一些优化标志也会影响它。例如-Os 最小化代码大小。
使用静态库的项目比使用源代码编译的项目大 6.2 倍。这是为什么呢?
我们需要查看您的程序,以及您的编译器和链接器切换以更好地解释正在发生的事情。根据这些数字,我猜测正在发生一些死代码剥离,但并没有您预期的那么多:
项目 1(源)大小:210kb 项目 2(静态库)大小:1,303kb
我一直认为链接器应该只使用我在代码中引用的内容。这只是链接器效率低下吗?
在构建 Crypto++ 库时,请使用 make lean 配方。它添加了函数部分 (-ffunction-sections) 和数据部分 (-fdata-sections),因此链接器可以更好地丢弃未使用的代码和数据。另请参阅 Crypto++ wiki 上的 GNUmakefile | Makefile Targets。
当您链接您的应用程序时,请使用适当的链接器开关。使用 GCC/LD,那将是 -Wl,--gc-sections。在 Apple/DYLD 下,应该是 -Wl,-dead_strip。
您还可以去除调试符号,这将进一步减小二进制文件的大小。我不清楚你是用符号构建还是在之后剥离它们。
如果您完全剥离并丢弃符号,那么堆栈跟踪将几乎无用。如果您将符号保留在脱机文件中,那么您可能能够理解堆栈跟踪。另请参阅 Crypto++ wiki 上的 Debug Symbols。
以下是针对用户调查lean 目标的结果。另请参阅 Crypto++ 用户组上的 'make lean' target?。
测试程序:
int main( int, char** ) {
Integer j("100000000000000000000000000000000");
j %= 1999;
cout << "j: " << j << endl;
return 0;
}
精益(使用make lean 构建的库,使用-Wl,--gc-sections 链接的程序):
$ ls -l integer.exe
-rwx------ 1 jwalton staff 162012 Jan 4 13:00 integer.exe
正常(使用make 构建的库,没有特殊的链接器开关):
$ ls -l integer.exe
-rwx------ 1 jwalton staff 2636952 Jan 4 13:02 integer.exe
lean 目标是在 Crypto++ 5.6.3 发布后添加的。如果需要,您需要从 Master 获取代码:
git clone https://github.com/weidai11/cryptopp.git cryptopp
或者,您可以从Commit 9696b9e5e79ff18a 手动将以下补丁应用到 GNUmakefile。在第 270 行左右添加它:
+# Dead code stripping. Issue 'make lean'.
+ifeq ($(findstring lean,$(MAKECMDGOALS)),lean)
+ifeq ($(findstring -ffunction-sections,$(CXXFLAGS)),)
+CXXFLAGS += -ffunction-sections
+endif # CXXFLAGS
+ifeq ($(findstring -fdata-sections,$(CXXFLAGS)),)
+CXXFLAGS += -fdata-sections
+endif # CXXFLAGS
+ifneq ($(IS_DARWIN),0)
+ifeq ($(findstring -Wl,-dead_strip,$(LDFLAGS)),)
+LDFLAGS += -Wl,-dead_strip
+endif # CXXFLAGS
+else # BSD, Linux and Unix
+ifeq ($(findstring -Wl,--gc-sections,$(LDFLAGS)),)
+LDFLAGS += -Wl,--gc-sections
+endif # LDFLAGS
+endif # MAKECMDGOALS
+endif # Dead code stripping
以下是食谱所在:
+.PHONY: lean
+lean: libcryptopp.a cryptest.exe
+