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.
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
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>
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}