我在这里和其他论坛上看到了很多问题,其中建议使用编译参数-static,有时甚至-static -static-libgcc与编译参数一起使用。这在 Alpine 上不起作用,但在 Ubuntu 和 Fedora 上工作得很好。
我用 C 语言编写了一个简单的 hello-world 程序,然后将其编译为gcc -static test.c. 生成的二进制文件仍然亮起ldd。看,
$ gcc -s test.c -static
$ ldd ./a.out
/lib/ld-musl-x86_64.so.1 (0x7f043eae8000)
$ file ./a.out
./a.out: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, stripped
Run Code Online (Sandbox Code Playgroud)
在 Ubuntu 上运行相同的命令显示:
$ gcc -s test.c -static
$ file ./a.out
./a.out: ELF 64-bit LSB executable, x86-64, version 1 (GNU/Linux), statically linked, for GNU/Linux 3.2.0, BuildID[sha1]=bf6bfa1c78c541ae4e81586bcd050923bca9e34a, stripped
Run Code Online (Sandbox Code Playgroud)
在任何平台上静态链接 libc 本身的正确且一致的方法是什么?这与 GCC 本身的编译方式有关吗?
我在这里为那些天真地来到这里搜索诸如此类的关键字的人回答我自己的问题static link libc。
如果这是针对 MSVC,您唯一的选择是/MT或/MTd。但如果您来这里寻找 GCC,欢迎来到位置独立的代码兔子洞。
GCC 有多种变体,它们针对特定目标进行了修补,或者只是因为它们可以进行修补。因此,如果您有 GCC 版本 6.0,并期望命令行参数生成相同的行为,那么您可能会成为某些不良补丁工作的受害者。
本问题中的某些版本的 GCC 强制执行与位置无关的可执行文件 ( -fPIE -pie),并默默地忽略该-static选项,如此例中所示。我想知道这是否应该作为错误报告给 Alpine 维护人员。要强制它忽略 PIE,请传递-no-pie给您的 GCC。
$ gcc -no-pie -static test.c
Run Code Online (Sandbox Code Playgroud)
如果你这样做
$ file ./a.out
/lib/ld-musl-x86_64.so.1: ./a.out: Not a valid dynamic program
Run Code Online (Sandbox Code Playgroud)
有关如何操作的详细信息,请fPIE阅读OpenBSD 的static这些幻灯片。
您的 Ubuntu 二进制文件未启用 PIE。如果您传递-no-pie到 Alpine 上的 GCC,它的二进制文件同样不会启用 PIE,但随后它将根据您的需要进行静态链接。