Previously, I wrote about using NuGet for software components, which are still in active development. One of the most important factors was the capability to override the nuget package’s content with content fetched from a directory, e.g., a working copy clone. The key element for this was a MSBuild variable
The original plan was to edit this variable using a project property page. While having a UI is nice, this has proven not to work on larger projects. The reason is simple: in larger projects, we talk about a vs solution with multiple vc projects, and many of these projects might reference our NuGet package. If we now need to switch to our local directory, we need to adjust the project properties for every project consuming the package. This is tiring and error prone. Forget to adjust just one project and you might end up with inconsistent builds. Therefore, I was seeking a more centralized configuration.
I updated the code examples to reflect the updates I recently came up with.
Dev. Override – II
The principle idea of having a variable to control the override remains valid. The targets in your nuget might look like this:
<?xml version="1.0" encoding="utf-8"?> <Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <!-- ... --> <!-- Compiler settings: defines and includes --> <ItemDefinitionGroup Condition="'$(NugetDevPackageTest_testLib_DevDir)' == ''"> <ClCompile> <PreprocessorDefinitions>HAS_NUGETDEVPACKAGETEST_TESTLIB;%(PreprocessorDefinitions)</PreprocessorDefinitions> <AdditionalIncludeDirectories>$(MSBuildThisFileDirectory)include\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> </ClCompile> </ItemDefinitionGroup> <ItemDefinitionGroup Condition="'$(NugetDevPackageTest_testLib_DevDir)' != ''"> <ClCompile> <PreprocessorDefinitions>HAS_NUGETDEVPACKAGETEST_TESTLIB;HAS_NUGETDEVPACKAGETEST_TESTLIB_DEVDIR;%(PreprocessorDefinitions)</PreprocessorDefinitions> <AdditionalIncludeDirectories>$(NugetDevPackageTest_testLib_DevDir)\Project\include\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> </ClCompile> </ItemDefinitionGroup> <!-- ... --> </Project>
The obvious question is the definition of our DevDir variable.
For this is propose a central msbuild xml at the level of the vs solution!
We include it in our targets file, right after the root Project tag starts:
<ImportGroup> <Import Project="$(SolutionDir)packagesoverride.xml.user" Condition="Exists('$(SolutionDir)packagesoverride.xml.user') and '$(HAS_packagesoverride)' != 'True'" /> </ImportGroup>
This line imports the msbuild xml file, if it exists. Notice, how the file name is generic and not related to our specific package. This is because multiple nuget packages can share this file!
The content of this central configuration is very simple:
<?xml version="1.0" encoding="utf-8"?> <Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <PropertyGroup> <HAS_packagesoverride>True</HAS_packagesoverride> <NugetDevPackageTest_testLib_DevDir>C:\Dev\SomeProject\Dir</NugetDevPackageTest_testLib_DevDir> </PropertyGroup> </Project>
Now if you need to override a nuget package for your whole solution, just create this file!
Drawback 1: If the file did not exist previously, an you create it, then you need to rebuild all projects with nugets referencing this package. Because they might be affected by this file.
However, once the file does exist, changes to the file are currectly and automatically detected by visual studio, and build operations are correctly triggered in the affected projects. So, it might be a nice idea to keep a file with an empty property group in place, just in case.
If you need to override multiple nugets at once, just add multiple entries into this one property group.
Drawback 2: There is no UI. So you need to edit it in your favorite text editor, meaning, you are prone to all typing errors you can come up with.
All in all, I believe this central file for the nuget override configuration is an improvement.