Question

J'ai une grosse solution avec beaucoup de projets, avec VS2008 SP1, et au moins une fois par jour, je rencontre l'erreur LNK2022. Si je reconstruis complètement la solution, cela fonctionne bien, mais ce n’est pas amusant.

Cela se produit lorsqu'une DLL dépendante est modifiée de manière "insignifiante" (c'est-à-dire sans modification de méthodes ou de classes) et que le projet de référence est ultérieurement construit. Il échoue lors de la fusion des métadonnées, peu importe ce que cela signifie.

La première chose à noter est que la DLL partagée est référencée avec #using à partir de plusieurs fichiers .CPP.
Deuxièmement, si je supprime le fichier AssemblyInfo.cpp de la DLL partagée, le problème disparaît (mais je suis Vous ne savez pas s’il s’agit d’une solution judicieuse? ).

Je l'ai réduit dans la mesure du possible au solution contenant 2 projets de bibliothèque de classes CLR (le projet xxx dépend de Partagé ):

 alt text

Voici le contenu de chaque fichier:

Shared.cpp:

public ref class Shared
{
};

inc.h:

#pragma once
#using "Shared.dll"
public ref class Common
{
private:
    Shared^ m_fred;
};

xxx.cpp et xxx2.cpp:

#include "inc.h"

Pour reproduire, reconstruisez d’abord la solution. Ça va construire OK.
Maintenant, enregistrez Shared.cpp et construisez la solution, elle se formera correctement et affichera:

...
2>------ Build started: Project: xxx, Configuration: Debug Win32 ------
2>Inspecting 'd:\xxx\xxx\Debug\Shared.dll' changes ...
2>No significant changes found in 'd:\xxx\xxx\Debug\Shared.dll'.
2>xxx - 0 error(s), 0 warning(s)
========== Build: 2 succeeded, 0 failed, 0 up-to-date, 0 skipped ==========

Enregistrez maintenant xxx.cpp et générez la solution. Le message suivant échoue:

1>------ Build started: Project: xxx, Configuration: Debug Win32 ------
1>Compiling...
1>xxx.cpp
1>Linking...
1>xxx2.obj : error LNK2022: metadata operation failed (80131188) : Inconsistent field declarations in duplicated types (types: Common; fields: m_fred): (0x04000001).
1>LINK : fatal error LNK1255: link failed because of metadata errors
1>xxx - 2 error(s), 0 warning(s)
========== Build: 0 succeeded, 1 failed, 1 up-to-date, 0 skipped ==========

MODIFIER :
Les différences entre l'IL pour xxx.obj et xxx2.obj sont les suivantes:

(pour xxx.obj)
// AssemblyRef # 2 (23000002)
// ---------------------------------------------------- -------
// jeton: 0x23000002
// clé publique ou jeton:
// Nom: Partagé
// Version: 1.0.3412.16 606
// Version majeure: 0x00000001
// Version mineure: 0x00000000
// Numéro de construction: 0x00000d54
// Numéro de révision: 0x000040 de
// Locale:
// Blob HashValue: 1c bb 8f 13 7e ba 0a c7 26 c6 fc cb f9 éd 71 bf 5d ab b0 c0
// Indicateurs: [aucun] (00000000)

(pour xxx2.obj)
// AssemblyRef # 2 (23000002)
// ---------------------------------------------------- -------
// jeton: 0x23000002
// clé publique ou jeton:
// Nom: Partagé
// Version: 1.0.3412.16 585
// Version majeure: 0x00000001
// Version mineure: 0x00000000
// Numéro de construction: 0x00000d54
// Numéro de révision: 0x000040 c9
// Locale:
// Blob HashValue: 64 d3 12 9d e3 f6 2b 59 ac ff e5 3b 38 f8 fc 6d f4 d8 b5
// Indicateurs: [aucun] (00000000)

Cela signifie pour moi que xxx2.obj utilise toujours l'ancienne version de Shared.dll et entre en conflit avec xxx.obj, qui utilise le fichier Shared.dll mis à jour. Alors, comment puis-je contourner cela alors?

Était-ce utile?

La solution 2

Microsoft a répondu à mon message Connect avec une solution de contournement bien meilleure:

  

Il semble que le problème soit causé par   le décalage dans la version entre le   deux .objs. Une meilleure solution consiste à   remplacer

     

[assembly: AssemblyVersionAttribute ("1.0. *")];

     

avec

     

[assembly: AssemblyVersionAttribute ("1.0.0.1")];

     

dans AssemblyInfo.cpp. Cela garantira   que la version ne change pas   entre les constructions incrémentielles.

Cela fonctionne pour moi et c'est évidemment préférable à la désactivation de la fonctionnalité.
Quoi qu’il en soit, la réponse acceptée a été choisie et ne peut pas être modifiée maintenant: (

Autres conseils

Ce problème est dû à la nouvelle fonctionnalité de création incrémentielle gérée dans Visual Studio 2008. Comme vous l'avez constaté, les métadonnées ont été modifiées, mais pas de manière à ce que la fonctionnalité de génération incrémentielle gérée soit considérée comme significative. Cependant, si vous forcez la recompilation de l’un des fichiers cpp, elle saisit les nouvelles métadonnées, les incorpore dans l’obj, puis l’éditeur de liens voit un conflit.

Il existe deux manières de résoudre ce problème. Un moyen simple qui semble fonctionner, à partir de la réponse de demoncodemonkey ci-dessous indique un numéro de version explicite dans les métadonnées de l'assembly référencé pour indiquer au compilateur que l'assembly référencé est en fait à la même version:

  

Remplacer

[assembly:AssemblyVersionAttribute("1.0.*")];
     

avec

[assembly:AssemblyVersionAttribute("1.0.0.1")];
     

dans AssemblyInfo.cpp. Cela garantira que la version ne   changer entre les versions incrémentielles.

Une autre solution pour éviter ce problème consiste à désactiver la fonctionnalité. Nous pouvons recompiler inutilement certains fichiers cpp, mais cela vaut mieux que l'échec de l'éditeur de liens.

Dans les propriétés du projet, sous Propriétés de configuration > Général, définissez & Activer la création incrémentielle gérée " au n °

Essayez ceci dans xxx.cpp et xxx2.cpp:

#ifndef _PROTECT_MY_HEADER
#define _PROTECT_MY_HEADER
#include  "inc.h"
#endif

#pragma une fois ne suffit pas à protéger l'en-tête dans ce cas.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top