【问题标题】:Static Library linked Program VS Source Code Compiled program huge size difference静态库链接程序 VS 源代码编译程序巨大的大小差异
【发布时间】:2016-04-02 03:08:44
【问题描述】:

我有一个库 (Crypto++),编译该库时总共有将近 50MB。

我获取了 Crypto++ 的源代码,并且只添加了我将在我的应用程序中使用的算法的源文件。 然后我创建了应用程序并决定将 Crypto++ 编译为静态库并将其链接到同一项目的克隆版本。

所以现在我有 2 个项目:

项目 1:只有编译所需的源文件,只使用我需要的算法 AES、SHA256 等。

项目 2:只有头文件和 Crypto++ 链接的静态库。

现在,当我编译这两个项目时,我应该(或者我一直认为)看到两个 exe 具有相同的大小,因为链接器只会将我在项目 2 中使用的源链接到 exe,基本上它会链接我在项目 1 中使用的完全相同的文件。 但事实并非如此,我看到项目 1 与项目 2 的巨大差异...... 使用静态库的项目比使用源代码编译的项目大6.2倍。(均在Release模式下编译)

项目 1(源)大小:210kb 项目 2(静态库)大小:1,303kb

这是为什么?我一直认为链接器应该只使用我在代码中引用的内容。这只是链接器效率低下吗?

有人可以启发我吗?

【问题讨论】:

    标签: c++ static size crypto++


    【解决方案1】:

    链接器只会使用它所引用的内容。您观察到的行为是整个加密库构建为一个对象这一事实的直接结果。链接器别无选择,只能包含整个内容。如果您拥有库的源代码并将其与您的项目一起构建,则链接器可以执行您所期望的操作。

    【讨论】:

      【解决方案2】:

      我有一个库(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
      +
      

      【讨论】:

        猜你喜欢
        • 2013-06-23
        • 2013-12-09
        • 1970-01-01
        • 2013-10-04
        • 2017-05-08
        • 2023-03-19
        • 1970-01-01
        • 1970-01-01
        • 2012-05-02
        相关资源
        最近更新 更多