I have a big solution with lots of projects, using VS2008 SP1, and at least once a day I encounter the LNK2022 error. If I do a full rebuild of the solution it builds fine, but this is not fun.
It happens when a dependent DLL is changed 'insignificantly' (i.e. without changing any methods or classes), and the referencing project is later built. It fails when merging the metadata - whatever that means.
First thing to note is that the shared DLL is referenced with #using
from multiple .CPP files.
Second thing is that if I delete the AssemblyInfo.cpp from the shared DLL then the problem goes away (but I'm not sure if this is a sensible fix?).
I've narrowed it down as far as possible into the following solution containing 2 CLR Class Library projects (the xxx project depends on Shared):
Here are the contents of each file:
Shared.cpp:
public ref class Shared
{
};
inc.h:
#pragma once
#using "Shared.dll"
public ref class Common
{
private:
Shared^ m_fred;
};
xxx.cpp and xxx2.cpp:
#include "inc.h"
To reproduce, first rebuild the solution. It will build OK.
Now save Shared.cpp and build the solution, it will build fine and show:
...
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 ==========
Now save xxx.cpp and build the solution, it fails with the following message:
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:
The differences between the IL for xxx.obj and xxx2.obj are as follows:
(for xxx.obj)
// AssemblyRef #2 (23000002)
// -------------------------------------------------------
// Token: 0x23000002
// Public Key or Token:
// Name: Shared
// Version: 1.0.3412.16606
// Major Version: 0x00000001
// Minor Version: 0x00000000
// Build Number: 0x00000d54
// Revision Number: 0x000040de
// Locale:
// HashValue Blob: 1c bb 8f 13 7e ba 0a c7 26 c6 fc cb f9 ed 71 bf 5d ab b0 c0
// Flags: [none] (00000000)
(for xxx2.obj)
// AssemblyRef #2 (23000002)
// -------------------------------------------------------
// Token: 0x23000002
// Public Key or Token:
// Name: Shared
// Version: 1.0.3412.16585
// Major Version: 0x00000001
// Minor Version: 0x00000000
// Build Number: 0x00000d54
// Revision Number: 0x000040c9
// Locale:
// HashValue Blob: 64 af d3 12 9d e3 f6 2b 59 ac ff e5 3b 38 f8 fc 6d f4 d8 b5
// Flags: [none] (00000000)
This implies to me that xxx2.obj is still using the old version of Shared.dll, and that is conflicting with xxx.obj which is using the updated Shared.dll. So how can I workaround that then?