"LNK2022: l'opération des métadonnées a échoué" me rendant fou
j'ai une grande solution avec beaucoup de projets, en utilisant VS2008 SP1, et au moins une fois par jour je rencontre L'erreur LNK2022. Si je fais une reconstruction complète de la solution qu'elle construit très bien, mais ce n'est pas amusant.
cela se produit quand une DLL dépendante est changée 'insignificantly' (i.e. sans changer aucune méthode ou classe), et le projet de référencement est construit plus tard. 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
de multiple .Fichiers CPP.
Deuxièmement, si je supprime AssemblyInfo.rpc à partir de la DLL partagée le problème disparaît (mais je suis je ne sais pas si c'est un bon fix? ).
Je l'ai réduit autant que possible dans la suivante solution contenant 2 projets de bibliothèque CLR classe (le xxx projet dépend de partagé ):
texte alternatif http://i42.tinypic.com/jg2vds.png
Voici le contenu de chaque fichier:
partagé.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, d'abord reconstruire la solution. Il s'appuiera sur OK.
Maintenant, sauvegardez partagé.cpp et construire la solution, il construira amende et montrer:
...
2>------ Build started: Project: xxx, Configuration: Debug Win32 ------
2>Inspecting 'd:xxxxxxDebugShared.dll' changes ...
2>No significant changes found in 'd:xxxxxxDebugShared.dll'.
2>xxx - 0 error(s), 0 warning(s)
========== Build: 2 succeeded, 0 failed, 0 up-to-date, 0 skipped ==========
sauvez maintenant xxx.cpp et construire la solution, il échoue avec le message suivant:
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 les IL pour xxx.obj et xxx2.obj sont comme suit:
(pour xxx.obj)
// AssemblyRef #2 (23000002)
// -------------------------------------------------------
// Jeton: 0x23000002
// Clé publique ou jeton:
// Nom: Partagé
// Version: 1.0.3412.16 606
// Version majeure: 0 x 00000001
// Version mineure: 0 x 00000000
// Numéro de construction: 0x00000d54
// Numéro de révision: 0x000040 de
// Paramètres régionaux:
// HashValue Blob: 1C bb 8f 13 7e ba 0A C7 26 c6 fc cb F9 ed 71 bf 5d ab b0 c0
// Drapeaux: [aucun] (00000000)
(pour xxx2.obj)
// AssemblyRef #2 (23000002)
// -------------------------------------------------------
// Jeton: 0x23000002
// Clé publique ou jeton:
// Nom: Partagé
// Version: 1.0.3412.16 585
// Version majeure: 0 x 00000001
// Version Mineure: 0 x 00000000
// Numéro de construction: 0x00000d54
// Numéro de révision: 0x000040 C9 "1519700920
// Paramètres régionaux:
// HashValue Blob: 64 af d3 12 9d e3 f6 2b 59 ac ff E5 3b 38 f8 fc 6D f4 d8 b5
// Drapeaux: [aucun] (00000000)
Cela implique pour moi que xxx2.obj utilise toujours l'ancienne version de Partager.dll, et qui est en conflit avec xxx.obj qui utilise le Shared mis à jour.DLL. Alors, comment puis-je solution de contournement?
3 réponses
ce problème est causé par la nouvelle fonctionnalité de construction incrémentale gérée de Visual Studio 2008. Comme vous l'avez repéré, les métadonnées ont changé, mais pas d'une manière que l'gérés incrémentielle construire fonctionnalité estime beaucoup. Cependant, si vous forcez une recompilation d'un des fichiers cpp, il saisit les nouvelles métadonnées, les intègre dans l'obj, et alors le linker voit un conflit.
Il y a deux façons de résoudre ce problème. Une façon simple qui semble fonctionner, de la réponse de demoncodemonkey au-dessous de est de spécifier un numéro de version explicite dans les métadonnées d'assemblage référencées pour indiquer au compilateur que l'assemblage référencé est en fait dans la même version:
remplacer
[assembly:AssemblyVersionAttribute("1.0.*")];
avec
[assembly:AssemblyVersionAttribute("1.0.0.1")];
dans
AssemblyInfo.cpp.
Cela permettra d'assurer que la version n'est pas changement entre les constructions progressives.
le autre façon d'éviter ce problème est de désactiver la fonctionnalité. Nous pouvons recompiler certains fichiers cpp inutilement, mais c'est mieux que de voir le linker échouer.
dans les propriétés du projet, sous Propriétés de Configuration > Généralités, mettez "Enable Managed Incremental Build" à No.
Microsoft a répondu à mon post Connect, avec une bien meilleure solution:
Il semble que le problème est causé par l'incompatibilité de version entre le de deux .objs. Une meilleure solution est de remplacer
[assembly:AssemblyVersionAttribute ("1.0.* ")];
avec
[Assemblée: AssemblyVersionAttribute ("1.0.0.1")];
in AssemblyInfo.rpc. Cela permettra d'assurer que la version ne change pas entre des versions.
cela fonctionne pour moi et évidemment c'est 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 changée maintenant: (
essayez ceci en xxx.cpp et xxx2.cpp:
#ifndef _PROTECT_MY_HEADER
#define _PROTECT_MY_HEADER
#include "inc.h"
#endif
#pragma once
n'est pas suffisant pour protéger l'en-tête dans ce cas.