使用 GCC 编译非必要的目标文件

Posted

技术标签:

【中文标题】使用 GCC 编译非必要的目标文件【英文标题】:Compiling nonessential object files with GCC 【发布时间】:2010-02-07 03:53:47 【问题描述】:

考虑以下示例

g++ a.o b.o c.o -o prog

如果c.o 没有向prog 贡献任何可执行代码,并且在任何其他文件中也没有对c.o 的任何依赖,那么GCC 是否还会将c.o 的内容包含在prog?

换句话说,除了编译时间之外,将不必要的文件编译成可执行文件会产生什么(如果有的话)负面后果?

提前致谢;干杯!

【问题讨论】:

您可以尝试使用和不使用额外库进行链接,看看可执行文件的大小是否相同。 我不了解 GCC,但无论您是否引用它们,MSVC 都会包含所有 .obj 文件的内容,但它只会包含您引用的 .lib 文件的部分。我希望 GCC 也一样 所描述的步骤通常称为“链接”。术语“编译”通常用于描述目标文件的生成。 【参考方案1】:

除了您的可执行文件可能不必要地大之外,没有任何负面影响。链接器可能会为您删除未使用的代码,这会将事情缩小。您可以在输出可执行文件上使用某种对象查看工具(otoolobjdumpnm 等)来查看您的程序中是否有额外的符号。

我使用的是 Mac,所以如果您使用的是标准的 gcc 工具集,会有一些差异,但这里有一个示例:

$ make
gcc -o app main.c file2.c
gcc -Wl,-dead_strip -o app_strip main.c file2.c
$ ls -l app*
-rwxr-xr-x  1 carl  staff  8744 Feb  6 20:05 app
-rwxr-xr-x  1 carl  staff  8704 Feb  6 20:05 app_strip

我认为在非 Apple gcc 世界中,您将通过 -Wl,--gc-sections 而不是我的示例中的 -Wl,-dead_strip。您可以看到的两个可执行文件的大小差异是由于剥离了额外的功能:

$ nm app | cut -c 20- > app.txt
$ nm app_strip | cut -c 20- > app_strip.txt 
$ diff app.txt app_strip.txt 
8d7
< _function2

【讨论】:

【参考方案2】:

llvm 可以消除链接步骤中的死代码。它使用特殊的链接器llvm-ld

此外,使用-fwhole-ipo(英特尔)将有助于去除死符号。

【讨论】:

【参考方案3】:

我只是用我目前正在使用的一些 C 代码尝试了它——我链接到一个对象,该对象包含一个(尚未)在程序中其他任何地方使用的方法。该代码包含在生成的可执行文件中,通过针对 elf 文件运行 nm 并观察方法 T 确实存在进行检查,即使使用了 -O2 和 -O3 也是如此。

【讨论】:

【参考方案4】:

是的,GCC 将包括所有目标文件。使用最新的编译器(开发版本 4.5.0),您可以使用 -flto(链接时优化)来执行此操作。

【讨论】:

以上是关于使用 GCC 编译非必要的目标文件的主要内容,如果未能解决你的问题,请参考以下文章

gcc 简单使用笔记

如何将 GCC LTO 与不同优化的目标文件一起使用?

linux下的gcc编译器

windows下使用gcc完成头文件和目标文件编译

使用readelf和objdump解析目标文件 ***

gcc 可以用 keil-arm 编译器编译的目标文件编译吗?