.NET Core Compile Time Flags

If you are writing a program in .NET Core and want to build a self contained executable in release mode and use compile time flags there are a few tricks to get it to work. In this post I document how I got it working.

The example code is a simple program that prints out if a compile time flag is set or not. I am using docker to compile it but the same commands and setup should work without docker.

Docker file

The trick is to run the build with a parameter and then publish what was built using --no-build

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
FROM mcr.microsoft.com/dotnet/core/sdk:3.1-alpine

# setup directory and files
RUN mkdir -p /app
WORKDIR /app
COPY ./test.cs ./
COPY ./test.csproj ./

# restore dependencies if you have them
RUN dotnet restore

# build and publish with the flag set
RUN dotnet build -r linux-musl-x64 --configuration Release -p:MyFlag=true
RUN dotnet publish -r linux-musl-x64 --configuration Release --no-build --self-contained true -o ./artifacts/linux-flag

# build and publish with the flag not set set
RUN dotnet build -r linux-musl-x64 --configuration Release
RUN dotnet publish -r linux-musl-x64 --configuration Release --no-build --self-contained true -o ./artifacts/linux-noflag

# run with the flag and without
RUN ./artifacts/linux-flag/test && ./artifacts/linux-noflag/test
CMD ./artifacts/linux-flag/test && ./artifacts/linux-noflag/test

Project

The MyFlag parameter passed in on the command line is used to conditionally define a constant that the compiler will use.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<Project Sdk="Microsoft.NET.Sdk">

    <PropertyGroup>
        <OutputType>Exe</OutputType>
        <TargetFramework>netcoreapp3.1</TargetFramework>
        <RuntimeIdentifier>linux-musl-x64</RuntimeIdentifier>
        <RuntimeIdentifiers>win7-x64;osx.10.11-x64;linux-musl-x64</RuntimeIdentifiers>
        <PublishTrimmed>true</PublishTrimmed>
        <PublishSingleFile>true</PublishSingleFile>
        <FileVersion>1.0.0</FileVersion>
        <Version>1.0.0</Version>
    </PropertyGroup>
    <PropertyGroup Condition="$(MyFlag) != ''">
      <DefineConstants>MYFLAG</DefineConstants>
    </PropertyGroup>

    <ItemGroup>
    </ItemGroup>

</Project>

C# Code

Some code to test the builds.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
using System;

namespace MyFlagTest
{
  class Program
  {
    static void Main(string[] args)
    {
#if MYFLAG
      Console.WriteLine("MYFLAG is set");
#else
      Console.WriteLine("MYFLAG is not set");
#endif
    }
  }
}