10

I'm porting a solution from MSVS2005 to MSVS2012. The projects are in C++ .NET but use homemade native C++ libraires too. We had no problem building the projects with 2005 but now, I'm unable to build a project using 2012. I get the following error message:

MyFile.obj : error LNK2022: metadata operation failed (801311E4) : Duplicate managed types have different visibilities.

What does this mean? What info do you need to help me?

Thanks for your help?

pnuts
  • 58,317
  • 11
  • 87
  • 139
dom_beau
  • 2,437
  • 3
  • 30
  • 59
  • You can get duplicate types from #including a .h file with a ref class declaration in multiple .cpp files. The linker falls over when they don't exactly match. Like public in one but internal in another. – Hans Passant Sep 28 '12 at 18:27
  • Excuse me Hans, I don't understand perfectly. How a header included in many source files could declare the ref class in a different way since it is the **same** code??? – dom_beau Sep 28 '12 at 18:37
  • I don't know, I can't see your code from here. Macros are always a good way to cause random lossage. – Hans Passant Sep 28 '12 at 18:57
  • It is suggested to use _ildasm_ to help solving the problem. But what file will I load if no .dll is generated (link error)? I missed something? – dom_beau Sep 28 '12 at 19:27
  • Do you have something small that you duplicated the name of accidentally? Maybe a small enum that you used the same name in 2 different .cpp files? It doesn't have to be from a .h file. (I'm assuming you didn't do anything silly like `#define internal public` that would affect how a .h file is parsed.) – David Yaw Sep 28 '12 at 21:26
  • I don't know David, I'll have a look at this. But my point is that it compiled fine with MSV 2005... ??? I repeat my former question: how to use __ildasm__ in this case? – dom_beau Oct 01 '12 at 11:48

5 Answers5

8

I found the bug. It is a mix of everything that has been suggested here.

Somewhere in the project, a native C++ header file is included. A class in this file is made public with:

#include "File_Where_ClassName_Is_Defined.h"
#pragma make_public( ClassName )

But in my own code, I include a second header that itself includes the header where the made public class is defined. So, at this point, the class is "made public" in one file and "not made public" in another file in the same project. The "duplicate with different visibilities" comes from there.

The only point that sent me on the wrong path was the error message: "Duplicate managed types have different visibilities". But here, it is an unmanaged type.

So, if you encounter this error someday, look for a #pragma make_public(...) in the project then look for a duplicated inclusion in your problematic file.

dom_beau
  • 2,437
  • 3
  • 30
  • 59
  • Amazing!! I first read this thinking it was a long-shot, but I had exactly this problem. I was using `make_public` to turn an unmanaged class into an inaccessible (to C# code) managed class. Moving the pragma into the main include file solved it for me. Thanks for tripping on this one ahead of me!!! –  Jul 01 '14 at 21:03
4

I had the same problem, and indeed had the same condition described in dom_beau's answer, so I'm pretty sure I had the same underlying cause as well. However, to be able to resolve the error, I had to find the actual offending classes (there were a few, and the error messages do little to help you find them!).

So I wrote the following LINQ query which finds all classes defined in multiple *.obj files with conflicting visibilities. It may be useful to someone, so I'm posting it here.

// Analyze text files produced by ildasm when given *.obj files.
// Use "for %1 in (*.obj) do ildasm /text %1 > %1-ildasm.txt" to produce the files.

from file in Directory.GetFiles(@"your project's intermediate folder")
where file.EndsWith("-ildasm.txt")
let lines = File.ReadAllLines(file)
from i in Enumerable.Range(0, lines.Count() - 1)
where lines[i].Contains("TypDefName:")
let type = lines[i].Substring(16,lines[i].IndexOf(" (")-17)
let flags = lines[i+1]
group new {file, flags} by type into g
where g.Select(t=>t.flags).Distinct().Count() > 1
select g
Yodan Tauber
  • 3,907
  • 2
  • 27
  • 48
  • +1: Looked like a lot of work for someone not used to ildasm and LINQ, but it works great, I ran into this same scenario and the query pointed to the one offending class. I added the missing make_public pragma and built successfully. – dario_ramos Sep 10 '13 at 14:46
  • That solution worked perfectly for me. For the LINQ query I used LINQPad. – Radoslav Hristov Mar 27 '14 at 09:16
  • Really wish I'd found this post a couple of months ago – Joe Jan 28 '20 at 20:03
3

Microsoft fixed this issue in hotfix: KB2848798.

It helped me to migrate VS2010 solution to VS2012.

You can download it here

Relevant detail from above hotfix link: CLR issue 1

Symptoms

After you upgrade from Microsoft Visual Studio 2010 to Visual Studio 2012, some C++/CLI projects cannot build, and they report linker errors that resemble the following:

MSVCMRTD.lib(mstart.obj) : error LNK2022: metadata operation failed (801311E4)

Volmart
  • 121
  • 4
1

Had the same issue upgrading from VS2008 to VS2012. An alternative solution to the hotfix for me was to move the

#pragma make_public( ClassName )

statement from the .cpp file where it was up to now to stdafx.h.

ggo
  • 471
  • 7
  • 17
1

I had the same problem trying to compile a VC++2013 project on a Win2008R2 machine (which compiled absolutely fine on Win8.1). Just removing any duplicate #include did not solve the problem for me.

However, I then enabled precompiled headers and moved all make_public() statements of that project to stdafx.h, and that finally did it!

mthierba
  • 5,587
  • 1
  • 27
  • 29