Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
556 views
in Technique[技术] by (71.8m points)

msbuild - How can I build multiple configurations in parallel?

I have a Visual Studio 2012 Solution with twelve Solution Configurations. Each Solution Configuration is independent (i.e., the outputs of each configuration are entirely unrelated).

The Question: How can I build all twelve configurations in one step, i.e. by running a single MSBuild command on the command line, and how can I get the configurations to be built in parallel?

As an example, if there were just two configurations, Release/AnyCPU and Debug/AnyCPU, I would want both of these to build at the same time, in parallel.

For completeness, the following is what I have tried; I don't yet have a solution to this problem.


To build all of the projects at once, I created a new project file with a Build target that runs the MSBuild task on the Solution file for each configuration:

<Target Name="Build">
  <MSBuild Projects="cxxreflect.sln" Properties="SolutionDir=$(MSBuildProjectDirectory);Configuration=Release;Platform=Win32"     Targets="$(BuildCommand)" />
  <MSBuild Projects="cxxreflect.sln" Properties="SolutionDir=$(MSBuildProjectDirectory);Configuration=Release;Platform=x64"       Targets="$(BuildCommand)" />
  <MSBuild Projects="cxxreflect.sln" Properties="SolutionDir=$(MSBuildProjectDirectory);Configuration=Release;Platform=ARM"       Targets="$(BuildCommand)" />
  <MSBuild Projects="cxxreflect.sln" Properties="SolutionDir=$(MSBuildProjectDirectory);Configuration=Release(ZW);Platform=Win32" Targets="$(BuildCommand)" />
  <MSBuild Projects="cxxreflect.sln" Properties="SolutionDir=$(MSBuildProjectDirectory);Configuration=Release(ZW);Platform=x64"   Targets="$(BuildCommand)" />
  <MSBuild Projects="cxxreflect.sln" Properties="SolutionDir=$(MSBuildProjectDirectory);Configuration=Release(ZW);Platform=ARM"   Targets="$(BuildCommand)" />

  <MSBuild Projects="cxxreflect.sln" Properties="SolutionDir=$(MSBuildProjectDirectory);Configuration=Debug;Platform=Win32"       Targets="$(BuildCommand)" />
  <MSBuild Projects="cxxreflect.sln" Properties="SolutionDir=$(MSBuildProjectDirectory);Configuration=Debug;Platform=x64"         Targets="$(BuildCommand)" />
  <MSBuild Projects="cxxreflect.sln" Properties="SolutionDir=$(MSBuildProjectDirectory);Configuration=Debug;Platform=ARM"         Targets="$(BuildCommand)" />
  <MSBuild Projects="cxxreflect.sln" Properties="SolutionDir=$(MSBuildProjectDirectory);Configuration=Debug(ZW);Platform=Win32"   Targets="$(BuildCommand)" />
  <MSBuild Projects="cxxreflect.sln" Properties="SolutionDir=$(MSBuildProjectDirectory);Configuration=Debug(ZW);Platform=x64"     Targets="$(BuildCommand)" />
  <MSBuild Projects="cxxreflect.sln" Properties="SolutionDir=$(MSBuildProjectDirectory);Configuration=Debug(ZW);Platform=ARM"     Targets="$(BuildCommand)" />
</Target>

This works great, except that each MSBuild task is invoked in sequence, so there's no parallelism (yes, there is parallelism within each configuration build, but I'd really like to get parallelism across configuration builds).

In an attempt to get the configurations to build in parallel, I tried to make use of the MSBuild task's BuildInParallel property. I wrote a pre-build task that generated project files for each configuration, then attempted to build all of these generated projects in parallel:

<Target Name="PreBuild" Outputs="%(ProjectConfiguration.Identity)" Returns="%(BuildProject.Identity)">
  <Message Text="Cloning Solution for Configuration:  %(ProjectConfiguration.Identity)" />
  <PropertyGroup>
    <BuildProjectPath>$(IntPath)\%(ProjectConfiguration.Platform)\%(ProjectConfiguration.Configuration)uild.proj</BuildProjectPath>
  </PropertyGroup>
  <ItemGroup>
    <BuildProject Include="$(BuildProjectPath)" />
  </ItemGroup>
  <MakeDir Directories="$(IntPath)\%(ProjectConfiguration.Platform)\%(ProjectConfiguration.Configuration)" />
  <WriteLinesToFile
    File="$(BuildProjectPath)"
    Lines="&lt;?xml version='1.0' encoding='utf-8'?&gt;
&lt;Project DefaultTargets='Build' ToolsVersion='4.0' xmlns='http://schemas.microsoft.com/developer/msbuild/2003'>
  &lt;Target Name='Build'&gt;
    &lt;MSBuild
      Projects='$(SlnPath)'
      Properties='
        SolutionDir=$(MSBuildProjectDirectory)\%3b
        Configuration=%(ProjectConfiguration.Configuration)%3b
        Platform=%(ProjectConfiguration.Platform)
      '
      Targets='$(BuildCommand)'
    /&gt;
  &lt;/Target&gt;
&lt;/Project&gt;"
    Overwrite="true" />

</Target>
<Target Name="Build" DependsOnTargets="PreBuild">
  <Message Text="%(BuildProject.Identity)" />
  <MSBuild Projects="%(BuildProject.Identity)" Properties="BuildCommand=$(BuildCommand)" BuildInParallel="true" />
</Target>

Unfortunately, while this does build all twelve configurations, it builds them serially. My guess is that when MSBuild performs dependency analysis on the set of projects to be built, it identifies that they all depend on the same Solution file, so it decides they cannot be built in parallel. (This is just a guess; I could be completely wrong. I know very little about MSBuild.)

I am also using the /m switch when building.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Take advantage of the MSBuild Task's BuildInParallel option, and pass all the projects in a single call. The examples here give the basic approach:

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
    <ItemGroup>
        <ProjectToBuild Include="a1.sln">
            <Properties>Configuration=Debug</Properties>
        </ProjectToBuild>
        <ProjectToBuild Include="a1.sln">
            <Properties>Configuration=Release</Properties>
        </ProjectToBuild>
    </ItemGroup>
    <Target Name="Build">
        <MSBuild Projects="@(ProjectToBuild)" BuildInParallel="true" />
    </Target>
</Project>

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...