Adding AssemblyMetadataAttribute using new SDK project, with MSBuild
Stuart Lang
Posted on March 10, 2019
Now that we have the new project system, and we can define common assembly info in our .csproj
, we can say good-bye to AssemblyInfo.cs
, well, I still see these left around for general assembly attributes.
For example it is quite common to see an InternalsVisibileTo.cs
file these days, instead of AssemblyInfo.cs
, see here for an example.
However what if you want to add your own assembly attribute with a value you want to pass in as an MSBuild property? For example, an AssemblyMetadataAttribute
that contains a git commit hash?
Well, we are in luck, there is an AssemblyAttribute
item we can add to our ItemGroup! If we had a property named CommitHash
we could write the following:
<AssemblyAttribute Include="System.Reflection.AssemblyMetadataAttribute" Condition="$(CommitHash) != ''" >
<_Parameter1>CommitHash</_Parameter1>
<_Parameter2>$(CommitHash)</_Parameter2>
</AssemblyAttribute>
Great! One last thing, we need to say when this is going to happen, and that is before CoreGenerateAssemblyInfo
, so:
<Target Name="AddGitMetadaAssemblyAttributes"
BeforeTargets="CoreGenerateAssemblyInfo">
<ItemGroup>
<AssemblyAttribute Include="System.Reflection.AssemblyMetadataAttribute" Condition="$(CommitHash) != ''" >
<_Parameter1>CommitHash</_Parameter1>
<_Parameter2>$(CommitHash)</_Parameter2>
</AssemblyAttribute>
</ItemGroup>
</Target>
Cool. But wait! It doesn't always work. Sometimes when I do a build, the value doesn't change. What gives?
So it turns out in .NET SDK 2 and up, there are lots of measures to improve performance, one of which is the <AssemblyName>.AssemblyInfoInputs.cache
file, which appears in the obj
folder, and just contains a hash of the AssemblyInfo
inputs as you'd expect.
The hash is calculated internally only by the _Parameter1
values, so in our example where we put the varying data in _Parameter2
, this doesn't bust the cache. We can see the logic for this here in CreateGeneratedAssemblyInfoInputsCacheFile
.
As a hacky workaround, we can temporarily add our values to _Parameter1
then remove them after the hash is generated. Like this:
<Target Name="GitMetadataAssemblyInfoCacheFileFix"
BeforeTargets="CreateGeneratedAssemblyInfoInputsCacheFile" >
<ItemGroup>
<AssemblyAttribute Include="TemporaryAdditionalHashItem" Condition=" $(CommitHash) != '' ">
<_Parameter1>$(CommitHash)</_Parameter1>
</AssemblyAttribute>
</ItemGroup>
</Target>
<Target Name="CleanupTemporaryAdditionalHashItem"
AfterTargets="CreateGeneratedAssemblyInfoInputsCacheFile;AddGitMetadaAssemblyAttributes" >
<ItemGroup>
<AssemblyAttribute Remove="TemporaryAdditionalHashItem" />
</ItemGroup>
</Target>
Now we recompile whenever there is a change to our added value. For the end result, see here.
UPDATE: In the upcoming SDK at the time of writing (2.1.300), this hack is no longer required as @natemcmaster has fixed it here. Hurray!
Posted on March 10, 2019
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.