Skip to content

Instantly share code, notes, and snippets.

@jonathanduke
Last active September 27, 2023 17:43
Show Gist options
  • Save jonathanduke/ab4fc1880e8b245d3f939b122f301938 to your computer and use it in GitHub Desktop.
Save jonathanduke/ab4fc1880e8b245d3f939b122f301938 to your computer and use it in GitHub Desktop.
Build targets for Visual Studio to automatically include Git commit hash and other build metadata in assembly info
<!--
Based on: https://gist.github.com/jonathanduke/ab4fc1880e8b245d3f939b122f301938#file-buildassemblyinfo-targets
Dependent on: https://gist.github.com/jonathanduke/ab4fc1880e8b245d3f939b122f301938#file-gitbuildprops-targets
Public domain: http://unlicense.org/
Modify as you wish, but you are encouraged to leave this comment for future reference in case the original is updated.
-->
<Project>
<Import Project="GitBuildProps.targets" />
<Target Name="BuildAssemblyInfo" BeforeTargets="BeforeBuild" DependsOnTargets="InitializeSourceControlInformation" Condition=" '$(Configuration)' == 'Release' ">
<PropertyGroup Condition="!$(Deterministic)">
<GenerateAssemblyFileVersionAttribute>false</GenerateAssemblyFileVersionAttribute>
</PropertyGroup>
<ItemGroup Condition="!$(Deterministic)">
<AssemblyAttribute Include="AssemblyFileVersion">
<_Parameter1>$(VersionPrefix.Substring(0,$(VersionPrefix.LastIndexOf('.')))).$([System.String]::Format("{0:%d}.{1:0}",$([System.DateTime]::Now.Subtract($([System.DateTime]::Parse("2000-01-01")))),$([MSBuild]::Divide($([System.DateTime]::Now.TimeOfDay.TotalSeconds),2))))</_Parameter1>
</AssemblyAttribute>
</ItemGroup>
<ItemGroup Condition=" !$(Deterministic) And !('$(TargetFrameworkIdentifier)' == '.NETFramework' And $([MSBuild]::VersionLessThan($(TargetFrameworkVersion), 4.5))) ">
<AssemblyAttribute Include="AssemblyMetadata">
<_Parameter1>BuildDate</_Parameter1>
<_Parameter2>$([System.String]::Format("{0:yyyy-MM-ddTHH:mm:sszzz}",$([System.DateTime]::Now)))</_Parameter2>
</AssemblyAttribute>
</ItemGroup>
<ItemGroup Condition=" '$(SourceRevisionId)' != '' And !('$(TargetFrameworkIdentifier)' == '.NETFramework' And $([MSBuild]::VersionLessThan($(TargetFrameworkVersion), 4.5))) ">
<AssemblyAttribute Include="AssemblyMetadata">
<_Parameter1>SourceRevisionId</_Parameter1>
<_Parameter2>$(SourceRevisionId)</_Parameter2>
</AssemblyAttribute>
</ItemGroup>
</Target>
</Project>
<!--
Based on: https://gist.github.com/jonathanduke/ab4fc1880e8b245d3f939b122f301938#file-directory-build-props
Public domain: http://unlicense.org/
Modify as you wish, but you are encouraged to leave this comment for future reference in case the original is updated.
-->
<Project>
<PropertyGroup>
<Product>Sample</Product>
<Company>Example, Inc.</Company>
<Copyright>Copyright © $([System.String]::Format("2019-{0:yyyy}",$([System.DateTime]::Now)).Replace("2019-2019", "2019")) $(Company)</Copyright>
<Authors>$(Company)</Authors>
</PropertyGroup>
<PropertyGroup Condition=" '$(TargetFramework)$(Description)' == '' ">
<Description>$(MSBuildProjectName)</Description>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' != 'Release' And '$(VersionSuffix)' == '' ">
<VersionSuffix>$(Configuration.ToLower())</VersionSuffix>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' != 'Release' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<DefineConstants>$(DefineConstants);DEBUG;TRACE</DefineConstants>
<Optimize>false</Optimize>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
<DebugType>pdbonly</DebugType>
<DefineConstants>$(DefineConstants);RELEASE;TRACE</DefineConstants>
<Optimize>true</Optimize>
<PathMap>$(SolutionDir)=$(SolutionName)</PathMap>
</PropertyGroup>
<PropertyGroup>
<LangVersion>latest</LangVersion>
<Deterministic>false</Deterministic>
</PropertyGroup>
</Project>
<!--
Based on: https://gist.github.com/jonathanduke/ab4fc1880e8b245d3f939b122f301938#file-directory-build-targets
Dependent on: https://gist.github.com/jonathanduke/ab4fc1880e8b245d3f939b122f301938#file-buildassemblyinfo-targets
Public domain: http://unlicense.org/
Modify as you wish, but you are encouraged to leave this comment for future reference in case the original is updated.
-->
<Project>
<Import Project="BuildAssemblyInfo.targets" />
<PropertyGroup Condition=" '$(VersionPrefix)' == '' ">
<VersionPrefix>3.2.1</VersionPrefix>
</PropertyGroup>
<PropertyGroup Condition=" '$(VersionSuffix)' == '' ">
<VersionSuffix>beta</VersionSuffix>
</PropertyGroup>
<PropertyGroup Condition=" '$(AssemblyVersion)' == '' And '$(VersionPrefix)' != '' ">
<AssemblyVersion>$(VersionPrefix.Substring(0,$(VersionPrefix.LastIndexOf('.')))).0.0</AssemblyVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
<SignAssembly>true</SignAssembly>
<AssemblyOriginatorKeyFile>$(SolutionDir)$(SolutionName).snk</AssemblyOriginatorKeyFile>
</PropertyGroup>
<PropertyGroup Condition="$(GeneratePackageOnBuild)">
<IncludeSymbols>True</IncludeSymbols>
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
</PropertyGroup>
<Target Name="BasePathMapOnSourceRevision" BeforeTargets="BeforeBuild" DependsOnTargets="InitializeSourceControlInformation" Condition=" '$(Configuration)' == 'Release' ">
<PropertyGroup Condition=" '$(SourceRevisionId)' != '' ">
<PathMap>$(SolutionDir)=$(SolutionName)\$(SourceRevisionId)</PathMap>
</PropertyGroup>
</Target>
<Target Name="PostPackNuGetPush" AfterTargets="Pack" Condition="$(GeneratePackageOnBuild)">
<Exec Command="IF EXIST &quot;$(SolutionDir)&quot; COPY /Y &quot;$(OutputPath)$(PackageId).$(PackageVersion).*nupkg&quot; &quot;$(SolutionDir)&quot;" />
</Target>
</Project>
<!--
Based on: https://gist.github.com/jonathanduke/ab4fc1880e8b245d3f939b122f301938#file-gitbuildprops-targets
Public domain: http://unlicense.org/
Modify as you wish, but you are encouraged to leave this comment for future reference in case the original is updated.
-->
<Project>
<Target Name="SetSourceRevisionId" BeforeTargets="InitializeSourceControlInformation" Condition=" '$(SourceRevisionId)' == '' And '$(Configuration)' == 'Release' ">
<Exec Command="git describe --long --always --dirty --exclude=*" EchoOff="true" StandardOutputImportance="low" ConsoleToMSBuild="true">
<Output TaskParameter="ConsoleOutput" PropertyName="SourceRevisionId" />
</Exec>
</Target>
</Project>
/*
Based on: https://gist.github.com/jonathanduke/ab4fc1880e8b245d3f939b122f301938#file-packaging-cs
Public domain: http://unlicense.org/
Modify as you wish, but you are encouraged to leave this comment for future reference in case the original is updated.
*/
using System;
using System.Diagnostics;
using System.IO;
using System.Reflection;
public class Packaging
{
public static void Main(string[] args)
{
if (args.Length > 1)
{
var nugetPath = new FileInfo(args[0]).FullName;
var nuspec = new FileInfo(args[1]).FullName;
var repoPath = new FileInfo(args[2]).FullName;
if (File.Exists(nugetPath) && File.Exists(nuspec) && Directory.Exists(repoPath))
{
var assembly = typeof(Packaging).Assembly;
var version = assembly.GetCustomAttribute<AssemblyInformationalVersionAttribute>()?.InformationalVersion.Split('+')[0];
var authors = assembly.GetCustomAttribute<AssemblyCompanyAttribute>()?.Company;
var copyright = assembly.GetCustomAttribute<AssemblyCopyrightAttribute>()?.Copyright;
var process = Process.Start(new ProcessStartInfo(nugetPath)
{
Arguments = $@"pack ""{nuspec}"" -NoPackageAnalysis -OutputDirectory ""{repoPath}"" -Properties version=""{version}"";author=""{authors}"";copyright=""{copyright}""",
CreateNoWindow = true,
UseShellExecute = false,
RedirectStandardError = true,
RedirectStandardOutput = true
});
process.OutputDataReceived += (sender, e) => { if (!string.IsNullOrWhiteSpace(e.Data)) Console.WriteLine(e.Data); };
process.BeginOutputReadLine();
process.ErrorDataReceived += (sender, e) => { if (!string.IsNullOrWhiteSpace(e.Data)) Console.Error.WriteLine(e.Data); };
process.BeginErrorReadLine();
process.WaitForExit();
}
}
}
}
<!--
Based on: https://gist.github.com/jonathanduke/ab4fc1880e8b245d3f939b122f301938#file-packaging-csproj
Dependent on: https://gist.github.com/jonathanduke/ab4fc1880e8b245d3f939b122f301938#file-packaging-cs
Public domain: http://unlicense.org/
Modify as you wish, but you are encouraged to leave this comment for future reference in case the original is updated.
-->
<Project>
<Import Sdk="Microsoft.NET.Sdk" Project="Sdk.props" />
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net45</TargetFramework>
<NuGetCommandLineVersion Condition=" '$(NuGetCommandLineVersion)' == '' ">5.10.0</NuGetCommandLineVersion>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="NuGet.CommandLine" Version="$(NuGetCommandLineVersion)">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup>
<Import Sdk="Microsoft.NET.Sdk" Project="Sdk.targets" />
<!--
The following configuration makes sure that the program executes during each release build, even if no changes are detected.
-->
<PropertyGroup Condition="'$(Configuration)' == 'Release'">
<PostBuildEvent>"$(TargetPath)" "$(NuGetPackageRoot)\nuget.commandline\$(NuGetCommandLineVersion)\tools\NuGet.exe" "$(SolutionDir)\Website\package.nuspec" "$(SolutionDir)"</PostBuildEvent>
<RunPostBuildEvent>OnBuildSuccess</RunPostBuildEvent>
<GenerateAssemblyFileVersionAttribute>false</GenerateAssemblyFileVersionAttribute>
</PropertyGroup>
<Target Name="CreateBuildAssemblyInfo" BeforeTargets="BeforeCompile" Condition="'$(Configuration)' == 'Release'">
<ItemGroup>
<BuildAssemblyAttributes Include="AssemblyFileVersion">
<_Parameter1>$(VersionPrefix.Substring(0,$(VersionPrefix.LastIndexOf('.')))).$([System.String]::Format("{0:%d}.{1:0}",$([System.DateTime]::Now.Subtract($([System.DateTime]::Parse("2000-01-01")))),$([MSBuild]::Divide($([System.DateTime]::Now.TimeOfDay.TotalSeconds),2))))</_Parameter1>
</BuildAssemblyAttributes>
</ItemGroup>
<WriteCodeFragment Language="C#" OutputDirectory="$(IntermediateOutputPath)" OutputFile="BuildAssemblyInfo.g.cs" AssemblyAttributes="@(BuildAssemblyAttributes)">
<Output TaskParameter="OutputFile" ItemName="Compile" />
<Output TaskParameter="OutputFile" ItemName="FileWrites" />
</WriteCodeFragment>
</Target>
</Project>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment