25

C ++(およびCは、それほど重要ではありませんが)標準では、プログラム内のすべての変換単位が同じ定義を持つ必要があると規定されています。これには、コンパイラスイッチなどが含まれます。たとえば、MSVC ++では、すべての変換ユニットで適切なバージョンのCランタイムライブラリにリンクする必要があります(/MT/MD/MTd対)。/MDd

ただし、使用したいサードパーティの依存関係がいくつかあり、次のようなものがあります。

  • それらはすべて異なるビルドシステムを使用しています(autoconfがあり、cmakeがあり、独自の手巻きのものがあるように見えるものがあります。)
  • ビルドシステムは、これらの種類のスイッチをすべて構成で公開しているわけではなく、ハードコーディングされているスイッチは、システムごとに設定が異なります。(たとえば、あるライブラリはとを強制/MD/MDd、別のライブラリはとを強制/MTします/MTd

これらの種類のものを処理するための最良の方法が何であるかはわかりません。次のオプションについて説明しました。

  • サードパーティの依存関係を中心に独自のビルドシステムを構築します。
    • PRO:物事が一致することはわかっています
    • PRO:クロスプラットフォームサポートを正しい方法で実行できることを私たちは知っています
    • CON:サードパーティの各ビルドシステムがどのように機能するかは正確にはわかりません
    • CON:たくさんの仕事
    • CON:サードパーティの依存関係が変更された場合に中断します
  • サードパーティのビルドシステムを使用して、必要な処理を実行するように変更してみてください。
    • PRO:作業が少ないようです
    • CON:サードパーティのシステムを壊す可能性があります
    • CON:サードパーティの依存関係が変更された場合に中断します
    • CON:私たち自身のビルドを本当に複雑にする

しかし、私たちは何をすべきかわかりません。そして、私たちはこの種の問題を抱えているのは私たちだけだとは信じられません。上記のオプションの1つを実行する必要がありますか、それとも私が考えていなかった3番目の選択肢を実行する必要がありますか?

4

4 に答える 4

7

厳密に言えば、すべてのライブラリが同じランタイムにリンクする必要はありません。それらがDLLであると仮定すると、それらがDLL境界を介してCRTデータ構造を渡す場合にのみ問題になります。FILE*あるランタイムを使用してDLLにを作成し、別のランタイムに対してリンクされているDLLからそれを使用することは、災害のレシピです。あるランタイムを使用してDLLを呼び出しmallocたり、別のランタイムからDLLを呼び出したりすると、多くの楽しい問題が発生します。newfreedelete

ただし、CRT関連のものがすべてDLLの内部に保持されている限り、別のCRTを使用するDLLに安全にリンクできます。これは、デバッグビルドがリリースCRTに対してリンクされたライブラリを使用できることも意味します。繰り返しますが、ライブラリ間でCRTデータ構造を混在させようとしない限り。

また、ほとんどのコンパイラフラグはABIに影響を与えないため、ライブラリ(またはファイル)間で安全に異なる可能性があることにも注意してください。ABIを変更するものは、パッキングやスタックの位置合わせを強制する場合のように、一般的に明らかです。

つまり、基本的には次のようになります。

  • 可能な限り、ライブラリは自分で作成します。ほとんどの場合、これは、かなり単純な方法で、リンクするランタイムを制御できることを意味します。これには、ビルドシステムのごくわずかな調整が必要になる場合がありますが、通常は、ほとんどのビルドシステムにオプションがあるデバッグビルドとリリースビルドのどちらをビルドするかを指定するだけです。(ライブラリがビルドシステムにVisual Studioを使用している場合は、可能な場合は2010にアップグレードしようとします)
  • ライブラリ独自のビルドシステムを使用します。それ以外のものは、ただの惨めさのレシピです。ビルドシステムが実際にライブラリのソースコードと同期していることを信頼できるようにしたいのですが、それを確実にする最も簡単な方法は、ソースコードに付属しているビルドシステムを使用することです。
  • ライブラリを構築することが現実的でない場合は、そのまま使用し、リンク先のランタイムを配布する必要があります。これは避けようとしますが、他に選択肢がない場合でも十分安全です。
  • ライブラリを構築するとき、それがどのように行われたかを内部wikiに正確に文書化します。これは、ライブラリの新しいバージョンにアップグレードしたり、ライブラリを再構築したりする必要がある場合に非常に役立ちます。

現在、3つの異なるVSランタイム(2005、2008、2010)に依存しています。これは対処するのが面倒ですが、機能します。そして、そのうちの1つか2つについては、独自のコードのデバッグビルドであっても、常にリリースバージョンを使用します。

維持するのは少し面倒ですが、機能します。そして、私はそれを行うためのより良い方法を本当に見ることができません。

もちろん、サードパーティの依存関係の数を最小限に抑える必要があります。サードパーティのライブラリを選択する場合は、そのビルドシステムを考慮する必要があります。いくつかは他のものよりも作業するのがはるかに苦痛です。

しかし、最終的には、正常に動作するビルドシステムがない、またはビルドするのが非常に苦痛で、努力する価値がない、またはできる場所にあるいくつかのライブラリを使用する必要が生じる可能性があります。 tライブラリのデバッグバージョンを作成します。そして、あなたが得ることができるものを取りなさい。使用したいランタイムを使用させます。

于 2012-06-01T18:37:06.527 に答える
2

その通りです。このような問題を抱えているのはあなただけではありません。

私たちの経験では、依存関係の疎結合 (ファイルを手動でコピーするという派手な言い方) とサード パーティのビルド システムの変更が最も効果的です (特に Windows 用にビルドする場合)。

私たちが便利だと思ったいくつかのこと:-

特定のバージョンに適用する必要があった変更を文書化し (Wiki ページを使用します)、ここで必要な手順/依存関係 (たとえば、OpenSSL のビルドに必要な Perl インタープリター) を含め、ビルドを使用する前に、含まれているすべてのテストを実行します。

ここでは、サードパーティによって生成された名前を使用するよりも、出力ライブラリの名前を変更して、一貫して ABI に従ってマークされるようにすることが非常に役立つことがわかりました。

そのため、サードパーティの C++ 依存関係 X は、最終的にディレクトリ構造 (svn にコミット) に格納されます。

X/[version_number]/include (lib を使用するヘッダー ファイル)

X/[version_number]/lib/Windows (手動でビルドされ、テストされ、名前が変更されたライブラリ)

例えば

X-vc100.lib X-vc100-gd.lib

(ブースト名http://www.boost.org/doc/libs/1_49_0/more/getting_started/windows.html#library-namingは完全に理にかなっていると思われるため、実際に名前をコピーしました)

次に、特定のサード パーティの依存関係をビルド システムで選択できます (VS の場合、ユーザー マクロとして名前が付けられたすべての依存関係を含む継承されたプロパティ シートを使用するため、$(x_inc) をプロジェクトのインクルード ディレクトリに追加し、$(x_lib ) をライブラリに追加 - これらのマクロは、その特定のプロジェクトに必要なバージョンと abi を選択します。

于 2012-06-01T18:28:30.200 に答える
2

特定のライブラリについて意図的に言及していないと思いますか?

とにかく、ビルドシステムでこのサードパーティのコードが本当に必要かどうかを自問する必要があります。

私たちが使用するサードパーティのライブラリは、(それぞれのビルド スクリプトを使用して) 1 回コンパイルされ、適切な VC スイッチがチェックされます。次に、DLL または LIB ファイルが、ライブラリを使用するアプリのソース管理にチェックインされます。

そのため、サードパーティのライブラリのコンパイルは、サードパーティのリリースごとに 1 回だけ行うものであり、サードパーティのライブラリを構築する複雑さでビルド システムに負担をかけることはありません。

どちらのアプローチにも有効な議論があると思います。おそらく、ビルドシステム内にサードパーティのライブラリが必要な/したい理由の質問に詳細を提供できます。

于 2012-06-01T18:13:44.910 に答える
1

決定的な答えはありません。サード パーティのコード インターフェイスがどのように設計されているかによって異なります。インターフェースが密結合の場合 (たとえば、非不透明なデータ型を共有する場合)、独自のビルドとオプションを使用してそれらを再構築することをお勧めします。インターフェイスを分析し、それらを統合する方法を決定する必要があります。一方、インターフェイスがシンプルで簡単に分離できる場合は、それらを dll として構築し、オンデマンドで呼び出すことができます。もちろん、異なるバージョンの C ライブラリがアプリケーションにロードされ、それらはすべて io バッファー、メモリ管理などの異なるインスタンスを持ちます。

ソース コードを利用できる場合は、それらを独自のビルドに統合するためにより多くの時間を費やすことをお勧めします。

于 2012-06-01T19:07:38.457 に答える