Visual Studio 2010奇怪的“警告LNK4042”


80

我刚刚被Visual Studio 2010(C ++)发出的一些不重要的警告打了头(或几乎没有)。

编译结果如下:

1 Debug \ is.obj:警告LNK4042:对象指定了多次;忽略了其他功能
1 Debug \ make.obj:警告LNK4042:对象指定了多次;忽略了其他功能
1 Debug \ view.obj:警告LNK4042:指定的对象不止一次;额外功能被忽略
1 identity.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函数void __cdecl test::identity::identity(void)(?identity @ 0test @@ YAXXZ)中引用的@ identity @ test @@ 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已两次传递给链接器,并且将被忽略。

无需再搜索:Visual已使我的文件夹层次结构整齐地变平,因此无法整齐地编译源代码。

目前,我只是想重命名文件,应该可以解决这个问题。

...但是有没有办法让Visual Studio不展平文件层次结构?


3
刚得到同样的东西,真令人讨厌,我们必须手动“修复”它。很高兴你在我面前问。:)
GManNickG 2011年

5
很久以前,我放弃了SO搜索。:) 谷歌。
GManNickG 2011年

37
我刚刚在VS 2013中解决了一个类似的问题。对我来说,问题是正在编译头文件,就好像它是独立的C ++文件一样。因此,我最终得到了两个名称相同的目标文件:一个用于foo.cpp,一个用于foo.h。解决方案是转到foo.h的相应页面,并将“配置属性”->“常规”->“项目类型”更改为“ C / C ++标头”,然后进行干净的构建。
Adrian McCarthy 2014年

1
@AdrianMcCarthy我遇到了同样的问题,您的建议解决了它。
trenki 2015年

1
@AdrianMcCarthy的评论是解决方案。必须是由于Add->“ New Item”向导自动设置文件的项目类型。
达斯汀·比瑟

Answers:


99

如果您打开整个项目的属性,并将C/C++ -> Output Files -> "Object File Name"下面的值更改为以下内容,则只是想交叉发布我认为会得到答案的内容:

$(IntDir)/%(RelativeDir)/

在VS 2010下,我相信这将消除所有目标文件的歧义(因为我相信Windows在任何疯狂的情况下都不会让您在同一目录中拥有两个名称相同的文件)。也请在此处查看详细信息。


啊! 现在,这是我一回到家就需要尝试的方法:D
Matthieu M.

7
只是要添加:%(RelativeDir)似乎没有剥离任何../ ..(不是应该,但是似乎也没有任何替代方法),因此您可能必须添加“ fake”目录使您的文件构建在“正确”目录中。例如,我有$(IntDir)/ a / a /%(RelativeDir)/,因为它可以在$(IntDir)中构建,因为在我的.cpp路径中有两个../(路径相对于$(ProjectDir ), 我认为)。另请注意,%(RelativeDir)带有%,$(IntDir)带有$(答案是正确的,只是通过快速阅读,可能会错过这一事实)。
n1ckp 2011年

2
嗯...我不知道为什么默认没有设置。好吧,我想我会把它添加到每个项目中(几乎没有任何编译没有此修复程序)
Navin

这在Visual Studio 2012更新1中有效,但是自从我对更新4进行补丁以来,VS似乎不再想要为目标文件创建中间目录。:((请参阅stackoverflow.com/questions/30212698。)–
托马斯·杨

cl.exe在CLI中使用该怎么办?
学习

143

链接器警告LNK4042也有类似的问题:对象多次指定;演员忽略了。在我的情况下,Visual Studio尝试使用相同的名称-MyClass.h和编译头文件和源文件MyClass.cpp。发生这种情况是因为我将.cpp文件重命名为,.h而Visual Studio感到困惑。通过查看Debug目录中的编译器日志,我注意到了问题。要解决此问题,只需.h从项目中删除文件,然后再次添加即可。


2
感谢您发布此信息!旧的删除文件并将其添加回例程也对我有用。我真的开始把头撞在墙上。
韦斯

3
感谢@AndreyLevichev-此回复也为我解决了这个问题。在项目文件中非常清楚的是,.h文件位于“ ClCompile”组而不是“ ClInclude”组中
jglouie 2012年

35
或者,您可以右键单击foo.h解决方案资源管理器中的文件,然后将“项目类型”设置为“ C / C ++标头”,而不是“ C / C ++编译器”。
Thomas Eding 2012年

为此+1。如果我没有看到您的评论,我永远不会发现我的问题。
crocboy

2
@Yaur -或者更好的是,将其更改为一个CLInclude条目
TED

8

在“解决方案资源管理器”窗口,属性,C / C ++,输出文件,目标文件名设置中,右键单击.cpp文件。默认值为$(IntDir)\,这就是进行展平的过程。所有.obj文件都将进入$(IntDir),即调试配置中的“ Debug”目录。

您可以说更改设置$(IntDir)\is2.obj。或从一组中选择所有文件(使用Shift + Click),然后将设置更改为$(IntDir)\identity\

或者,您可以更改.cpp文件名,以使.obj文件不会相互覆盖。在两个目录中具有完全相同名称的文件有点奇怪。

或者,您可以创建多个项目,例如以身份和范围为文件创建.lib项目。例如,通常在makefile项目中完成。但是,这确实使管理编译和链接设置更加麻烦,除非您使用项目属性表。


谢谢,我已经重命名了文件,因为这是更简单的方法。有没有办法要求Visual保存我在项目中精心构建的层次结构?我知道几个文件使用相同的文件名是很奇怪的,但是我更喜欢按子目录对事物进行群集,而不是给我的文件加上前缀...而且将它们放在子目录中并以子目录名称作为前缀都是多余的!
Matthieu M.

您可以同时更改多个文件的设置。在单击以选中它们时,请按住CTRL键。上次尝试使用`$(IntDir)\ $(ParentName)`很麻烦。
汉斯·帕桑

@Hans:猜想我会继续使用不同的名称,我对解决方案并不满意,但是因为它仅用于单元测试部分,所以我相信我会接受。
Matthieu M.

是否可以$(IntDir)在属性表中设置每个文件?我知道您可以在属性表中为整个项目设置它,但是我不知道您是否可以基于正在编译的文件的路径来设置它。(我的猜测不是,但我是完整的MSBuild
新手

@James,项目属性表具有项目范围,它们影响所有文件。
汉斯·帕桑

6

右键单击头文件->属性-> ItemType(选择C / C ++ Header)。对Cpp文件执行相同操作,但选择C / C ++编译器(对我有用)


这是我要寻找的最后一件事。非常感谢。
McLeary

4

我在C / C ++->输出文件->“对象文件名”下使用$(IntDir)\%(Directory)\。


虽然与接受的答案基本相同,但是使用%(Directory)代替%(RelativeDir)会更安全一些。正如n1ckp在接受的答案注释中所指出的那样,根据项目在磁盘上的确切结构,相对目录可能最终会将.obj文件放置在意外的位置。
user1593842

3

我在stdafx.cpp中遇到了这个问题。stdafx.cpp以某种方式被复制,因此有了第二个StdAfx.cpp(请注意不同的情况)。

在删除StdAfx.cpp之后,一切正常!

使用VS 2010。


发生了类似的问题,但是不是重复文件,而是在ClCompile ItemGroup中两次列出了相同文件。
尼古拉斯·贝茨沃斯

3

除了删除和制作新文件外,您还可以更改编译/包含设置。

转到您的project.vcxproj文件,用编辑器打开它,找到html like line <ItemGroup>

它看起来应该像这样:

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

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

假设您的实现文件为.cpp,声明为.hpp。如果您有多个实现文件,请确保所有实现文件都列在第一部分之间;对于第二部分,同样要声明多个声明文件。


2

我曾经在相同的项目.c.cpp文件中使用相同的文件名。这些文件在各处的文件夹中,其他人提供的解决方案造成了混乱,并导致了地狱文件夹(在我的情况下)。即使发布版本也会覆盖调试版本!

一个不错的(不是完美的)解决方案是使用$(ParentName),但是由于某些人无法理解的原因,它已从更高版本的Visual Studio(2015+)中删除。

我现在成功使用的是:$(IntDir)%(Filename)%(Extension).obj

至少将.c构建的目标文件与.cpp分开。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.