Visual Studio 2010的奇怪“警告 LNK4042”

我刚刚被 VisualStudio2010(C + +)的一些重要警告击中了头部。

汇编的结果如下:

1 Debug is.obj: 警告 LNK4042: 对象指定不止一次; 额外的内容被忽略
1 Debug make.obj: 警告 LNK4042: 对象指定不止一次; 额外值被忽略
1 Debug view.obj: 警告 LNK4042: 对象指定不止一次; 额外的内容被忽略
错误 LNK2019: 未解析的外部符号 < code > void _ _ cdecl Test: : Identity: : view (void) (? view@Identity@test@@ YAXXZ)在函数 void __cdecl test::identity::identity(void)(? Identity@0test@@ YAXXZ) < br > 中引用 1 Identity.obj: 错误 LNK2019: 函数 void __cdecl test::identity::identity(void)中引用的未解析的外部符号 void __cdecl test::identity::make(void)(? make@Identity@test@@ YAXXZ)(? Identity@0test@@ YAXXZ)
1 range.obj: 错误 LNK2019: 函数 void __cdecl test::range::range(void)中引用的未解析外部符号 void __cdecl test::range::is(void)(? is@range@test@@ YAXXZ)(? range@0test@@ 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已经两次传递给链接器,其中一次将被忽略。

不再搜索: 可视化已经整齐地压平了我的文件夹层次结构,因此无法整齐地编译源代码。

目前,我只是在考虑重命名这些文件,这应该能解决这个问题..。

... 但是有没有一种方法可以让 Visual Studio 不去平化文件层次结构呢?

45491 次浏览

Right-click the .cpp file in the Solution Explorer window, Properties, C/C++, Output Files, Object File Name setting. The default is $(IntDir)\, that's what is doing the flattening. All the .obj file will go into $(IntDir), the "Debug" directory in the debug configuration.

You can change the setting, say $(IntDir)\is2.obj. Or select all the files from one group (use Shift+Click) and change the setting to, say, $(IntDir)\identity\

Or you can change the .cpp filename so that .obj files don't overwrite each other. Having files with the exact same name in two directories is a bit odd.

Or you can create multiple projects, creating, say, .lib projects for the files in identity and range. Commonly done in makefile projects for example. That does however make managing the compile and link settings more of a hassle unless you use project property sheets.

Just wanted to cross post what I believe to be the answer, if you open the properties for the entire project, and the change the value under C/C++ -> Output Files -> "Object File Name" to be the following:

$(IntDir)/%(RelativeDir)/

Under VS 2010, I believe this will disambiguate all of the object files (as I believe windows won't let you under any crazy circumstances have two files with the same names in the same directory). Please also check out the details here.

I had a similar problem with linker warning LNK4042: object specified more than once; extras ignored. In my case Visual Studio was trying to compile both header and source files with the same name - MyClass.h and MyClass.cpp. It happened because I renamed .cpp file to .h and Visual Studio got confused. I noticed the problem by looking at the compiler logs in the Debug directory. To resolve just remove .h file from the project then add it again.

I had this problem with stdafx.cpp. Somehow stdafx.cpp got duplicated, so there was a second StdAfx.cpp (mind the different case).

After I removed the StdAfx.cpp everything worked fine!

Using VS 2010.

Alternatively to deleting and making a new file you can change the compile/include settings.

Go to your project.vcxproj file, open it with an editor, find the html like line <ItemGroup>.

It should look something like:

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

and

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

Assuming your implementation files are .cpp and your declarations are .hpp. Make sure your all your implementation files are listed between the first section if you have more then one and likewise for the second section for multiple declaration files.

I use $(IntDir)\%(Directory)\ under C/C++ -> Output Files -> "Object File Name".

Right click on header file -> Property -> ItemType (select C/C++ Header). Do the same with Cpp file but select C/C++ Compiler (it's work for me)

I used to have in the same project .c and .cpp files with the same filenames. The files were in folders all over the place and the solutions provided by others created a mess, and folder hell (in my case). Even Release builds would overwrite Debug builds!

A good (not perfect) solution would be to use $(ParentName), but for some reason beyond anyone's grasp it has been removed from later versions of Visual Studio (2015+).

What I use succesfully now is: $(IntDir)%(Filename)%(Extension).obj

which at least separates .c built object files from .cpp.

I'd like to point out one possible reason for why the ItemType of a .h file would change from C/C++ header to C/C++ compiler:

  1. In the Solution Explorer window of VS (2019 here), right click the project name, choose Add -> New Item;
  2. Select the C++ File (.cpp) template, but type something.h in the name input area, then click OK to add it;
  3. Then you'll encounter the LNK4042 warning if the something.h file be included within more than one .cpp files.

I just overcame a similar error message, and lots more with the procedure below. Symptom: one linker error for every invocation of every function defined in a particular header, plus one at the end of output for every function defined in the header.

Then I remembered that when I had originally created this header, I accidentally had selected "add->new item->c++ file" and though I named it 'whatever.h', it seems Visual Studio considered them both the same kinds of files because of the incorrect action I used to add one. Examining the build output logs made this obvious.

SOLUTION (Using VS Community 2019)

  1. Back up project first (just to be safe).
  2. Right-click the offending header file and select "Exclude from project" (this will not delete them; the VS project will just ignore them).
  3. Do same for the matching .c or .cpp file.
  4. Do Build->Clean on project
  5. Do Build->Rebuild on project -- there of course will be errors---
  6. Right-click Header Files->Add->Existing Item, then select the .h file
  7. Right-click Source Files->Add->Existing Item, the select the .c or .cpp file
  8. Do Build->Rebuild on project.

This completely cleaned it up for me, relieving me of many irritating linker errors including LNK4042 from the title of this question.

I resolved it changing filenames in my project. There was two files named main.c and main.cpp. I changed one of them and worked.