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