Domanda

Ho una grande soluzione con molti progetti, usando VS2008 SP1, e almeno una volta al giorno ho riscontrato l'errore LNK2022. Se eseguo una ricostruzione completa della soluzione, la soluzione va bene, ma non è divertente.

Succede quando una DLL dipendente viene cambiata 'in modo insignificante' (cioè senza cambiare metodi o classi) e il progetto di riferimento viene successivamente creato. Non riesce quando si uniscono i metadati, qualunque cosa significhi.

La prima cosa da notare è che la DLL condivisa fa riferimento a #using da più file .CPP.
La seconda cosa è che se elimino AssemblyInfo.cpp dalla DLL condivisa il problema scompare (ma sono non sei sicuro che si tratti di una soluzione ragionevole? ).

L'ho ridotto il più possibile nella seguente solution contenente 2 progetti CLR Class Library (il progetto xxx dipende da Condiviso ):
 alt text

Ecco i contenuti di ciascun file:

Shared.cpp:

public ref class Shared
{
};

inc.h:

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

xxx.cpp e xxx2.cpp:

#include "inc.h"

Per riprodurre, ricostruire prima la soluzione. Costruirà OK.
Ora salva Shared.cpp e crea la soluzione, funzionerà bene e mostrerà:

...
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 ==========

Ora salva xxx.cpp e crea la soluzione, fallisce con il seguente messaggio:

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 ==========

Modifica :
Le differenze tra IL per xxx.obj e xxx2.obj sono le seguenti:

(per xxx.obj)
// AssemblyRef # 2 (23000002)
// ------------------------------------------------ -------
// Token: 0x23000002
// Chiave pubblica o token:
// Nome:
condiviso // Versione: 1.0.3412.16 606
// Versione principale: 0x00000001
// Versione secondaria: 0x00000000
// Numero di build: 0x00000d54
// Numero di revisione: 0x000040 de
// Impostazioni locali:
// HashValue Blob: 1c bb 8f 13 7e ba 0a c7 26 c6 fc cb f9 ed 71 bf 5d ab b0 c0
// Flags: [none] (00000000)

(per xxx2.obj)
// AssemblyRef # 2 (23000002)
// ------------------------------------------------ -------
// Token: 0x23000002
// Chiave pubblica o token:
// Nome:
condiviso // Versione: 1.0.3412.16 585
// Versione principale: 0x00000001
// Versione secondaria: 0x00000000
// Numero di build: 0x00000d54
// Numero di revisione: 0x000040 c9
// Impostazioni locali:
// HashValue Blob: 64 af d3 12 9d e3 f6 2b 59 ac ff e5 3b 38 f8 fc 6d f4 d8 b5
// Flags: [none] (00000000)

Ciò implica per me che xxx2.obj sta ancora utilizzando la vecchia versione di Shared.dll e che è in conflitto con xxx.obj che utilizza il file Shared.dll aggiornato. Quindi, come posso risolvere il problema allora?

È stato utile?

Soluzione 2

Microsoft ha risposto al mio post su Connect, con una soluzione molto migliore:

  

Sembra che il problema sia causato da   la mancata corrispondenza nella versione tra   due .objs. Una soluzione alternativa è   sostituire

     

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

     

con

     

[assembly: AssemblyVersionAttribute (" 1.0.0.1 ")];

     

in AssemblyInfo.cpp. Questo assicurerà   che la versione non cambia   tra build incrementali.

Questo funziona per me e ovviamente è preferibile disabilitare la funzione.
Comunque la risposta accettata è stata scelta e non può essere cambiata ora :(

Altri suggerimenti

Questo problema è causato dalla nuova funzionalità Managed Incremental Build in Visual Studio 2008. Come notato, i metadati sono cambiati, ma non in modo che la funzione di build incrementale gestita consideri significativa. Tuttavia, se imponi una ricompilazione di uno dei file cpp, prende i nuovi metadati, li incorpora nell'obj e quindi il linker vede un conflitto.

Esistono due modi per risolvere questo problema. Un modo semplice che sembra funzionare, dalla la risposta di demoncodemonkey in basso deve specificare un numero di versione esplicito nei metadati dell'assembly di riferimento per indicare al compilatore che l'assembly di riferimento si trova effettivamente nella stessa versione:

  

Sostituire

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

con

[assembly:AssemblyVersionAttribute("1.0.0.1")];
     

in AssemblyInfo.cpp. Questo assicurerà che la versione non lo faccia   cambia tra build incrementali.

Il modo alternativo per evitare questo problema è disabilitare la funzione. Potremmo ricompilare inutilmente alcuni file cpp, ma è meglio che il linker fallisca.

Nelle proprietà del progetto, in Proprietà di configurazione > Generale, imposta " Abilita gestione incrementale gestita " al n.

Prova questo in xxx.cpp e xxx2.cpp:

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

#pragma una volta non è sufficiente per proteggere l'intestazione in questo caso.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top