18

我有一个包含十二个解决方案配置的 Visual Studio 2012 解决方案。每个解决方案配置都是独立的(即每个配置的输出完全不相关)。

问题: 如何一步构建所有十二个配置,即通过在命令行上运行单个 MSBuild 命令,以及如何并行构建配置?

例如,如果只有两种配置,Release/AnyCPU 和 Debug/AnyCPU,我希望这两种配置可以同时并行构建。

为了完整起见,以下是我尝试过的;我还没有解决这个问题的方法。


为了一次构建所有项目,我创建了一个带有构建目标的新项目文件,该目标在每个配置的解决方案文件上运行 MSBuild 任务:

<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>

这很好用,除了每个 MSBuild 任务都是按顺序调用的,所以没有并行性(是的,每个配置构建中都有并行性但我真的很想跨配置构建获得并行性)。

为了使配置并行构建,我尝试利用 MSBuild 任务的 BuildInParallel 属性。我编写了一个预构建任务,为每个配置生成项目文件,然后尝试并行构建所有这些生成的项目:

<Target Name="PreBuild" Outputs="%(ProjectConfiguration.Identity)" Returns="%(BuildProject.Identity)">
  <Message Text="Cloning Solution for Configuration:  %(ProjectConfiguration.Identity)" />
  <PropertyGroup>
    <BuildProjectPath>$(IntPath)\%(ProjectConfiguration.Platform)\%(ProjectConfiguration.Configuration)\build.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>

不幸的是,虽然这确实构建了所有十二种配置,但它是按顺序构建的。我的猜测是,当 MSBuild 对要构建的项目集执行依赖关系分析时,它会识别出它们都依赖于同一个解决方案文件,因此它决定它们不能并行构建。(这只是一个猜测;我可能完全错了。我对 MSBuild 知之甚少。)

我也在构建时使用 /m 开关。

4

1 回答 1

22

利用 MSBuild 任务的 BuildInParallel 选项,在一次调用中传递所有项目。这里的例子给出了基本的方法:

<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>
于 2012-10-20T04:19:11.037 回答