如果不需要对象,可以防止对象被链接?

时间:2010-03-23 19:20:30

标签: c++ optimization linker makefile arm

我有一个我用make构建的ARM项目。我正在根据源目录中所有.c和.cpp文件的名称创建要链接的目标文件列表。但是,如果从未使用过,我希望将对象排除在链接之外。即使我将这些对象包含在要链接的对象列表中,链接器也会自动从.elf文件中排除这些对象吗?如果没有,有没有办法生成只需要链接的对象的列表?

7 个答案:

答案 0 :(得分:2)

您必须以不同方式编译代码以去除未使用的函数和数据。通常所有对象都被编译成相同的符号,因此如果不使用它们就不能单独省略。

将以下两个开关添加到编译器行: -ffunction-sections -fdata-sections 编译时,编译器现在将各个函数和数据放入它们自己的部分,而不是将它们全部放在一个模块部分中。

然后,在链接器中指定以下内容: --gc截面 这指示链接器删除未使用的部分(“gc”用于垃圾收集)。它将垃圾收集部分文件和整个文件。例如,如果你正在编译一个对象,但只在对象中使用100个100的函数,它将丢弃你没有使用的其他99个。

如果遇到未找到函数的问题(由于各种原因,如库之间的externs而发生),您可以在链接器文件(* .ld)中使用.keep指令,以防止对这些单独函数进行垃圾回收

享受你的小应用程序。

答案 1 :(得分:1)

如果您使用的是RealView,似乎有可能。本节讨论它:

3.3.3未使用的部分删除

未使用的节删除会删除从未执行的代码或不执行的数据 从最终图像中提到的代码。这种优化可以通过控制来实现 --remove, - no_remove, - first, - pop和--keep链接器选项。使用--info unused 链接器选项,用于指示链接器生成已使用的未使用部分的列表 消除。

答案 2 :(得分:1)

像很多人说的那样,答案是“依赖”。根据我的经验,RVCT非常适合死代码剥离。在最终链接阶段几乎总是会删除未使用的代码和数据。另一方面,GCC(至少没有LLVM后端)在整个图像静态分析中相当差,并且在删除未使用的代码方面做得不好(如果您的代码位于不同的部分,那么对您而言则有祸了!需要长跳)。您可以采取一些措施来缓解它,例如使用函数节,它为每个函数创建一个单独的部分,并启用一些更好的死代码剥离。

让您的链接器生成二进制文件的映射文件,这样您就可以看到它的内容以及被剥离的内容。

答案 3 :(得分:0)

根据编译器/链接器和优化级别的复杂程度,链接器不会链接到未被调用的代码中。

答案 4 :(得分:0)

您使用的是什么编译器/链接器?一些链接器会自动执行此操作,有些链接器将该功能作为命令行选项提供。

答案 5 :(得分:0)

根据我的经验,许多编译器不会在目标文件的基础上包含未使用的代码。有些可能没有这个解决方案,并且将包括整个库(“因为这会使构建过程更快”)。

例如,给定文件junk.c并且它有三个功能:Func1Func2Func3。构建过程创建一个目标文件junk.o,其中包含所有三个函数。如果未使用函数Func2,则无论如何都会包含它,因为链接器不能从对象文件中排除一个函数。

另一方面,给定文件:Func1.cFunc2.cFunc3.c,使用上述函数,每个文件一个。如果未使用Func2中的Func2.c,则链接器将不包含它。

一些链接器足够聪明,可以将文件排除在库之外。但是,每个链接器的文件包含粒度都不同(因此文件排除)。请阅读您的链接器手册或联系其客户支持以获取确切信息。

我建议将可疑功能移动到一个单独的文件中(每个文件一个功能)并重建。测量前后的代码大小。此外,Debug和Release链接之间可能存在差异。 Debug链接可能是惰性的,只是将所有内容都放入,而Release链接则需要花费更多精力来删除未使用的代码。

只是我的想法和经验,你的里程可能会变化(YMMV)。

答案 6 :(得分:0)

传统上,链接器链接在命令行中指定的所有目标文件中,即使它们可以被省略并且程序也没有任何未解析的符号。这意味着您可以通过包含一个目标文件来故意改变程序的行为,该目标文件执行从静态初始化触发但不直接或间接从main调用的内容。

通常,如果将大多数目标文件放在静态库中,并将此库与包含入口点的单个目标文件链接,则链接器将仅选择库的成员(迭代地),以帮助解决未解析的符号引用。原始目标文件或随后包含的文件因为它解决了以前未解析的符号。

简而言之,将大部分目标文件放在库中,只需将其与包含入口点的一个对象链接即可。