"LNK2022: сбой операции с метаданными" сводит меня с ума

у меня есть большое решение с большим количеством проектов, используя VS2008 SP1, и по крайней мере один раз в день я сталкиваюсь с ошибкой LNK2022. Если я сделаю полную перестройку решения, он построит отлично, но это не весело.

это происходит, когда зависимая DLL изменяется "незначительно" (т. е. без изменения каких-либо методов или классов), а ссылочный проект позже строится. Он терпит неудачу при объединении метаданных-что бы это ни значило.

Первое, что нужно отметить, это то, что общая DLL ссылка #using из нескольких .CPP файлы.
Во-вторых, если я удалю AssemblyInfo.cpp из общей DLL, тогда проблема уходит (но я не уверен, что это разумное решение?).

я сузил его, насколько это возможно, до следующего решение содержащий 2 проекта библиотеки классов CLR ( xxx зависит от Shared):
alt-текст 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:xxxxxxDebugShared.dll' changes ...
2>No significant changes found in 'd:xxxxxxDebugShared.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 следующие:

(по ХХХ.параметр obj)
// AssemblyRef #2 (23000002)
// -------------------------------------------------------
// Знак: 0x23000002
// Открытый ключ или токен:
// Имя: Shared
// Версия: 1.0.3412.16606
// Основной Версия: слово 0x00000001
// Второстепенная версия: от 0x00000000
// Номер сборки: 0x00000d54
// Номер редакции: 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
// Флаги: [нет] (00000000)

(для xxx2.параметр obj)
// AssemblyRef #2 (23000002)
// -------------------------------------------------------
// Знак: 0x23000002
// Открытый ключ или токен:
// Имя: Shared
// Версия: 1.0.3412.16585
// Основная версия: 0x00000001
// Второстепенная версия: от 0x00000000
// Номер сборки: 0x00000d54
// Номер редакции: 0x000040c9
// Locale:
// Hashvalue Blob:64 af d3 12 9d e3 f6 2b 59 ac ff e5 3b 38 F8 fc 6d f4 d8 В5
// Флаги: [нет] (00000000)

это означает для меня, что xxx2.obj по-прежнему использует старую версию Shared.dll, и это противоречит xxx.obj, который использует обновленный общий ресурс.файл DLL. Так как я могу обойти это?

3 ответов


эта проблема вызвана новой функцией управляемого инкрементного построения в Visual Studio 2008. Как вы заметили, метаданные действительно изменились, но не так, как функция управляемой инкрементной сборки считает значимым. Однако, если вы принудительно перекомпилируете один из файлов cpp, он захватывает новые метаданные, внедряет их в obj, а затем компоновщик видит конфликт.

есть два способа решить эту проблему. Простой способ, который, кажется, работает, от demoncodemonkey по ответ ниже - указать явный номер версии в метаданных ссылочной сборки, чтобы указать компилятору, что ссылочная сборка фактически находится в той же версии:

заменить

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

С

[assembly:AssemblyVersionAttribute("1.0.0.1")];

на AssemblyInfo.cpp. Это гарантирует, что версия не изменение между инкрементными построениями.

альтернативный способ избежать этой проблемы-отключить эту функцию. Мы можем перекомпилировать некоторые файлы cpp излишне, но это лучше, чем сбой компоновщика.

в свойствах проекта в разделе свойства конфигурации > общие задайте для параметра" включить управляемую инкрементную сборку " значение Нет.


Microsoft ответила на мой пост Connect, с гораздо лучшим обходным путем:

похоже, что проблема вызвана несоответствие в версии между два.objs. Лучшее решение - заменить

[сборка: AssemblyVersionAttribute ("1.0.*")];

с

[сборка: AssemblyVersionAttribute ("1.0.0.1")];

в AssemblyInfo.СРР. Это обеспечит что версия не меняется между инкрементное построение.

Это работает для меня, и, очевидно, это предпочтительнее, чем отключить функцию.
В любом случае принятый ответ был выбран и не может быть изменен сейчас: (


попробуйте это в xxx.cpp и xxx2.cpp:

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

#pragma once недостаточно для защиты заголовка в этом случае.