85

I'm possibly just blind, but is there a command line to specify conditional compilation symbols in MSBUILD?

I currently have this Line in my buildscript:

SET MSBUILD=C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\MSBuild.exe
SET CONFIG=Debug
%MSBUILD% /p:Configuration=%CONFIG% /p:OutputPath=..\..\output source\MyProject\MyProject.csproj

And I'd like to add a condition. In Visual Studio, i can just go into Project Properties => Build => Conditional compilation symbols, but I have not seen that option for msbuild?

Bonus Karma if you know if I can completely override all symbols already specified in the .csproj files to make sure that only the conditionals from my Buildscript go in.

Matt
  • 25,467
  • 18
  • 120
  • 187
Michael Stum
  • 177,530
  • 117
  • 400
  • 535
  • And BTW, this is not a duplicate of http://stackoverflow.com/questions/296147/msbuild-conditional-compilation because the other question has the same title but the answer only includes Visual Studio/Project File modification. – Michael Stum Jan 26 '09 at 14:39

4 Answers4

153

Have you seen this? (most info is in the penultimate post)

/p:DefineConstants="MYSYMBOL1;MYSYMBOL2"
Michael Stum
  • 177,530
  • 117
  • 400
  • 535
Tomalak
  • 332,285
  • 67
  • 532
  • 628
  • 5
    Added the Code, that was it, thanks! It overrides all Constants that may be defined in the .csproj file, which is good as well. – Michael Stum Jan 26 '09 at 15:47
  • 6
    For this to work for me, I was forced to add this to the command line: /t:Rebuild – Dan W Sep 02 '12 at 18:33
  • using xbuild from os x terminal I get `MSBUILD: error MSBUILD0005: Invalid syntax. Property name and value expected as =[]` – Sanandrea Nov 10 '16 at 14:30
  • Worked great. /p:DefineConstants="QCBUILD" My solution has lots of projects in it. This seems to be solution global. Does anyone want to point me to how to get a solution global conditional compilation symbol while using the Visual Studio (not command line)? – user922020 May 04 '18 at 15:10
  • Is there any way to append to the existing defines? – James Esh Dec 18 '18 at 16:03
  • 5
    Note that this will *replace* the existing defines, so if you were relying on things like NETCOREAPP or NETFRAMEWORK being defined, you'll lose those. To append to the existing defines, it's better to add a property in your `.csproj` file like: `$(DefineConstants);FOO;BAR`. – rmunn Sep 24 '19 at 08:03
  • As of MS Build from Visual Studio 2019, this doesn't seem to work for a C++ project - the defined symbols don't get to the command line, passed to the C++ compiler. – Eugene Mayevski 'Callback Feb 12 '21 at 19:08
22

I had to use a space instead of a semicolon a la this post by Björn Lasar: http://www.linqinpark.net/2009/01/13/MSBuildWithMultipleDefineConstants.aspx

Update: the blog has disappeared; retrieved via Internet Archive:

Recently I had to use MSBuild directly to automate some builds. I also had to configure some preprocessor defines based upon a configuration. This is usually done by an Argument like this

"/p:DefineConstants=MY_PREPROC_FLAG"

Nothing special here since there are enough comments on the web about that. Today I needed one Flag more and I used the commandline syntax similar to how I knew it from the IDE:

"/p:DefineConstants=MY_PREPROC_FLAG;YET_ANOTHER_FLAG"

but this one didn't work.

So the point is that if you want to support multiple defines to a project by commandline you'll have to separate them by simple spaces...

"/p:DefineConstants=MY_PREPROC_FLAG YET_ANOTHER_FLAG" 

and it will be added to the (semicolon-separated) Defines from the IDE. Good to know I think...

Ruben Bartelink
  • 59,778
  • 26
  • 187
  • 249
  • How do you test for the existence of these symbols? I tried if '$(SIGN_ASSEMBLY)' == '' goto :exit but if the symbol doesn't exist, you get the same empty string. – Quark Soup Dec 23 '16 at 17:52
  • @MikeDoonsebury one always uses the presence of a value, and its specific value, i.e. `== "True"` - not sure what you mean with the goto exit in msbuild - the equivalent would be to put a `Condition` on the ` – Ruben Bartelink Dec 24 '16 at 09:34
6

/p:DefineConstants is an all or nothing deal.

If you just want to turn off trace symbol, you can't just do it with: msbuild /p:DefineTrace=false

You have to define something to override all the symbols already defined: msbuild /p:DefineConstants="RANDOM-SYMBOL"

Thanks Michael Stum point this hidden rule out I have also wrote a blog about it --- dead link

Regis Portalez
  • 4,675
  • 1
  • 29
  • 41
leliao
  • 91
  • 1
  • 3
  • 1
    "all the symbols" is really important here. If you use /p: DefineConstants to define a constant you will lose all the other defined constant in a project. DefineConstants should contain all the constants need in the project you can not mix and match constants defined in project and defined with DefineConstants – Jitendra Feb 01 '19 at 20:06
1

What is said in the answers is valid for C# code, and also for ASP.NET "codebehind" C# code. For ASP.NET web projects, if you want to do conditional compilation in the ASPX pages as well, it works a bit differently to conditionally render HTML on the page (note I've removed MasterPageFile="..." AutoEventWireup="true" CodeBehind="..." Inherits="..." which you usually have in the <%@ ... %> declaration as well):

<%@ Page Title="MyPage" Language="C#" CompilerOptions="/d:DebugSym1;DebugSym2" %>

<% #if DebugSym1 %>         
    <h4>Section1</h4>
<% #else %>
    <h4>(Section 1 skipped)</h4>
<% #endif %>

<% #if DebugSym2 %>         
    <h4>Section2</h4>
<% #else %>
    <h4>(Section 2 skipped)</h4>
<% #endif %>

If you remove DebugSym1 or DebugSym2 from the CompilerOptions, then the #else part of the relevant #if statement is rendered.

I thought this was worth mentioning for completeness of this topic and can save you time. More you can find in this article, if you're interested.

Matt
  • 25,467
  • 18
  • 120
  • 187