.NET Core Compile Time Flags

23 May 2020

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

1FROM mcr.microsoft.com/dotnet/core/sdk:3.1-alpine
2
3# setup directory and files
4RUN mkdir -p /app
5WORKDIR /app
6COPY ./test.cs ./
7COPY ./test.csproj ./
8
9# restore dependencies if you have them
10RUN dotnet restore
11
12# build and publish with the flag set
13RUN dotnet build -r linux-musl-x64 --configuration Release -p:MyFlag=true
14RUN dotnet publish -r linux-musl-x64 --configuration Release --no-build --self-contained true -o ./artifacts/linux-flag
15
16# build and publish with the flag not set
17RUN dotnet build -r linux-musl-x64 --configuration Release
18RUN dotnet publish -r linux-musl-x64 --configuration Release --no-build --self-contained true -o ./artifacts/linux-noflag
19
20# run with the flag and without
21RUN ./artifacts/linux-flag/test && ./artifacts/linux-noflag/test
22CMD ./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<Project Sdk="Microsoft.NET.Sdk">
2
3    <PropertyGroup>
4        <OutputType>Exe</OutputType>
5        <TargetFramework>netcoreapp3.1</TargetFramework>
6        <RuntimeIdentifier>linux-musl-x64</RuntimeIdentifier>
7        <RuntimeIdentifiers>win7-x64;osx.10.11-x64;linux-musl-x64</RuntimeIdentifiers>
8        <PublishTrimmed>true</PublishTrimmed>
9        <PublishSingleFile>true</PublishSingleFile>
10        <FileVersion>1.0.0</FileVersion>
11        <Version>1.0.0</Version>
12    </PropertyGroup>
13    <PropertyGroup Condition="$(MyFlag) != ''">
14      <DefineConstants>MYFLAG</DefineConstants>
15    </PropertyGroup>
16
17    <ItemGroup>
18    </ItemGroup>
19
20</Project>

C# Code

Some code to test the builds.

1using System;
2
3namespace MyFlagTest
4{
5  class Program
6  {
7    static void Main(string[] args)
8    {
9#if MYFLAG
10      Console.WriteLine("MYFLAG is set");
11#else
12      Console.WriteLine("MYFLAG is not set");
13#endif
14    }
15  }
16}