locked
Setting a preprocessor based on property set in target. RRS feed

  • Question

  • So we have a variable which is currently an environment var and on loading of the sln it uses that variable to determine which project is active and selects certain things specific to that project (Preprossor define) 

    So this preprocess define lets call it GAME_1 or GAME_2 gets set. We have a tool we have created where we can load variables from an ini from a dll. So inside a target I can find out if it is game 1 or game 2 without needing the environment varaible. 

    So my issue is I can't get the preprocess to recognise the change. So in our earliest target we set this. 

    <UsingTask AssemblyFile="$bin\IniVars.dll" TaskName="msbuild.IniVarsInit" />
      <Target Name="SetGameItentifier">
    
        <IniVarsInit>
          <Output TaskParameter="IniVars" ItemName="IniVars"/>
        </IniVarsInit>    
        <PropertyGroup>
          <GameItentifier>%(IniVars.GameIdentifier)</GameItentifier>
        </PropertyGroup>
        <Message Text="GameItentifier: $(GameItentifier)" />
      </Target>
    

    and the preprocessor are included in a props file. 

    <ItemDefinitionGroup>        
        <ClCompile>
          <PreprocessorDefinitions Condition="'$(GameItentifier)' == 'game1'">GAME_1;%(PreprocessorDefinitions)</PreprocessorDefinitions>
          <PreprocessorDefinitions Condition="'$(GameItentifier)' == 'game2'">GAME_2;%(PreprocessorDefinitions)</PreprocessorDefinitions>
        </ClCompile>
      </ItemDefinitionGroup>

    So my question is how would it be possible to get those preprocessor values set from the GameItentifier value. I have it set in the default root props file and we overwrite it in the target. 

    Thanks!

    Chris

    Wednesday, August 5, 2020 12:44 AM

All replies

  • I didn't test, but if the problem is that MSBuild evaluates Condition in ItemDefinitionGroup too early, then perhaps this could work in the props file:

      <ItemDefinitionGroup>        
        <ClCompile>
          <PreprocessorDefinitions>$(GameSpecificPreprocessorDefinitions);%(PreprocessorDefinitions)</PreprocessorDefinitions>
        </ClCompile>
      </ItemDefinitionGroup>
      <PropertyGroup>
        <GameSpecificPreprocessorDefinitions Condition="'$(GameItentifier)' == 'game1'">GAME_1</GameSpecificPreprocessorDefinitions>
        <GameSpecificPreprocessorDefinitions Condition="'$(GameItentifier)' == 'game2'">GAME_2</GameSpecificPreprocessorDefinitions>
      </PropertyGroup>
    Or perhaps you'd even need to move this PropertyGroup into the Target that sets GameItentifier.

    • Edited by ranta Wednesday, August 5, 2020 9:40 AM uniform name of property
    Wednesday, August 5, 2020 9:37 AM
  • Hi Mapledropbear,

    You need to execute your target before build, which is like:

    <Target Name="SetGameItentifier" BeforeTargets="Build">

    Best Regards,

    Dylan


    MSDN Community Support Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com

    Wednesday, August 5, 2020 10:19 AM
  • Hi Mapledropbear,

    You need to execute your target before build, which is like:

    <Target Name="SetGameItentifier" BeforeTargets="Build">

    Best Regards,

    Dylan

    tried this. it didn't make a difference. No matter how early I even added initial target to the ini var and it STILL didn't make a difference I can print Messages to see the value has correctly set but the preprocessor list doesn't update properly to add the GAME_1 define
    Wednesday, August 5, 2020 12:46 PM
  • I didn't test, but if the problem is that MSBuild evaluates Condition in ItemDefinitionGroup too early, then perhaps this could work in the props file:

      <ItemDefinitionGroup>        
        <ClCompile>
          <PreprocessorDefinitions>$(GameSpecificPreprocessorDefinitions);%(PreprocessorDefinitions)</PreprocessorDefinitions>
        </ClCompile>
      </ItemDefinitionGroup>
      <PropertyGroup>
        <GameSpecificPreprocessorDefinitions Condition="'$(GameItentifier)' == 'game1'">GAME_1</GameSpecificPreprocessorDefinitions>
        <GameSpecificPreprocessorDefinitions Condition="'$(GameItentifier)' == 'game2'">GAME_2</GameSpecificPreprocessorDefinitions>
      </PropertyGroup>
    Or perhaps you'd even need to move this PropertyGroup into the Target that sets GameItentifier.

    Thanks! I tried this approach all I ended up with in my pre processor commands is an additional 

    $(GameSpecificPreprocessorDefinitions);%(PreprocessorDefinitions)


    So the value isn't being updated in time. If I set the value right before it's used to the environment var it works. but if I set it to the inivar it doesn't


    Wednesday, August 5, 2020 12:46 PM
  • Hi Mapledropbear,

    Actually, you should create a custom MSBuild script to get what you want. Please move SetGameItentifier target from the old targets file into the MSBuild script and then add a msbuild task which builds the vcxproj file directly.

    Reason

    Make sure that the target SetGameItentifier executes before the whole build process and make sure that MSBuild reads the property GameItentifier after you assign the new value to it. In your function, there is no way to pass the new value from the custom target SetGameItentifier because MSBuild reads all properties very early. And at that time, target always runs after MSBuild reads all properties including GameItentifier. So your new value GameItentifier is always after MSbuild reads the property GameItentifier under the condition.

    So the condition is null and always false. So the issue persists.

    You should make sure that the target SetGameItentifier executes before the whole build process so that it will succeed.

    Solution

    Please follow my solution.

    1) create a file called test.proj and then move the SetGameItentifiertarget from the old targets file into the test.proj file.

    Add these in test.proj file:

    <Project>
    
        <UsingTask AssemblyFile="$bin\IniVars.dll" TaskName="msbuild.IniVarsInit" />
         
        <Target Name="SetGameItentifier">   
            <IniVarsInit>
              <Output TaskParameter="IniVars" ItemName="IniVars"/>
            </IniVarsInit>    
            <PropertyGroup>
              <GameItentifier>%(IniVars.GameIdentifier)</GameItentifier>
            </PropertyGroup>
            <Message Text="GameItentifier: $(GameItentifier)" />
         <MSBuild Projects="xxx\xxx.vcxproj(the path of the vcxproj file)" Targets="Build" Properties="GameItentifier=$(GameItentifier)"></MSBuild>   
          </Target>
    
    </Project>


    2) keep your other content unchanged in <project_name>.vcxproj file and only add a target in it to check whether the PreprocessorDefinitions changes.

    <Target Name="showPara" AfterTargets="Build">
        <Message Importance="high" Text="%(ClCompile.PreprocessorDefinitions)==============$(GameItentifier)"></Message>
    </Target>

    3) open Develoepr Command Prompt for VS2019 and then run test.proj file directly to build your project.

    msbuild xxx\test.proj -t:SetGameItentifier -v:detailed

    4) You will see the changed PreprocessorDefinitions as expected.

    Best Regards,

    Perry


    MSDN Community Support Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com



    Thursday, August 6, 2020 8:04 AM