24

私は静的にコンパイルされた一連のライブラリを持っており、ライブラリ間にかなり深い依存関係があります。たとえば、実行可能ファイル X はライブラリ A と B を使用し、A はライブラリ C を使用し、B はライブラリ C と D を使用します。

X -> A
     A -> C
X -> B
     B -> C
     B -> D

X を A および B にリンクするときに、C および D もライブラリのリストに追加されていない場合にエラーが発生するのは望ましくありません。A および B がこれらのライブラリを内部で使用するという事実は、X が必要としない実装の詳細です。について知ること。また、依存関係ツリーのどこかに新しい依存関係が追加されると、A または B を使用するプログラムのプロジェクト ファイルを再構成する必要があります。深い依存関係ツリーの場合、必要なライブラリのリストが非常に長くなり、保守が困難になる可能性があります。

そのため、A プロジェクトのライブラリアン セクションの「追加の依存関係」設定を使用して、C.lib を追加しています。B のプロジェクトの同じセクションに、C.lib と D.lib を追加します。これにより、ライブラリアンは C.lib を A.lib にバンドルし、C.lib と D.lib を B.lib にバンドルします。

しかし、X をリンクすると、A.lib と B.lib の両方に C.lib の独自のコピーが含まれます。これは、次の行に沿って大量の警告につながります

A.lib(c.obj) : 警告 LNK4006 "symbol" (_symbol) は既に B.lib(c.obj) で定義されています。2 番目の定義は無視されました。

警告を受けずにこれを達成するにはどうすればよいですか? 単純に警告を無効にする方法はありますか、それとももっと良い方法がありますか?

編集:より良い代替手段がないため、単に警告を無効にすることを示唆する複数の回答を見てきました。まあ、これは問題の一部です:私はそれを無効にする方法さえ知りません!

4

9 に答える 9

15

私の知る限り、リンカーの警告を無効にすることはできません。ただし、リンカーのコマンドラインパラメーターを使用して、それらのいくつかを無視できます。/無視:4006

リンカー - >コマンドライン設定の下のプロジェクトプロパティに配置します(正確な場所は覚えていません)。

これも読んでください:

リンク/無視

MSDN フォーラム - LNK 警告を非表示にする

ワセク

于 2009-02-27T13:45:14.023 に答える
9

更新関連するすべてのプロジェクトを単一のソリューションでビルドできる場合は、これを試してください:

  • すべてのプロジェクトを 1 つの sln に入れます。
  • プロジェクトのリンカーまたはライブラリアン プロパティから静的ライブラリへのすべての参照を削除します。
  • ソリューション エクスプローラーの各プロジェクトのコンテキスト メニューに [プロジェクトの依存関係...] オプションがあります。プロジェクト間の依存関係を定義するために使用します。

それはうまくいくはずです。前に言ったことを無効にするわけではありません。C/C++ プログラムを構築する基本的なモデルは変わりません。VS (少なくとも 2005 以降) は、必要なすべての静的ライブラリをリンカ コマンド ラインに追加するのに十分スマートです。プロジェクトのプロパティで確認できます。

もちろん、既にコンパイル済みの静的ライブラリを使用する必要がある場合、この方法は役に立ちません。次に、それらを直接または間接的に使用する exe または dll プロジェクトにすべて追加する必要があります。


私はあなたがそれについて何もできないと思います。静的ライブラリ プロジェクトから他の静的ライブラリへの参照を削除し、必要なすべての静的ライブラリ プロジェクトを exe または dll プロジェクトの依存関係として追加する必要があります。A.lib または B.lib を含むプロジェクトには C.lib も含める必要があるという事実を受け入れる必要があります。

別の方法として、ライブラリをよりリッチなモデルを提供する dll に変換することができます。

静的にコンパイルされたライブラリは、dll のように、依存情報などを含む実際のライブラリではありません。それらを構築するときに、それらが依存するライブラリを実際に提供する必要がないことがわかりますか? 必要なのはヘッダーだけです。見る?静的ライブラリが何かに依存しているとは言えません。

静的ライブラリは、コンパイル済みでまだリンクされていないオブジェクト コードの単なるアーカイブです。それは一貫した全体ではありません。各オブジェクト ファイルは個別にコンパイルされ、ライブラリ内で個別のエンティティのままになります。リンクは、exe または dll をビルドするときに発生します。そのとき、すべてのオブジェクト コードを提供する必要があります。それは、すべてのシンボルと依存関係の解決が行われるときです。

他の静的ライブラリを静的ライブラリの依存関係に追加すると、ライブラリアンはすべてのコードをまとめてコピーするだけです。次に、exe をビルドするときに、リンカーはシンボルの重複に関する多くの警告を表示します。これらの警告をブロックできるかもしれませんが (方法はわかりません)、注意してください。異なる定義を持つ実際の重複シンボルなど、実際の問題を隠す可能性があります。また、ライブラリに静的データが定義されている場合でも、おそらく機能しません。

于 2009-02-25T23:01:18.433 に答える
4

Microsoft(R)インクリメンタルリンカーバージョン9.00.x(link.exe)は引数/ ignore:4006を認識しています

于 2009-02-27T16:00:44.527 に答える
3

A、B、C、D を含む 1 つのライブラリを作成し、それに対して X をリンクできます。

これはライブラリであるため、実際に参照されるオブジェクト モジュールのみが最終的な実行可能ファイルにリンクされます。

于 2009-02-24T20:38:17.847 に答える
1

この警告を取得する 1 つの方法は、インライン ステートメントを使用せずにヘッダーでメンバー関数を定義することです。

// Foo.h

class Foo
{
    void someFunction();
};

void Foo:someFunction() // Warning!  - should be "inline void Foo::someFunction()"
{
    // do stuff
}
于 2011-07-20T09:29:08.470 に答える
0

問題は、ライブラリ C のシンボルをローカライズしていないことです。したがって、A と B をリンクすると ODR 違反になります。これらを非公開にする方法が必要です。デフォルトでは、すべてのシンボルがエクスポートされます。これを行う 1 つの方法は、エクスポートする必要があるファイルを明示的に指定する、A と B の両方に特別なリンカー定義ファイルを用意することです。

[1] ODR = 1 つの定義規則。

于 2009-02-19T11:59:01.597 に答える
0

C.lib は A.Lib と B.lib の両方の一部である必要があり、A.Lib は B.lib を知る必要がないため、リンカーの警告 (LNK4006) を無視/無効にすることが最善の方法だと思います。それ自体は C.Lib を使用します。

于 2009-02-19T11:59:37.057 に答える
-1

これはリンク エラーを修正しない可能性がありますが、依存関係ツリーの問題を解決するのに役立つ場合があります。

私がしていることは、 #pragma を使用して、それを必要とする .cpp ファイルに lib を含めることです。例えば:

#pragma comment(lib:"wsock32") 

私が言ったように、そのオブジェクトファイルにシンボルが保持されるかどうかはわかりません。試してみるには、例を作成する必要があります。

于 2009-02-25T23:19:54.660 に答える
-3

リンカの警告を無効にする方法を誰も説明しないことに、かわいそうなフロディンは不満を感じているようです。まあ、私は同様の問題を抱えていました.何年もの間、数百の警告が表示されたという事実に単純に耐えてきました. ただし、 Link /ignoreからの情報のおかげで、リンカーの警告を無効にする方法がわかりました。

私は Visual Studio 2008 を使用しています。プロジェクト -> 設定 -> 構成プロパティ -> ライブラリアン -> コマンド ライン -> 追加オプションで、"/ignore:4006" を追加しました (引用符なし)。今、私の警告はなくなりました!

于 2010-08-15T00:27:33.630 に答える