如何使用 make/gcc 静态 link 除 glibc 之外的所有库?
How to statically link all libraries except glibc using make/gcc?
我正在尝试编译一个程序,使所有库都静态地包含在最终的二进制文件中,但我仍然希望 glibc 是动态链接的。如果我使用“-static”,它会静态编译所有库,包括 glibc。基本上我需要一个 -static 参数以及类似 -exclude=glibc 的参数
使用 "make" 的示例以及使用纯 "gcc" 的示例都很棒。 运行 "ldd" 在最终的二进制文件上应该只显示动态链接的 glibc。
您可以 link 使用 -Bstatic
and -Bdynamic
静态库的子集。在 GCC 命令行上,这看起来像这样(linking 静态针对 PCRE,仅作为示例):
-Wl,-Bstatic -lpcre -Wl,-Bdynamic
请注意 -lanl
、-ldl
、-lm
、-lmvec
、-lnsl
、-lpthread
、-lresolv
、-lrt
、-lutil
都是 glibc 的一部分,因此必须在 -Wl,-Bdynamic
之后(以便动态地 linked)。对于 -lcrypt
,这取决于分布。
您所要求的可以在某些系统上大约完成,但不能使用 GCC 的 -static
选项。该选项对 linking:
具有全局影响
On systems that support dynamic linking, this overrides -pie and prevents linking with the shared libraries. On other systems, this option has no effect.
要对 linking 进行所需级别的控制,您需要将标志传递给 linker。您可以使用 GCC 的 -Wl
选项来做到这一点。如果您正在使用 GCC,那么您可能也在使用 GNU linker,并且在支持静态和动态 linking 的构建目标上,它有多种混合它们的机制。特别是,GNU linker 的 -Bstatic
标志及其对应的 -Bdynamic
标志每个仅对命令行上以它们命名的库有效,直到下一个这样的标志。也就是说,它们允许您在为静态 linking 和动态 linking 指定库之间来回切换。
示例:
此 C 程序需要 linked 数学库,这不是 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
静态 linked,但 libc 动态 linked:
gcc -o link_test link_test.c -Wl,-Bstatic -lm -Wl,-Bdynamic
任何数量的附加 -l
选项、库名称和目标文件名都可以与 -lm
一起放在 -Wl,-Bstatic
和 -Wl,-Bdynamic
选项之间;所有这些对象都将被静态 linked。虽然 libc
没有明确地 linked(GCC 不需要),但在显式参数列表的末尾将 link 类型切换为 "dynamic" 对我来说确实如此, 导致 libc 被动态 linked:
$ 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 不同。)
请注意,您的 objective 即 "Running 'ldd' on the final binary should show only glibc dynamically linked" 不一定可行,如上面的 ldd
输出所示。如果您的可执行文件完全是动态 linked,那么除了任何动态库之外,它还将包含动态加载器 linked,并且可能还有特定于平台的伪库,例如 linux-vdso.so.1
.
您要求提供一个 makefile 示例,但这就像只要求 "write me a program"。这与 make
无关,并且有无数种方法可以将上述方法合并到 makefile 中。但既然你问了,这是最简单的变体之一:
生成文件
link_test: link_test.c
gcc -o $@ $< -Wl,-Bstatic -lm -Wl,-Bdynamic
我正在尝试编译一个程序,使所有库都静态地包含在最终的二进制文件中,但我仍然希望 glibc 是动态链接的。如果我使用“-static”,它会静态编译所有库,包括 glibc。基本上我需要一个 -static 参数以及类似 -exclude=glibc 的参数 使用 "make" 的示例以及使用纯 "gcc" 的示例都很棒。 运行 "ldd" 在最终的二进制文件上应该只显示动态链接的 glibc。
您可以 link 使用 -Bstatic
and -Bdynamic
静态库的子集。在 GCC 命令行上,这看起来像这样(linking 静态针对 PCRE,仅作为示例):
-Wl,-Bstatic -lpcre -Wl,-Bdynamic
请注意 -lanl
、-ldl
、-lm
、-lmvec
、-lnsl
、-lpthread
、-lresolv
、-lrt
、-lutil
都是 glibc 的一部分,因此必须在 -Wl,-Bdynamic
之后(以便动态地 linked)。对于 -lcrypt
,这取决于分布。
您所要求的可以在某些系统上大约完成,但不能使用 GCC 的 -static
选项。该选项对 linking:
On systems that support dynamic linking, this overrides -pie and prevents linking with the shared libraries. On other systems, this option has no effect.
要对 linking 进行所需级别的控制,您需要将标志传递给 linker。您可以使用 GCC 的 -Wl
选项来做到这一点。如果您正在使用 GCC,那么您可能也在使用 GNU linker,并且在支持静态和动态 linking 的构建目标上,它有多种混合它们的机制。特别是,GNU linker 的 -Bstatic
标志及其对应的 -Bdynamic
标志每个仅对命令行上以它们命名的库有效,直到下一个这样的标志。也就是说,它们允许您在为静态 linking 和动态 linking 指定库之间来回切换。
示例:
此 C 程序需要 linked 数学库,这不是 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
静态 linked,但 libc 动态 linked:
gcc -o link_test link_test.c -Wl,-Bstatic -lm -Wl,-Bdynamic
任何数量的附加 -l
选项、库名称和目标文件名都可以与 -lm
一起放在 -Wl,-Bstatic
和 -Wl,-Bdynamic
选项之间;所有这些对象都将被静态 linked。虽然 libc
没有明确地 linked(GCC 不需要),但在显式参数列表的末尾将 link 类型切换为 "dynamic" 对我来说确实如此, 导致 libc 被动态 linked:
$ 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 不同。)
请注意,您的 objective 即 "Running 'ldd' on the final binary should show only glibc dynamically linked" 不一定可行,如上面的 ldd
输出所示。如果您的可执行文件完全是动态 linked,那么除了任何动态库之外,它还将包含动态加载器 linked,并且可能还有特定于平台的伪库,例如 linux-vdso.so.1
.
您要求提供一个 makefile 示例,但这就像只要求 "write me a program"。这与 make
无关,并且有无数种方法可以将上述方法合并到 makefile 中。但既然你问了,这是最简单的变体之一:
生成文件
link_test: link_test.c
gcc -o $@ $< -Wl,-Bstatic -lm -Wl,-Bdynamic