28

So, both this and this are pretty clear. Simply pass /p:DefineConstants="SYMBOL"

It doesn't work at all for me, even in a test project. I'm expecting that passing /p:DefineConstants="SYMBOL" will override any conditional compilation constants defined in the csproj. Not the case however...

Full code listing below:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DefineConstants
{
    class Program
    {
        static void Main(string[] args)
        {
#if DEV
            Console.WriteLine("DEV");
#elif UAT 
            Console.WriteLine("UAT");
#else
            Console.WriteLine("No environment provided");
#endif
        }
    }
}

.csproj file is:

<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup>
    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
    <Platform Condition=" '$(Platform)' == '' ">x86</Platform>
    <ProductVersion>8.0.30703</ProductVersion>
    <SchemaVersion>2.0</SchemaVersion>
    <ProjectGuid>{57A2E870-0547-475C-B0EB-66CF9A2FE417}</ProjectGuid>
    <OutputType>Exe</OutputType>
    <AppDesignerFolder>Properties</AppDesignerFolder>
    <RootNamespace>DefineConstants</RootNamespace>
    <AssemblyName>DefineConstants</AssemblyName>
    <TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
    <FileAlignment>512</FileAlignment>
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
    <PlatformTarget>x86</PlatformTarget>
    <DebugSymbols>true</DebugSymbols>
    <DebugType>full</DebugType>
    <Optimize>false</Optimize>
    <OutputPath>bin\Debug\</OutputPath>
    <DefineConstants>TRACE;DEBUG</DefineConstants>
    <ErrorReport>prompt</ErrorReport>
    <WarningLevel>4</WarningLevel>
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
    <PlatformTarget>x86</PlatformTarget>
    <DebugType>pdbonly</DebugType>
    <Optimize>true</Optimize>
    <OutputPath>bin\Release\</OutputPath>
    <DefineConstants>TRACE</DefineConstants>
    <ErrorReport>prompt</ErrorReport>
    <WarningLevel>4</WarningLevel>
  </PropertyGroup>
  <ItemGroup>
    <Reference Include="System" />
    <Reference Include="System.Core" />
    <Reference Include="System.Xml.Linq" />
    <Reference Include="System.Data.DataSetExtensions" />
    <Reference Include="System.Data" />
    <Reference Include="System.Xml" />
  </ItemGroup>
  <ItemGroup>
    <Compile Include="Program.cs" />
    <Compile Include="Properties\AssemblyInfo.cs" />
  </ItemGroup>
  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
       Other similar extension points exist, see Microsoft.Common.targets.
  <Target Name="BeforeBuild">
  </Target>
  <Target Name="AfterBuild">
  </Target>
  -->
</Project>

built using:

C:\Windows\Microsoft.NET\Framework\v4.0.30319\msbuild DefineConstants.sln /p:DefineConstants="DEV;DEBUG" /p:Configuration="Debug" /p:Platform="x86"

Running the program shows:

No environment provided

Help!

Community
  • 1
  • 1
Steven P
  • 1,956
  • 1
  • 16
  • 17

3 Answers3

32

Using DefineConstants definitely does work. Which means you are doing something wrong. My guess is you first built the project without defining anything, then built it again. MSBuild will then see the project was built already and won't build again, but just copy output files. You should post the output of msbuild so we can be sure, but for reference I compiled your project using the necessary switches only and here is the result (full msbuild output omitted):

> msbuild ConsoleApplication1.sln /p:DefineConstants="DEV" /t:Rebuild
....
Building solution configuration "Debug|x86".
Project ... is building ConsoleApplication1.csproj" (Rebuild target(s)).
...
> ConsoleApplication1\bin\Debug\DefineConstants.exe
DEV
> msbuild ConsoleApplication1.sln /p:DefineConstants="UAT" /t:Rebuild
...
> ConsoleApplication1\bin\Debug\DefineConstants.exe
UAT
> msbuild ConsoleApplication1.sln /t:Rebuild
...
> ConsoleApplication1\bin\Debug\DefineConstants.exe
No environment provided 
stijn
  • 34,664
  • 13
  • 111
  • 163
  • 1
    Is it documented somewhere that Rebuild is required in order for DefineConstants to work, or is this just implied common sense? So there is no way to do incremental builds using DefineConstants? – JohnZaj Jul 17 '14 at 16:41
  • @jJack Depends on what you mean with *incremental*: if you first edit A.cs, then Build, then edit B.cs and Build again, it should work. Though I'm not 100% sure that when changing DefineConstants before building B.cs would still affect A.cs - you can just try it of course. – stijn Jul 18 '14 at 06:53
0

It seems you are not passing conditional compilation symbol. That's why you are getting output as : No environment provided. Just go to project properties and than click on build tab (left side below application). you will find one box asking for conditional compilation symbol. Just write your constants as per your desired output. for ex. in your example, to print "DEV" write DEV at conditional compilation box and rebuild your project. i am sure it will work.

Note: if you want pass any symbol than as per your code it will print : No environment selected.

  • 3
    Be cautious when answering an old question. This one is over 5 years old and has an accepted answer. This one currently adds little to nothing extra. - From [Review](https://stackoverflow.com/review) – Takarii Aug 01 '17 at 05:54
  • Hi, its true. But why i put this ans, it might help other people looking for same question. – Sanket Raval Aug 02 '17 at 07:13
-1

It will work if you alter the output directory depending on the conditional compilation symbol:

<OutputPath>bin\$(Configuration)\$(DefineConstants)\</OutputPath>

This will convince the incremental build to do its work when you change the property in console input.

For a real solution, you'd likely pass a different property and used some more elaborate authoring to define constants and output path.

Update

For this to work, the DefineConstants property must be defined prior the OutputPath property in each PropertyGroup in your .csproj. Otherwise, the DefineConstants property is likely to be empty at the time when the OutputPath property is defined.

tm1
  • 1,180
  • 12
  • 28