我有一个我用make构建的ARM项目。我正在根据源目录中所有.c和.cpp文件的名称创建要链接的目标文件列表。但是,如果从未使用过,我希望将对象排除在链接之外。即使我将这些对象包含在要链接的对象列表中,链接器也会自动从.elf文件中排除这些对象吗?如果没有,有没有办法生成只需要链接的对象的列表?
答案 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)
让您的链接器生成二进制文件的映射文件,这样您就可以看到它的内容以及被剥离的内容。
答案 3 :(得分:0)
根据编译器/链接器和优化级别的复杂程度,链接器不会链接到未被调用的代码中。
答案 4 :(得分:0)
您使用的是什么编译器/链接器?一些链接器会自动执行此操作,有些链接器将该功能作为命令行选项提供。
答案 5 :(得分:0)
根据我的经验,许多编译器不会在目标文件的基础上包含未使用的代码。有些可能没有这个解决方案,并且将包括整个库(“因为这会使构建过程更快”)。
例如,给定文件junk.c
并且它有三个功能:Func1
,Func2
和Func3
。构建过程创建一个目标文件junk.o
,其中包含所有三个函数。如果未使用函数Func2
,则无论如何都会包含它,因为链接器不能从对象文件中排除一个函数。
另一方面,给定文件:Func1.c
,Func2.c
和Func3.c
,使用上述函数,每个文件一个。如果未使用Func2
中的Func2.c
,则链接器将不包含它。
一些链接器足够聪明,可以将文件排除在库之外。但是,每个链接器的文件包含粒度都不同(因此文件排除)。请阅读您的链接器手册或联系其客户支持以获取确切信息。
我建议将可疑功能移动到一个单独的文件中(每个文件一个功能)并重建。测量前后的代码大小。此外,Debug和Release链接之间可能存在差异。 Debug链接可能是惰性的,只是将所有内容都放入,而Release链接则需要花费更多精力来删除未使用的代码。
只是我的想法和经验,你的里程可能会变化(YMMV)。
答案 6 :(得分:0)
传统上,链接器链接在命令行中指定的所有目标文件中,即使它们可以被省略并且程序也没有任何未解析的符号。这意味着您可以通过包含一个目标文件来故意改变程序的行为,该目标文件执行从静态初始化触发但不直接或间接从main
调用的内容。
通常,如果将大多数目标文件放在静态库中,并将此库与包含入口点的单个目标文件链接,则链接器将仅选择库的成员(迭代地),以帮助解决未解析的符号引用。原始目标文件或随后包含的文件因为它解决了以前未解析的符号。
简而言之,将大部分目标文件放在库中,只需将其与包含入口点的一个对象链接即可。