4

Preamble: I am trying to integrate my C# csproj with the rest of our C++ and C++/CLI code-base cmake build. I have received advise against trying to do this, because CMake doesn't co-operate well with .NET in Visual Studio, but after implementing some customizations, I feel that I am very close.

Part of my customization is using the configure_file command to edit the csproj file at CMake time, to customize it depending on the type of build (e.g. x86, x64) that is happening.

The problem is that I use some ProjectReference tags to reference the C++/CLI projects:

<ProjectReference Include="..\..\WrapperProject\WrapperProject.vcproj">
  <Project>{7BD6E175-CDD1-4F8D-A3B2-0AC862E62C03}</Project>
  <Name>WrapperProject</Name>
</ProjectReference>

... and the GUIDs cannot remain static, since they change for the project whenever the CMake cache is rebuilt (correct me if I'm mistaken).

So what I would like to do is find our at CMake time what GUIDs are planned for these projects and to edit the vcproj file accordingly.

Google tells me that people are able to use 'set_property' to set the GUID, like so:

set_property(CACHE ${target_name}_GUID_CMAKE PROPERTY VALUE ${MY_GUID} )

... but I can't seem to find the getter equivalent. I've tried things like this:

get_property(WRAPPER_GUID CACHE INTERNAL PROPERTY WrapperTargetName_GUID_CMAKE)

... without luck. Your help is appreciated!

Kohanz
  • 1,510
  • 16
  • 35
  • 1
    Since it's possible to set fixed project GUID from CMake, you should be able to write fixed ProjectReference tags also, right? – ronkot Mar 15 '13 at 07:04

3 Answers3

4

After playing around with this more, I realized what Fraser pointed out - that this method wouldn't always work because I can't expect the GUIDs to be available on a fresh run of CMake. So I went the route that I had seen suggested on the CMake mailing list, which is to explicitly set the GUID values myself.

So in the CMakeLists.txt for each C++/CLI wrapper project, I have something like this:

# Set a global cache variable for this project GUID
# The TestAppNet csproj needs this GUID to properly reference this project
set_property(GLOBAL PROPERTY Wrapper_GUID "1897F4D1-E929-444E-9343-00F094113772") 
get_property(projectGUID GLOBAL PROPERTY Wrapper_GUID)
MESSAGE( STATUS "Setting project GUID to: ${projectGUID}")
set(Wrapper_GUID_CMAKE "${projectGUID}" CACHE INTERNAL "Project GUID")

And in the C# project CMakeLists.txt, I have this:

get_property(CMAKE_WRAPPER_GUID GLOBAL PROPERTY Wrapper_GUID)
MESSAGE( STATUS "Setting Wrapper GUID to: ${CMAKE_WRAPPER_GUID}" )

... and then the CMAKE_WRAPPER_GUID is used as a variable in the .csproj file that is populated during the configure_file command.

I'm not sure if this is efficient, but it seems to work!

Kohanz
  • 1,510
  • 16
  • 35
  • 1
    In case anyone wonders, this GUID cache entry is used in CMake source code in cmGlobalVisualStudio7Generator::GetGUID function. CMake Git commit c85367f408befa419185a4fec4816ea0ee3e1ee6 modifies the behavior so that CMake no longer creates a _GUID_CMAKE cache variable (in favor of a deterministic GUID). However it looks like it will still honor a GUID provided by the user in that variable. – James Johnston Aug 04 '15 at 13:53
2

Your syntax is slightly off. You probably meant:

get_property(WRAPPER_GUID CACHE WrapperTargetName_GUID_CMAKE PROPERTY VALUE)

However, this is a relatively convoluted way to get the value. You can just do:

set(WRAPPER_GUID ${WrapperTargetName_GUID_CMAKE})

Finally, this isn't ideal since the GUID isn't available until after the first run of CMake. So for a fresh build tree, you'd have to run CMake twice before this would be usable.

Fraser
  • 74,704
  • 20
  • 238
  • 215
  • Thank you. This is helpful. I ended up solving the problem in a slightly different way, to avoid the dilemma you pointed out. In brief, I explicitly set the values in the CMakeLists.txt for each respective C++/CLI project and then I retrieve them in the CMakeLists.txt for the C# project and use those values to generate the ProjectReference nodes. – Kohanz Mar 15 '13 at 12:29
0

Setting it doesn't seem to work for me, however it can be predicted/re-computed from yourcmake code:

https://github.com/Kitware/CMake/blob/85dc7c763a12366d49ac2dddc53f65d52d675c00/Source/cmGlobalVisualStudio7Generator.cxx#L636-L656

You can use string(UUID) for this in your cmake code:

function(get_target_uuid VARIABLE TARGET)
  set(
    CMAKE_MSVC_PROJECT_UUID_NAMESPACE
    "ee30c4be-5192-4fb0-b335-722a2dffe760"
  )
  string(
    UUID TARGET_UUID
    NAMESPACE "${CMAKE_MSVC_PROJET_UUID_NAMESPACE}"
    NAME "${CMAKE_BINARY_DIR}|${TARGET}"
    TYPE MD5
    UPPER
  )
  set("${VARIABLE}" "${TARGET_UUID}" PARENT_SCOPE)
endfunction()
Fred Emmott
  • 194
  • 1
  • 6