我的链接器是否会链接不需要的源文件中的对象?

时间:2013-04-20 17:43:57

标签: c linker

编译项目时,如果我的源文件包含没有使用过的函数的文件,那么不需要的目标文件是否会包含在编译器的输出中?

e.g。

foo.c的

int main() {return 0;}

bar.c

void unusedFunction {;}

编译器执行:

gcc foo.c bar.c -o output

如果我从编译器命令中省略了bar.c,输出文件会不会更小?

3 个答案:

答案 0 :(得分:4)

大多数链接器会链接不需要的文件,除非你告诉他们不要。有标志。

假设您链接了两个不需要的文件:目标文件和库:

gcc main.o unneeded.o -lunneeded

对于GNU Binutils或Gold,对于不需要的符号/对象文件,标志为--gc-sections,对于库,标志为--as-needed。但是,它们是链接器标志,因此它们必须以-Wl,为前缀。请注意,这些标志的顺序是重要的 - 标志仅适用于命令行上的标志后出现的库和目标文件,因此必须首先指定标志。

gcc -Wl,--as-needed -Wl,--gc-sections main.o unneeded.o -lunneeded

在OS X上,有一个不同的链接器,因此标志不同。 -dead_strip标志删除不需要的符号/目标文件,-dead_strip_dylibs标志删除不需要的库。

gcc -Wl,-dead_strip -Wl,-dead_strip_dylibs main.o unneeded.o -luneeded

实施例

$ cat main.c
int main() { }
$ cat unneeded.c
void unneeded() { }
$ gcc -c main.c
$ gcc -c unneeded.c

如果我们正常联系,我们会得到一切......

$ gcc main.o unneeded.o -lz
$ nm a.out | grep unneeded
0000000000400574 T unneeded
$ readelf -d a.out | grep NEEDED
 0x0000000000000001 (NEEDED)             Shared library: [libz.so.1]
 0x0000000000000001 (NEEDED)             Shared library: [libc.so.6]

有了正确的旗帜,我们就能得到我们需要的......

$ gcc -Wl,--as-needed -Wl,--gc-sections main.o unneeded.o -lz
$ nm a.out | grep unneeded
$ readelf -d a.out | grep NEEDED
 0x0000000000000001 (NEEDED)             Shared library: [libc.so.6]

答案 1 :(得分:1)

编译命令中引用的每个源或目标文件都将包含在最终的可执行文件中。

要仅包含所需内容,请从对象构建静态库,并在链接时引用它,而不是单个对象。静态库是为此目的而发明的。

答案 2 :(得分:0)

使用Scons(http://www.scons.org/)或Gradle(http://www.gradle.org/)之类的东西来计算依赖关系,然后只链接相应的位(假设您使用的是静态链接)

动态链接是另一回事 - 你得到了很多,因为其他程序可能需要额外的东西。

但至于给定的命令行会将其链接进去。如果不需要,为什么要首先添加它呢?