Mixed C# and C++ sln

We are currently using VS 2022 for Windows dev but may need to move to both macOS and Linux soon. Our sln contain mostly C# assemblies but also some CMake based C++ libs. They way we do this in VS is to use vcxproj as “dummy” projects including

- Directory.Build.props
- MyLib.vcxproj.filters

so the C++ are displayed in the solution explorer. 

These dummy projects have pre-build commands

   <PreBuildEvent>
     <Command>call "$(VsInstallRoot)\VC\Auxiliary\Build\vcvars64.bat"
cmake --preset "Win-x64-Debug"
cmake --build "$(ProjectDir)/build/Win-x64-Debug/"
   </Command>
   </PreBuildEvent>

We set the dependencies in the sln such that these C++ projects would be built first and their binary outputs can serve as input to the consuming C# interop assemblies (doing pinvoke). This works fine. It even works in Rider on Windows but as you mentioned earlier this would not work on Linux or macOS.

What would be your proposal for such a mixed project solution that would work for at least Windows and Linux (and optimally for macOS).

Note: the main C++ dev work is done in the pure CMake projects (currently also VS) but it is nice-to-have to at least see the C++ files in the mixed sln. Also helpful is mixed mode debugging in VS.

Question summary:

- how to structure mixed mode solutions for Rider on Windows and Linux

- Display of C++ files in Rider possible?

- mixed mode (incl. native) debugging possible in Rider?

Note: if that would need the All Products Pack that would be ok.

Thank you very much in advance!

0
13 comments

Hello Fabian Huegle,

Rider does not currently support non-UE C++ projects on Linux and macOS. Please consider following (★) RIDER-71199 CMake support in Rider to monitor progress.

Regarding mixed mode debugging - currently, mixed mode debugging is available on Windows in Unity (mono) projects. We have plans to support mixed mode debugging for .NET runtime in the future. This feature is being implemented in the scope of RIDER-11810 Support mixed-mode debugging.

Unfortunately, the only thing I can suggest at this time is to try separating the project (if possible) into a CMake-based C++ project and sln-based C# project. Then use CLion and Rider when working on each project separately. However, mixed mode debugging will still be unavailable.

0

Thank you. I guess you mentioned a while ago that in Rider you should be able to build the cmake part within a rider sln as a pre-build or so on Linux. How would that be done. Optimally, in a fashion that would work on Linux and Windows.

0

The cmake really is its own project. Visualizing it in Rider would be just nice to have. Important is that you are able to clone, build, run. Hence, when loading the C# sln in Rider the cmake part shall be built as a pre-condition automatically. I would assume that on Windows it nees all 3 steps (vcvars64.bat, cmake preset, cmake build) and on Linux it should be good to only have cmake preset and build…

0

Fabian Huegle, you can build your C++ project by invoking cmake as a target from .csproj by executing relevant CLI commands. As an example, you can invoke cmake --build in .csproj like this:

  <Target Name="BuildNativeLibraryFoo" BeforeTargets="Restore">
    <Exec Command="cmake --build {path_to_library} --config {Release/Debug/etc}"/>
  </Target>

You can change when the CMake build command is executed by modifying the value of BeforeTargets.

Note, however, that until CMake support is implemented in Rider, you will not be able to work with that project in Rider, so the suggestion to use CLion to edit the project still applies.

0

One more thing I came accross:
- I analyzed a problem where LibraryImport (of our own C++) would work on Windows but not on Linux
- I eventually found the programming error and was able to fix it
- But: in VS 2022 is was very simple to switch on mixed mode debugging to check whe the struct was marshalled wrongly to the unmanaged world (also the Hex Memory viewer was very helpful (which seems you decided to only implement a workaround (https://youtrack.jetbrains.com/issue/RIDER-62867))
- it seems mixed mode debugging on Linux would not work with Rider

What is your proposed process to do that?
- Like start the app (not in Debugger from Rider?)
- Attach CLion to the process with the C++ cmake project loaded?

Hence, what would be a feasible way to debug the C++ parts in a running .net process?

0

Fabian Huegle, regrettably, there are no known workarounds for mixed mode debugging support on Linux until RIDER-11810 Support mixed-mode debugging is implemented.

Currently, mixed mode debugging is under development and has very limited support. The only supported scenario is C# projects that target Mono runtime on Windows. Regrettably, I cannot give you an ETA for when mixed mode debugging is supported on Linux, targeting .NET runtime.

0

Thank you very much. What about debugging of the C++ portion in a C# / C++ mixed sln with LibraryImport. Could I start the process in Rider (no debugging) and attach e.g. CLion to the process?

0

Fabian Huegle, in general, this is unlikely to work with P/Invoke. However, I do not know the exact details of your project, so I can suggest the following approach as a potential workaround that might be worth trying:

  • Introduce an interrupt into a native code you want to debug (SIGINT)
  • Run your project with Rider
  • Use Attach to Process in CLion note that you might want to try both LLDB and GDB in this case
  • Try to hit the interrupt in your project

Importantly, there is a chance you might see two processes with the same PID listed in the attachment popup. If this happens and CLion shows identical process names and PIDs, you will need to try each one to find the correct process to attach to.

0

So, I tests. Again, this is the setup:
- C# UI app using Avalonia
- C++ library with a C-API
- Interop C# assembly using LibraryImport to call the C-Api functions

To debug the native code on Linux I did the following:
- Build the C++ lib and the C# sln in Debug
- Run the C# app in Rider (no Debugger)
- Open the C++ (cmake) project in CLion
- Set breakpoint in the body of a called C-api function
- Attach CLion to the C# app created process
- Make the app call the C++ function

=> breakpoint is hit in CLion

So, it does work. CLion also remembers the process so attaching again is a bit less cumbersome. Still this is pretty manual. And if such a C-Api function were to be called directly after start of the C# app, there would not be enough time to attach to the process, hence, I wonser whether you could automate this even if it still needs both Rider and CLion. 

Also, mixed mode debugging would not often be needed. It would be ok to just have either C# debugging or native debugging.

0

Hello Fabian Huegle,

 

Thank you for the update.

The reason I mentioned introducing intentional interrupt earlier is to cover cases when native code is called soon after startup - it should give you the time to attach the debugger. 

 

Unfortunately, there are no communication channels between Rider and CLion that would allow you to pass unambiguous attach requests (meaning passing exact PIDs). However, I can suggest trying to the Attach to an Unstarted Process feature in CLion if the name of the process is consistent. You can find more about this feature under Ability to attach the debugger to an unstarted process.

For example, if you are launching a process that is always called foo, you can:

  • Set breakpoint in your C++ code
  • Invoke Run → Attach to an Unstarted Process
  • Set  *foo* as a lookup pattern in the Command line field
  • Use Attach with <debugger> so that CLion starts monitoring processes launched on the system
  • Launch the project in Rider

If the name of the process is not consistent and you cannot use a process name mask, I'm afraid there is no way to further simplify or automate the process.

 

Let me know if it helps.

1

Thank you for your support. That sounds doable. 

Most likely the mixed-mode thing is not on your prio list. Still a bit sad that VS is the only thing that does it. I agree, you do not need that very often. But once you do need it you would want the fastest turnaround times possible. 

Anyhow, great you are providing this direct support!

0

Mixed-mode debugging is fairly high on the priority list and is under active development at the moment. This feature covers a lot of different configurations (.NET, .NET Framework, mono on three operating systems), so it is difficult to predict when Linux+.NET will be available. Apologies for the inconvenience.

1

We found a solution as follows:

  • link the C++ code into your interop .net assembly
    • exclude build and bin folders otherwise your C++ will never be built but copied from cache
    • So, now you can see the C++ as a subfolder of your interop project in solution explorer
  • Add prebuild steps to the interop assembly for building C++ 
    • Do not forget clean

As a result there remain only the csproj items in the sln but you still see your C++ code and the code is build automatically.

Thanks for the support.

0

Please sign in to leave a comment.