How can I make my managed NuGet package support C++/CLI projects?

后端 未结 7 1715
暗喜
暗喜 2020-12-04 14:03

I have made a NuGet package that works well when I use it from a C# project. It contains a DLL in the lib/net40 directory, and the DLL gets added as a reference

相关标签:
7条回答
  • 2020-12-04 14:22

    Easy workaround is to wrap such NuGet in a regular .NET project (C#) and reference the same in your C++/CLI project.

    0 讨论(0)
  • 2020-12-04 14:23

    There seem to be actually a possibility to enable "regular" NuGet packages to be installed and automatically referenced from C++/CLI projects using following steps (at least with NuGet >= 2.5):

    1. Add (or modify) a build\<ProjectName>.targets file to your project to be packaged and put following content into it (make sure to replace <AssemblyName> with an actual value):

      <?xml version="1.0" encoding="utf-8" ?>
      <Project ToolsVersion="4.0"
               xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
        <!-- for C++/CLI projects only -->
        <ItemGroup Condition="'$(Language)' == 'C++'">
          <Reference Include="<AssemblyName>">
            <!--
              this .targets file is installed next to the assembly,
              so we do not have to figure out any versions or paths here ourselves
            -->
            <HintPath>
              $(MSBuildThisFileDirectory)..\lib\native\<AssemblyName>.dll
            </HintPath>
          </Reference>
        </ItemGroup>
      </Project>
      
    2. In the .nuspec of the packaged project add one or more file entries to also place the assembly in lib\native\ directory at the target machine:

      <package>
        <metadata>
          ...
        </metadata>
        <files>
          ...
          <!--
            add a copy of the assembly to lib\native to prevent NuGet
            from complaining about incompatible native projects
          -->
          <file src="bin\$configuration$\$id$.dll" target="lib\native\" />
          <file src="bin\$configuration$\$id$.xml" target="lib\native\" />
      
          <!-- don't forget about the .targets file containing the reference -->
          <file src="build\$id$.targets" target="build\" />
        </files>
        ...
      </package>
      

    Even if NuGet does not add assembly references to C++/CLI projects, it still inserts any .props and .targets files provided by a package. And the custom target from step 1 will add a reference to our packaged assembly.

    One drawback of this solution, as far as I could see it, is that the reference added in such a way is not displayed in the Commpon Properties/Framework and References section of the C++/CLI project. There may also be others, so use it at your own risk...

    0 讨论(0)
  • 2020-12-04 14:26

    Credentials are actually encrypted with the machinekey where the package source was added. Unless using the plaintext variant, the setApiKey command should probably be run as part of the build.

    0 讨论(0)
  • 2020-12-04 14:33

    As mentioned in the answer to this port (Nuget won't install Entity Framework into C++/CLI project), NuGet will not make the changes to a C++/CLI project for you. It will however download and unpackage the dependency for you. We use it from the command line as part of our make dependencies. The command line will look something like this:

    /.NuGet/NuGet.exe
          Install 
          -NonInteractive 
          -ConfigFile $ENV{SRC_ROOT}/.nuget/NuGet.config 
          -OutputDirectory $ENV{SRC_ROOT}/packages 
          $ENV{SRC_ROOT}/packages.config
    

    Note that the command line areguments are separated one to a line to make reading easier. Also we decided to check NuGet into our source control un the .NuGet folder. The goal was to make it easier to setup a build machine for our various environments (not all of which use Visual Studio). Once you have run this command for the first time, you must manually add the dependencies to your C++/CLI project.
    Hope that helps.

    0 讨论(0)
  • 2020-12-04 14:33

    The installer tries to add a reference to itself in the C# startup project. Make a C# project the startup project in the solution before install. Create a dummy C# project if you do not have one

    0 讨论(0)
  • 2020-12-04 14:45

    The answers above have issues with second-level dependencies (at least in my case on Visual Studio 2019).

    To solve the issue, I usually create an empty c# console application and reference all the packages there.

    Then I use this post build snippet to copy everything except the project main artifacts to a common store named packages in the solution folder.

      <Target Name="PostBuild" AfterTargets="PostBuildEvent">
        <PropertyGroup>
          <SharedLibraries>$(SolutionDir)\packages</SharedLibraries>
        </PropertyGroup>
    
        <ItemGroup>
          <Artifacts Include="$(OutDir)\**" />
        </ItemGroup>
    
        <RemoveDir Condition=" Exists('$(SharedLibraries)')" Directories="$(SharedLibraries)" />
        <MakeDir Condition=" !Exists('$(SharedLibraries)')" Directories="$(SharedLibraries)" />
    
        <Copy SourceFiles="@(Artifacts)" DestinationFolder="$(SharedLibraries)\%(RecursiveDir)" />
    
        <ItemGroup>
          <ExtraFiles Include="$(SharedLibraries)\$(ProjectName).*"></ExtraFiles>
        </ItemGroup>
    
        <Delete Files="@(ExtraFiles)" />
    
      </Target>
    

    The whole packages folder is then deployed with a custom task in the c++/cli project.

    This solution is suitable if the referenced packages target AnyCPU otherwise some tinkering is necessary to use different folders for each processor architecture, and probably won't work.

    This solution is not elegant, however solves the purpose to reliable consume nuget packages (indirectly) from a c++/cli project.

    The plus of this solution with respected to other ones posted here, is that paths are not versioned, therefore c++/cli projects won't ever be changed during normal package upgrade.

    0 讨论(0)
提交回复
热议问题