Ethan Reesor
Ethan Reesor

Reputation: 2180

List defined preprocessor symbols for C#

When running dotnet, msbuild, or csc, I want to output a list of defined preprocessor symbols, similar to gcc -dM -E. How can I do this?

Upvotes: 1

Views: 755

Answers (1)

rmunn
rmunn

Reputation: 36688

The defined preprocessor symbols are listed in a proprety called DefineConstants. To echo them, you could add a target to your project file like the following:

<Target Name="EchoDebugInfo" BeforeTargets="CoreCompile">
    <Message Importance="high" Text="Just before building, current compile defines are $(DefineConstants)"></Message>
</Target>

In my test run (using dotnet build with no extra parameters), this printed:

Just before building, current compile defines are TRACE;DEBUG;NETCOREAPP;NETCOREAPP2_2

Note that if you omit Importance="high", the importance of the message defaults to "normal", which won't show in the default verbosity of dotnet build. Setting Importance="high" allowed me to get the output without changing the default verbosity of the dotnet build command.

BTW, if you try to define the BeforeBuild target as suggested in the Visual Studio docs, you'll discover that it doesn't work if you're using the new .Net Core-style projects (e.g., <Project Sdk="Microsoft.NET.Sdk">). This is because the SDK project is auto-imported after your project file, so you'll see something similar to this message in the build logs:

Overriding target "BeforeBuild" in project "/home/rmunn/path/to/project/Project.fsproj" with target "BeforeBuild" from project "/usr/share/dotnet/sdk/3.0.100/Microsoft.Common.CurrentVersion.targets".

And then your BeforeBuild target doesn't work. There's a note in the MSDN docs that explains this (emphasis in original):

SDK-style projects have an implicit import of targets after the last line of the project file. This means that you cannot override default targets unless you specify your imports manually as described in How to: Use MSBuild project SDKs.

If you need full control over when the SDK project is imported, then that's the way to go. But for this simple use case, I prefer to define my own target and use BeforeTargets="CoreCompile" to place it in the correct place in the build order.

Upvotes: 3

Related Questions