Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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.

Now that NuGet supports C++, how do I actually modify my package so that the DLL can be added as a managed reference in a C++/CLI project? I can't find any tutorials explaining this. If I try to just add the package as is, I get the following error:

You are trying to install this package into a project that targets 'Native,Version=v0.0', but the package does not contain any assembly references or content files that are compatible with that framework.

One would think that the solution is to put the files under lib/native, but according to http://docs.nuget.org/docs/reference/support-for-native-projects, that is not supported. Also, simply putting the DLL directly under lib doesn't seem to do anything.

Apparently, I am supposed to do this with a .props or .targets file under build/native, but what do I need to put into those files to make this work ?

like image 331
Tor Hovland Avatar asked Sep 09 '13 09:09

Tor Hovland


People also ask

How do I add a NuGet package to terminal?

Find and install a packageOpen the project/solution in Visual Studio, and open the console using the Tools > NuGet Package Manager > Package Manager Console command. Find the package you want to install.

Which command is used to install NuGet packages using dotnet CLI?

Use the dotnet restore command, which restores packages listed in the project file (see PackageReference). With . NET Core 2.0 and later, restore is done automatically with dotnet build and dotnet run .

Can I use NuGet with C++?

Nuget doesn't support C++/CLI projects, the package manager for C++ projects is vcpkg. Don't bother. One trick you could use is add a dummy C# project to the solution and use its Nuget support to get the library.


2 Answers

As Patrick O'Hara wrote, NuGet will not make changes to a C++/CLI project for you. See GitHub Issue NuGet/Home#1121 - Cannot install managed packages into a CLI project. However, using the NuGet command line utility, NuGet.exe, you can have NuGet download and unpack the desired package(s).

For a complete example, here were steps that I took to add a reference to OptimizedPriorityQueue 1.0.0 in a Visual Studio 2013 C++/CLI project:

  1. Open the Package Manager Console if not already open (TOOLS > NuGet Package Manager > Package Manager Console).
  2. In the Package Manager Console, install the NuGet.CommandLine package:

     Install-Package NuGet.CommandLine 

    (Note: As of this writing, the latest version of NuGet.CommandLine is 2.8.6. It may be different for you.)

  3. Within your project folder, there should now be a .nuget\packages.config XML file with the following contents:

    <?xml version="1.0" encoding="utf-8"?> <packages>   <package id="NuGet.CommandLine" version="2.8.6" /> </packages> 
  4. In a text editor such as Notepad++, add a <package> element for the desired package. In this case, I added:

    <package id="OptimizedPriorityQueue" version="1.0.0" /> 

    .. within the <packages> element.

  5. Open a command prompt (I opened a VS2013 Developer Command Prompt, but a regular command prompt should work.)

  6. cd into the project folder.
  7. Run the following command, changing the version number of NuGet.CommandLine if different:

     .\packages\NuGet.CommandLine.2.8.6\tools\NuGet.exe Install -NonInteractive -OutputDirectory packages .nuget\packages.config 

    For me, the output was:

     Installing 'OptimizedPriorityQueue 1.0.0.0'. Successfully installed 'OptimizedPriorityQueue 1.0.0.0'. All packages listed in packages.config are already installed. 
  8. Right click on the project in Visual Studio and select Properties. Under Common Properties > References, click the Add New Reference… button.
  9. Select Browse on the left hand side. Next to the Add Reference dialog's OK and Cancel buttons, there is a Browse… button. Click that to open a file selection dialog.
  10. Navigate to the DLLs that NuGet unpacked to the packages subdirectory of your project folder and click the Add button. Click OK to close the Add Reference dialog.
  11. You should now be able to use the assembly in your C++/CLI project:

    using namespace Priority_Queue;  //... 
like image 106
Daniel Trebbien Avatar answered Oct 29 '22 14:10

Daniel Trebbien


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...

like image 32
swalex Avatar answered Oct 29 '22 15:10

swalex