使用静态glibc编译共享库(.so)

7
我正在编写一些需要成为共享对象(.so)的代码。
我的构建机器上的libc可能比发布的机器新,因此我想静态链接它以避免兼容性问题。(我的程序使用memcpy,这显然是GLIBC_2.14的事情,而它可以低至2.5)。
同时使用-shared和-static编译无法工作,因为crtbeginT.o没有使用-fPIC进行编译。
编辑:这可能不是GCC linking libc static and some other library dynamically, revisited?的重复,因为那个问题谈论的是主elf静态链接libc,而这个问题是关于共享对象静态链接libc的。

请问您能否发布一下您的gcc选项? - KimKulling
1
你所描述的做法是没有意义的,因为这样会导致使用你的库的任何应用程序同时使用两个不同版本的glibc -- 一个通过你的库,另一个是它自己直接依赖的glibc。这正是你希望避免的问题(我猜测),所以按照你的建议做并没有任何好处。 - John Bollinger
7
根据经验,如果您设置了一个包含所需旧发行版/版本及匹配您的“发布”机器所用较旧glibc的VirtualBox虚拟机,并在该虚拟机上构建您的发布版本(您仍可在新的开发发行版上进行开发/测试),相比于试图解决glibc兼容性问题,您将节省大量时间。如果您正在创建包含较新glibc部分的共享库,该库将加载到与较旧glibc链接的进程中,则更是如此。请不要这样做。 - nos
1
你甚至不需要一个虚拟机,可以在chroot环境下完成(我从来没有自己设置过,只使用过预配置的,所以不确定需要多少工作)。此外也可以使用Docker进行设置。 - MK.
你需要做的是构建并链接到你愿意支持的最旧版本的Glibc。相信我,memcpy函数不是在2.14版本引入的;它自从最初的版本就存在于库中。 - davmac
显示剩余8条评论
1个回答

8
您想在共享库中静态链接glibc。
您不应该这样做。
如果您尝试这样做,您将面临C++ One Definition Rule (ODR)违规的问题。这是因为glibc的某些部分将来自于目标机器的“旧”版本,而另一些部分将来自于您的库的“新”版本。结果是未定义的行为。
正确的解决方案很简单:使用旧版glibc(与您部署的最旧目标一样旧)。或者多次构建,每次构建一个您需要的glibc版本(如果您确实需要新的glibc功能)。即使您认为需要新的glibc功能,也请考虑将该功能复制粘贴到具有不同名称的库中,以避免冲突。
关于memcpy,参见:https://dev59.com/vmoy5IYBdhLWcg3wBJgx#8823419 - 以及手动修复:https://dev59.com/VW865IYBdhLWcg3wA5yc#5977518

那么,追求不可能的事情是没有意义的。我会设置一个虚拟机,谢谢。 - Eric. J. Lara
2
静态链接glibc还存在风险,可能会运行与底层运行时内核系统调用接口不匹配的glibc版本。 - Andrew Henle

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