0

I'm using this idea to inject preprocessor definitions from a command line build script using a global named $(DefineConstants).

vcxproj file snippet:

  <PropertyGroup Label="Globals">
    <DefineConstants></DefineConstants>
  </PropertyGroup>
...
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
    <ClCompile>
      <PreprocessorDefinitions>$(DefineConstants);WIN32;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>

My script launches msbuild with the following (abridged) command line:

msbuild.exe Solution.sln /p:DefineConstants=FOO%3BBAR

where FOO%3BBAR is dynamic and comes from any number of user-supplied values. (Using %3B as a separator comes from this thread since using a raw ; character results in an error.)

But the compiler (cl) command line shows that the entire value of $(DefineConstants) is getting placed into a single /D switch instead of getting split into multiple.

ClCompile:
  CL.exe ... /D "FOO;BAR" /D WIN32 /D _WINDOWS

It's as if the semicolons inside the variable aren't expanded. Is there any way to make it produce /D FOO /D BAR?

Summary of things I've tried so far:

msbuild command line results in cl command line comment
/p:DefineConstants=FOO%3BBAR /D "FOO;BAR" wrong: not split into multiple /D
/p:DefineConstants="FOO;BAR" /D "\"FOO" /D "BAR\"" wrong: split, but includes \"
/p:DefineConstants=FOO;BAR n/a error: property not valid
tomocafe
  • 1,425
  • 4
  • 20
  • 35

1 Answers1

1

I tested with the following small test file:

<Project>
  <Target Name="TestProp">
    <Message Text="$(DefineConstants)" />
  </Target>
</Project>

Example commands and outputs:

MSBuild Command Output Comment
1 msbuild test.proj /p:DefineConstants=FOO;BAR MSB1006 error
2 msbuild test.proj /p:DefineConstants=FOO;DefineConstants=BAR BAR
3 msbuild test.proj /p:DefineConstants=FOO,DefineConstants=BAR BAR
4 msbuild test.proj /p:DefineConstants="FOO;BAR" FOO;BAR
5 msbuild test.proj /p:"DefineConstants=FOO;BAR" FOO;BAR
6 msbuild test.proj /p:DefineConstants=FOO%3BBAR FOO;BAR

The /property switch (short version /p) to MSBuild defines an MSBuild Property. The /property switch accepts one or more name/value pairs delimited by semicolon or comma.

Example 1 is an error because the switch is expecting a name/value pair after the semicolon. BAR is either a name without a value or a value without a name.

The same name can appear multiple times. MSBuild just redefines the property. Essentially the last value is used. This is what is happening in examples 2 and 3.

Examples 4 and 5 use quotes to show the semicolon is part of one name/value pair.

Example 6 is hex encoding the semicolon.

Note that in examples 4, 5, and 6 the value of the DefineConstants property doesn't include quotes.

When $(DefineConstants) is replaced in PreprocessorDefinitions it should be :

      <PreprocessorDefinitions>FOO;BAR;WIN32;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>

But somewhere in your project, quotes are being added. Is there code that you haven't shown, that is modifying the DefineConstants property?

Jonathan Dodds
  • 2,654
  • 1
  • 10
  • 14