web-dev-qa-db-fra.com

L'étrange "avertissement LNK4042" de Visual Studio 2010

Je viens d'être battu (plutôt difficilement) sur la tête par un avertissement non trivial de Visual Studio 2010 (C++).

La compilation a donné la sortie suivante:

1 Debug\is.obj: avertissement LNK4042: objet spécifié plusieurs fois; extras ignorés
1 Debug\make.obj: avertissement LNK4042: objet spécifié plusieurs fois; extras ignorés
1 Debug\view.obj: avertissement LNK4042: objet spécifié plusieurs fois; extras ignorés
1 identité.obj: erreur LNK2019: symbole externe non résolu void __cdecl test::identity::view(void) (? Vue @ identité @ test @@ YAXXZ) référencé dans la fonction void __cdecl test::identity::identity(void) (? Identité @ 0 test @ @YAXXZ)
1 identité.obj: erreur LNK2019: symbole externe non résolu void __cdecl test::identity::make(void) (? Make @ identité @ test @@ YAXXZ) référencé dans la fonction void __cdecl test::identity::identity(void) (? Identité @ 0 test @ @YAXXZ)
1 range.obj: erreur LNK2019: symbole externe non résolu void __cdecl test::range::is(void) (? Is @ range @ test @@ YAXXZ) référencé dans la fonction void __cdecl test::range::range(void) (? Range @ 0test @ @YAXXZ)

Les erreurs de l'éditeur de liens sont toujours difficiles à déboguer ... mais il y avait des références non résolues, et donc j'ai vérifié ... mais la source est bien formée ... et finalement ça m'a frappé:

Ma hiérarchie de dossiers ressemble à ceci:

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

ainsi que la hiérarchie dans la solution (je la configure toujours de manière à imiter la "vraie" structure de dossiers).

Et les sorties de diagnostic:

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

Avec un avertissement qui dit que le .obj a été transmis deux fois à l'éditeur de liens et celui-ci sera ignoré.

Ne cherchez plus: Visual a bien aplati ma hiérarchie de dossiers et n'est donc pas en mesure de compiler correctement la source.

Pour le moment, je pense simplement à renommer les fichiers, cela devrait couvrir le problème ...

... mais existe-t-il un moyen pour que Visual Studio NE PAS aplatir la hiérarchie des fichiers?

75
Matthieu M.

Je voulais juste croiser ce que je pense être la réponse, si vous ouvrez les propriétés pour l'ensemble du projet et modifiez la valeur sous C/C++ -> Output Files -> "Object File Name" comme suit:

$ (IntDir) /% (RelativeDir) /

Sous VS 2010, je pense que cela va lever l'ambiguïté de tous les fichiers objets (car je pense que Windows ne vous permettra en aucun cas d'avoir deux fichiers avec les mêmes noms dans le même répertoire). Veuillez également consulter les détails ici .

96
M. Tibbits

J'ai eu un problème similaire avec l'avertissement de l'éditeur de liens LNK4042: objet spécifié plus d'une fois; extras ignorés. Dans mon cas, Visual Studio essayait de compiler à la fois les fichiers d'en-tête et les fichiers source avec le même nom - MyClass.h et MyClass.cpp. C'est arrivé parce que j'ai renommé .cpp fichier vers .h et Visual Studio sont devenus confus. J'ai remarqué le problème en consultant les journaux du compilateur dans le répertoire Debug. Pour résoudre, supprimez simplement .h fichier du projet puis ajoutez-le à nouveau.

129
Andrey Levichev

Cliquez avec le bouton droit sur le fichier .cpp dans la fenêtre Explorateur de solutions, Propriétés, C/C++, Fichiers de sortie, paramètre Nom du fichier objet. La valeur par défaut est $(IntDir)\, c'est ce qui fait l'aplatissement. Tout le fichier .obj ira dans $ (IntDir), le répertoire "Debug" dans la configuration de débogage.

Vous pouvez modifier le paramètre, par exemple $(IntDir)\is2.obj. Ou sélectionnez tous les fichiers d'un groupe (utilisez Maj + Clic) et changez le paramètre en, par exemple, $(IntDir)\identity\

Ou vous pouvez modifier le nom de fichier .cpp afin que les fichiers .obj ne se remplacent pas. Avoir des fichiers portant exactement le même nom dans deux répertoires est un peu étrange.

Ou vous pouvez créer plusieurs projets, en créant, par exemple, des projets .lib pour les fichiers d'identité et de plage. Couramment fait dans les projets makefile par exemple. Cela rend cependant la gestion des paramètres de compilation et de liaison plus compliquée, sauf si vous utilisez des feuilles de propriétés de projet.

8
Hans Passant

Cliquez avec le bouton droit sur le fichier d'en-tête -> Propriété -> ItemType (sélectionnez En-tête C/C++). Faites de même avec le fichier Cpp mais sélectionnez C/C++ COmpiler (ça marche pour moi)

5
Phạm Mạnh

J'utilise $ (IntDir) \% (Directory)\sous C/C++ -> Fichiers de sortie -> "Nom du fichier objet".

4
Csimbi

J'ai eu ce problème avec stdafx.cpp. D'une manière ou d'une autre, stdafx.cpp a été dupliqué, il y a donc eu un deuxième StdAfx.cpp (attention aux différents cas).

Après avoir supprimé le StdAfx.cpp, tout a bien fonctionné!

Utilisation de VS 2010.

3
Knasterbax

Vous pouvez également supprimer et créer un nouveau fichier, vous pouvez modifier les paramètres de compilation/inclusion.

Allez dans votre fichier project.vcxproj, ouvrez-le avec un éditeur, trouvez le HTML comme la ligne <ItemGroup>.

Cela devrait ressembler à ceci:

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

et

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

En supposant que vos fichiers d'implémentation sont .cpp et vos déclarations sont .hpp. Assurez-vous que tous vos fichiers d'implémentation sont répertoriés entre la première section si vous en avez plus d'un et de même pour la deuxième section pour les fichiers de déclaration multiples.

3
user1222064

J'avais l'habitude d'avoir dans le même projet . C et . Cpp fichiers avec les mêmes noms de fichiers. Les fichiers étaient dans des dossiers partout et les solutions fournies par d'autres ont créé un gâchis et un enfer de dossiers (dans mon cas). Même les versions Release écraseraient Debug les versions!

Une bonne solution (pas parfaite) serait d'utiliser $ (ParentName), mais pour une raison inconnue, il a été supprimé des versions ultérieures de Visual Studio (2015+).

Ce que j'utilise avec succès maintenant est: $ (IntDir)% (Filename)% (Extension) .obj

qui sépare au moins . c fichiers d'objets construits de . cpp.

2
Bill Kotsias