У меня есть большое решение с большим количеством проектов, использующих VS2008 SP1, и, по крайней мере, один раз в день я сталкиваюсь с ошибкой LNK2022. Если я сделаю полную перестройку решения, оно будет хорошо, но это не весело.
Это происходит, когда зависимая DLL изменяется «незначительно» (т. Е. Без изменения каких-либо методов или классов), а ссылочный проект создается позже. Сбой при объединении метаданных - что бы это ни значило.
Первое, что нужно отметить, это то, что на общую DLL ссылается #using
из нескольких файлов .CPP.
Во-вторых, если я удаляю AssemblyInfo.cpp из общей библиотеки DLL, проблема устраняется (но я не уверен, является ли это разумным решением проблемы? ).
Я максимально сузил его до следующего решения , содержащего 2 проекта библиотеки классов CLR (проект xxx зависит от Shared ):
Вот содержимое каждого файла:
Shared.cpp:
public ref class Shared
{
};
inc.h:
#pragma once
#using "Shared.dll"
public ref class Common
{
private:
Shared^ m_fred;
};
xxx.cpp и xxx2.cpp:
#include "inc.h"
Чтобы воспроизвести, сначала перестройте решение. Будет нормально.
Теперь сохраните Shared.cpp и постройте решение, оно будет нормально работать и покажет:
...
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 ==========
Теперь сохраните xxx.cpp и постройте решение, оно завершится ошибкой со следующим сообщением:
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 ==========
EDIT
Различия между IL для xxx.obj и xxx2.obj заключаются в следующем:
(для xxx.obj)
// AssemblyRef # 2 (23000002)
// ------------------------------------------------ -------
// токен: 0x23000002
// Открытый ключ или токен:
// Имя: Shared
// Версия: 1.0.3412.16 606
// Основная версия: 0x00000001
// Малая версия: 0x00000000
// Номер сборки: 0x00000d54
// Номер редакции: 0x000040 de
// Язык:
// HashValue Blob: 1c bb 8f 13 7e ba 0a c7 26 c6 fc cb f9 ed 71 bf 5d ab b0 c0
// Флаги: [нет] (00000000)
(для xxx2.obj)
// AssemblyRef # 2 (23000002)
// ------------------------------------------------ -------
// токен: 0x23000002
// Открытый ключ или токен:
// Имя: Shared
// Версия: 1.0.3412.16 585
// Основная версия: 0x00000001
// Малая версия: 0x00000000
// Номер сборки: 0x00000d54
// Номер редакции: 0x000040 c9
// Язык:
// HashValue Blob: 64 af d3 12 9d e3 f6 2b 59 ac ff e5 3b 38 f8 fc 6d f4 d8 b5
// Флаги: [нет] (00000000)
Это означает, что xxx2.obj все еще использует старую версию Shared.dll, и это конфликтует с xxx.obj, использующим обновленный Shared.dll. Так как я могу обойти это тогда?