Support for `dotnet` CLI and ninja generator for C#

Copy/paste from issues/20227:https://gitlab.kitware.com/cmake/cmake/-/issues/20227#note_1053240

First, implementing this feature must support more than just Visual Studio generators. .NET 5 and now especially .NET 6 are absolutely cross platform tools (except for .NET MAUI on Linux, but oh well), and so the build tooling must be similarly available.

In fact, this is exactly why I’d be interesting in this feature. I keep “dreaming” of a system where I should be able to easily have C++ code travel alongside C# code, and build it all together across platforms, with SWIG into the mix. And this without needing middle steps like composing the native libraries and the bindings into a Nuget package.

This is the problem that needs solving. On Windows or Mac, the .csproj experience is unbeatable with VS[for Mac], so for just being another build system on those platforms there is no need. And there’s Cake also, for example.

So CMake must really consider what the market gap really is and, in my humble opinion, it’s that.

That said, I think that the power of .csproj's should be leveraged as a solution. Generators like Ninja could very well just have a build command to a generated file with dotnet build <file>, assuming the availability of dotnet CLI tooling, which I think would be a good compromise, basically resulting in support for .NET >5.

Then it would be important to also discuss things like how to manage .NET dependencies the .NET way. How to include nuget packages? Maybe as a target property? Maybe introducing a way for find_package to resolve those?

Then, I saw some discussion on the name of the language in CMake. Well, in one hand, supporting one .NET language is kinda supporting them all… I doubt a .csproj is very different from whatever is the filename for an F# project… But yeah, it’s probably not ideal to use DOTNET as the name, and use individual language names.

PS: Sorry for the half-incoherent rant.

Having find_package be able to find nuget packages makes sense. Though maybe it would actually end up being like find_package(PkgConfig) where there is a nuget_find_package(name TARGET_PREFIX name::) to create imported targets for you.

As stated above, we’ll need proper dependencies for these to know when to rerun it. We’ll also need to know the outputs so that anything that depends on it knows what that when it needs something-from-dotnet-run.dll it needs to run that target. dyndep can help here if there’s a way to ask “what files will you write?” to dotnet. Without that, the build.ninja is not much better than a naked shell script (IMO) since the “safe” solution is “dotnet rules are always out of date and cannot be depended upon by other targets”.