C++ Project support

Nov 23, 2011 at 10:49 PM

I really like the NuGet approach to manage external project dependencies and would like to see that work also for C++ projects. This took me to work item 868 and to the fork created by rodolfograve.

I started yesterday to investigate how to add C++ project support to NuGet. I solved a first issue with getting the full path name of a C++ project and that got me a better view of the task ahead !

The whole NuGet system is based on the VSLang automation project model, way down into it's roots. However to add support for C++ projects, we need to be able to work with the VCProject automation model. These two models don't have much in common which means some refactoring is going to be necessary to manage both types of projects. 

The differences in the project models comes from the differences of the languages and how source code is put together.  When using external libraries in C++ we need the library dll, plus some header files and an import library.

These files don't necessarly need to be added to the project tree, the inclusion is done through compiler and linker settings. Importing a NuGet package for C++ would mean to be able to adjust the project settings automatically.

This is still a bit confused, but I'd like some feedback on how to tackle the task so it best fits in the nuget architecture.

  • Can the standard package layout be extended to add support for the C++ dependencies ? 

                    For example in the lib directory, add a c++ target directory which would include the dlls, the import libraries and the headers (each in separate sub folders)

  • Should the project settings be modified out of the box or through powershell scripts ?
  • Since C++ projects don't always target a Framework version or provide "references", would it be wise to differentiate the project interfaces  to reflect this ? Or would it be more suitable to press the c++ approach in the existing interfaces ?
Nov 24, 2011 at 3:11 AM

Thanks for jumping on this work item. I know it's been sitting on the backlog for a while. To answer your questions:

  • Yes, it's certainly possible to extend the package layout convention to support C++ dependencies. When you are working on it, do post your proposal on this thread and we'll evaluate it.
  • We should strive to modify project settings out of the box (in managed code).
  • It depends. What interfaces are you referring to? Can you give more concrete examples?
Nov 24, 2011 at 9:46 PM

Concerning the package layout here's a first proposal:

  • The import libraries associated to the package dlls should be added along side the dlls. If a package provides a dll build against a specific c/c++ runtime version the dlls should be grouped in the compiler specific directories (similar to the framework versions). The microsoft runtime comes in four variants: single threaded (release and debug), multi-threaded (release and debug). The runtime can also be statically linked or dynamically linked. This brings the variant count up to 8 ! All these variants need to be considered  as they can't be mixed together as soon as C++ objects are passed across dll bounderies. Differentiation between release and debug variant should be done by placing the respective versions in sub folders, "release" and "debug"
  • Since the c++ compiler (in unmanaged compilation) produces native processor code, it may also be necessary to add processor target variants. 
  • A library can be added as a static or shared library to a project. To differentiate the two cases I would suggest using two separate packages.
  •  Header files associated with the libraries should be layed out in an "inc" folder place at the root of the package. 

Here's a sample layout:

       inc \

               MyAPI.h <- interface header      

        lib \
















When a package is included in a project, some build settings might need to be adjusted or checked such as preprocessor symbols, default structure alignment settings, include paths need to be added, exception handling or RTTI might be required...

Where should all these requirements be formulated,  in the package definition, or in the post install scripts ? 


Concerning the interface modifications I mentioned:

NuGet uses the FrameworkName type to identify framework target versions. The problem is that this class can't represent the visual studio runtime names. To handle that, without changing everything I think that wrapping the FrameworkName class in a class which could handle both would be the best solution.  I'm not mistaking one of the core spots where this class comes into play is in the IProjectSystem interface. This is the interface I was referring  to in my previous post. This interface would probably need to be extended to handle adding import libraries, and include paths to the project.

It's hard for me to predict right now where extensions/modifications are going to be necessary. That's at least the first spot I identified.

Nov 28, 2011 at 6:51 PM

Hi teajay, sorry about the delay in my response. I think most of your proposal make sense. Here's a few points that I want to call out:

  • If we include the 'inc' folder as a sibling of the 'lib' folder, it implies that this whole package is only targeted to C++ projects, because 'inc' doesn't make sense for other types of projects. Maybe 'inc' should be a child of 'vc100-mt'?
  • What does the '100' in 'vc100' refer to?
  • Does the 'mt' and 'md' refer to statically and dynamically-linked?
  • Regarding 'debug' and 'release' categorization, we also have received requests to support those for .NET projects too. We need to think more about it to make sure we have a consistent story for both .NET projects and native C++ projects.
  • Also, are you familiar with the C++ managed project type as well? Are you planning to support it? I want to make sure if we do, we have a consistent design for both native and managed C++ projects, if that's possible.

For the build settings, I've changed my mind, and I now think they should be done in the install.ps1 script. Putting those in package definition will bloat the .nuspec schema too much.

I think adding more members to IProjectSystem is the right way.

Nov 28, 2011 at 8:30 PM
Hi Dotnetjunky, 
Let me answers the questions in a different order to make understanding the answers easier.
  • The 100 in vc100 is meant do represent the compiler version with which the library is compatible. For now, there will only be vc100 until a new compiler version comes. The compiler version numbering scheme I propose is the same as the one used in the boost library.
  • mt and md refer to the build settings used to produce c++ code, which refer to different runtime versions. As stated earlier,  you can't mix these settings if objects are passed across dll boundaries.
  • I'm not sure that placing the inc folder under the vc10 folder would make a lot of sense, because a package could include several binary versions of a library (vc100-mt, vc100-md, vc200-mt etc...) which will all refer to the same headers. That's why I proposed to put it on the same level as the lib folder. I don't find it offending to leave the inc directory empty or not require it's inclusion in the package for .NET only packages. It's there if there is something to put in there.  Including the inc folder wouldn't necessarily mean a package is c++ only, it could very well be present in mixed packages. One other argument in favor of placing the inc folder on the same level as the lib folder is that there are also some header only libraries out there. To name only one boost !
  • In the c++ world providing release and debug versions of a library is absolutely necessary because of the different runtime environments the library is linked against. It's the same problem as with mt, md and compiler versions: you can't pass objects across dll boundaries  which aren't managed by the same runtime heap.  The debug runtime includes some neat memory management debug helpers which can't be used without the proper binaries. 
  • I don't think that there's anything in the way to support managed C++ as well as unmanaged. It's just a couple of compiler settings which differ. The visualstudio extension model is the same, as well a the project structure. So yes, I'm planning to support managed C++ as well.
  • For the build settings, I would split those in two categories: 
  1. the path settings (include file and linker settings) , and import libraries required
  2. and the other settings ( defines, compiler settings etc). 

I would propose to manage the first category out of the box whereas the second category would need to be modified through scripts. The reason I propose this, is that in most simple cases, it sufficient to add the include path to the compiler and linker search paths and maybe add an import library reference. The more complex libraries may require additional defines or compiler / linker settings.

For the parameters coming through the scripts, there's going to be one difficulty: who is responsible for removing modifications when uninstalling a package ? I'm not yet aware of all the nuget internals: is there already a place where some rollback information can be stored ? 

Nov 28, 2011 at 11:45 PM

My replies:

  • I'm thinking we should not allow mixed packages, for simplicity's sake. In other words, if a package is meant for C++ projects, then it must not contain managed assemblies. I can't think of a package that can target both managed and native projects. With that, I can live with the top-level 'inc' folder.
  • If we specify the folder name based on compiler version, is there a way to check the current project to know what compiler version it is running? I'd guess yes but just want to make sure.
  • If a package contains two folders for two compiler versions, does it need two different header files or it can share one header?
  • Regarding the build settings, that sounds good to me. We should keep the number of settings in the first category as small as possible.
  • As for who is reponsible for removing modification, it should be nuget for category 1 and uninstall.ps1 for category 2.  Nuget currently doesn't store any rollback information, so it's a bit tricky for the uninstall case. I have to understand more about the settings to answer your question.

All in all, before you start coding, I think we need to see the overall picture of how a C++ package is installed into a C++ project, e.g. which file/assemblies are added, which settings are modified, etc.

Is it possible that you can create a sample C++ package that you have in mind (hint: use NuGet Package Explorer) and a typical C++ project with and without the package installed? You can add the files manually for now.

Dec 2, 2011 at 11:14 PM

Any update on this?

Dec 4, 2011 at 11:20 AM

Sorry for the delay. I've been very busy until the end of the week. I'll put something together this afternoon and post an update.

Dec 4, 2011 at 9:21 PM

Just to make sure you find it, I posted a comment with the samples I put together in workitem 868.

Dec 6, 2011 at 6:52 PM

Thanks. I looked at the solution in your zip file. I see you have a nice package layout. However, in the NuGetCPPSample, I'm not seeing the packages content get added. For example, I'm not seeing the .h files added, and the .dll files are not referenced. Am I missing something?

Dec 6, 2011 at 8:07 PM

The headers and libs aren't supposed to appear directly in the project. They appear in the project settings through the include paths which are set as well as a reference to the import libraries for the dlls.

You'll have to open the project properties to see what the package install step will have to add in the project settings.

Dec 6, 2011 at 11:34 PM

Here's what I see in the Project Property Pages.

Include Directories:  $(VCInstallDir)include;$(VCInstallDir)atlmfc\include;$(WindowsSdkDir)include;$(FrameworkSDKDir)\include;

Reference Directories: $(VCInstallDir)atlmfc\lib;$(VCInstallDir)lib

Lib Directories: $(VCInstallDir)lib;$(VCInstallDir)atlmfc\lib;$(WindowsSdkDir)lib;$(FrameworkSDKDir)\lib

They don't seem to include the files from the package. ???

Dec 8, 2011 at 2:50 PM
Edited Dec 8, 2011 at 2:51 PM

Look in the NuGetCPPSample.vcxproj file and you will find the additional references:

 <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

 In the IDE you'll find this in the c++ preprocessor settings and in the linker settings.

Dec 24, 2011 at 10:01 PM

Just pushed a Christmas treat here: https://hg01.codeplex.com/forks/teajay/868cppprojectsupport

This is a fork with initial c++ project support for nuget. It works for Managed and Unmanaged C++ as far as I've tested. I would be very pleased to get some feedback on what I've achieved so far. 

To make sure it's referenced also in the corresponding work item I'll cross post this there.

Dec 25, 2011 at 4:08 AM

Very cool. I'll take a look soon and let you know.

Dec 28, 2011 at 8:02 PM

Hey, sorry for the delay but I'm currently occupied with fixing other important fixes for nuget. I'll promise to look at it in the new year. I'll also try to get other NuGet team members to look at it too.

Dec 29, 2011 at 9:11 PM

Take your time, I'm in no hurry. 

Here are some points that I think should require some carefull eyes:

  1. The framework version parsing scheme is limited to versions smaller than 10.0, for VS2010, we've just reached the limit. I fixed it just for the C++ case as I didn't now how the parsing scheme should be adapted for the other cases.
  2. For C++ projects, to determine which "framework" version should be used, we need to look through all the project  configurations. Each configuration could match a different target framework. Moreover the modifications needed to integrate the package in the C++ project are located under the configuration. This is why I adapted the ProjectSystem interfaces to be able to match up a target framework with a project configuration. This might not be the best design, any suggestions are welcome.
  3. In order for the package dlls to be copied to the project output directory, the package installation creates a custom build step which performs the copy. This could be again a subject of discussion. For now it works, but there may be room for improvement.

In the pushed version, there aren't any sofisticated package creation rule checks. I intend to implement the following rules:

  1. Forbid mixed package types (Managed, unmanaged)
  2. Check that the provided include paths really exist in the package
  3. Check that headers are provided with the dlls and import libraries
  4. Check that import libraries are provided

I also wanted to provide a helper powershell command-let to add / remove defines in the preprocessor configuration as this will probably be necessary for many packages but I didn't find out where to start....

Feb 6, 2012 at 9:17 PM

I managed to get a fork working with c++ projects which you can try it out by building nuget from the source contained in the fork here : https://hg01.codeplex.com/forks/teajay/868cppprojectsupport.


If you have any comments, bug reports or anything else regarding the subject, let me know by posting here or in workitem 868. I do intend to help the nuget devs get this feature working and integrated in the official nuget version as soon as possible. But they seem to be pretty busy right now on other spots. 

@dotnetjunky: Anything new on your front ?

Feb 8, 2012 at 1:12 AM

Hey @teajay,

We really appreciate the help on this!  We are planning to get this incorporated in the relatively near future, probably as part of a NuGet 1.8 release.  It looks like NuGet 1.8 is going to be themed around package authoring improvements, including how we have project type support implemented.  We will review your contributions as part of that work.  We'll contact you with any questions or concerns while we're doing so.

Thanks again for your help, and we'll let you know when we start incorporating this.

Jeff Handley

Apr 10, 2012 at 2:38 PM

I'm watching this with great interest. What I missed in the discussion above is support for different platforms (x86 and x64 binaries, for example).

Currently, when linking Visual C++ binaries you need to differentiate between these things:

  • Platform: x86, x64, WinRT x86, WinRT x64, WinRT ARM
  • Compiler/C++ Standard Library version: msvc-9.0, msvc-10.0, msvc-11.0
  • (Debug and Release) sometimes: A DLL with a C API and clean memory management (like Windows' user32.dll or FreeType.dll) can exist as a Release build only. DLLs exposing a C++ API cannot.
  • (Static and Dynamic Runtime) perhaps: All projects since VC++ 2005 or so default to the dynamic runtime. In multi-DLL projects, only the dynamic runtime makes sense (otherwise you'd have several copies of the C runtime in memory). I'd drop this one and just default to the dynamic runtime in all cases. If someone needs a single-file run-anywhere .exe, he can add the library sources to his project.

My own scheme is this:


And for libraries requiring separate Debug/Release binaries:


As you can see, I tried to keep the number of subdirectories down to a reasonable level.

This also enables C++ programmers to use placeholders in their library directories instead of repeating through the configuration 4-6 times straight for each project configuration. For example, in the above case a project could just enter NuGetReferences\ogre\msvc-10.0-$(Platform)-$(Configuration)\ into the library directory once for all configurations.

I'm happy with any scheme you guys come up with, but it should include the platform. Doing so without going 4 directory levels deep would be a bonus ;)

For reference, you can see this very scheme at work in third-party binary repository: https://devel.nuclex.org/external/svn

Apr 11, 2012 at 11:29 AM

Out of curiosity: why do you prefer a flat folder structure instead of nested? Is there any technical reason for that with C/C++ or just personal preference?

Apr 12, 2012 at 11:04 AM

It would probably be possible to support both types of structures (flat and deep) without to much trouble. The elements in the folder names would have to match however.

I came up with another idea for the platform encoding which would be to include the platform in the dll name:


Don't know if it's any good.

Apr 21, 2012 at 3:34 PM
Edited Apr 21, 2012 at 3:35 PM
TripleEmcoder wrote:

Out of curiosity: why do you prefer a flat folder structure instead of nested? Is there any technical reason for that with C/C++ or just personal preference?

Because deep folder structures make it more difficult to see the options you have available.

This goes doubly for the cases where a command line user (PowerShell or DOS Prompt) has to type several commands and compare several listings whereas everything could appear in just one listing. And for VCSs like Subversion (TortoiseSvn), where it takes moment to see the contents of the directory, each additional directory one has to open adds a little bit to the annoyance :)

But it is all personal preference, of course!


teajay wrote:

It would probably be possible to support both types of structures (flat and deep) without to much trouble. The elements in the folder names would have to match however.

I came up with another idea for the platform encoding which would be to include the platform in the dll name:


Don't know if it's any good.

I experimented with that scheme before I came up with my current one.

The problem was that many C++ libraries have their own name encoded (for example, a call to GetModuleHandle("OgreMain.dll") to get at its own HINSTANCE - yep that specific example is actually in that very library 2 times), meaning they will no longer work when the DLLs are renamed.

I think it's a worthwhile goal to be able to include the original distributions in NuGet, without renaming DLLs whether supported by the specific library or not (and thus requiring a custom build with modified sources to work).

Apr 30, 2012 at 8:56 AM

I finally implemented the target machine architecture support the way Cygon suggested. The reason for this choice is that is fits with the FrameworkName decomposition scheme and was easiest to integrate in the compatible framework lookup mechanism.

I just pushed the necessary changes in the https://hg01.codeplex.com/forks/teajay/868cppprojectsupport fork which I also updated to match the NuGet 1.9 development status. If it should still make it in the 1.8 version I can also update the 1.8 branch of the fork.

I still have to write some unit test for the new features added and it'll be ready for a first review.

Apr 30, 2012 at 9:11 AM
Edited Apr 30, 2012 at 9:12 AM

I also extended the command line tool "pack" command to support vcxproj files. Symbol packages should also be supported, I didn't get to test this extensively, I only checked that the package contents matched my expectations.

When using the -build option with the pack command I chose to build all the available project configurations and extract for each configuration the produced files and added them to the package. This could be a problem with certain project configurations which are meant for profiling or code coverage builds, which aren't meant to be added to a package. I think it would be wise to find a way to exclude certain project configurations from the extraction. If someone has a good idea how to make this possible ... 

Apr 30, 2012 at 9:16 AM

@teajay, could you share an example C++ project and the resulting pair of packages (regular + symbols), so that we might have a look at the impact on SymbolSource this will have?

May 2, 2012 at 10:26 AM

@TripleEncoder, I'll provide a package as soon as I can. I'm still fighting with some unit test issues.

What are your concerns about the impact on symbolsource ? Diskspace, bandwidth, number of files contained in a package ? The spectrum can be very wide and you will probably not get all this information from a small sample project.

One thing I know is that pdbs tend to be much bigger with c++ projects than with C# projects.

May 2, 2012 at 10:42 AM

My primary concern is that we have assumed DLLs and PDBs to be managed code only in our processing. Of course this will not replace full testing, but we'd like to get the big picture as soon as we can. The other aspects that you mention should not cause problems.

May 7, 2012 at 9:38 PM

I got the Git fork updated with all the modifications needed to get C++ project support :  https://git01.codeplex.com/forks/teajay/868cppprojectsupport 


@TipleEmcoder: Check the Workitem 868 for a sample package. If you need a more elaborate package, let me know I'll put something together. (Sorry for the delay ... I was enjoying some vacation :) )

May 11, 2012 at 11:31 PM

I know I'm late to the party, but I'd recommend against INCLUDE override.  You're going to start getting into cross package naming conflict and package install order issues because of that.  In general, I'd much rather see a model where NuGet defines an inc root or package root and people reference headers relative to that, with only the inc root in the INCLUDE path.  Of course with this you need to also abstract the version from the inc root (so aggregating package inc folders via hardlinks into a real inc root)

packages\elmahUnmanaged.1.2.2\inc => packages\inc\elmahUnmanaged

then consumers would
#include "inc\elmahUnmanaged\foo.h";
instead of
#include "foo.h"

Internally we have a package system that goes very broad and deep in the dependency chain and we're often fighting with package developers to be specific in their naming just to avoid these types of problems but you still find 'node.h', 'utils.h', whatever cropping up.  IMO, fallback paths are things to avoid wherever possible - they add complication to understanding, management, and incremental (e.g., detect dropping a file into the fallback path and needing a rebuild) and it would be best to be more specific in references than to grow and manage the INCLUDES list.

Alternatively you could try to enforce at package time that every header in an inc dir had the project id as a prepend, but that would lock out some standard packages from crossing over easily (boost).

May 12, 2012 at 12:50 AM
Edited May 12, 2012 at 8:20 AM
zjrunner wrote:

I know I'm late to the party, but I'd recommend against INCLUDE override.  You're going to start getting into cross package naming conflict and package install order issues because of that.  In general, I'd much rather see a model where NuGet defines an inc root or package root and people reference headers relative to that, with only the inc root in the INCLUDE path.  Of course with this you need to also abstract the version from the inc root (so aggregating package inc folders via hardlinks into a real inc root)

True, libraries which have their headers at the root include level are just asking for problems.

But I don't think the "inc" directory you are suggesting is such a good idea:

  • Some libraries are written in a way that doesn't allow their headers to be put in a subdirectory (for example, if a header does #include "helpers/helper.h" instead of #include "../helpers/helper.h" to access a header in another, parallel subdirectory, this will break the library). You'd end up with lots of special case packages in NuGet that either add their own include in addition to the "inc root" directory or don't.
  • You'd end up with non-standard code. Code that uses the library with the original header layout (i.e. all example code, downloadable demo projects, cross-platform code that wants to include the same headers from Linux) would use #include <FooLib.h> whereas any project that added the library via NuGet would now have to use #include <Foo/FooLib.h>.
  • Chopping up the libraries that way means every project has access even to headers of libraries that it doesn't reference. Thus the "inc root", as you call it, robs developers of fine-grained control over which headers are available to which project. This contributes to the problem you're having: with separate include directories, two libraries can have a same-named file (eg. config.h) as long as they're not referenced by the same project. With this "inc root" they'd overwrite each other at the file system level unless you force them into the layout your proposed.
  • Lastly, I don't think it's NuGet's job to fix badly designed libraries, especially not if the fix would break well-designed ones (like Boost which you mentioned yourself) or force package creators to come up with different directory layouts on a per-case basis (depending on whether a library already uses a subdirectory, if it supports having its headers moved into subdirectories and so on), confusing users.

You can achieve the same with separate include directories per project and I think it's much cleaner, too:

For example, if you added Boost, its version.hpp would end up in NuGetReferences\Boost\Include\boost\version.hpp and the project would have NuGetReferences\Boost\Include\ added to its include paths. All standard boost-using code (#include <boost/date_time.h>) you can find on the net would work,

Another example: FreeType has a root-level header "ft2build.h" but everything else is in the "freetype" subdirectory. So there would be a NuGetReferences\FreeType\include\ft2build.h and the project would have NuGetReferences\FreeType\include\ added to the include paths. Again, all standard FreeType code out there would work.

Last example, libpng, a library with many root-level headers that all start with the letters "png". There would be a NuGetReferences\LibPng\include\png.h and the project would have NuGetReferences\LibPng\include\ added to the include paths. In this case, the library tries to avoid collisions via the prefix.

May 12, 2012 at 8:10 AM

I agree with Cygon. I find this aproach much more appropriate. What we could do however would be to add a rule in the package analysis which would warn about potential issues if the inc folder layout has "dangerous" constructs. 

The rule could be rather simple: check that no include files end up being visible when using an #include "..." construct in the client project.

What do you think of that ?

May 12, 2012 at 8:38 AM
Edited May 12, 2012 at 8:57 AM

I think the warning would be a good idea.

For some existing libraries, it's just a fact of life and the warning would have to be ignored, but it would at least help police library authors using NuGet :)

EDIT: By the way, I wanted to check it out for myself, but the link to your Git fork you posted comes up with 404 Page not Found.

EDIT2: Nevermind, I found it: http://nuget.codeplex.com/SourceControl/network/forks/teajay/868cppprojectsupport

Jun 1, 2012 at 11:46 PM

all good points, thanks.  I guess I'm coming from an environment where there are already hundreds of poorly created packages with overlap and I'm pulling my hair out at times.  Warning during packaging and potentially redirecting to a documentation page with packaging standards that covers include folders and the overlap issue would be good.  depending on global ownership of prefixes also seems brittle (ft2/png) so hopefully people take that to heart and go with package-named subdirs.

Aug 25, 2012 at 3:50 PM

What's the status on this? Did native C++ support been merged into 1.8 or 2.0 and I missed the notice?

Aug 26, 2012 at 12:28 PM

Apologize for our silence on this. Unfortunately, due to other higher priority work, we haven't looked into supporting native C++ since 1.8. Rest assured that this is on the top of our backlog list. We will address this soon.

Aug 27, 2012 at 8:29 AM

Now this is good news ! 

I haven't updated the fork for some months now and I'm going to need this feature in a couple of weeks. This means I'll be investing some time to bring the fork up to date. I'm really looking forward to this !

Oct 2, 2012 at 7:58 PM

Any ETA on the native C++ support?

Oct 2, 2012 at 10:00 PM

ETA is around December time frame.

Nov 6, 2012 at 8:20 PM

This feature is being push out a bit; now aiming for February (NuGet 2.3), and the contribution is coming from someone outside the core NuGet team, @fearthecowboy.

Further discussion can be found here: http://nuget.codeplex.com/discussions/396720