Generate C# project using CMake

45,438

Solution 1

As of CMake 3.8.2, CSharp project generation is officially supported by CMake.

To build the default Visual Studio 2017 generated C#/WPF project using CMake, create a CMakeList.txt file as follows.

  • Project Declaration

      project(Example VERSION 0.1.0 LANGUAGES CSharp)
    
  • Include CMake CSharpUtilities if you are planning on using WPF or other designer properties.

      include(CSharpUtilities)
    
  • Add all cs, xaml, settings, properties

      add_executable(Example
          App.config
          App.xaml
          App.xaml.cs
          MainWindow.xaml
          MainWindow.xaml.cs
    
          Properties/AssemblyInfo.cs
          Properties/Resources.Designer.cs
          Properties/Resources.resx
          Properties/Settings.Designer.cs
          Properties/Settings.settings)
    
  • Link designer files, xaml files, and other properties files with their corresponding cs files

      csharp_set_designer_cs_properties(
          Properties/AssemblyInfo.cs
          Properties/Resources.Designer.cs
          Properties/Resources.resx
          Properties/Settings.Designer.cs
          Properties/Settings.settings)
    
      csharp_set_xaml_cs_properties(
          App.xaml
          App.xaml.cs
          MainWindow.xaml
          MainWindow.xaml.cs)
    
  • Set app App.xaml properties file as program entry point (if project is a WPF project)

      set_property(SOURCE App.xaml PROPERTY VS_XAML_TYPE "ApplicationDefinition")
    
  • Set other csproj file flags

      set_property(TARGET Example PROPERTY VS_DOTNET_TARGET_FRAMEWORK_VERSION "v4.6.1")
      set_property(TARGET Example PROPERTY WIN32_EXECUTABLE TRUE)
      // ...
    
  • Add libraries

      set_property(TARGET Example PROPERTY VS_DOTNET_REFERENCES
          "Microsoft.CSharp"
          "PresentationCore"
          "PresentationFramework"
          "System"
          "System.Core"
          "System.Data"
          "System.Data.DataSetExtensions"
          "System.Net.Http"
          "System.Xaml"
          "System.Xml"
          "System.Xml.Linq"
          "WindowsBase")
    

For a working WPF example, see https://github.com/bemehiser/cmake_csharp_example

For a WinForms example, see this answer.

Solution 2

CMake 2.8.9 and up add a TYPE parameter to include_external_msproject like so:

include_external_msproject(
    MyProject MyProject.csproj
    TYPE FAE04EC0-301F-11D3-BF4B-00C04F79EFBC)

This lets you specify that the project is C# (the magic GUID above), otherwise things struggle (see docs).

You will probably still want to use the configure_file template approach mentioned elsewhere with your .csproj file to get the right paths into it, unless you're building straight into your source tree.

The good news is that you can wildcard your C# files in the .csproj.template file like so:

<ItemGroup>
  <Compile Include="${DOS_STYLE_SOURCE_DIR}\**\*.cs" />
</ItemGroup>

And you'll need something like this in your CMakeLists.txt to convert CMake's unix-style forwardslash path separators into Windows-style backslashes, otherwise it will compile the files but they won't show up as links in the project in Visual Studio:

FILE(TO_NATIVE_PATH "${CMAKE_CURRENT_SOURCE_DIR}" DOS_STYLE_SOURCE_DIR)

Then it's just:

CONFIGURE_FILE(MyProject.csproj.template MyProject.csproj)

In your CMakeLists.txt to configure the template file into a real project file with the right wildcard path.

HTH.

Solution 3

Just in case anyone is still looking for information about this, there is really no reason to generate C# projects with CMake, they are cross platform by design. On Linux, C# projects are generally managed with MonoDevelop which can read .csproj files from visual studio just fine. This should enable cross-platform development of C# projects. The only potential issue would be if you had native c++ projects mixed with c# projects (like a backend written in c++ with a GUI in c#), in this case just have cmake copy over your .csproj files as though they were data and you should be good to go. CMake is intended to set up your build environment to be cross platform. This comes in really handy with c++ where code is built in a very different way on linux than on windows (or other OSs if youre into that), but is kind of unnecessary for c# which can execute cross-platform, and, thanks to design decisions by the mono team, can build cross platform. CMake does provide some great tools to automate things, but much of this functionality can be recovered with a properly configured .csproj file. Anyway I know this question is over a year old but it's one of the top search results I stumbled on when I was looking up how to do this. I've since made this realization.

Solution 4

To piggy-back on the answer provided by @the_storyteller, CMake v3.8 and greater indeed supports C# as a first-class language. Because a WPF example was already provided, here is a complete CMake example for a simple Windows Forms application. I've provided the optional commands for linking in other libraries built locally in the source tree, and linking 3rd party library dependencies.

Note that Windows Forms applications require the use of the csharp_set_windows_forms_properties CMake command, whereas WPF projects use csharp_set_designer_cs_properties and csharp_set_xaml_cs_properties.

CMakeLists.txt

cmake_minimum_required(VERSION 3.8)

project(MyWinFormApp LANGUAGES CSharp)

# Include CMake utilities for CSharp, for WinForm and WPF application support.
include(CSharpUtilities)

# Define the executable, including any .cs files. 
# The .resx and other Properties files are optional here, but including them makes them visible in the VS solution for easy editing. 
add_executable(MyWinFormApp
    App.config
    Form1.cs
    Form1.Designer.cs
    Form1.resx
    Program.cs
    Properties/AssemblyInfo.cs
    Properties/Resources.Designer.cs
    Properties/Resources.resx
    Properties/Settings.Designer.cs
    Properties/Settings.settings
)

# Set the .NET Framework version for the executable.
set_property(TARGET MyWinFormApp PROPERTY VS_DOTNET_TARGET_FRAMEWORK_VERSION "v4.6.1")
# Set the executable to be 32-bit.
set_property(TARGET MyWinFormApp PROPERTY WIN32_EXECUTABLE TRUE)
# Set the C# language version (defaults to 3.0).
set(CMAKE_CSharp_FLAGS "/langversion:latest")

# Set the source file properties for Windows Forms use.
csharp_set_windows_forms_properties(
    Form1.cs
    Form1.Designer.cs
    Form1.resx
    Program.cs
    Properties/AssemblyInfo.cs
    Properties/Resources.Designer.cs
    Properties/Resources.resx
    Properties/Settings.Designer.cs
    Properties/Settings.settings
)

# If necessary, link in other library dependencies that were built locally in this source tree.
target_link_libraries(MyWinFormApp MyLocalLib)

# If necessary, link in other library/DLL references, such as 3rd party libraries.
set_property(TARGET MyWinFormApp PROPERTY 
    VS_DOTNET_REFERENCE_MyThirdPartyLib /path/to/libs/MyThirdPartyLib.dll)

# Add in the .NET reference libraries.
set_property(TARGET MyWinFormApp PROPERTY VS_DOTNET_REFERENCES
    "Microsoft.CSharp"
    "System"
    "System.Core"
    "System.Data"
    "System.Drawing"
    "System.Windows.Forms"
)

Solution 5

I was finally able to generate a valid solution using the second c# module - kde. Although, cmake created a number of .vcproj files while I expected to get .csproj, but I guess that is the only form "Visual Studio 8 2005" generator can offer.

Nevertheless I was able to successfully build this solution and produce executables and dll libraries.

Share:
45,438
Leonid
Author by

Leonid

Updated on July 08, 2022

Comments

  • Leonid
    Leonid almost 2 years

    I'm trying to generate a C# project within an existing C++ CMake code base on Windows. After some research, I could find only two projects that built their own CSharp compilers for CMake: gdcm and kde.

    I tried both of them. Unfortunately, the first one failed to generate a C# project. Instead it created a VS C++ project with cs files in it, and because of C++ flags set for linker, the build always failed with errors. After experimenting with the sample project they provided, I wonder whether this could be due to a limitation of the "Visual Studio 8 2005" code generator?

    The second project was primarily aimed at Mono, so I wasn't successful with it either.

    Has anyone had a positive experience with building C# projects using one of those CMake modules or something else?