是否有可能编译在所有Linux发行版中执行的C/c++源代码而不重新编译?
如果答案是肯定的,我可以使用任何外部(非标准C/c++)库吗?
我想分发我的二进制应用程序,而不是分发源代码。
不,您不能编译在所有Linux发行版中执行的可执行文件。然而,你可以编译一个可执行文件,它可以在大多数人们会关心的发行版上工作。
-
编译32位。编译您愿意支持的最低CPU级别
-
构建自己的glibc版本。使用
--enable-kernel
选项设置您愿意支持的最小内核版本 -
编译您计划自己使用的所有其他库。
使用你的glibc编译头和你选择的CPU/编译器标志。 静态链接。
对于无法静态链接到的任何内容(例如,如果需要访问系统的默认名称解析或需要PAM),则必须设计自己的helper进程和API。将源代码释放给辅助进程,让它们(或您的安装程序)编译。
在你需要支持的所有平台上进行彻底的测试。
你可能需要调整一些库,如果它们调用的函数不能使用这种机制。包括dlopen
、gethostbyname
、iconv_open
等。(这些功能基本上依赖于动态链接。参见上面的第5步。当你链接这些时,你会得到一个警告。)
另外,如果不小心,时区可能会中断,因为您的代码可能不理解系统的区域格式或区域文件位置。(你不会得到这些警告。它就是不工作。)
大多数这样做的人都是在最低支持的CPU是Pentium 4和最低支持的内核版本是2.6.0的情况下构建的。
不同的安装有两个不同之处。建筑与图书馆。
-
为不同的体系结构使用一个二进制文件是不可能的;曾经有人尝试在一个文件(fatelf)中包含多个arch的二进制文件,但它没有被广泛使用,也不太可能获得动力。所以至少你必须为ia32、amd64、arm等分发单独的二进制文件。(大多数(如果不是全部)amd64发行版的内核编译支持运行ia32代码)
-
发行版包含不同版本的库。只要API没有改变,你就可以链接到那个库。一些库确保在主要编号内的二进制向后兼容性(因此GTK2.2应用程序将与GTK2.30库运行良好,但不一定反之亦然)。如果你想要确保,你必须静态地链接你使用的所有库,除了最基本的库(可能只有
libc6
,它在发行版之间是二进制兼容的)。这可能会增加二进制文件的大小,这也是为什么例如Acrobat Reader的下载量相对较大的原因之一,尽管应用程序本身的功能并不特别丰富。 -
c++ ABI有一个过渡时期,它在gcc 2.9和3 (IIRC)之间发生了变化,但是旧的ABI实际上只适用于旧的安装。这应该不再是一个问题,如果你静态链接,它是无关的。
一般不
有几个障碍。
不同的体系结构
32位二进制文件可以在x86_64系统上运行,反之则不能。另外还有很多ARM系统。
内核ABI内核ABI变化非常缓慢,但它确实在变化,因此您不能真正支持所有可能的版本。请注意,在某些地方内核2.2仍在使用。
你能做的就是创建一个静态链接的二进制文件。这样的二进制文件将包含应用程序所依赖的所有库,并且它将在具有相同架构和合理相似内核版本的所有系统上工作。