Visual Studio2010の奇妙な「警告LNK4042」


81

Visual Studio 2010(C ++)からの重要な警告に、頭を殴られたばかりです(ほとんどありません)。

コンパイルにより、次の出力が得られました。

1 Debug \ is.obj:警告LNK4042:オブジェクトが複数回指定されました。エクストラは無視され
ます1Debug \ make.obj:警告LNK4042:オブジェクトが複数回指定されました。エクストラは無視され
ます1Debug \ view.obj:警告LNK4042:オブジェクトが複数回指定されました。エクストラは無視され
ます1identity.obj :エラーLNK2019 :void __cdecl test::identity::view(void)関数void __cdecl test::identity::identity(void)(?identity @ 0test @@ YAXXZ)で参照される未解決の外部シンボル(?view @ identity @ test @@ YAXXZ)
1 identity.obj:エラーLNK2019 :未解決の外部シンボルvoid __cdecl test::identity::make(void)(?make @ identity @ test @@ YAXXZ)関数void __cdecl test::identity::identity(void)(?identity @ 0test @@ YAXXZ)で参照
1 range.obj:エラーLNK2019:void __cdecl test::range::is(void)関数void __cdecl test::range::range(void)(?range @ 0test )で参照される未解決の外部シンボル(?is @ range @ test @@ YAXXZ)@@ YAXXZ)

リンカーエラーは常にデバッグするのが面倒です...しかし、未解決の参照があったので、チェックしました...しかし、ソースは整形式です...そして最後にそれは私を襲いました:

私のフォルダ階層は次のようになります。

src/
  identity/
    is.cpp
    make.cpp
    view.cpp
  range/
    is.cpp
    make.cpp
    view.cpp

ソリューションの階層も同様です(「実際の」フォルダー構造を模倣するように常に設定しています)。

そして診断出力:

Debug\is.obj
Debug\make.obj
Debug\view.obj

.objがリンカに2回渡され、1つは無視されるという警告とともに。

これ以上検索しない:Visualはフォルダ階層をきちんとフラットにしているため、ソースをきちんとコンパイルできません。

現時点では、ファイルの名前を変更することを考えています。これで問題が解決するはずです...

...しかし、Visual Studioでファイル階層をフラット化しないようにする方法はありますか?


3
これと同じことがわかりました。手動で「修正」する必要があるのは本当に面倒です。あなたが私の前に尋ねてくれてうれしい。:)
GManNickG 2011年

5
私はずっと前にSO検索をあきらめました。:)グーグル。
GManNickG 2011年

38
VS 2013で同様の問題を解決しました。私にとっての問題は、ヘッダーファイルがスタンドアロンのC ++ファイルであるかのようにコンパイルされていたことでした。そのため、同じ名前の2つのオブジェクトファイルが作成されました。1つはfoo.cpp用で、もう1つはfoo.h用です。解決策は、foo.hの適切なページに移動し、[構成のプロパティ]-> [一般]-> [アイテムタイプ]を[C / C ++ヘッダー]に変更して、クリーンビルドを実行することでした。
エイドリアンマッカーシー

1
@AdrianMcCarthy私も同じ問題を抱えていましたが、あなたの提案で解決しました。
trenki 2015年

1
@AdrianMcCarthyのコメントが解決策です。[追加]-> [新しいアイテム]ウィザードがファイルのアイテムタイプを自動的に設定するためである必要があります。
ダスティンバイザー2016年

回答:


99

プロジェクト全体のプロパティを開いて、下の値をC/C++ -> Output Files -> "Object File Name"次のように変更した場合、私が答えだと思うものをクロスポストしたかっただけです。

$(IntDir)/%(RelativeDir)/

VS 2010では、これによりすべてのオブジェクトファイルが明確になると思います(Windowsでは、クレイジーな状況では、同じディレクトリに同じ名前の2つのファイルを含めることができないと思います)。詳細はこちらもご覧ください。


ああ!これは、家に帰ったらすぐに試す必要があることです:D
Matthieu M.

7
追加するだけです:%(RelativeDir)はパス内の../ ..を削除しないようです(そうすべきではありませんが、代替手段もないようです)ので、「偽の」ディレクトリを追加する必要があるかもしれませんファイルを「正しい」ディレクトリにビルドするため。たとえば、$(IntDir)/ a / a /%(RelativeDir)/があるので、.cppのパスに2つの../があるため、$(IntDir)に組み込むことができます(パスは$(ProjectDirに相対的です) )、 おもう)。また、%(RelativeDir)は%であり、$(IntDir)は$であることに注意してください(正解です。速く読むだけでは、その事実を見逃す可能性があります)。
n1ckp 2011年

2
うーん...なぜこれがデフォルトで設定されていないのだろうか。まあ、私はこれをすべてのプロジェクトに追加するだけだと思います(この修正なしではほとんど何もコンパイルされません)
Navin 2013年

これはVisualStudio 2012アップデート1で機能しましたが、アップデート4にパッチを適用したため、VSはオブジェクトファイルの中間ディレクトリを作成したくないようです。:((stackoverflow.com/questions/30212698を参照してください
Thomas Young

cl.exeCLIで使用する場合の方法は?
学習

145

リンカ警告LNK4042で同様の問題が発生しました。オブジェクトが複数回指定されました。エクストラは無視されます。私の場合、VisualStudioは同じ名前のヘッダーファイルとソースファイルの両方をコンパイルしようとしていました-MyClass.hMyClass.cpp。これは、.cppファイルの名前をに変更し.h、VisualStudioが混乱したために発生しました。Debugディレクトリ内のコンパイラログを見て、問題に気づきました。解決するに.hは、プロジェクトからファイルを削除してから、もう一度追加します。


2
これを投稿してくれてありがとう!古いファイルを削除して、それを元に戻すルーチンは、私にとってもトリックでした。私は本当にこれの壁に頭をぶつけ始めていました。
2011

3
@AndreyLevichevに感謝します-この応答は私にとっても問題を修正しました。プロジェクトファイルでは、.hファイルが「ClInclude」グループではなく「ClCompile」グループにあることは明らかです
jglouie 2012年

35
またはfoo.h、ソリューションエクスプローラーでファイルを右クリックし、[アイテムタイプ]を[ C / C ++コンパイラ]ではなく[C / C ++ヘッダー]に設定することもできます。
Thomas Eding 2012年

このために+1。あなたのコメントを見ていなかったら、私は自分の問題を見つけることはなかっただろう。
crocboy 2013年

2
@ Yaur-またはさらに良いことに、それをCLIncludeエントリに変更します
TED

8

ソリューションエクスプローラーウィンドウ、プロパティ、C / C ++、出力ファイル、オブジェクトファイル名の設定で.cppファイルを右クリックします。デフォルトは$(IntDir)\、フラット化を行っていることです。すべての.objファイルは、デバッグ構成の「Debug」ディレクトリである$(IntDir)に配置されます。

たとえば、設定を変更できます$(IntDir)\is2.obj。または、1つのグループからすべてのファイルを選択し(Shift +クリックを使用)、設定を次のように変更します。$(IntDir)\identity\

または、.objファイルが相互に上書きしないように.cppファイル名を変更することもできます。2つのディレクトリにまったく同じ名前のファイルがあるのは少し奇妙です。

または、複数のプロジェクトを作成して、たとえば、IDと範囲のファイルの.libプロジェクトを作成することもできます。たとえば、makefileプロジェクトで一般的に行われます。ただし、プロジェクトのプロパティシートを使用しない限り、コンパイルとリンクの設定を管理するのは面倒です。


おかげで、簡単な方法だったので、すでにファイルの名前を変更しました。プロジェクトで慎重に構築した階層を保持するようにVisualに依頼する方法はありませんか?複数のファイルに同じファイル名を付けるのはおかしいと思いますが、ファイルの前に付けるのではなく、サブディレクトリごとにクラスター化することを好みます...そして、サブディレクトリにファイルを置き、サブディレクトリ名の前に付けるのは冗長です!
Matthieu M.

複数のファイルの設定を同時に変更できます。Ctrlキーを押しながらクリックして選択します。前回試したとき、 `$(IntDir)\ $(ParentName)`の使用は問題でした。
ハンスパザント2010

@Hans:それでは、別の名前を使い続けると思います。ソリューションにはそれほど満足していませんが、単体テストの部分のみを対象としているので、一緒に使用すると思います。
Matthieu M.

$(IntDir)プロパティシートでファイルごとに設定することはできますか?プロパティシートでプロジェクト全体に設定できることは知っていますが、コンパイルするファイルのパスに基づいて設定できるかどうかはわかりません。(私の推測はノーですが、私は完全なMSBuild
初心者です

@ James、プロジェクトプロパティシートにはプロジェクトスコープがあり、すべてのファイルに影響します。
ハンスパッサント2010

7

ヘッダーファイル->プロパティ-> ItemTypeを右クリックします(C / C ++ヘッダーを選択します)。Cppファイルでも同じことを行いますが、C / C ++コンパイラを選択します(私にとってはうまくいきます)


これは私が探していると思う最後のことでした。どうもありがとう。
McLeary 2017年

4

C / C ++->出力ファイル->「オブジェクトファイル名」の下で$(IntDir)\%(Directory)\を使用します。


受け入れられた回答と基本的に同じですが、%(RelativeDir)の代わりに%(Directory)を使用する方が少し安全です。受け入れられた回答コメントのn1ckpに記載されているように、プロジェクトがディスク上でどの程度正確に構造化されているかによっては、相対ディレクトリによって.objファイルが予期しない場所に配置される可能性があります。
user1593842 2018年

4

新しいファイルを削除して作成する代わりに、コンパイル/インクルード設定を変更できます。

project.vcxprojファイルに移動し、エディターで開いて、行のようなhtmlを見つけます<ItemGroup>

次のようになります。

<ItemGroup>
<ClCompile Include="implementation.cpp" />
</ItemGroup>

そして

<ItemGroup>
<ClInclude Include="declaration.hpp" />
</ItemGroup>`

実装ファイルが.cppであり、宣言が.hppであると仮定します。複数の宣言ファイルがある場合は、最初のセクションの間にすべての実装ファイルがリストされていることを確認してください。複数の宣言ファイルの場合は、2番目のセクションも同様です。


3

stdafx.cppでこの問題が発生しました。どういうわけかstdafx.cppが複製されたので、2番目のStdAfx.cppがありました(別のケースに注意してください)。

StdAfx.cppを削除した後、すべてが正常に機能しました。

VS2010を使用します。


同様の問題がありましたが、ファイルが複製される代わりに、ClCompileItemGroupに2回リストされた同じファイルでした。
ニコラスベッツワース2015年

2

以前は、同じプロジェクトに同じファイル名の.cファイルと.cppファイルがありまし。ファイルはいたるところにあるフォルダにあり、他の人が提供したソリューションは混乱を引き起こし、フォルダは地獄になりました(私の場合)。リリースビルドでさえ、デバッグビルドを上書きします!

良い(完璧ではない)解決策は$(ParentName)を使用することですが、何らかの理由で、それはVisual Studio(2015+)の新しいバージョンから削除されました。

私が今うまく使っているのは、$(IntDir)%(Filename)%(Extension).objです。

これは、少なくとも.cビルドオブジェクトファイルを.cppから分離します。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.