Pergunta

Eu tenho uma solução grande com lotes de projetos, usando VS2008 SP1, e pelo menos uma vez por dia eu encontrar o erro LNK2022. Se eu reconstruir um completo da solução que constrói bem, mas isso não é divertido.

Isso acontece quando uma DLL dependente é alterado 'insignificante' (ou seja, sem alterar quaisquer métodos ou classes), eo projeto de referência é construído mais tarde. Ele falha ao mesclar os metadados -. O que isso significa

A primeira coisa a notar é que a DLL compartilhada é referenciado com #using de vários arquivos .CPP.
A segunda coisa é que, se eu apagar o AssemblyInfo.cpp do DLL compartilhada então o problema vai embora (mas eu sou não sei se isso é uma solução sensata? ).

Eu reduzi-lo o mais longe possível na href="http://www.2shared.com/file/5575794/7f03c4c4/xxx.html" rel="nofollow solução seguinte contendo 2 projetos de biblioteca de classes CLR (o xxx projeto depende de Shared ):
text alt

Eis o conteúdo de cada arquivo:

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"

Para reproduzir, primeiro recriar a solução. Ele vai construir OK.
Agora salve Shared.cpp e construir a solução, ele vai construir bem e 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 ==========

Agora salve xxx.cpp e construir a solução, ele falha com a seguinte mensagem:

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 :
As diferenças entre a IL para xxx.obj e xxx2.obj são como se segue:

(para xxx.obj)
// AssemblyRef # 2 (23000002)
// ------------------------------------------------ -------
// token: 0x23000002
// chave pública ou Token:
// Nome:
Shared // Versão: 1.0.3412.16 606
// Versão Major: 0x00000001
// versão menor: 0x00000000
// número de compilação: 0x00000d54
// Número de Revisão: 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: [nenhum] (00000000)

(para xxx2.obj)
// AssemblyRef # 2 (23000002)
// ------------------------------------------------ -------
// token: 0x23000002
// chave pública ou Token:
// Nome:
Shared // Versão: 1.0.3412.16 585
// Versão Major: 0x00000001
// versão menor: 0x00000000
// número de compilação: 0x00000d54
// Número de Revisão: 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: [nenhum] (00000000)

Isto implica para mim que xxx2.obj ainda está usando a versão antiga do Shared.dll, e que está em conflito com xxx.obj que está usando o Shared.dll atualizado. Então, como posso resolver isso então?

Foi útil?

Solução 2

Microsoft respondeu ao meu post Connect, com uma melhor solução muito:

Parece que o problema é causado por a incompatibilidade na versão entre o dois .objs. Uma solução melhor é substitua

[montagem: AssemblyVersionAttribute ( "* 1.0")];

com

[montagem: AssemblyVersionAttribute ( "1.0.0.1")];

em AssemblyInfo.cpp. Isso irá garantir que a versão não muda entre compilações incrementais.

Isso funciona para mim e, obviamente, isso é preferível a desativação do recurso.
De qualquer forma a resposta aceita foi escolhido e não pode ser mudado agora: (

Outras dicas

Esse problema é causado pela nova gestão recurso de compilação incremental no Visual Studio 2008. Como você viu, os metadados se alterou, mas não de uma forma que o recurso de compilação incremental conseguiu considera signifcant. No entanto, se você forçar uma recompilação de um dos arquivos do CPP, que agarra o novo metadados, incorpora-lo no obj, e em seguida, o vinculador vê um conflito.

Existem duas formas para resolver este problema. Uma maneira simples que parece trabalho, de resposta abaixo é especificar um número de versão explícita na referenciado assembly metadados para instruir o compilador que a referência de montagem é de fato na mesma versão:

Substitua

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

com

[assembly:AssemblyVersionAttribute("1.0.0.1")];

em AssemblyInfo.cpp. Isso irá garantir que a versão não mudança entre compilações incrementais.

A maneira alternativa para evitar este problema é desativar o recurso. Podemos recompilar alguns arquivos CPP desnecessariamente, mas é melhor do que ter o vinculador falhar.

Nas propriedades do projeto, em Configuração de Propriedades> Geral, defina "Ativar Managed compilação incremental" para Não.

Tente isto em xxx.cpp e xxx2.cpp:

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

#pragma once não é suficiente para proteger o cabeçalho neste caso.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top