如何静态链接到 libstdc++. 喜欢升级的GCC的朋友快来看看。

转载 2013年12月05日 15:24:42

Linking libstdc++ statically

Christopher Baus writes about his problems linking 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_cast or catch objects 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.)

相关文章推荐

linux下用cmake对caffe静态编译时-static-libstdc++参数无效的问题

以下是用于cmake 生成 Makefile文件对Caffe进行静态库连接编译的shell脚本,#!/bin/bash # cmake 静态编译 caffe-ssd 代码脚本 # author guy...
  • 10km
  • 10km
  • 2017-06-12 17:50
  • 794

CentOS 6.5 升级gcc到4.8 以及libstdc++

CentOS 6.5 自带gcc太旧不支持c11, 升级到4.8的步骤:引用: http://cache.baiducontent.com/c?m=9d78d513d99216f31eb0d5690...
  • norsd
  • norsd
  • 2016-05-24 21:28
  • 3960

编译4.7.2的gcc的针对libstdc++的configure解读

http://www.tuicool.com/articles/nMjmay When configuring libstdc++, you'll have to configure...

gcc编译静态库到自己的程序 解决在不同linux下因libc版本问题而不能运行

1.先用yum下载安装glibc和libstdc++的静态库 sudo yum install glibc-static libstdc++-static 2.在编译选项LDFLAGS中添加-stat...
  • snoyfl
  • snoyfl
  • 2016-06-17 11:43
  • 2532

让C/C++程序一次编译可以发布到多版本Linux之上

转自:战魂小筑, http://www.cppblog.com/sunicdavy/archive/2012/04/20/172108.html 最近页游开放平台比较多, 每个平台要...

【计算机视觉】目标检测之ECCV2016 - SSD Single Shot MultiBox Detector

本文转载自: http://www.cnblogs.com/lillylin/p/6207292.html SSD论文阅读(Wei Liu——【ECCV2016】S...

ssd目标检测整理

ssd目标检测整理

SSD+caffe︱Single Shot MultiBox Detector 目标检测+fine-tuning(二)

承接上一篇SSD介绍:SSD+caffe︱Single Shot MultiBox Detector 目标检测(一) 如果自己要训练SSD模型呢,关键的就是LMDB格式生成,从官方教程weili...

LINUX-Opencv3.2SSDdemo&&TensorFlowdemo运行配置

Opencv3.2去年12月底更新,其中有本人想要使用的tensorflow相关demo。因而花了3天在香蕉派(类似树莓派)和个人电脑上进Opencv3.2的配置,现在网上还没发现相关配置攻略,自己也...

使用keras实现目标检测之SSD

最近参加了百度某大数据比赛,其中需要用到检测模型。 使用keras实现ssd目标检测,keras实现ssd源码:https://github.com/rykov8/ssd_keras 等忙完了决赛...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)