如何使用 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 显示为唯一的动态链接库。
我该如何实现这一目标?
I have a requirement that I link all my libraries statically including libstdc++, libc, pthread etc. There is one omniorb library which I want to link dynamically.
Currently I have dynamically linked all the libraries.
ldd shows the following
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
I need ldd to show libomniDynamic4.so.1 as the only dynamically linked library.
How do I achieve this?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
尝试制作一个在所有发行版上运行的 Linux 可执行文件,是吗?祝你好运...但我离题了...
您想查看 g++ 的
-v
标志输出。它显示了 g++/ld 执行的内部链接命令。具体来说,您需要检查最终的链接命令collect2
及其所有参数。然后,您可以指定要链接的 .a 库的确切路径。您还必须跟踪所有内容的静态库。我的 libstdc++.a 位于 /usr/lib/gcc/x86_64-linux-gnu/4.4/libstdc++.a咆哮:我对 Linux 最大的抱怨是可执行文件的破碎状态。为什么我不能在一台机器上编译二进制文件并将其复制到另一台机器上并运行它!?由于 libc/libstdc++ ABI 不兼容,即使是一个版本分开的 Ubuntu 发行版也会生成无法在另一个版本上运行的二进制文件
编辑 #1 我只是想添加 此页面上的脚本生成可执行文件 .so 依赖项的 .png。 这是 <当尝试执行您所描述的操作时非常有用。
请注意 ldd将列出链上的所有依赖项,而不仅仅是可执行文件的直接依赖项。因此,即使您的可执行文件仅依赖于omniorb.so,但omniorb.so依赖于libphread.so,
ldd
的输出也会列出该内容。查找 readelf 的联机帮助页以仅查找二进制文件的直接依赖项。另一件需要注意的事情。如果omniorb.so 依赖于libstdc++.so,那么您别无选择,只能依赖同一个库。否则,ABI 不兼容将破坏您的代码和omniorb 代码之间的RTTI。
Trying to make a linux executable that runs on all distros eh? Good luck...But I digress...
You want to look at the
-v
flag output for g++. It shows the internal link commands executed by g++/ld. Specifically, you'll want to inspect the the final link commandcollect2
and all of its arguments. You can then specify the exact paths to the .a libs you want to link against. You'll also have to track down static libs of everything. My libstdc++.a is in/usr/lib/gcc/x86_64-linux-gnu/4.4/libstdc++.a
rant on: My biggest complaint about linux is the fractured state of executables. Why cant I compile a binary on one machine and copy it to another and run it!? Even the Ubuntu distros one release apart will produce binary files that cannot be run on the other due to libc/libstdc++ ABI incompatibilites
edit #1 I just wanted to add that The script on this page produces a .png of an executables .so dependencies. This is very useful when attempting to do what you describe.
Be aware
ldd <exename>
will list all dependencies down the chain, not just immediate dependencies of the executable. So even if your executable only depended upon omniorb.so, but omniorb.so depended upon, libphread.so,ldd
's output would list that. Look up the manpage ofreadelf
to find only the immediate dependencies of a binary.One other item that to be aware of. if omniorb.so depends upon libstdc++.so, you'll have no choice but to be dependant on that same lib. Otherwise ABI incompatibilities will break RTTI between your code and omniorb's code.
这是不可能。
首先,
ldd
将始终显示任何 (x86_64
) 的ld-linux-x86-64.so.2
需要动态链接的二进制文件。如果您使用动态链接(使用libomniDynamic4.so.1
),那么您将得到ld-linux-x86-64.so.2< /代码>。
其次,
linux-vdso.so.1
由内核“注入”到您的进程中。你也无法摆脱它。接下来的问题是为什么您想要尽量减少动态库的使用。最常见的原因通常是错误地认为“大部分静态”二进制文件更可移植,并且可以在更多系统上运行。在 Linux 上,这与事实相反。
如果实际上您正在尝试实现可移植的二进制文件,则存在多种方法。到目前为止(根据我的经验)最好的方法是使用 apgcc。
That is impossible.
First,
ldd
will always showld-linux-x86-64.so.2
for any (x86_64
) binary that requires dynamic linking. If you use dynamic linking (which you would withlibomniDynamic4.so.1
), then you will getld-linux-x86-64.so.2
.Second,
linux-vdso.so.1
is "injected" into your process by the kernel. You can't get rid of that either.Next, the question is why you want to minimize use of dynamic libraries. The most common reason is usually mistaken belief that "mostly static" binaries are more portable, and will run on more systems. On Linux this is the opposite of true.
If in fact you are trying to achieve a portable binary, several methods exist. The best one so far (in my experience) has been to use apgcc.
构建在许多 Linux 发行版上运行的单个二进制文件非常困难,并且静态链接不是关键点。
请注意,使用较旧的 glibc 版本(即旧的 Linux 发行版)构建的二进制文件也可以在较新的 Linux 发行版上运行。这是可行的,因为 glibc 是向后兼容的。
获得所需结果的一种可能方法是:
在旧的 Linux 操作系统上编译二进制文件
使用命令 ldd 找出编译的二进制文件所需的所有库或 lsof
(运行时)二进制文件,详细信息此处
将旧版 Linux 操作系统所需的库复制到“custom-lib”文件夹中
将
始终将这个 custom-lib 文件夹与您的二进制文件捆绑/释放
创建一个 bash 脚本,将 custom-lib 文件夹放在
LD_LIBRARY_PATH
环境变量中的文件夹列表顶部,然后调用您的二进制文件。 /p>通过这种方式,通过使用 bash 脚本执行二进制文件,我能够在具有不同 Linux 版本的各种嵌入式设备上执行二进制文件。
但总会有一些失败的问题案例。
请注意,我总是使用 cli 应用程序/二进制文件对此进行测试。
其他可能的方法..
似乎还有编译 glibc-back 兼容的二进制文件的优雅方法,例如 这个似乎编译与旧版 ABI 兼容的二进制文件。但我没有检查过这条路线。
It is very difficult to build a single binary that runs on a lot of Linux distros and linking statically is not the key point.
Please note that a binary built with an older glibc version--i.e., an old Linux distro--may run on newer Linux distros as well. This works because glibc is back-compatible.
A possible way to attain the desired result is:
compile the binary on an old Linux OS
find out all the required libraries for your compiled binary using the command ldd or lsof
(when running) on the binary, details here
copy the required libraries of the old Linux OS in a 'custom-lib' folder
always bundle/release this custom-lib folder with your binary
create a bash script that puts the custom-lib folder on top of the folders list in
LD_LIBRARY_PATH
environment variable, and then invokes your binary.In this way, by executing the binary with the bash script, I was able to execute binaries on a wide range of embedded devices with very different Linux versions.
But there are always problematic cases where this fails.
Please note, I always tested this with cli applications/binaries.
Other possible ways..
There also seems to be elegant ways to compile glibc-back-compatible binaries, for example this that seems to compile binaries compatible with older ABI. But I have not checked this route.
链接时,在指定要静态链接的库之前使用 -static,在要动态链接的库之前使用 -dynamic。您最终应该得到如下所示的命令行:
当然,您需要要静态链接的库的 .a 版本(废话)。
when linking, use -static before specifying the libraries you want to link statically to, and use -dynamic before the libraries you want to link dynamically to. You should end up with a command line looking like this:
Of course, you'll need .a versions of the libraries you want to link statically (duh).