C++ 如何使二进制文件与不同的发行版兼容

C++ 如何使二进制文件与不同的发行版兼容,c++,linux,ubuntu,dynamic-linking,software-distribution,C++,Linux,Ubuntu,Dynamic Linking,Software Distribution,我需要创建一个能与尽可能多的发行版一起工作的可执行文件。我读了很多关于这方面的信息,发现有两种方式:静态链接和动态链接。第一种解决方案避免了将可执行文件带到库中,但它在许可证方面存在一些问题。第二种解决方案似乎更合适。 通过动态链接,链接器向可执行ELF头添加它所需的库的所有引用,并且操作系统在执行二进制文件之前加载这些库 命令readelf-d显示所需的库: Dynamic section at offset 0x149d80 contains 33 entries: Tag T

我需要创建一个能与尽可能多的发行版一起工作的可执行文件。我读了很多关于这方面的信息,发现有两种方式:静态链接和动态链接。第一种解决方案避免了将可执行文件带到库中,但它在许可证方面存在一些问题。第二种解决方案似乎更合适。 通过动态链接,链接器向可执行ELF头添加它所需的库的所有引用,并且操作系统在执行二进制文件之前加载这些库

命令
readelf-d
显示所需的库:

Dynamic section at offset 0x149d80 contains 33 entries:
Tag        Type                         Name/Value
0x0000000000000001 (NEEDED)             Shared library: [libopencv_highgui.so.2.4]
0x0000000000000001 (NEEDED)             Shared library: [libopencv_imgproc.so.2.4]
0x0000000000000001 (NEEDED)             Shared library: [libopencv_core.so.2.4]
0x0000000000000001 (NEEDED)             Shared library: [libstdc++.so.6]
0x0000000000000001 (NEEDED)             Shared library: [libm.so.6]
0x0000000000000001 (NEEDED)             Shared library: [libgcc_s.so.1]
0x0000000000000001 (NEEDED)             Shared library: [libpthread.so.0]
0x0000000000000001 (NEEDED)             Shared library: [libc.so.6]
0x000000000000000f (RPATH)              Library rpath: [$ORIGIN/lib]
当命令ldd显示从我的可执行文件调用的所有库时:

linux-vdso.so.1 =>  (0x00007fffbb14c000)
libopencv_highgui.so.2.4 => /home/user/./lib/libopencv_highgui.so.2.4 (0x00007f19398d0000)
libopencv_imgproc.so.2.4 => /home/user/./lib/libopencv_imgproc.so.2.4 (0x00007f1939410000)
libopencv_core.so.2.4 => /home/user/./lib/libopencv_core.so.2.4 (0x00007f1938fb7000)
libstdc++.so.6 => /home/user/./lib/libstdc++.so.6 (0x00007f1938cb3000)
libm.so.6 => /home/user/./lib/libm.so.6 (0x00007f19389b7000)
libgcc_s.so.1 => /home/user/./lib/libgcc_s.so.1 (0x00007f19387a0000)
libpthread.so.0 => /home/user/./lib/libpthread.so.0 (0x00007f1938583000)
libc.so.6 => /home/user/./lib/libc.so.6 (0x00007f19381c3000)
libtiff.so.4 => /usr/lib/x86_64-linux-gnu/libtiff.so.4 (0x00007f1937f49000)
libgstreamer-0.10.so.0 => /usr/lib/x86_64-linux-gnu/libgstreamer-0.10.so.0 (0x00007f1937c62000)
libgobject-2.0.so.0 => /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0 (0x00007f1937a13000)
libglib-2.0.so.0 => /lib/x86_64-linux-gnu/libglib-2.0.so.0 (0x00007f193771d000)
libgstapp-0.10.so.0 => /usr/lib/x86_64-linux-gnu/libgstapp-0.10.so.0 (0x00007f1937511000)
libgstvideo-0.10.so.0 => /usr/lib/x86_64-linux-gnu/libgstvideo-0.10.so.0 (0x00007f19372f5000)
libdc1394.so.22 => /usr/lib/x86_64-linux-gnu/libdc1394.so.22 (0x00007f1937081000)
libv4l1.so.0 => /usr/lib/x86_64-linux-gnu/libv4l1.so.0 (0x00007f1936e7b000)
libavcodec.so.53 => /usr/lib/x86_64-linux-gnu/libavcodec.so.53 (0x00007f193606b000)
libavformat.so.53 => /usr/lib/x86_64-linux-gnu/libavformat.so.53 (0x00007f1935d6a000)
libavutil.so.51 => /usr/lib/x86_64-linux-gnu/libavutil.so.51 (0x00007f1935b4a000)
libswscale.so.2 => /usr/lib/x86_64-linux-gnu/libswscale.so.2 (0x00007f1935904000)
librt.so.1 => /lib/x86_64-linux-gnu/librt.so.1 (0x00007f19356fb000)
libgomp.so.1 => /usr/lib/x86_64-linux-gnu/libgomp.so.1 (0x00007f19354ec000)
/lib64/ld-linux-x86-64.so.2 (0x00007f1939bca000)
libjpeg.so.8 => /usr/lib/x86_64-linux-gnu/libjpeg.so.8 (0x00007f193529b000)
libz.so.1 => /lib/x86_64-linux-gnu/libz.so.1 (0x00007f1935084000)
libgmodule-2.0.so.0 => /usr/lib/x86_64-linux-gnu/libgmodule-2.0.so.0 (0x00007f1934e80000)
libxml2.so.2 => /usr/lib/x86_64-linux-gnu/libxml2.so.2 (0x00007f1934b23000)
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f193491f000)
libffi.so.6 => /usr/lib/x86_64-linux-gnu/libffi.so.6 (0x00007f1934717000)
libpcre.so.3 => /lib/x86_64-linux-gnu/libpcre.so.3 (0x00007f19344d9000)
libgstbase-0.10.so.0 => /usr/lib/x86_64-linux-gnu/libgstbase-0.10.so.0 (0x00007f1934286000)
liborc-0.4.so.0 => /usr/lib/x86_64-linux-gnu/liborc-0.4.so.0 (0x00007f193400b000)
libraw1394.so.11 => /usr/lib/x86_64-linux-gnu/libraw1394.so.11 (0x00007f1933dfb000)
libusb-1.0.so.0 => /lib/x86_64-linux-gnu/libusb-1.0.so.0 (0x00007f1933bec000)
libv4l2.so.0 => /usr/lib/x86_64-linux-gnu/libv4l2.so.0 (0x00007f19339e0000)
libvpx.so.1 => /usr/lib/libvpx.so.1 (0x00007f193373a000)
libvorbisenc.so.2 => /usr/lib/x86_64-linux-gnu/libvorbisenc.so.2 (0x00007f193326b000)
libvorbis.so.0 => /usr/lib/x86_64-linux-gnu/libvorbis.so.0 (0x00007f193303f000)
libtheoraenc.so.1 => /usr/lib/x86_64-linux-gnu/libtheoraenc.so.1 (0x00007f1932e01000)
libtheoradec.so.1 => /usr/lib/x86_64-linux-gnu/libtheoradec.so.1 (0x00007f1932be6000)
libspeex.so.1 => /usr/lib/x86_64-linux-gnu/libspeex.so.1 (0x00007f19329cd000)
libschroedinger-1.0.so.0 => /usr/lib/libschroedinger-1.0.so.0 (0x00007f1932719000)
libgsm.so.1 => /usr/lib/libgsm.so.1 (0x00007f193250b000)
libva.so.1 => /usr/lib/x86_64-linux-gnu/libva.so.1 (0x00007f19322f5000)
libbz2.so.1.0 => /lib/x86_64-linux-gnu/libbz2.so.1.0 (0x00007f19320e4000)
libv4lconvert.so.0 => /usr/lib/x86_64-linux-gnu/libv4lconvert.so.0 (0x00007f1931e6f000)
libogg.so.0 => /usr/lib/x86_64-linux-gnu/libogg.so.0 (0x00007f1931c67000)
现在我已经使用了链接器的选项来设置RPATH-Wl、-RPATH、\$$ORIGIN/lib(),因此在执行之前,链接器看起来是RPATH的第一条路径。如果未设置DT_运行路径(),则为真。在我的Ubuntu 12.04 64位上,如果我用ldd检查,这是正确的,所有库都指向正确的路径。 在Debian 7 64位上,如果openCV库不存在,ldd将返回

linux-vdso.so.1 =>  (0x00007fffcf157000)
linux-vdso.so.1 =>  (0x00007fffcf157000)
libopencv_highgui.so.2.4 => /home/user/./lib/libopencv_highgui.so.2.4 (0x00007fd15d4a1000)
libopencv_imgproc.so.2.4 => /home/user/./lib/libopencv_imgproc.so.2.4 (0x00007fd15cfe1000)
libopencv_core.so.2.4 => /home/user/./lib/libopencv_core.so.2.4 (0x00007fd15cb88000)
libstdc++.so.6 => /home/user/./lib/libstdc++.so.6 (0x00007fd15c884000)
libm.so.6 => /home/user/./lib/libm.so.6 (0x00007fd15c588000)
libgcc_s.so.1 => /home/user/./lib/libgcc_s.so.1 (0x00007fd15c371000)
libpthread.so.0 => /home/user/./lib/libpthread.so.0 (0x00007fd15c154000)
libc.so.6 => /home/user/./lib/libc.so.6 (0x00007fd15bd94000)
libtiff.so.4 => /home/user/./lib/libtiff.so.4 (0x00007fd15bb2f000)
libgstreamer-0.10.so.0 => /home/user/./lib/libgstreamer-0.10.so.0 (0x00007fd15b848000)
libgobject-2.0.so.0 => /home/user/./lib/libgobject-2.0.so.0 (0x00007fd15b5f9000)
libglib-2.0.so.0 => /home/user/./lib/libglib-2.0.so.0 (0x00007fd15b303000)
libgstapp-0.10.so.0 => /home/user/./lib/libgstapp-0.10.so.0 (0x00007fd15b0f7000)
libgstvideo-0.10.so.0 => /home/user/./lib/libgstvideo-0.10.so.0 (0x00007fd15aedb000)
libdc1394.so.22 => /home/user/./lib/libdc1394.so.22 (0x00007fd15ac67000)
libv4l1.so.0 => /home/user/./lib/libv4l1.so.0 (0x00007fd15aa61000)
libavcodec.so.53 => /home/user/./lib/libavcodec.so.53 (0x00007fd159c51000)
libavformat.so.53 => /home/user/./lib/libavformat.so.53 (0x00007fd159950000)
libavutil.so.51 => /home/user/./lib/libavutil.so.51 (0x00007fd159730000)
libswscale.so.2 => /home/user/./lib/libswscale.so.2 (0x00007fd1594ea000)
librt.so.1 => /home/user/./lib/librt.so.1 (0x00007fd1592e1000)
libgomp.so.1 => /home/user/./lib/libgomp.so.1 (0x00007fd1590d2000)
/lib64/ld-linux-x86-64.so.2 (0x00007fd15d79b000)
libjpeg.so.8 => /home/user/./lib/libjpeg.so.8 (0x00007fd158e81000)
libz.so.1 => /home/user/./lib/libz.so.1 (0x00007fd158c6a000)
libgmodule-2.0.so.0 => /home/user/./lib/libgmodule-2.0.so.0 (0x00007fd158a66000)
libxml2.so.2 => /home/user/./lib/libxml2.so.2 (0x00007fd158709000)
libdl.so.2 => /home/user/./lib/libdl.so.2 (0x00007fd158505000)
libffi.so.6 => /home/user/./lib/libffi.so.6 (0x00007fd1582fd000)
libpcre.so.3 => /home/user/./lib/libpcre.so.3 (0x00007fd1580bf000)
libgstbase-0.10.so.0 => /home/user/./lib/libgstbase-0.10.so.0 (0x00007fd157e6c000)
liborc-0.4.so.0 => /home/user/./lib/liborc-0.4.so.0 (0x00007fd157bf1000)
libraw1394.so.11 => /home/user/./lib/libraw1394.so.11 (0x00007fd1579e1000)
libusb-1.0.so.0 => /home/user/./lib/libusb-1.0.so.0 (0x00007fd1577d2000)
libv4l2.so.0 => /home/user/./lib/libv4l2.so.0 (0x00007fd1575c6000)
libvpx.so.1 => /home/user/./lib/libvpx.so.1 (0x00007fd157320000)
libvorbisenc.so.2 => /home/user/./lib/libvorbisenc.so.2 (0x00007fd156e51000)
libvorbis.so.0 => /home/user/./lib/libvorbis.so.0 (0x00007fd156c25000)
libtheoraenc.so.1 => /home/user/./lib/libtheoraenc.so.1 (0x00007fd1569e7000)
libtheoradec.so.1 => /home/user/./lib/libtheoradec.so.1 (0x00007fd1567cc000)
libspeex.so.1 => /home/user/./lib/libspeex.so.1 (0x00007fd1565b3000)
libschroedinger-1.0.so.0 => /home/user/./lib/libschroedinger-1.0.so.0 (0x00007fd1562ff000)
libgsm.so.1 => /home/user/./lib/libgsm.so.1 (0x00007fd1560f1000)
libva.so.1 => /home/user/./lib/libva.so.1 (0x00007fd155edb000)
libbz2.so.1.0 => /home/user/./lib/libbz2.so.1.0 (0x00007fd155cca000)
libv4lconvert.so.0 => /home/user/./lib/libv4lconvert.so.0 (0x00007fd155a55000)
libogg.so.0 => /home/user/./lib/libogg.so.0 (0x00007fd15584d000)
在我安装openCV的openSuse 12.3 64位上,路径$ORIGIN/lib(libogg)外部有一些库,这似乎是正确的

$ORIGIN/lib中的每个库都可以与其他库链接,并且它们可以与文件夹中的库不同。例如,如果我在Debian 7中键入ldd,我会得到

./libavformat.so.53: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.14' not found (required by ./libavformat.so.53)
linux-vdso.so.1 =>  (0x00007fff31499000)
libavcodec.so.53 => /usr/lib/x86_64-linux-gnu/libavcodec.so.53 (0x00007f5dfe09b000)
libavutil.so.51 => /usr/lib/x86_64-linux-gnu/libavutil.so.51 (0x00007f5dfde7a000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f5dfdbf7000)
libbz2.so.1.0 => /lib/x86_64-linux-gnu/libbz2.so.1.0 (0x00007f5dfd9e7000)
libz.so.1 => /lib/x86_64-linux-gnu/libz.so.1 (0x00007f5dfd7d0000)
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f5dfd5b3000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f5dfd229000)
libxvidcore.so.4 => /usr/lib/x86_64-linux-gnu/libxvidcore.so.4 (0x00007f5dfcef2000)
libx264.so.123 => /usr/lib/x86_64-linux-gnu/libx264.so.123 (0x00007f5dfcb69000)
libvpx.so.1 => /usr/lib/x86_64-linux-gnu/libvpx.so.1 (0x00007f5dfc8ca000)
libvorbisenc.so.2 => /usr/lib/x86_64-linux-gnu/libvorbisenc.so.2 (0x00007f5dfc3fb000)
libvorbis.so.0 => /usr/lib/x86_64-linux-gnu/libvorbis.so.0 (0x00007f5dfc1cd000)
libtheoraenc.so.1 => /usr/lib/x86_64-linux-gnu/libtheoraenc.so.1 (0x00007f5dfbf8c000)
libtheoradec.so.1 => /usr/lib/x86_64-linux-gnu/libtheoradec.so.1 (0x00007f5dfbd70000)
libspeex.so.1 => /usr/lib/x86_64-linux-gnu/libspeex.so.1 (0x00007f5dfbb57000)
libschroedinger-1.0.so.0 => /usr/lib/x86_64-linux-gnu/libschroedinger-1.0.so.0 (0x00007f5dfb88a000)
libopenjpeg.so.2 => /usr/lib/x86_64-linux-gnu/libopenjpeg.so.2 (0x00007f5dfb668000)
libmp3lame.so.0 => /usr/lib/x86_64-linux-gnu/libmp3lame.so.0 (0x00007f5dfb3dd000)
libgsm.so.1 => /usr/lib/x86_64-linux-gnu/libgsm.so.1 (0x00007f5dfb1d0000)
libdirac_encoder.so.0 => /usr/lib/x86_64-linux-gnu/libdirac_encoder.so.0 (0x00007f5dfaf40000)
libva.so.1 => /usr/lib/x86_64-linux-gnu/libva.so.1 (0x00007f5dfad28000)
/lib64/ld-linux-x86-64.so.2 (0x00007f5dff22e000)
libogg.so.0 => /usr/lib/x86_64-linux-gnu/libogg.so.0 (0x00007f5dfab22000)
liborc-0.4.so.0 => /usr/lib/x86_64-linux-gnu/liborc-0.4.so.0 (0x00007f5dfa8a4000)
libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f5dfa59d000)
libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f5dfa387000)
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f5dfa182000)
因此,是否有可能只从$ORIGIN/lib中的库获取依赖的可执行文件?我使用Ubuntu 12.04 64位编译,但如果我尝试在Debian 7 64位上执行,我会得到链接器ld-linux-x86-64的分段错误。因此,在openSuse 12.3 64位中,我会得到

./binary: relocation error: /home/user/lib/libopencv_highgui.so.2.4: symbol avformat_network_init, version LIBAVFORMAT_53 not defined in file libavformat.so.53 with link time reference
ldd LIBAV格式

ldd libavformat.so.53
linux-vdso.so.1 =>  (0x00007fff8c3c5000)
libavcodec.so.53 => /usr/local/lib/libavcodec.so.53 (0x00007f3634b37000)
libavutil.so.51 => /usr/local/lib/libavutil.so.51 (0x00007f3634916000)
libm.so.6 => /lib64/libm.so.6 (0x00007f36346bf000)
libbz2.so.1.0 => not found
libz.so.1 => /lib64/libz.so.1 (0x00007f36344a7000)
libpthread.so.0 => /lib64/libpthread.so.0 (0x00007f3634289000)
libc.so.6 => /lib64/libc.so.6 (0x00007f3633ef9000)
libvo-amrwbenc.so.0 => /usr/local/lib/libvo-amrwbenc.so.0 (0x00007f3633cdf000)
libvo-aacenc.so.0 => /usr/local/lib/libvo-aacenc.so.0 (0x00007f3633ac0000)
libtheoraenc.so.1 => /usr/local/lib/libtheoraenc.so.1 (0x00007f3633885000)
libtheoradec.so.1 => /usr/local/lib/libtheoradec.so.1 (0x00007f363366c000)
libspeex.so.1 => /usr/local/lib/libspeex.so.1 (0x00007f3633451000)
libopencore-amrwb.so.0 => /usr/local/lib/libopencore-amrwb.so.0 (0x00007f363323d000)
libopencore-amrnb.so.0 => /usr/local/lib/libopencore-amrnb.so.0 (0x00007f3633013000)
libmp3lame.so.0 => /usr/local/lib/libmp3lame.so.0 (0x00007f3632d8a000)
libfaac.so.0 => /usr/local/lib/libfaac.so.0 (0x00007f3632b77000)
/lib64/ld-linux-x86-64.so.2 (0x00007f3635f35000)
libogg.so.0 => /usr/local/lib/libogg.so.0 (0x00007f363296f000)
二进制文件位于/home/user/中。
有没有其他无源代码分发二进制文件的解决方案?

Yikes!这是一个惊人数量的依赖关系!您将很难使所有这些依赖关系在各种各样的发行版中工作,尤其是因为您可能非常严格地依赖于其中一些发行版的特定版本(即,如果您希望动态链接到OpenCV,那么至少您可能只支持提供相同主版本的发行版)

正如您所指出的,您永远不应该创建完全静态的二进制文件(这只在非常特定的情况下有用,因为静态编译的二进制文件是最不可移植的)。规则:永远不要在libc中静态链接(如果这样做,则禁止调用
dlopen
)。您可以静态链接libstdc++,这样做可以在更大范围的发行版上提供兼容性,而代价是略微增加二进制大小。libm、libpthread与libc基本相同,像libz这样的古老库是安全的,因为它们有一个非常稳定的ABI

对于其余部分,您将需要稍微分离依赖关系树,并尝试静态链接最糟糕的运行时依赖关系,记住您也必须链接它们的依赖关系!因此,如果您发现必须在libavcodec中进行静态链接,那么很可能也需要发布libspeex(除非它有一个非常稳定的ABI,我不知道该库的具体情况)


关于Debian7libc问题:这可能是最容易解决的问题。您只需在希望支持的最旧发行版上编译即可。如果您在较新的Ubuntu或Suse版本上编译,您将依赖于比Debian 7更新版本的glibc。在较旧的计算机上进行编译可以(它将在较新的发行版上运行正常)。

您可以在您的计算机上进行编译,但在目标计算机上进行链接吗?你可以带上你需要的图书馆,检查一下有什么,如果需要的话可以用你的。嗨,谢谢你的提示。目前,我通过在我的机器中编译一个静态库并在每个目标机器上链接来解决这个问题。
ldd libavformat.so.53
linux-vdso.so.1 =>  (0x00007fff8c3c5000)
libavcodec.so.53 => /usr/local/lib/libavcodec.so.53 (0x00007f3634b37000)
libavutil.so.51 => /usr/local/lib/libavutil.so.51 (0x00007f3634916000)
libm.so.6 => /lib64/libm.so.6 (0x00007f36346bf000)
libbz2.so.1.0 => not found
libz.so.1 => /lib64/libz.so.1 (0x00007f36344a7000)
libpthread.so.0 => /lib64/libpthread.so.0 (0x00007f3634289000)
libc.so.6 => /lib64/libc.so.6 (0x00007f3633ef9000)
libvo-amrwbenc.so.0 => /usr/local/lib/libvo-amrwbenc.so.0 (0x00007f3633cdf000)
libvo-aacenc.so.0 => /usr/local/lib/libvo-aacenc.so.0 (0x00007f3633ac0000)
libtheoraenc.so.1 => /usr/local/lib/libtheoraenc.so.1 (0x00007f3633885000)
libtheoradec.so.1 => /usr/local/lib/libtheoradec.so.1 (0x00007f363366c000)
libspeex.so.1 => /usr/local/lib/libspeex.so.1 (0x00007f3633451000)
libopencore-amrwb.so.0 => /usr/local/lib/libopencore-amrwb.so.0 (0x00007f363323d000)
libopencore-amrnb.so.0 => /usr/local/lib/libopencore-amrnb.so.0 (0x00007f3633013000)
libmp3lame.so.0 => /usr/local/lib/libmp3lame.so.0 (0x00007f3632d8a000)
libfaac.so.0 => /usr/local/lib/libfaac.so.0 (0x00007f3632b77000)
/lib64/ld-linux-x86-64.so.2 (0x00007f3635f35000)
libogg.so.0 => /usr/local/lib/libogg.so.0 (0x00007f363296f000)