C++/CLI and CMake

2020-02-11 00:56发布

问题:

I am trying to set up a C++/CLI project using cmake. I have had success doing this with visual studio 2010, but I am now working with a legacy solution that requires visual studio 2008. In visual studio 2010, it is enough to set up my cmake like this:

set_target_properties(${PROJECT_NAME} PROPERTIES VS_DOTNET_REFERENCES "${CMAKE_CURRENT_SOURCE_DIR}/../OrionMaster/3rdParty/GMap.NET.Core.dll;System;System.Core;System.Data;System.Drawing;System.Xml;WindowsBase")
set_target_properties(${PROJECT_NAME} PROPERTIES COMPILE_FLAGS "/clr /EHa")
set_target_properties(${PROJECT_NAME} PROPERTIES DEBUG_POSTFIX "d")

if(CMAKE_CXX_FLAGS_DEBUG MATCHES "/RTC1")
   string(REPLACE "/RTC1" " " CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}")
endif()

if(CMAKE_CXX_FLAGS MATCHES "/EHsc")
   string(REPLACE "/EHsc" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
endif()

When I then examine the project under visual studio 2010, I can see all the references and "Common Language Runtime Support" is turned on. When I try it in visual studio 2008, I don't see any references, and the project is set to "No Common Language Runtime Support" If i then look at the compiler options, I can see /clr is being passed to the compiler. However I still get a lot of compiler errors, probably because it is lacking references. Does anyone know a way to set this up properly?

回答1:

The only "real" source code reference to the VS_DOTNET_REFERENCES property is in the CMake source file Source/cmVisualStudio10TargetGenerator.cxx.

What this means in practice: VS_DOTNET_REFERENCES is only implemented for the CMake generator for Visual Studio 2010 and any of the generators that inherit from it. (Which now exist in the latest CMake version for VS 2012 and 2013...)

Modifying the CMake source code to support this property for earlier versions of Visual Studio is probably possible, but it is work yet to be done at this point.



回答2:

As @DLRdave points out, CMake only does this for Visual Studio 2010 generator.

Try this workaround instead of VS_DOTNET_REFERENCES for other generators:

# Note that /FU and ${asmPath} must not be separated by a space, else CMake
# will remove duplicate "/FU" options.
target_compile_options(target PRIVATE "/FU${asmPath}")

For system assemblies like System.dll, PresentationCore.dll, etc. you should provide a full absolute path to the compiler via asmPath. You need to use the reference assemblies and not the assemblies not installed on your computer. As an example, for a target framework of 3.5 in Visual Studio 2008, you'd need to search for the referenced file in these directories, in this order:

C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\v3.5
C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\v3.0
C:\Windows\Microsoft.NET\Framework\v2.0.50727

You'll note that if you use MSBuild to build a standard C# or C++/CLI project, you'll see that it also passes absolute paths to files in the above locations (try examining the build log). You do NOT want to use non-reference assemblies outside of the above locations except for the legacy v2.0 location shown above.

For more on reference assemblies: http://blogs.msdn.com/b/msbuild/archive/2007/04/12/new-reference-assemblies-location.aspx

Unfortunately, to really learn the rules for resolving these locations, you have to grovel in the C:\Windows\Microsoft.NET\Framework\v3.5\Microsoft.Common.targets file. It isn't exactly publicly documented. Also note that these search/resolving rules are NOT the same as those documented for csc.exe /reference or cl.exe /FU flags. Those rules look like they would tend to use runtime assemblies, not reference assemblies - which would be incorrect.