Nuget packages have become the de facto way for .net libraries to be consumed by other projects and interestingly, Microsoft also use this technology to supply some of their C++ libraries – specifically they use this to provide the code used to connect to Xbox Live (Microsoft.Xbox.Live.SDK.Cpp.UWP). This got us thinking as to how to best share common code between our games. This shared code is within a library called BorsukCore.
Initially, we had the following approach to a clean build:
- Build BorsukCore (Includes our custom code, the DirectX toolkit and a few other libraries)
- Build SpacegirlCore
- Build SpacegirlWindowsCore
- Build Spacegirl (Win32 build)
Note that we had an equivalent build step for the UWP build (to cover the MS store / X1) and this doesn’t show the testing projects.
This meant that not only each time that a change was made to BorsukCore, the whole build would be performed, but that was also true for each change on the main game code. This increased the turn around time for each iteration. This wasn’t too bad for SG1, but got annoying when this was SG2 came along.
To that end, we set out to change matters by creating Nuget packages for the various projects built as part of BorsukCore. We mimicked the approach of MS by having separate Nuget packages for header files and .lib files. This left us with:
- BorsukSoftware.Games.BorsukCore – headers
- BorsukSoftware.Games.BorsukCore.x64 – libraries for both debug and release builds
We also have similar packages for our build of GoogleTest (which we use for unit testing the C++ game code), as the implementation of these is identical to the main ones, we don’t go into the details of these.
Structure of the packages
- include (directory)
- debug (directory of libs)
- release (directory of libs)
NB It’s really important that the names of the .targets files are the same as the containing Nuget package otherwise when one tries to add them later in Visual Studio one will get infuriating errors.
Building the packages
There are lots of articles already available on the web detailing how to build the packages. The following are probably the best starting points (we used these to guide us)
Note that article #2 is wrong when it says that VS doesn’t do anything to help. If the .targets files are named consistently with the name of the package then VS will be your friend! This point is made clear in article #3.
Uploading the packages
This entirely depends on the CI process that one uses. We have a CI job which:
- builds the core libraries in both debug and release modes
- Runs the unit tests
- Creates the packages from the .nuspec files
- Uploads them to our internal repository
Consuming the packages
Once the packages have been uploaded, then one can simply add a Nuget reference to them in VS and everything should work. VS will automatically add a link to your .targets file from the project’s file. If this doesn’t happen, then this is usually because the .targets file isn’t named consistently with the name of the Nuget package.
By moving to the nuget packages approach we were able to improve our development experience both by avoiding the need to rebuild everything on each commit (~3 minutes a time) and also making it easier to put together prototypes using the common library.