[解決済み] libstdc++ を静的にリンクする: 何かゴチャゴチャは?
質問
Ubuntu 12.10 で GCC 4.7 の libstdc++ を使用して構築された C++ アプリケーションを、かなり古いバージョンの libstdc++ が付属する Ubuntu 10.04 を実行しているシステムにデプロイする必要があります。
現在、私は
-static-libstdc++ -static-libgcc
でコンパイルしていますが、このブログの記事で提案されているように
libstdc++ を静的にリンクする
. 作者は、libstdc++を静的にコンパイルするときに、動的にロードされたC++のコードを使用しないように警告しています。それでも、今のところ、すべてが順調に進んでいるようです。Ubuntu 10.04 で C++11 の機能を利用することができ、これは私が求めていたものです。
私は、この記事が 2005 年のものであり、おそらくその後に多くの変更があったことに注目しています。そのアドバイスはまだ最新ですか? 私が注意すべき潜んでいる問題はありますか?
どのように解決するのですか?
そのブログ記事はかなり不正確です。
私が知る限り、C++ ABI の変更は GCC のすべてのメジャー リリースで導入されています (すなわち、異なる第 1 または第 2 バージョン番号のコンポーネントを持つもの)。
そうではありません。GCC 3.4 以降に導入された唯一の C++ ABI の変更は後方互換性があり、C++ ABI はほぼ 9 年間安定していたことを意味します。
さらに悪いことに、ほとんどの主要な Linux ディストリビューションは GCC スナップショットおよび/または GCC バージョンにパッチを適用しており、バイナリを配布する際にどの GCC バージョンを扱っているか正確に知ることが事実上不可能になっています。
たとえば、Fedora の 4.6.3 20120306 (Red Hat 4.6.3-2) は、上流の FSF 4.6.x リリースと ABI 互換で、他のどのディストロの 4.6.x でもほぼ確実に互換性があります。
GNU/Linux では、GCC のランタイムライブラリは ELF シンボルバージョニングを使用しているので、オブジェクトやライブラリに必要なシンボルのバージョンを確認するのは簡単で、もし、あなたが
libstdc++.so
があれば、それがあなたのディストロの別のバージョンからわずかに異なるパッチが適用されたバージョンであっても問題なく動作します。
が、これが動作するためには、C++ コード (または C++ ランタイム サポートを使用するコード) は動的にリンクしてはいけません。
これも真実ではありません。
とはいえ、静的にリンクすることで
libstdc++.a
への静的なリンクは、あなたにとって1つの選択肢です。
ライブラリを動的にロードする場合、うまくいかないことがあるのは、(
dlopen
を使用して) 動的にロードした場合に動作しない理由は、依存する libstdc++ シンボルが、(静的に) リンクした時にはアプリケーションで必要とされていなかったかもしれないからです。 これは共有ライブラリを動的にリンクすることで解決できます。
libstdc++.so
(ELFシンボルインター フェースとは、実行ファイルに存在するシンボルは共有ライブラリによって使用され、 実行ファイルに存在しないシンボルは、どの
libstdc++.so
にリンクされます。 もしあなたのアプリケーションが
dlopen
を使わないアプリケーションでは、気にする必要はありません。
もう一つの選択肢 (そして私が好むもの) は、より新しい
libstdc++.so
をアプリケーションと一緒に展開し、それがデフォルトのシステムの
libstdc++.so
の前に見つかるようにします。これは、ダイナミックリンカーが正しい場所を探すように
$LD_LIBRARY_PATH
環境変数を使うか、あるいは
RPATH
を設定する。 私はどちらかというと
RPATH
を使うことを好みます。これは、アプリケーションが動作するために環境が正しく設定されていることに依存しないためです。 もしアプリケーションをリンクするときに
'-Wl,-rpath,$ORIGIN'
でリンクすると (シングルクォートで囲むのは、シェルが
$ORIGIN
を展開しようとするのを防ぐためです)、実行ファイルには
RPATH
の
$ORIGIN
で、ダイナミックリンカーに実行ファイル自身と同じディレクトリにある共有ライブラリを探すように指示します。もし、より新しい
libstdc++.so
を実行ファイルと同じディレクトリに置くと、実行時にそれが見つかり、問題は解決します。 (別の方法として、実行ファイルを
/some/path/bin/
に、より新しい libstdc++.so を
/some/path/lib/
でリンクし
'-Wl,-rpath,$ORIGIN/../lib'
など、実行ファイルからの相対的な位置を固定し、RPATHを
$ORIGIN
)
関連
-
[解決済み】C++エラーです。"配列は中括弧で囲まれたイニシャライザーで初期化する必要がある"
-
[解決済み】抽象クラス型の無効なnew-expression
-
[解決済み】文字列関数で'char const*'のインスタンスを投げた後に呼び出されるterminate [閉店].
-
[解決済み] クラスにデフォルトコンストラクタが存在しない。
-
[解決済み】IntelliSense:オブジェクトに、メンバー関数と互換性のない型修飾子がある
-
[解決済み】Visual C++で "Debug Assertion failed "の原因となる行を見つける。
-
[解決済み] 式はクラス型を持つ必要があります。
-
[解決済み] [Solved] インクルードファイルが開けません。'stdio.h' - Visual Studio Community 2017 - C++ Error
-
[解決済み】1つ以上の多重定義されたシンボルが見つかる
-
[解決済み】クラスのコンストラクタへの未定義参照、.cppファイルの修正も含む
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】C++ クラスヘッダが含まれているときに「不明な型」があるのはなぜですか?重複
-
[解決済み】非静的メンバ関数への参照を呼び出す必要がある
-
[解決済み】C++ 式はポインタからオブジェクトへの型を持っている必要があります。
-
[解決済み] string does not name a type Errorが発生するのはなぜですか?
-
[解決済み】C++の変数はイニシャライザーを持っているが、不完全な型?
-
[解決済み] 既に.objで定義されている-二重包含はない
-
[解決済み】Visual C++で "Debug Assertion failed "の原因となる行を見つける。
-
[解決済み】Eclipse IDEでC++エラー「nullptrはこのスコープで宣言されていません」が発生する件
-
[解決済み】'std::cout'への未定義の参照
-
[解決済み] スタックアロケーションにより初期化されていない値が作成された