Home

Awesome

Pekspro.BuildInformationGenerator

Build status NuGet

This project simplifies the process of adding build information to your .NET projects. It uses a source generator to embed details like build time, commit ID and branch directly into your code.

By default, the values are faked in debug mode. This can be changed in the [BuildInformation] attribute with the FakeIfDebug property.

Usage

Create a new partial class in your project and add the [BuildInformation] (from the Pekspro.BuildInformationGenerator namespace) attribute and define which information you want. For example:

[BuildInformation(AddBuildTime = true, AddGitCommitId = true)]
partial class MyBuildInformation
{

}

Constants will automatically be added to this class that you can use like this:

Console.WriteLine($"Build time: {MyBuildInformation.BuildTime}");
Console.WriteLine($"Commit id: {MyBuildInformation.Git.CommitId}");

Installation

Add the package to your application with:

dotnet add package Pekspro.BuildInformationGenerator

This adds a <PackageReference> to your project. It's recommended that you also add the attributes PrivateAssets and ExcludeAssets like below to exclude the source generator to your final assembly:

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net8.0</TargetFramework>
  </PropertyGroup>

  <ItemGroup>
      <PackageReference Include="Pekspro.BuildInformationGenerator" Version="0.2.0" 
        PrivateAssets="all" ExcludeAssets="runtime" />
  </ItemGroup>
</Project>

Setting PrivateAssets="all" means any projects referencing this one won't get a reference to the Pekspro.BuildInformationGenerator package.

Setting ExcludeAssets="runtime" ensures the Pekspro.BuildInformationGenerator.Attributes.dll file is not copied to your build output (it is not required at runtime).

Configuration

The [BuildInformation] attribute has a number of properties you can set to control the generated class.

PropertyDescription
AddBuildTimeBuild time (in UTC).
AddLocalBuildTimeLocal build time.
AddAssemblyVersionAssembly version.
AddOSVersionOS version of the machine where the build happens.
AddGitCommitIdCommit id.
AddGitBranchBranch name.
AddDotNetSdkVersion.NET SDK version.
AddWorkloadMauiVersionWorkload for .NET MAUI.
AddWorkloadWasmToolsVersionWorkload for WebAssembly tools.

If everything is set to true, the generated class will look like this:

static partial class BuildInfoAll
{

    /// <summary>
    /// Build time: 2024-06-22 09:57:54
    /// Value was taken from the system clock.
    /// </summary>
    public static readonly global::System.DateTime BuildTime = new global::System.DateTime(638546470747876765L, global::System.DateTimeKind.Utc);

    /// <summary>
    /// Local build time: 2024-06-22 11:57:54 (+02:00)
    /// Value was taken from the system clock.
    /// </summary>
    public static readonly global::System.DateTimeOffset LocalBuildTime = new global::System.DateTimeOffset(638546542747876765L, new global::System.TimeSpan(72000000000));

    /// <summary>
    /// Build information related to git.
    /// </summary>
    static public partial class Git
    {

        /// <summary>
        /// The commit id in git at the time of build.
        /// Value was taken from the AssemblyInformationalVersion attribute.
        /// </summary>
        public const string CommitId = "552a8218395c744446b12d2e7a2662ce19ddecbb";

        /// <summary>
        /// The short commit id in git at the time of build.
        /// Value was taken from the AssemblyInformationalVersion attribute.
        /// </summary>
        public const string ShortCommitId = "552a8218";

        /// <summary>
        /// The git branch used at build time.
        /// Value was taken from the git branch command.
        /// </summary>
        public const string Branch = "main";

    }

    /// <summary>
    /// Version of the assembly.
    /// Value was taken from assembly version attribute.
    /// </summary>
    public const string AssemblyVersionString = "0.2.0.0";

    /// <summary>
    /// OS version of the building machine.
    /// Value was taken from Environment.OSVersion.
    /// </summary>
    public const string OSVersion = "Microsoft Windows NT 10.0.22631.0";

    /// <summary>
    /// .NET SDK version used at build time.
    /// Value was taken from the dotnet --version command.
    /// </summary>
    public const string DotNetSdkVersion = "8.0.205";

    /// <summary>
    /// Build information related to .NET Workloads.
    /// </summary>
    static public partial class Workloads
    {

        /// <summary>
        /// MAUI version used at build time.
        /// Value was taken from the dotnet workload list command.
        /// </summary>
        public const string MauiVersion = "8.0.7/8.0.100";

        /// <summary>
        /// wasm-tools version used at build time.
        /// Value was taken from the dotnet workload list command.
        /// </summary>
        public const string WasmToolsVersion = "";

    }

}

You can view your generated code by right clicking on your class name and selecting Go to definition.

Another option is to add this to your .csproj file:

<PropertyGroup>
  <EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
  <CompilerGeneratedFilesOutputPath>$(BaseIntermediateOutputPath)\$(Configuration)\GeneratedFiles</CompilerGeneratedFilesOutputPath>
</PropertyGroup>

You will then find the file in the obj directory.

Performance

You can specify if you want to have faked or real values:

PropertyDefaultDescription
FakeIfDebugtrueFake values if DEBUG is defined.
FakeIfReleasefalseFake values if RELEASE is defined.

To get the real values, BuildInformationGenerator might need to start a process. This should be fast, but probably nothing you want during normal development. In Visual Studio, a source generator can be called very often (every keystroke), so try to use fake values in development.

PropertyData source
BuildTimeDateTimeOffset.
LocalBuildTimeDateTimeOffset.
AssemblyVersionAssemblyVersion attribute.
OSVersionEnvironment.OSVersion.
Git.CommitIdAssemblyInformationalVersionAttribute attribute, by default but also the process git rev-parse HEAD as a fallback.
Git.BranchProcess git branch --show-current. The environment variable BUILD_SOURCEBRANCHNAME might be used instead, that is automatically set in Azure Devops where git cannot be used to the the branch.
DotNetSdkVersionProcess dotnet --version.
Workloads.MauiVersionProcess dotnet workload list.
Workloads.WasmToolsVersionProcess dotnet workload list

Requirements

This source generator requires the .NET 7 SDK. You can target earlier frameworks like .NET Core 3.1 etc, but the SDK must be at least 7.0.100.

Credits

This project is heavily inspired by the NetEscapades.EnumGenerators project.