如何使用g++静态链接除少数库外的所有库
How to statically link all libraries except a few using g++?
我有一个要求,即静态链接我的所有库,包括libstdc++、libc、pthread等。有一个omniorb库我想动态链接。
目前我已经动态链接了所有的库。ldd显示以下
linux-vdso.so.1 => (0x00007fff251ff000)
libpthread.so.0 => /lib64/libpthread.so.0 (0x00007f291cc47000)
libomniDynamic4.so.1 (0x00007f291c842000)
libstdc++.so.6 => /usr/lib64/libstdc++.so.6 (0x00007f291c536000)
libm.so.6 => /lib64/libm.so.6 (0x00007f291c2e0000)
libgomp.so.1 => /usr/lib64/libgomp.so.1 (0x00007f291c0d7000)
libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x00007f291bebf000)
libc.so.6 => /lib64/libc.so.6 (0x00007f291bb66000)
/lib64/ld-linux-x86-64.so.2 (0x00007f291ce63000)
librt.so.1 => /lib64/librt.so.1 (0x00007f291b95d000)
libomniORB4.so.1 (0x00007f291b6aa000)
libomnithread.so.3 (0x00007f291cf35000
我需要ldd来显示libomniDynamic4.so.1作为唯一的动态链接库。
我该如何做到这一点?
试图制作一个在所有发行版上运行的linux可执行文件,嗯?祝你好运但我离题了。。。
您需要查看g++的-v
标志输出。它显示了g++/ld执行的内部链接命令。具体来说,您将需要检查最终链接命令collect2
及其所有参数。然后,您可以指定要链接到的.a库的确切路径。您还必须跟踪所有内容的静态库。我的libstdc++.a在/usr/lib/gcc/x86_64-linux-gnu/4.4/libstdc++.a
中
咆哮:我对linux最大的抱怨是可执行文件的断裂状态。为什么我不能在一台机器上编译二进制文件,然后将其复制到另一台机器并运行它!?即使是相隔一个版本的Ubuntu发行版,由于libc/libstdc++ABI不兼容,也会产生无法在另一个版本上运行的二进制文件
edit#1我只是想补充一下,这个页面上的脚本生成了一个可执行文件.so依赖项的.png。这在尝试执行您所描述的操作时非常有用。
请注意,ldd <exename>
将列出链下的所有依赖项,而不仅仅是可执行文件的直接依赖项。因此,即使您的可执行文件只依赖omniorb.So,但omniorb.So依赖libphrad.So,ldd
的输出也会列出这一点。查找readelf
的手册页,只查找二进制文件的直接依赖项。
另一个需要注意的事项。如果omniorb.so依赖于libstdc++,那么您将别无选择,只能依赖于同一个lib。否则,ABI不兼容将破坏您的代码和omniorb的代码之间的RTTI。
我需要ldd来显示libomniDynamic4.so.1作为唯一的动态链接库。
这是不可能的。
首先,对于任何需要动态链接的(x86_64
)二进制文件,ldd
将始终显示ld-linux-x86-64.so.2
。如果使用动态链接(与libomniDynamic4.so.1
一样),则将获得ld-linux-x86-64.so.2
。
其次,linux-vdso.so.1
由内核"注入"到进程中。你也无法摆脱它。
接下来,问题是为什么要尽量减少动态库的使用。最常见的原因通常是错误地认为"大部分是静态的"二进制文件更具可移植性,并且将在更多的系统上运行。在Linux上,情况正好相反。
如果实际上您正在尝试实现一个可移植的二进制文件,那么有几种方法。迄今为止(根据我的经验)最好的一个是使用apgcc。
构建一个在许多Linux发行版上运行的二进制文件非常困难,静态链接不是关键。
请注意,使用旧的glibc版本(即旧的Linux发行版)构建的二进制文件也可能在新的Linux发行版本上运行。这是因为glibc是向后兼容的。
获得所需结果的一种可能方法是:
-
在旧的Linux操作系统上编译二进制文件
-
使用命令ldd或lsof查找已编译二进制文件所需的所有库(运行时)在二进制文件上,此处为详细信息
-
将旧Linux操作系统所需的库复制到"自定义lib"文件夹中
-
始终将这个自定义lib文件夹与您的二进制捆绑/发布
-
创建一个bash脚本,将自定义lib文件夹放在
LD_LIBRARY_PATH
环境变量中文件夹列表的顶部,然后调用您的二进制文件。
通过这种方式,通过使用bash脚本执行二进制文件,我能够在各种不同Linux版本的嵌入式设备上执行二进制文件。但总有问题的情况下,这是失败的。
请注意,我一直使用cli applications/binary进行测试。
其他可能的方式
似乎还有一些优雅的方法可以编译glibc向后兼容的二进制文件,例如,这似乎可以编译与旧ABI兼容的二进制代码。但我没有检查过这条路线。
链接时,在指定要静态链接到的库之前使用-static,在要动态链接到的库前使用-dynamic
g++ <other options here> -dynamic -lomniDynamic4 -static -lpthread -lm -lgomp <etc>
当然,您需要静态链接的库的.a版本(duh)。
- 如何创建一个CMake变量,除非显式重写,否则使用默认值
- C++:TypeDef使用元组
- 使用std::multimap迭代器创建std::list
- 从不同线程使用int64的不同字节安全吗
- 比较并显示使用最小值(a,b)和最大值(a、b)升序排列的4个数字
- 为什么在全局范围内使用"extern int a"似乎不行?
- 在C#中处理C++指针而不使用unsafe的最佳方法
- 使用C++库在Android项目中修改gradle中的cmake参数,用于插入指令的测试
- 如何使用Google Mock来模拟gettimeofday()
- 如何使用默认参数等选择模板专业化
- 为什么使用 "this" 指针调用派生成员函数?
- 使用新行和不使用新行读取文件
- 如何使用 < 和 > 命令获取 c++ 中的输入和输出?
- 如何确定我已使用非编码文件到达 EOF?
- 如何在cuSparse中使用cusparseXcoo2csr从coo转换为csc
- 使用CMake创建QML插件
- 使用 LLVM 的 libc++ 时,__1 符号从何而来?
- 在std::cout之后使用std::cin时,换行符从何而来
- 为什么以及在何处在C++中使用引用和指针
- 基例如何影响使用递归函数的哪些行