如何避免MSBuild重复构建已完成项目?自定义.proj配置问题
解决MSBuild分组构建时重复构建前置依赖项目的问题
问题背景
通过customBuild.proj编排MSBuild并行构建,按BuildGroup1→FixedDelay→BuildRemaining的顺序分组,其中BuildGroup1是所有项目的前置依赖,RemainingProjects计划包含解决方案中除BuildGroup1外的其他项目。但执行时BuildRemaining仍会重复构建BuildGroup1内的项目,即使配置了排除规则。
核心原因
原配置中BuildGroup1是Target节点而非ItemGroup集合,导致@(BuildGroup1)在RemainingProjects的排除规则中为空,无法过滤掉已构建的前置项目,最终RemainingProjects仍包含解决方案中所有项目。
解决方案
方法1:将BuildGroup1定义为ItemGroup,确保排除规则生效
修改customBuild.proj,先把BuildGroup1的项目定义为ItemGroup,再在Target中引用该集合,同时用这个集合过滤RemainingProjects:
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <!-- 定义BuildGroup1的项目集合 --> <ItemGroup> <BuildGroup1 Include=" ../CoreProject1.csproj; ../CoreProject2.vcxproj; ../CoreProject3.vcxproj; ../CoreLibrary1.vcxproj; ../CoreLibrary2.csproj; ../CoreLibrary3.csproj; ../CoreLibrary4.vcxproj; "/> </ItemGroup> <!-- 获取解决方案中所有项目,并排除BuildGroup1的项目 --> <ItemGroup> <SolutionProjects Include="$(MSBuildProjectDirectory)/MyApp.sln"> <GetSolutionProjects/> </SolutionProjects> <RemainingProjects Include="@(SolutionProjects)" Exclude="@(BuildGroup1)"/> </ItemGroup> <!-- 构建BuildGroup1,开启并行构建 --> <Target Name="BuildGroup1"> <MSBuild Projects="@(BuildGroup1)" BuildInParallel="true"/> </Target> <Target Name="FixedDelay" DependsOnTargets="BuildGroup1"> <Exec Command="PowerShell -Command Start-Sleep -Seconds 3"/> <Message Text="Delay Complete. Starting BuildRemaining..." Importance="high"/> </Target> <!-- 构建剩余项目,开启并行构建 --> <Target Name="BuildRemaining" DependsOnTargets="FixedDelay"> <MSBuild Projects="@(RemainingProjects)" BuildInParallel="true"/> </Target> <Target Name="BuildAll" DependsOnTargets="BuildGroup1;FixedDelay;BuildRemaining"/> </Project>
方法2:利用MSBuild增量构建特性(兜底方案)
即使不小心包含了已构建项目,MSBuild的增量构建会检查项目输出文件的时间戳,若输入文件未变更且输出文件已存在,会跳过构建。大部分.NET/VC项目默认已配置Build目标的Inputs和Outputs属性,也可在CLI中添加/p:BuildIncrementally=true强化该特性。
方法3:直接在BuildRemaining任务中指定排除参数
无需修改ItemGroup,直接在BuildRemaining的MSBuild任务中通过/p:ExcludeProjects参数排除BuildGroup1的项目:
<Target Name="BuildRemaining" DependsOnTargets="FixedDelay"> <MSBuild Projects="$(MSBuildProjectDirectory)/MyApp.sln" Properties="ExcludeProjects=../CoreProject1.csproj;../CoreProject2.vcxproj;../CoreProject3.vcxproj;../CoreLibrary1.vcxproj;../CoreLibrary2.csproj;../CoreLibrary3.csproj;../CoreLibrary4.vcxproj" BuildInParallel="true"/> </Target>
验证命令
保持原CLI命令不变,执行构建:
msbuild customBuild.proj /t:BuildAll /m /p:Configuration=Release /p:Platform=x64 /p:BuildInParallel=true
内容的提问来源于stack exchange,提问作者col-A
相关产品推荐
相关产品推荐

