У меня есть большое решение с большим количеством проектов, используя VS2008 SP1, и по крайней мере один раз в день я сталкиваюсь с ошибкой LNK2022. Если я полностью перестрою решение, оно строит отлично, но это не весело.
Это происходит, когда зависимая DLL изменяется "незначительно" (т.е. без изменения каких-либо методов или классов), и последующий проект ссылки. Это не удается при слиянии метаданных - что бы это ни значило.
Прежде всего следует отметить, что общая DLL ссылается на #using
из нескольких файлов .CPP.
Во-вторых, если я удалю AssemblyInfo.cpp из общей DLL, проблема исчезнет (но я не уверен, что это разумное решение?).
Я сузил его, насколько это возможно, в следующее решение, содержащее 2 проекта библиотеки классов CLR (xxx зависит от Общий):
alt text http://i42.tinypic.com/jg2vds.png
Вот содержимое каждого файла:
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 ==========
ИЗМЕНИТЬ:
Различия между IL для xxx.obj и xxx2.obj заключаются в следующем:
(для xxx.obj)
//AssemblyRef # 2 (23000002)
// ------------------------------------------------ -------
// Токен: 0x23000002
// Открытый ключ или токен:
// Имя: совместное использование
// Версия: 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
// Флаги: [none] (00000000)
(для xxx2.obj)
//AssemblyRef # 2 (23000002)
// ------------------------------------------------ -------
// Токен: 0x23000002
// Открытый ключ или токен:
// Имя: совместное использование
// Версия: 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
// Флаги: [none] (00000000)
Это означает, что xxx2.obj все еще использует старую версию Shared.dll, и это противоречит xxx.obj, который использует обновленную версию Shared.dll. Итак, как я могу это сделать?