I have created a number of nuget packages with msbuild targets that help me take care of common boilerplate in my .NET projects. Here I am working on a simple .props
file which is aimed to make the copyright information in the compiled assembly and the nuget package consistent.
Currently I am struggling with the fact that this props file does not get respected in all build phases of a target project.
The props file looks roughly like the following (full source code available in github):
<PropertyGroup>
<CopyrightYearCurrent Condition=" '$(CopyrightYearCurrent)' == '' ">$([System.DateTime]::get_UtcNow().get_Year())</CopyrightYearCurrent>
<CopyrightYear>$(CopyrightYearCurrent)</CopyrightYear>
<!-- CopyrightYearSince may be defined externally in the consuming project and is non-mandatory -->
<CopyrightYear Condition=" '$(Authors)' != '' AND '$(CopyrightYearSince)' != '' ">$(CopyrightYearSince)-$(CopyrightYearCurrent)</CopyrightYear>
</PropertyGroup>
<PropertyGroup>
<Copyright Condition=" '$(Authors)' != '' AND '$(Copyright)' == '' ">Copyright © $(Authors) $(CopyrightYear)</Copyright>
</PropertyGroup>
<PropertyGroup>
<AssemblyCompany Condition=" '$(AssemblyCompany)' == '' AND '$(Authors)' != '' ">$(Authors)</AssemblyCompany>
<AssemblyCopyright Condition=" '$(AssemblyCopyright)' == '' AND '$(Copyright)' != '' ">$(Copyright)</AssemblyCopyright>
</PropertyGroup>
In a target project, I have a DirectoryBuild.props
placed in my root directory, where I need to activate the props file.
My goal is, when I run dotnet build
, or dotnet pack
from the command line, the Copyright-related information from msbuild to propagate both to the assembly attributes, and to the nuget package.
Initially, during the development of the props, I just imported the props file using the MSBuild Import
directive into my DirectoryBuild.props
, and all was working as expected.
Because the props looked quite generic I decided to create a nuget package out of it so I can reuse it in more than a single project, and maintain it from a central place. Then I replaced the Import
of the props file inside of DirectoryBuild
with a PackageReference
directive.
Now, when I execute dotnet pack
, the produced nuget package (and the respective nuspec file which is auto-generated in the obj folder) no longer contain the copyright
field. At the same time, the compiled dll files have their copyright information correctly applied.
I have examined the complete msbuild output for both scenarios (using the command dotnet build -pp:msbuild.xml
) and there are no significant difference in the import order of the props file from the package vs the manually imported file from Directory.Build.props
, and so I am stuck with understanding the observed behaviour.
Here is the output of dotnet --info
if it is of any use to someone:
.NET SDK (reflecting any global.json): Version: 5.0.202 Commit: db7cc87d51
Runtime Environment: OS Name: Windows OS Version: 10.0.19042 OS Platform: Windows RID: win10-x64 Base Path: C:\Program Files\dotnet\sdk\5.0.202\
Host (useful for support): Version: 5.0.5 Commit: 2f740adc14
Update
Just to weed out any suspicions, the nuget package is properly built (the name of the package and the targets it imports are the same) and my IDE (JetBrains Rider) correctly detects that the .props
file from the nuget package is loaded.
Also, CopyrightYearSince
and Authors
are defined in my Directory.Build.props
before the PackageReference
directive.
Update 2
It seems the issue occurs only when generating the automatically produced nuspec file. Every override in a props file of a property that should take part in the nuspec is ignored, however, it is used appropriately in the other build tasks. The problem disapears if the props file is directly referred to, as opposed to being used from a nuget package.
It looks like the issue is more complex, because it happens when cross-targeting projects are involved.
Thanks to a github issue I got more insight on how the GenerateNuspec
task is working with imported msbuild tasks, props and targets, so I came to a solution for my own problem. The details below:
The use-case where the problematic behavior is observed is because:
build
, but not under the buildCrossTargeting
folders.GenerateNuspec
flow will only include custom props/targets present in the buildCrossTargeting
folder, thus my targets got ignoredbuild
and buildCrossTargeting
, the issue disappeared.Conclusion -- be very careful when creating your own msbuild targets as nuget packages -- scenarios such as cross-targeting projects need special handling!