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
As of NuGet 2.5, when the package installs, it checks inside the
/build/<framework> folder for files that are either called
<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
.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,
Given a simple
#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++.