82 votes

Visual Studio 2010's étrange "avertissement LNK4042"

Je viens de me faire battre (assez durement) 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é plus d'une fois ; les extras sont ignorés
1 Debug\make.obj : avertissement LNK4042 : objet spécifié plus d'une fois ; les extras sont ignorés
1 Debug\view.obj : avertissement LNK4042 : objet spécifié plus d'une fois ; les extras sont ignorés
1 identity.obj : erreur LNK2019 : symbole externe non résolu void __cdecl test::identity::view(void) (?view@identity@test@@YAXXZ) référencé dans la fonction void __cdecl test::identity::identity(void) (?identity@0test@@YAXXZ)
1 identity.obj : erreur LNK2019 : symbole externe non résolu void __cdecl test::identity::make(void) (?make@identity@test@@YAXXZ) référencé dans la fonction void __cdecl test::identity::identity(void) (?identity@0test@@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 du linker sont toujours une douleur à déboguer... mais il y avait des références non résolues, alors j'ai vérifié... mais le source est bien formé... et enfin j'ai compris :

Ma hiérarchie de dossiers ressemble à ceci :

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

et c'est également la hiérarchie dans la Solution (je la configure toujours de manière à imiter la structure de dossiers "réelle").

Et les sorties de diagnostic :

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

Avec un avertissement indiquant que le .obj a été passé deux fois au linker et qu'un sera ignoré.

Ne cherchez pas plus loin : Visual a aplati proprement ma hiérarchie de dossiers, et donc est incapable de compiler proprement le source.

En ce moment, je pense simplement à renommer les fichiers, cela devrait résoudre le problème...

... mais y a-t-il un moyen d'empêcher Visual Studio de niveler la hiérarchie des fichiers ?

3 votes

Vient de recevoir exactement la même chose, vraiment ennuyeux que nous devions le "corriger" manuellement. Heureusement que tu as demandé avant moi. :)

0 votes

@GMan : je suis surpris que tu aies pu le trouver du tout :) As-tu cherché en utilisant Google ou le moteur de recherche SO ?

5 votes

J'ai abandonné la recherche sur SO il y a longtemps. :) Google.

149voto

Andrey Levichev Points 491

J'ai rencontré un problème similaire avec un avertissement du lien LNK4042 : objet spécifié plusieurs fois ; extras ignorés. Dans mon cas, Visual Studio essayait de compiler à la fois des fichiers d'en-tête et des fichiers source portant le même nom - MyClass.h et MyClass.cpp. Cela s'est produit parce que j'ai renommé le fichier .cpp en .h et que Visual Studio s'est trouvé perdu. J'ai remarqué le problème en examinant les journaux du compilateur dans le répertoire Debug. Pour résoudre le problème, il suffit de supprimer le fichier .h du projet, puis de le réajouter.

2 votes

Merci d'avoir posté ceci! La vieille routine de supprimer le fichier et de le remettre a fonctionné pour moi aussi. J'étais vraiment sur le point de me cogner la tête contre le mur à cause de cela.

3 votes

Merci @AndreyLevichev -- cette réponse a également résolu le problème pour moi. Il est assez clair dans le fichier du projet qu'un fichier .h est dans le groupe "ClCompile" au lieu du groupe "ClInclude"

35 votes

Ou vous pouvez cliquer avec le bouton droit sur le fichier foo.h dans votre explorateur de solutions et définir "Type d'élément" sur "en-tête C/C++" plutôt que "compilateur C/C++".

99voto

M. Tibbits Points 3867

Je voulais juste partager ce que je crois être la réponse, si vous ouvrez les propriétés de l'ensemble du projet, et que vous modifiez la valeur sous C/C++ -> Fichiers de sortie -> "Nom du fichier objet" pour être la suivante :

$(IntDir)/%(RelativeDir)/

Sous VS 2010, je crois que cela permettra de dissocier tous les fichiers objets (car je crois que Windows ne permettra pas, dans des circonstances folles, d'avoir deux fichiers portant le même nom dans le même répertoire). Veuillez également consulter les détails ici.

0 votes

Ah! Maintenant, c'est quelque chose que je vais devoir essayer dès que je rentrerai à la maison :D

7 votes

Juste pour ajouter : il semble que %(RelativeDir) ne supprime pas les ../.. (ce n'est pas ce qui devrait être fait mais il ne semble pas y avoir d'alternative non plus) dans votre chemin donc vous pourriez avoir à ajouter un répertoire "factice" pour que vos fichiers soient construits dans le "bon" répertoire. Par exemple, j'ai $(IntDir)/a/a/%(RelativeDir)/ juste pour qu'il puisse être construit dans $(IntDir) à cause de deux ../ dans le chemin de mon .cpp (Les chemins sont relatifs au $(ProjectDir), je pense). Notez également que %(RelativeDir) est avec un % et $(IntDir) est avec un $ (la réponse est correcte, mais en lisant rapidement, ce fait pourrait être manqué).

2 votes

Hm... Je me demande pourquoi cela n'est pas défini par défaut. Eh bien, je suppose que je vais juste ajouter ceci à chaque projet (presque rien ne compile sans cette correction)

8voto

Hans Passant Points 475940

Faites un clic droit sur le fichier .cpp dans la fenêtre de l'Explorateur de solutions, Propriétés, C/C++, Fichiers de sortie, Paramètre de nom de fichier objet. La valeur par défaut est $(IntDir)\, c'est ce qui provoque l'aplatissement. Tous les fichiers .obj iront dans $(IntDir), le répertoire "Débogage" dans la configuration de débogage.

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

Ou vous pouvez modifier le nom du fichier .cpp pour éviter que les fichiers .obj s'écrasent mutuellement. Avoir des fichiers avec le même nom exact 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 dans identity et range. Communément fait dans des projets makefile par exemple. Cela rend cependant la gestion des paramètres de compilation et de liaison un peu plus compliquée à moins d'utiliser des feuilles de propriétés de projet.

0 votes

Merci, j'ai déjà renommé les fichiers puisque c'était la manière la plus simple de procéder. N'y a-t-il aucun moyen de demander à Visual de préserver la hiérarchie que j'ai soigneusement construite dans le projet ? Je sais que d'avoir le même nom de fichier pour plusieurs fichiers est étrange, mais je préfère regrouper les choses par sous-répertoire plutôt que de préfixer mes fichiers... et c'est redondant à la fois de les mettre dans un sous-répertoire et de les préfixer par le nom du sous-répertoire !

0 votes

Vous pouvez modifier les paramètres pour plusieurs fichiers en même temps. Maintenez la touche CTRL enfoncée tout en cliquant pour les sélectionner. Utiliser `$(IntDir)\$(ParentName)` a posé problème la dernière fois que j'ai essayé cela.

0 votes

@Hans: je suppose que je vais continuer à utiliser des noms différents alors, je ne suis pas si content de la solution, mais comme c'est seulement pour la partie des tests unitaires je suppose que je vais m'en contenter.

4voto

user1222064 Points 21

Alternativement à la suppression et à la création d'un nouveau fichier, vous pouvez modifier les paramètres de compilation/inclusion.

Allez dans votre fichier project.vcxproj, ouvrez-le avec un éditeur, trouvez la ligne similaire à du html .

Il devrait ressembler à quelque chose comme :

et

`

En supposant que vos fichiers d'implémentation soient en .cpp et vos déclarations en .hpp. Assurez-vous que tous vos fichiers d'implémentation soient 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.

3voto

Knasterbax Points 1383

J'avais ce problème avec stdafx.cpp. D'une manière ou d'une autre, stdafx.cpp s'est dupliqué, donc il y avait un second StdAfx.cpp (faites attention à la différence de cas).

Après avoir supprimé le StdAfx.cpp, tout fonctionnait correctement !

Utilisation de VS 2010.

0 votes

A eu un problème similaire, mais au lieu que le fichier soit dupliqué, c'était le même fichier répertorié deux fois dans l'ItemGroup ClCompile.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X