【发布时间】:2019-10-25 18:55:27
【问题描述】:
我正在尝试编译一个程序以将所有库静态地包含在最终的二进制文件中,但我仍然希望 glibc 能够动态链接。如果我使用“-static”,它会静态编译所有库,包括 glibc。基本上我需要一个 -static 参数以及 -exclude=glibc 之类的参数 使用“make”的例子和纯“gcc”的例子都会很棒。在最终的二进制文件上运行“ldd”应该只显示动态链接的 glibc。
【问题讨论】:
我正在尝试编译一个程序以将所有库静态地包含在最终的二进制文件中,但我仍然希望 glibc 能够动态链接。如果我使用“-static”,它会静态编译所有库,包括 glibc。基本上我需要一个 -static 参数以及 -exclude=glibc 之类的参数 使用“make”的例子和纯“gcc”的例子都会很棒。在最终的二进制文件上运行“ldd”应该只显示动态链接的 glibc。
【问题讨论】:
【讨论】:
-ffunction-sections -fdata-sections 和-Wl,--gc-sections 结合使用?当 gcc 没有设置 -static 时,-Wl,--gc-sections 无效。
-Wl,--gc-sections 至少在某些情况下没有-static 可以工作,因此您需要提供更多详细信息。
-Wl,--gc-sections 即使没有-static 也有一些(更少) 效果。不过,行为有所不同,具体如何变化尚不清楚。
您的要求可以在某些系统上大致完成,但不能使用 GCC 的 -static 选项。该选项对链接具有全局影响:
在支持动态链接的系统上,这会覆盖 -pie 并阻止与共享库的链接。在其他系统上,此选项无效。
要对链接进行所需的控制级别,您需要将标志传递给链接器。您可以使用 GCC 的 -Wl 选项来做到这一点。如果您使用的是 GCC,那么您可能也在使用 GNU 链接器,并且在支持静态和动态链接的构建目标上,它具有多种混合它们的机制。特别是,GNU 链接器的-Bstatic 标志及其对应的-Bdynamic 标志仅对命令行上以它们命名的库生效,直到下一个此类标志。也就是说,它们允许您在为静态链接和动态链接指定库之间来回切换。
示例:
此 C 程序需要链接数学库,而 GCC 不会自动链接:
link_test.c:
#include <stdio.h>
#include <math.h>
int main(void) {
printf("The square root of 2 is approximately %f\n", sqrt(2.0));
}
这个gcc 命令将导致-lm 被静态链接,但libc 被动态链接:
gcc -o link_test link_test.c -Wl,-Bstatic -lm -Wl,-Bdynamic
在-Wl,-Bstatic 和-Wl,-Bdynamic 选项之间可以放置任意数量的附加-l 选项、库名和目标文件名以及-lm;所有这些对象都将静态链接。尽管libc 没有显式链接(GCC 不需要),但在显式参数列表的末尾将链接类型切换为“动态”确实会导致 libc 被动态链接:
$ ldd link_test
linux-vdso.so.1 => (0x00007ffe185af000)
libc.so.6 => /lib64/libc.so.6 (0x00002b775f059000)
/lib64/ld-linux-x86-64.so.2 (0x00002b775ee35000)
(请注意 libm 没有出现在动态库列表中,不像 -Wl,-Bstatic 没有使用,但 libc 出现了。)
请注意,您的目标“在最终二进制文件上运行 'ldd' 应该只显示动态链接的 glibc”不一定可行,正如上面的 ldd 输出所示。如果您的可执行文件完全是动态链接的,那么除了任何动态库之外,它还将链接动态加载程序,并且可能还有特定于平台的伪库,例如linux-vdso.so.1。
您要求一个 makefile 示例,但这就像只要求“给我写一个程序”。这不是make 特有的,并且有无数种方法可以将上述方法合并到makefile 中。但既然你问了,这是最简单的变体之一:
生成文件
link_test: link_test.c
gcc -o $@ $< -Wl,-Bstatic -lm -Wl,-Bdynamic
【讨论】: