Pregunta

Tengo una gran solución con muchos proyectos, utilizando VS2008 SP1, y al menos una vez al día encuentro el error LNK2022. Si realizo una reconstrucción completa de la solución, funciona bien, pero esto no es divertido.

Ocurre cuando un DLL dependiente se cambia 'de manera insignificante' (es decir, sin cambiar ningún método o clase), y el proyecto de referencia se construye más tarde. Falla al fusionar los metadatos, sea lo que sea lo que signifique.

Lo primero que debe tener en cuenta es que la DLL compartida está referenciada con #using de múltiples archivos .CPP.
Lo segundo es que si elimino AssemblyInfo.cpp de la DLL compartida, el problema desaparece (pero estoy ¿No estoy seguro de que sea una solución razonable? ).

Lo he reducido lo más posible en la siguiente solución que contiene 2 proyectos de biblioteca de clases CLR (el proyecto xxx depende de Compartido ):
 texto alt

Aquí están los contenidos de cada archivo:

Shared.cpp:

public ref class Shared
{
};

inc.h:

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

xxx.cpp y xxx2.cpp:

#include "inc.h"

Para reproducir, primero reconstruya la solución. Se construirá bien.
Ahora guarde Shared.cpp y compile la solución, se compilará bien y mostrará:

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

Ahora guarde xxx.cpp y cree la solución, falla con el siguiente mensaje:

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

EDITAR :
Las diferencias entre el IL para xxx.obj y xxx2.obj son las siguientes:

(para xxx.obj)
// AssemblyRef # 2 (23000002)
// ------------------------------------------------ -------
// Token: 0x23000002
// Clave pública o token:
// Nombre: Shared
// Versión: 1.0.3412.16 606
// Versión principal: 0x00000001
// Versión menor: 0x00000000
// Número de compilación: 0x00000d54
// Número de revisión: 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
// Banderas: [ninguna] (00000000)

(para xxx2.obj)
// AssemblyRef # 2 (23000002)
// ------------------------------------------------ -------
// Token: 0x23000002
// Clave pública o token:
// Nombre:
compartido // Versión: 1.0.3412.16 585
// Versión principal: 0x00000001
// Versión menor: 0x00000000
// Número de compilación: 0x00000d54
// Número de revisión: 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
// Banderas: [ninguna] (00000000)

Esto implica para mí que xxx2.obj todavía usa la versión anterior de Shared.dll y que está en conflicto con xxx.obj, que usa Shared.dll actualizado. Entonces, ¿cómo puedo solucionar eso entonces?

¿Fue útil?

Solución 2

Microsoft respondió a mi publicación de Connect, con una solución mucho mejor:

  

Parece que el problema es causado por   el desajuste en la versión entre el   dos .objs. Una mejor solución es   reemplazar

     

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

     

con

     

[ensamblado: AssemblyVersionAttribute (" 1.0.0.1 ")];

     

en AssemblyInfo.cpp. Esto asegurará   que la versión no cambia   entre compilaciones incrementales.

Esto funciona para mí y, obviamente, es preferible deshabilitar la función.
De todos modos, la respuesta aceptada ha sido elegida y no se puede cambiar ahora :(

Otros consejos

Este problema se debe a la nueva característica de Compilación incremental administrada en Visual Studio 2008. Según lo descubrió, los metadatos cambiaron, pero no de una manera que la característica de compilación incremental administrada considera significativa. Sin embargo, si forzas una recompilación de uno de los archivos cpp, toma los nuevos metadatos, los incrusta en el objeto, y luego el enlazador ve un conflicto.

Hay dos formas de resolver este problema. Una manera simple que parece funcionar, desde la respuesta de demoncodemonkey a continuación es especificar un número de versión explícito en los metadatos del ensamblado referenciado para indicarle al compilador que el ensamblado al que se hace referencia está de hecho en la misma versión:

  

Reemplazar

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

con

[assembly:AssemblyVersionAttribute("1.0.0.1")];
     

en AssemblyInfo.cpp. Esto asegurará que la versión no   cambiar entre compilaciones incrementales.

La forma alternativa de evitar este problema es deshabilitando la función. Podemos recompilar algunos archivos cpp innecesariamente, pero es mejor que hacer que falle el enlazador.

En las propiedades del proyecto, en Propiedades de configuración > General, establezca " Habilitar compilación incremental gestionada " a No.

Pruebe esto en xxx.cpp y xxx2.cpp:

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

#pragma once no es suficiente para proteger el encabezado en este caso.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top