„LNK2022: Metadatenoperation fehlgeschlagen“ mich verrückt
-
03-07-2019 - |
Frage
Ich habe eine große Lösung mit vielen Projekten, VS2008 SP1 verwenden und mindestens einmal täglich begegne ich den LNK2022 Fehler. Wenn ich eine komplette Kompilierung der Lösung baut es in Ordnung, aber das ist kein Spaß.
Es passiert, wenn eine abhängige DLL geändert wird ‚unwesentlich‘ (das heißt, ohne irgendwelche Methoden oder Klassen zu ändern), und die Referenzierung Projekt wird später gebaut. Es schlägt fehl, wenn die Metadaten Zusammenführung -. Was immer das bedeutet
Die erste, was zu beachten ist, dass die gemeinsame DLL mit #using
von mehreren CPP-Dateien verwiesen wird.
Die zweite Sache ist, dass, wenn ich die AssemblyInfo.cpp aus der gemeinsam genutzten DLL lösche dann das Problem geht weg (aber ich bin nicht sicher? ).
Ich habe es verengt, so weit wie möglich nach unten in den folgenden Lösung , die 2 CLR-Klassenbibliothek Projekte (die xxx Projekt hängt von Shared ):
Hier ist der Inhalt jeder Datei:
Shared.cpp:
public ref class Shared
{
};
inc.h:
#pragma once
#using "Shared.dll"
public ref class Common
{
private:
Shared^ m_fred;
};
xxx.cpp und xxx2.cpp:
#include "inc.h"
zu reproduzieren, wieder aufzubauen zuerst die Lösung. Er baut auf OK.
speichern Jetzt Shared.cpp und bauen die Lösung, wird es bauen fein und zeigen:
...
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 ==========
Jetzt speichern xxx.cpp und die Lösung bauen, es schlägt mit der folgenden Meldung an:
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 ==========
Bearbeiten :
Die Unterschiede zwischen dem IL für xxx.obj und xxx2.obj sind wie folgt:
(für xxx.obj)
// AssemblyRef # 2 (23000002)
// ------------------------------------------------ -------
// Token: 0x23000002
// Public Key oder Token:
// Name: Gemeinsame
// Version: 1.0.3412.16 606
// Hauptversion: 0x00000001
// Nebenversion: 0x00000000
// Buildnummer: 0x00000d54
// Revisionsnummer: 0x000040 de
// Locale:
// HashValue Blob: 1c bb 8f 13 7e ba 0A c7 26 c6 fc cb f9 ed 71 bf 5d ab b0 c0
// Flags: [keine] (00000000)
(für xxx2.obj)
// AssemblyRef # 2 (23000002)
// ------------------------------------------------ -------
// Token: 0x23000002
// Public Key oder Token:
// Name: Gemeinsame
// Version: 1.0.3412.16 585
// Hauptversion: 0x00000001
// Nebenversion: 0x00000000
// Buildnummer: 0x00000d54
// Revisionsnummer: 0x000040 c9
// Locale:
// HashValue Blob: 64 af d3 12 9d e3 f6 2b 59 ac ff e5 3b 38 f8 fc 6d f4 d8 b5
// Flags: [keine] (00000000)
Das bedeutet für mich, dass xxx2.obj noch die alte Version von Shared.dll verwendet wird, und das mit xxx.obj in Konflikt, die die aktualisierte Shared.dll verwendet. So wie kann ich umgehen, dass dann?
Lösung 2
Microsoft antwortete auf meine Connect Post, mit einer viel besseren Abhilfe:
Es sieht aus wie das Problem verursacht wird, die Diskrepanz in der Version zwischen dem zwei .objs. Eine bessere Lösung wäre es, ersetzen
[assembly: Assembly ( "1,0 *")];
mit
[assembly: Assembly ( "1.0.0.1")];
in AssemblyInfo.cpp. Dadurch wird sichergestellt, dass die Version nicht ändert zwischen inkrementellen baut.
Das funktioniert für mich und offensichtlich ist dies vorzuziehen, um die Funktion zu deaktivieren.
Wie auch immer die Antwort akzeptiert wurde gewählt und kann jetzt nicht geändert werden: (
Andere Tipps
Dieses Problem wird durch die neue Managed Incremental Build-Funktion in Visual Studio verursacht 2008. Sie entdeckt, die Metadaten nicht geändert haben, aber nicht in einer Art und Weise, dass das verwaltete inkrementelle Merkmal signifcant hält. wenn Sie eine erneute Kompilierung eines der CPP-Dateien jedoch zwingen, es packt die neuen Metadaten, bettet sie in der OBJ, und dann sieht der Linker einen Konflikt.
Es gibt zwei Möglichkeiten, dieses Problem zu lösen. Eine einfache Möglichkeit, die von demoncodemonkey Antwort unter ist eine explizite Versionsnummer in der referenzierten Assembly Metadaten geben Sie den Compiler anzuweisen, dass die referenzierte Assembly in der Tat in der gleichen Version ist:
Ersetzen
[assembly:AssemblyVersionAttribute("1.0.*")];
mit
[assembly:AssemblyVersionAttribute("1.0.0.1")];
in
AssemblyInfo.cpp.
Dadurch wird sichergestellt, dass die Version nicht Wechsel zwischen inkrementellen baut.
Die alternative Möglichkeit, dieses Problem zu vermeiden, besteht darin, die Funktion zu deaktivieren. Wir können einige cpp Dateien unnötig neu kompilieren, aber es ist besser, als wenn der Linker versagen.
In den Projekteigenschaften unter Konfigurationseigenschaften> Allgemein eingestellt "Enable Managed Incremental Build" auf Nein.
Versuchen Sie, diese in xxx.cpp und xxx2.cpp:
#ifndef _PROTECT_MY_HEADER
#define _PROTECT_MY_HEADER
#include "inc.h"
#endif
#pragma once
ist nicht genug, um den Header in diesem Fall zu schützen.