我正在尝试编译一个开源项目的二进制文件,这样我们的用户就不必自己编译它了。
我注意到一些在32位ubuntu机器"A“上创建的二进制文件不能在32位机器"B”上运行,并报告了有关丢失.so文件的错误。
但是,如果我在机器"B“上从头开始编译,那么所有的错误都会消失。
为什么在目标机器上编译代码会消除这些错误,这有什么原因吗?我只运行了"./configure“和"make”,而不是"make-install",所以我并没有让这些.so文件在全球范围内可用。
会不会是编译器检测到系统库中缺少.so文件,并在这种情况下将静态库链接到可执行文件?
Ubuntu如何编译它的包,使一个i386包可以在所有x86机器上运行?
发布于 2011-02-11 06:04:20
我猜这个问题被称为“二进制兼容性”(堆栈溢出上有专门针对这些问题的a tag )。当您在一台机器上链接二进制文件时,周围的环境会影响该二进制文件,并且在另一台机器上运行后,它仍然会尝试查找与其编译时所在的环境相似的环境。
在这种情况下,对不同环境的容忍度称为二进制兼容性。
它是如何工作的?
这里的关键点是,即使您在不同的机器上为链接器指定了相同的选项,您仍然可以得到不同的二进制文件。例如,如果您使用-lfoo将二进制文件链接到一个共享库,那么您在其上构建的机器上安装的确切版本的foo (例如,libfoo.so.5)将被硬编码到二进制文件中。当它在机器B上运行时,它可能只包含libfoo.so.4,并且二进制文件将拒绝运行,因为它需要丢失的libfoo.so.5 so文件。这就是为什么重新编译很有帮助,没有它它就不能工作。
Ubuntu包--以及其他发行版的包--都是在相同的环境中(彼此的)编译的。这就是他们安装得很好的原因。发行版供应商注意到,每个下一个版本都向后兼容以前的版本。
我应该怎么做?
如果你想让你的软件与不同的发行版兼容,这比你想象的要容易。首先,尝试在尽可能旧的发行版上编译您的应用程序。正如我之前提到的,由于现代发行版通常是向后兼容的,您的软件很可能会在较新的发行版上运行,没有问题。
要更彻底地检查生成的包并获得有关兼容性的更多建议,您可以使用我们的免费Linux Application Checker工具。您可能还会对generic tips for packaging Linux soft感兴趣。
发布于 2011-02-11 05:42:49
如果你在一台机器上编译代码,如果你在这台机器上执行程序,你很可能不会得到任何关于缺少库的错误。在配置运行期间,会检测到所有需要的库(这是configure、autotools等存在的主要原因),并将适当的标志(如-lsomelib和-I/some/include/patch )写入makefile并传递给编译器和链接器。
如果您将该可执行文件复制到另一台计算机,则该计算机可能具有错误版本的库,或者根本没有该库,因此它可能无法运行。
配置脚本通常不会构建静态二进制文件,除非您显式地告诉它这样做。
Ubuntu包并不能在所有的x86机器上运行。但是包管理器会执行依赖关系解析,以确保没有丢失错误的库或库,否则将拒绝安装包。如果您不考虑缺少的依赖项而强制安装,那么您可能会再次遇到与缺少库相同的问题。
如果你想确保你的包能够在任何机器上运行,只需静态链接它即可。
如果在特定发行版(例如Ubuntu)上运行它就足够了,那么您可以自己创建一个包。这需要更多的努力。
发布于 2011-02-11 05:14:57
您可以使用像Ermine这样的项目来创建包含共享库的动态链接的本机二进制文件的发行版。
除此之外,你可以静态编译你的代码。这将要求您获取整个依赖关系树的源代码,编译它们,并在构建代码时引用这些已编译的二进制文件。不能针对其他共享库(.so文件)编译静态二进制文件。这可能是一个真正的痛苦,特别是当您的依赖项有自己的依赖项时。
https://stackoverflow.com/questions/4962662
复制相似问题