web-dev-qa-db-ja.com

同じコンパイラの異なるバージョンでコンパイルされたc ++を混合できますか

たとえば、GCC-4.9とGCC-4.6などでコンパイルされた一連のライブラリを混在させることができます。

VSなどのさまざまなコンパイラの「種類」をMinGWに含めることはできませんが、同じコンパイラの異なる世代を含めることはできますか?問題が発生する可能性はありますか?もしそうなら?

24
robby987

同じコンパイラの異なる世代は時々can互いに互換性がありますが、常にではありません。たとえば、GCC 4.7.0 変更されたC/C++ ABI は、4.7.0 +と4.7.0-でコンパイルされたライブラリが互いに互換性がない可能性が高いことを意味します(この例では、 4.6でコンパイルされたライブラリはnot 4.9でコンパイルされたライブラリと互換性があります。特定のコンパイラリリース内にABIバグがある可能性もあります GCC 4.7.0/4.7.1で発生したように

GCCバージョン4.7.0および4.7.1には、C++ 11モードのABIに影響するC++標準ライブラリへの変更がありました。データメンバーがstd :: listに追加され、そのサイズを変更し、一部のメンバー関数の定義を変更しました。 std :: pairのmoveコンストラクターは自明ではなく、std :: pair引数または戻り型を持つ関数の呼び出し規約を変更していました。 ABIの非互換性はGCCバージョン4.7.2で修正されましたが、その結果、GCC 4.7.0または4.7.1でコンパイルされたC++ 11コードは、異なるGCCバージョンおよびC++でコンパイルされたC++ 11コードと互換性がない場合があります任意のバージョンでコンパイルされた98/C++ 03コード。

GCC ABIのポリシーとガイドラインのページ は、下位互換性ではなく、上位互換性を維持しようとすることを示しています。

バージョン管理により、ライブラリバイナリの後続のリリースは、シリーズの以前のリリースとの互換性を維持しながら、新しいシンボルを追加して機能を追加することができます。したがって、ライブラリバイナリが慎重に管理された後続のライブラリバイナリに置き換えられた場合、ライブラリバイナリの初期リリースにリンクされたプログラムバイナリは引き続き正しく動作します。これは前方互換性と呼ばれます。

逆(下位互換性)は正しくありません。リリースシリーズのライブラリバイナリの最新バージョンにリンクされたプログラムバイナリを(追加のシンボルを追加して)取得し、ライブラリバイナリの最初のリリースで置き換えることはできません。

このページには、GCCが特定のコンポーネントのさまざまなバージョンをマークするために使用するバージョン管理システムに関するかなり長い説明と、GCC自体の背後にあるバージョン管理の説明もあります。

許可された変更

  • 次のようにすると、ライブラリのマイナーバージョン番号が「libstdc ++。so.3.0.4」から「libstdc ++。so.3.0.5」に増えます。

  • エクスポートされたグローバルまたは静的データメンバーの追加

  • エクスポートされた関数、静的または非仮想メンバー関数の追加

  • 追加のインスタンス化によるエクスポートされたシンボルの追加

  • その他の許可された変更が可能です。

禁止されている変更

次の完全ではないリストにより、ライブラリのメジャーバージョン番号が、たとえば「libstdc ++。so.3.0.4」から「libstdc ++。so.4.0.0」に増加します。

  • gcc/g ++コンパイラABIでの変更

  • エクスポートされたシンボルのサイズを変更する

  • エクスポートされたシンボルの配置の変更

  • エクスポートされたシンボルのレイアウトを変更する

  • エクスポートされたシンボルのマングリングの変更

  • エクスポートされたシンボルを削除する

  • 基本クラスを追加または削除して、型の継承プロパティを変更する

  • C++標準で指定されている型のサイズ、配置、またはレイアウトを変更する。これらは必ずしもインスタンス化されたり、ライブラリバイナリにエクスポートされたりする必要はなく、必要なすべてのロケールファセットやstd :: basic_streambufなどのものが含まれます。

  • 明示的なコピーコンストラクターまたはデストラクタを、暗黙のバージョンを持つクラスに追加します。これにより、コンパイラーが値による戻りステートメントまたはパラメーターでこのクラスを処理する方法が変更されます。このクラスのインスタンスをレジスターで渡す代わりに、コンパイラーは強制的にメモリーを使用します。詳細については、C++ ABIドキュメントの関数呼び出し規約とAPIに関するセクションを参照してください。

太字のビットに注意してください。完全な世界では、同じメジャーリリース番号のGCCバージョンはバイナリ互換です。これは完璧な世界ではないので、このようなコンパイラバージョンを混在させる前に非常に注意深くテストしてください。しかし、一般的には大丈夫でしょう。

24

異なるコンパイラーまたは同じコンパイラーの異なるバージョンから生成されたバイナリー・ファイルは、それらがABI(アプリケーション・バイナリー・インターフェース)互換である場合にのみ混合できます。

のようなもの:

  • 呼び出し手順
  • 名前マングリング
  • スレッドローカルストレージの処理

すべてABIの一部です。

これらのいずれかが変化すると、リンカーエラー、クラッシュ、またはその他の予期しない動作が発生することがわかります。原則として、コンパイラベンダーは少なくとも古いバージョンとの下位互換性を維持しようとすることがよくありますが、これを保証するものではありません。他の人が言ったように、ドキュメントを読むか、単にすべてを再コンパイルする必要があります。

3
doron