Deep Dive into NuGet Native (Part One)

Deep Dive into NuGet Native (Part One)

Rate This
  • Comments 6

Howdy!


Today I thought I’d start explaining how NuGet supports C/C++ packages under the covers, and look into how one could (theoretically) manually construct a package without using the CoApp PowerShell tools.

 

As I mentioned before, C/C++ packages built for NuGet didn't require a whole lot of change in NuGet itself—primarily because if we had made the Package Manager do all the complex work that was necessary to hook up a project, we’d be still implementing it all a year from now. 

Instead we chose to add a fairly simple (and often requested) feature to NuGet, the ability to import MSBuild project file fragments into the consuming project. Previously, some package creators had hacked their way into something similar by including an install.ps1 PowerShell script in the package. While this sort of thing was workable, it opens up an awful can of worms.  As well, NuGet needed to support actually working on C++ project types and needed to shoe-horn in a new “framework type” that could represent native packages (which was simply called native ).

 

As of NuGet 2.5, when the package installs, it checks inside the /build/<framework> folder for files that are either called <pkgName>.targets or <pkgName>.props . If it finds a .props, it places an <Import> into the top of the project file.  If it finds a .targets file, it places an <Import> into the bottom of the project file.  This allows the package creator to have finer grained control as to when something is declared—and if it can get overridden in the consuming project or not. 

At that point, NuGet’s involvement on how the package is integrated in the consuming project is pretty much complete. It’s now up to the package creator to craft the .targets and/or .props files in such a way enables the consuming project to effectively use the contents. 

The Simplest Package

Assume for a moment that we wanted to create a very simple package that contained only a single header file, and didn’t have any .lib files and didn’t have any redistributable files (ie, .dll  files). 

Given a simple mysample.h file: 


#pragma once #include <stdio.h> /* some simple function */ #define SimpleWriteString( str ) printf( str )

We then need to create the mysample.targets file that will ensure that we add the include directory into the consuming project.

 
<?xml version="1.0" encoding="utf-8"?> <Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" >   <ItemDefinitionGroup>     <ClCompile>       <AdditionalIncludeDirectories>$(MSBuildThisFileDirectory)..\..\lib\native\include\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>       <PreprocessorDefinitions>HAS_MYSAMPLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>     </ClCompile>   </ItemDefinitionGroup> </Project>
  

A very simple mysample.nuspec file (the .nuspec file is the manifest file used by NuGet to tell what is in the package. You can find more about the .nuspec file format from the docs on nuget.org ).


<?
xml version="1.0" encoding="utf-8"?> <package>   <metadata>     <id>MySample</id>     <version>1.2.3</version>     <authors>Garrett Serack</authors>     <owners>CoApp Project, Garrett Serack</owners>     <requireLicenseAcceptance>false</requireLicenseAcceptance>     <description>A sample library.</description>     <releaseNotes>First Release of MySample library</releaseNotes>     <copyright>Copyright 2013</copyright>     <title>MySample Library</title>     <summary>A sample library</summary>     <tags>native, MySample</tags>   </metadata>   <files>     <file src="MySample.h" target="\lib\native\include\mysample.h" />     <file src="mysample.targets" target="\build\native\mysample.targets" />   </files> </package>
  

 Once we have those, it's fairly trivial to build the package with just the NuGet command-line tool:


c:\MySample\> nuget pack
Attempting to build package from 'MySample.nuspec'. Successfully created package 'C:\MySample\MySample.1.2.3.nupkg'

Of course if all libraries were this easy, we'd never needed to make a special tool to build packages for C++.

Next Time: We'll dig into how we hook up .lib files to the linker, and making sure that redistributable files are copied to the output directory.

Also : In case you missed it, you might want to check out the Channel 9 Interview on NuGet/C++

  • Channel 9 link is a little off and references post editor:

    blogs.msdn.com/.../GoingNative-16-Garrett-Serak-Inside-NuGet-for-C

  • The forums or whateverthehell thatcrap is is just stupid.  It is THE MOST stupid thing MS has ever done, even nore than Win8.  Well.

  • Your channel9 link links to a login page. This link works for me:

    "channel9.msdn.com/Shows/C9-GoingNative/GoingNative-16-Garrett-Serak-Inside-NuGet-for-C"

    channel9.msdn.com/.../GoingNative-16-Garrett-Serak-Inside-NuGet-for-C

  • Sorry about that broken link -- fixed.

  • Great stuff.  Didn't even know NuGet was being extended to support C/C++ packages until I stumbled across this.  The MSBuild fragment injection is awesome.

  • Do you plan to release C++11 compiler support?

Page 1 of 1 (6 items)