ここではどのような魔法が行われているのでしょうか?
これは主に ELF シンボルのバージョン管理の魔法です。これについて私が見た最良の参考文献は、Ulrich Drepper による共有ライブラリの作成方法、特にセクション 3 です。
古いバージョンの libstdc++ にリンクする gcc 4.4.7 を提供するにはどうすればよいでしょうか? ありえないと思いました。
libstdc++ の開発者は、ABI の互換性に注意を払っています。これにより、libstdc++ の 2 つの異なるバージョン間で導入された新しいシンボルを簡単に確認できます。
libstdc++ のABI 互換性ページを見ると、GCC 4.1 の libstdc++ には GLIBCXX_3.4.8 があり、GCC 4.4 のストック (FSF リリース) には GLIBCXX_3.4.13 があることがわかります。その後、libstdc++ バージョンのスクリプトを調べて、これら 2 つのバージョン間でどのシンボルが追加されたかを確認できます。
シンボルのバージョンを確認するためのより経験的な方法は、readelf のようなツールを使用することです。たとえば、私の Ubuntu システムでは、readelf --dyn-syms --wide /usr/lib/x86_64-linux-gnu/libstdc++.so.6 | c++filt
次のような出力が表示されます (選択された短い行がいくつかあります)。
223: 000000000006dbe0 2121 FUNC GLOBAL DEFAULT 12 std::ios_base::Init::Init()@@GLIBCXX_3.4
...
226: 00000000002ed920 1 OBJECT GLOBAL DEFAULT 27 std::adopt_lock@@GLIBCXX_3.4.11
シンボル名の末尾の . の後のシンボル バージョンに注意してください@@
。
この stdc++_nonshared ライブラリは何ですか?
上記の段落のドットを結合すると、stdc++_nonshared は、ストック libstdc++.so.6.0.13 には含まれるが libstdc++.so.6.0.8 には含まれないシンボルを含む静的ライブラリです。
.so ファイルにそのテキストを含めることができるとは知りませんでした。誰がそれを解析し (動的リンカだと思います)、その仕様と結果は何ですか?
実行時リンカーではなく、通常のリンカーがこれを解析します。リンカー スクリプトでの INPUTについては、binutils のドキュメントを参照してください。結果として、この特別な libstdc++.so.6.0.13 とリンクすると、リンカーは libstdc++.so.6.0.8 に対して動的にリンクし、余分なシンボルを含むライブラリに対して静的にリンクします。
これの欠点は、この方法でコンパイルされたアプリケーションが、必要なすべてのシンボルを含むストック libstdc++.so.6.0.13 のみに動的にリンクされている同じアプリケーションよりも少し肥大化することです。利点は、独立したソフトウェア ベンダーが libstdc++ の独自のコピーを出荷する必要なく、新しい標準ライブラリの機能を古いシステムの標準インストールで使用できることです。
この魔法はどこまで行ける?libstdc++ 6.0.3 で gcc4.7 を使用できますか? 互換性のスペクトルは何ですか
魔法が何であるかがわかったので、お使いの GCC 4.4 のこのバージョンが、Centos 5 (元は Red Hat 5) のためだけに作成された特別なバージョンであることを理解できるでしょう。おそらく、libstdc++ 6.0.3 のみを必要とするバイナリを生成する GCC 4.7 を作成できますが、正しいシンボルを stdc++_nonshared.a に配置するために、GCC ツリーにパッチを適用するという重要な作業が必要になります。少なくとも gcc44 RPM のソースを調べて、Red Hat がそこでどのようにそれを行ったかを確認できます。
Red Hat は、 Red Hat Developer Toolsetでこのアプローチを継続しているようです。執筆時点では、GCC 4.8.1 は EL5 用のバイナリをビルドできる最新のコンパイラであり、ターゲット システムに libstdc++.so.6.0.8 をインストールするだけで済みます。これは、C++11 で記述したいが、EL5 または EL6 にデプロイできる必要がある開発者にとって優れています。