Search code examples
.net.net-corec++-clivisual-studio-2022googletest

Changing .NET framework 4.7.2 to .NET Core 6.0 for a C++/CLI project


I have a Visual Studio C++/CLI project which contains some Google unit tests, and the configuration type of the project is Application (an executable). I am trying to build the project by changing from .NET framework 4.7.2 to .NET Core 6.0 by following the steps here: https://learn.microsoft.com/en-us/dotnet/core/porting/cpp-cli.

But I am getting the following error: C++/CLI projects targeting .NET Core must be dynamic libraries. Upon looking at the corresponding SDK file which throws the error:

<NETSdkError Condition="('$(Language)' == 'C++' and '$(_EnablePackageReferencesInVCProjects)' != 'true') and $(OutputType) != 'library' and '$(TargetFrameworkIdentifier)' == '.NETCoreApp'" ResourceName="NoSupportCppNonDynamicLibraryDotnetCore" />

It seems .NET Core does not support C++/CLI executables:

Upon searching I can think of two ways around this

  • Change the project to procduce a dynamic library (dll) instead of an executable. Expose a method from the dll to run all the tests. Create another C++ native/C# executable project which references this dll and runs the method. This method is along the lines of the post from here: Dynamic dll load and googletest.

  • Re-write all the tests in C# or some other unit test framework in C++/CLI.

Is there some other way with minimal changes? What is recommended?


Solution

  • You absolutely need to change to output a library (DLL), just like the error tells you to. Then it's up to you how you want to handle unit testing. I would start by making a wrapper command line project that just passes arguments to the DLL entry point. Then I would rewrite the tests in MSTest at my leisure.

    According to Mike Rousos at Microsoft:

    Migrating a vcxproj to .NET Core

    Now for the interesting part – updating the sample app to run on .NET Core. The changes needed are actually quite minimal. If you’ve migrated C# projects to .NET Core before, migrating C++/CLI projects is even simpler because the project file format doesn’t change. With managed projects, .NET Core and .NET Standard projects use the new SDK-style project file format. For C++/CLI projects, though, the same vcxproj format is used to target .NET Core as .NET Framework.

    All that’s needed is to make a few changes to the project file. Some of these can be done through the Visual Studio IDE, but others (such as adding WinForms references) can’t be yet. So the easiest way to update the project file, currently, is to just unload the project in VS and edit the vcxproj directly or to use an editor like VS Code or Notepad.

    Replace <CLRSupport>true</CLRSupport> with <CLRSupport>NetCore</CLRSupport>. This tells the compiler to use /clr:netcore instead of /clr when building. This change can be done through Visual Studio’s project configuration interface if you prefer. Note that <CLRSupport> is specified separately in each configuration/platform-specific property group in the sample project’s project file, so the update needs to be made four different places. Replace <TargetFrameworkVersion>4.7.2</TargetFrameworkVersion> with <TargetFramework>netcoreapp6.0</TargetFramework>. These settings can be modified through Visual Studio’s project configuration interface in the ‘Advanced’ tab. Note, however, that changing a project’s CLR support setting as described in the previous step won’t change automatically, so be sure to clear the “.NET Target Framework Version” setting before selecting .NET Core Runtime Support. Replace .NET Framework references (to System, System.Data, System.Windows.Forms, and System.Xml) with the following reference to WinForms components from the Windows Desktop .NET Core SDK. This step doesn’t have Visual Studio IDE support yet, so it must be done by editing the vcxproj directly. Notice that only a reference to the Windows Desktop SDK is needed because the .NET Core SDK (which includes libraries like System, System.Xml, etc.) is included automatically. There are different Framework references for WinForms, WPF, or both (as explained in the migration docs).

        <FrameworkReference Include="Microsoft.WindowsDesktop.App.WindowsForms" />
    

    With those changes made, the C++/CLI project will build successfully targeting .NET Core. If you’re using the latest version of Visual Studio 2019 (16.5 or 16.6 preview 1), everything should work at runtime, too, and the migration is done!

    Prior to Visual Studio 2019 16.5 preview 2, C++/CLI libraries didn’t generate the .runtimeconfig.json file necessary for C++/CLI libraries to indicate which version of .NET Core they use, so it had to be added manually. So, if you’re using an older version of Visual Studio, you’ll need to create this CppCliInterop.runtimeconfig.json file manually and make sure it’s copied to the output directory:

    {
      "runtimeOptions": {
        "tfm": "netcoreapp6.0",
        "framework": {
          "name": "Microsoft.WindowsDesktop.App",
          "version": "6.0.3"
        }
      }
    }
    

    The app can now run on .NET Core!