如何静态链接到 libstdc++. 喜欢升级的GCC的朋友快来看看。
2013-12-05 15:24
309 查看
Linking libstdc++ statically
Christopher Baus writes about his problemslinking libstdc++ statically. Yes, making C++ binaries that will work properly in different Linux distributions is somewhat painful. The problem is not so much linking libstdc++ statically – it is just a library, after all – but the runtime support required
by C++ code in general, to enable features like RTTI and exception handling.
The runtime support code used by different parts of a C++ application needs to be compatible. If one part of the program needs to
dynamic_castor
catchobjects
provided by another, both parts must agree on certain implementation details: how to find vtables, how to unwind the stack, and so on.
For C++ and a few other GCC-supported languages with similar features, such details are specified by a C++ ABI.
Whenever the ABI used by GCC changes you'll end up with incompatible libraries produced by the different GCC versions. The same is true for plain C, but the C ABI is much simpler and has been around a lot longer so it's fairly stable.
As far as I know C++ ABI changes have been introduced with every major release of GCC (i.e. those with different first or second version number components). To make matters worse, most major Linux distributions use GCC snapshots and/or patch
their GCC versions, making it virtually impossible to know exactly what GCC versions you might be dealing with when you distribute binaries.
Note that this problem cannot, in general, be solved by linking statically. First of all, code compiled against different ABIs is simply not binary compatible. It doesn't matter if you manage to link binary incompatible code together, because it will never
work properly. Secondly, the language runtime support typically rely on some data being shared, e.g. to access some kind of lock or global data structure (similar to how C programs need a shared
errno).
Shared data implies that whenever more than one part of a program needs the runtime support, and any of those parts is dynamically loaded, the runtime support needs to be loaded dynamically too. Otherwise, the different program parts would end up with copies
of the data rather than one shared instance. That's the reason for putting the language runtime support code in a dynamic library by default.
There are many different workarounds and no perfect solution, but a fairly workable compromise is to link all C++ code into an executable while using dynamically loaded C libraries only. This way there is only one part of the program that needs the C++ runtime
support mechanisms, which can therefore be linked in statically. You can mix and match statically and dynamically linked C libraries, but no C++ code (or any code using the C++ runtime support) may be linked dynamically if this is to work.
Now, the practical problem people run into when trying to link libstdc++ statically is thatg++, the GCC front-end for compiling and linking
C++, adds the proper libraries and start-up code for C++ automatically and will link some of this code dynamically by default:
g++ -o example example.cpp ldd example linux-gate.so.1 => (0xffffe000) libstdc++.so.6 => /usr/lib/gcc/i686-pc-linux-gnu/3.4.3/libstdc++.so.6 (0xb7f17000) libm.so.6 => /lib/libm.so.6 (0xb7ef3000) libgcc_s.so.1 => /usr/lib/gcc/i686-pc-linux-gnu/3.4.3/libgcc_s.so.1 (0xb7eea000) libc.so.6 => /lib/libc.so.6 (0xb7dd0000) /lib/ld-linux.so.2 (0xb7feb000)
The resulting binary links to a shared version of libstdc++, the standard C++ library, and a shared version of libgcc, a GCC runtime support library required for exception handling among other things. This binary won't work on a machine with different versions
of those libraries, but since it doesn't need any other dynamically loaded C++ libraries, the incompatibility can be removed by linking libstdc++ and libgcc statically.
Consulting the GCC man page, you'll find the GCC option -static-libgcc mentioned. It makes the compiler link libgcc statically rather
than dynamically. Except when it doesn't:
g++ -static-libgcc -o example example.cpp ldd example linux-gate.so.1 => (0xffffe000) libstdc++.so.6 => /usr/lib/gcc/i686-pc-linux-gnu/3.4.3/libstdc++.so.6 (0xb7f17000) libm.so.6 => /lib/libm.so.6 (0xb7ef3000) libgcc_s.so.1 => /usr/lib/gcc/i686-pc-linux-gnu/3.4.3/libgcc_s.so.1 (0xb7eea000) libc.so.6 => /lib/libc.so.6 (0xb7dd0000) /lib/ld-linux.so.2 (0xb7feb000)
What happened here? Remember what I said earlier about not loading any C++ code dynamically? Since we are still linking dynamically to libstdc++, the runtime support code in libgcc must also be linked dynamically. g++ ignored
the -static-libgcc flag because linking libgcc statically would not result in a program that works properly. We need to link statically
to both libraries, or neither.
You can ask g++ to tell you exactly what steps are involved in linking a C++ program (try the -v flag
if you are curious) and invoke a slightly different set of commands in order to link your application with static versions of libstdc++ and libgcc. But integrating that into your own build process is painful, error-prone, and specific to the machine and compiler
version you use.
There's no -static-libstdc++ option to go along with -static-libgcc,
but you can let the compiler tell you the path to the static libstdc++ library it would use, and let g++look for libraries in a directory
where it will only find the static version (in this case our build directory):
ln -s `g++ -print-file-name=libstdc++.a` g++ -static-libgcc -L. -o example example.cpp ldd example linux-gate.so.1 => (0xffffe000) libm.so.6 => /lib/libm.so.6 (0xb7ef3000) libc.so.6 => /lib/libc.so.6 (0xb7dd0000) /lib/ld-linux.so.2 (0xb7feb000)
Once again, for this to work reliably you must not use dynamically loaded C++ code, including code loaded with
dlopen.
In particular, statically linking the runtime support code is contraindicated when creating dynamically loadable C++ libraries. Depending on your linker it might be possible, but planning to distribute such binaries is still very much an order for a super-sized
can of worms.
Update: As of GCC 4.5 there is now a -static-libstdc++ compiler
option which does what you'd expect it to do. (Thanks to Tim Hutt for pointing this out.)
相关文章推荐
- 重新整理了读S计划相关信息,做成了“使用手册”,不知如何开始的朋友看看
- C#/VC++做过数据分析软件的朋友进来看看,帮我分析一下这个软件是如何做的
- 一个漂亮的虚拟仪表控件,做UI喜欢UI的朋友可以进来看看 :-) ( BeauGauge Suite V2 )
- 如何升级Symbian Carbide C++的GCC编译器版本
- 如何使用高版本gcc 静态链接 (gcc 7.2 如何静态链接)
- 关于gcc、glibc和binutils模块之间的关系,以及在现有系统上如何升级的总结
- 关于gcc、glibc和binutils模块之间的关系,以及在现有系统上如何升级的总结
- 如何通过PPA安装/升级gcc和g++版本到4.8.1 (Ubuntu 12.04, 13.04, 10.04适用)
- 山寨google, 新做了1个网站 googler.cc ,做的很山寨 喜欢的朋友可以去看看哈
- 如何升级gcc版本
- 关于gcc、glibc和binutils模块之间的关系,以及在现有系统上如何升级的总结 .
- 刚建新站的朋友可以看看如何培养百度权重,搜索引擎是越来越智能化了。
- mac如何升级g++的版本?更改默认gcc版本
- 长期使用电脑的朋友可以看看, 如何减少电脑屏幕的辐射
- 如何升级gcc版本
- 【转载】如何升级linux上的gcc到最新版本
- 关于gcc、glibc和binutils模块之间的关系,以及在现有系统上如何升级的总结
- 如何升级Carbide C++的GCCE Tool Chain
- 寻找上海市乒友---喜欢打乒乓的朋友都进来看看
- [置顶] linux gcc版本如何升级到gcc4.8.2