views:

22

answers:

1

I have been writing a build system based on MSBuild, and am to the end of the project where I need to essentially run the one msbuild file 88 times by batching over three variables:

Configuration = Debug; Beta; Release; Evaluation
Platform = x86; x64
Language = CN; CS; DE; EN; ES; FR; IT; JP; KO; PL; TW

I want to build:
"Debug x86 CN", "Debug x86 CS", ... "Debug x86 TW"
"Debug x64 CN", ...

I can, of course, define 88 of these:

<ItemGroup>
  <ToBuild Include="Debug_x86_CN">
    <Configuration>Debug</Configuration>
    <Platform>x86</Platform>
    <Language>EN</Language>
  </ToBuild>
<ItemGroup>

And then batch based on metadata. But what a drag! Can I create the 88 permutations in code, so adding a language is as easy as adding three characters to an ItemGroup:

<ItemGroup>
  <AllConfigurations Include="Beta; Release; Evaluation;"/>
  <AllPlatforms Include="x86; x64" />
  <AllLanguages Include="CN; CS; DE; EN; ES; FR; IT; JP; KO; PL; TW" />
</ItemGroup>
+2  A: 

Thanks to Anders Ljusberg for posting an answer to this years ago. The solution is to use the CreateItem task to combine the individual ItemGroups into one ItemGroup. The cross product of each item needs to be done one at a time into a new ItemGroup (in this case _Config_X_Language and _Config_X_Language_X_Platform) to prevent empty metadata from leaking in (if you try to reuse _Config_X_Language, you'll get items with empty Platform, n addition to the platforms in $(Platform).

<ItemGroup>
  <Configuration Include="Beta; Release; Evaluation;"/>
  <Platform Include="x86; x64" />
  <Language Include="CN; CS; DE; EN; ES; FR; IT; JP; KO; PL; TW" />
</ItemGroup>

<!-- Create an ItemGroup that is the cross product of Configuration and Language: -->
<CreateItem Include="@(Configuration)" AdditionalMetadata="Language=%(Language.Identity);" >
  <Output ItemName="_Config_X_Language" TaskParameter="Include"/>
</CreateItem>
<!-- Create another ItemGroup that is the cross product of _Configuration_X_Language and Platform: -->
<CreateItem Include="@(_Config_X_Language)" AdditionalMetadata="Platform=%(Platform.Identity);" >
  <Output ItemName="_Config_X_Language_X_Platform" TaskParameter="Include"/>
</CreateItem>

<!-- Task batch over each unique set of metadata on AllBuilds -->
<MSBuild Projects="myproject.msbuild"
          Properties="Configuration=%(_Config_X_Language_X_Platform.Identity);
                      Platform=%(_Config_X_Language_X_Platform.Platform);
                      Language=%(_Config_X_Language_X_Platform.Language);"
          Targets="MyTarget"
          BuildInParallel="true" />
Brian Gillespie