如何编译C程序,使其不依赖于任何库?

4

即使是一个简单的“Hello World”程序也依赖于多个库:

libc.so.6 => /lib64/libc.so.6 (0x00000034f4000000)
/lib64/ld-linux-x86-64.so.2 (0x00000034f3c00000)

如何进行静态链接所有内容?

1
为什么这对你很重要?任何Linux系统都将拥有一个工作的C库和动态链接器。它们是ABI的一部分。 - hmakholm left over Monica
3
@Henning Makholm,“Linux ABI”在哪里描述?我的意思是ABI,它说libc.so.6ld-linux-x86-64.so.2是其中的一部分。您是否见过没有rootfs的嵌入式Linux? - osgx
@osgx:这主要是非正式的(非正式ABI仍然是ABI,只是更难确定它是什么),但我认为它在FHS某个地方有记载。 - hmakholm left over Monica
2个回答

8

使用-static参数进行链接。"对于支持动态链接的系统,这可以防止与共享库链接。"

编辑:是的,这会增加可执行文件的大小。你可以选择两种方法,一是像Marco van de Voort建议的那样(-nostdlib,编写自己的标准库或找到一个最小的标准库)。

另一种方法是尝试让GCC尽可能地删除不需要的内容。

gcc  -Wl,--gc-sections -Os -fdata-sections -ffunction-sections -ffunction-sections -static test.c -o test
strip test

在我的电脑上,将小测试从约800K减少到约700K,因此缩小并不是非常大。
先前的SO讨论:
来自其他链接单元的垃圾
使用gcc进行静态链接时如何仅包含已使用的符号?
使用GCC查找无法访问的函数(“死代码”) 更新2:如果您满意只使用系统调用,则可以使用gcc -ffreestanding -nostartfiles -static获得非常小的可执行文件。
尝试这个文件(small.c):
#include <unistd.h>

void _start() {
    char msg[] = "Hello!\n";
    write(1, msg, sizeof(msg));
    _exit(0);
}

使用以下命令进行编译:gcc -ffreestanding -nostartfiles -static -o small small.c && strip small。在我的系统上,这将生成一个大约5K的可执行文件(其中还有一些应该可以剥离的部分)。如果你想更深入地了解,请参考此指南

大小如此之大,是因为静态链接的程序实际上包含了库及其代码的副本,而不仅仅是包含对共享库中函数和代码的简单引用。 - James O'Doherty
@James O'Doherty,我该如何指示编译器仅包含必要的符号? - lexer
答案中的--gc-sections和其他节命令应该可以做到这一点。 - Marco van de Voort
1
@lexer(1),尝试阅读http://www.muppetlabs.com/~breadbox/software/tiny/teensy.html(以及可能在http://www.muppetlabs.com/~breadbox/software/tiny/中的其他内容)。 - David X

1

或者使用 -nostdlib 并实现自己的库和启动代码。

各种“在*nix上汇编”的网站可以给你一个实现的想法。

如果你只是想让你的二进制文件变小,那么从使用32位开始。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接