编译项目时,如果我的源文件包含一个没有使用函数的文件,编译器的输出中是否会包含不需要的目标文件?
例如
foo.c
int main() {return 0;}
酒吧.c
void unusedFunction {;}
编译器执行:
gcc foo.c bar.c -o output
如果我从编译器命令中省略 bar.c,输出文件会更小吗?
大多数链接器会链接不需要的文件,除非您告诉他们不要这样做。有这方面的标志。
假设您链接了两个不需要的文件:一个目标文件和一个库:
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
$猫main.c int main() { } $猫不需要.c 无效不需要(){} $ gcc -c main.c $ gcc -c 不需要的.c
如果我们正常链接,我们会得到一切......
$ gcc main.o 不需要的.o -lz $ nm a.out | 不需要 grep 0000000000400574 T 不需要 $ readelf -d a.out | 需要 grep 0x0000000000000001(需要)共享库:[libz.so.1] 0x0000000000000001(需要)共享库:[libc.so.6]
有了正确的标志,我们就得到了我们所需要的……
$ gcc -Wl,--as-needed -Wl,--gc-sections main.o unneeded.o -lz $ nm a.out | 不需要 grep $ readelf -d a.out | 需要 grep 0x0000000000000001(需要)共享库:[libc.so.6]
编译命令中引用的每个源文件或目标文件都将包含在最终的可执行文件中。
要仅包含所需的内容,请从您的对象构建一个静态库,并在链接时引用它,而不是单个对象。静态库就是为此目的而发明的。
使用 Scons ( http://www.scons.org/ ) 或 Gradle ( http://www.gradle.org/ ) 之类的东西来找出依赖关系,然后只链接适当的位(假设您使用的是静态链接)
动态链接是另一回事——你会得到很多,因为其他程序可能需要额外的东西。
但是对于给定的命令行,它将链接它。如果不需要,为什么要首先添加它?