在MSBuild中,使目标运行一次于解决方案级别

13

我需要一组任务仅在整个解决方案中执行一次。这些任务将修改每个项目以使每个项目运行单独的任务集。我们之前通过一个独立的项目来完成解决方案级别的任务,但我们想要摆脱这种方法。是否有人做过这个或者有任何关于如何实现这个的建议?

2个回答

8

由于解决方案文件不是MSBuild格式,因此它们不能轻松地被扩展或自定义。如果您想更好地控制构建过程,您需要创建一个“驱动程序”MSBuild文件来替换您的解决方案文件。在这个驱动文件中,您将构建所有需要的项目并执行一些额外的任务。您可以使用MSBuild任务来完成这个过程。下面是一个示例,展示如何构建多个项目。

<Project ...>
    <ItemGroup>
        <Projects Include="proj01.csproj"/>
        <Projects Include="proj02.csproj"/>
        <Projects Include="proj03.csproj"/>
    </ItemGroup>

    <Target Name="BuildAll">
        <MSBuild Projects="@(Projects)" BuildInParallel="true" />
    </Target>

</Project>

在您的情况下,您只需在构建项目之前执行任务。还请注意,我指定了值true用于BuildInParallel,表示MSBuild可以尝试同时构建多个项目。


这是一个有趣的想法。我相信如果我希望在构建项目之前执行一些其他任务,这也会起作用?(而那些额外的任务将修改项目本身。) - Chandam
创建这些构建文件是非常常见的情况。很多人更喜欢编写这些类型的构建文件,而不是使用解决方案进行生产构建。在我的情况下,我只使用Visual Studio的解决方案文件,从不用于实际构建。 - Sayed Ibrahim Hashimi
在这种方法中,如果我的 Project 1 依赖于 Project 2,那么 MSBuild 是否会构建两次 Project 2,从而延迟构建过程? - Nikhil
MSBuild具有增量构建功能,因此它应该知道已经构建并且是最新的。 - Sayed Ibrahim Hashimi
谢谢@SayedIbrahimHashimi,我打算尝试一下,看看效果如何。在我的工作中,我做了很多MSBuild定制,因此这些技巧总是有用的。 - Nikhil

1
一种替代方案是使用单个目标,该目标将调度到一个MSBuild被调用的目标,并尽可能删除许多全局属性。我的团队在Directory.Build.props导入的props文件的InitialTargets中有一个目标 - 类似于以下内容:
<Target Name="Prebuild">
  <MSBuild Projects="$(MSBuildThisFileFullPath)"
           Targets="PrebuildWorker"
           RemoveProperties="Configuration;Platform;TargetFramework;BuildProjectReferences" />
</Target>

由于 MSBuild 似乎会同步 {项目文件、全局属性、目标} 集上的并行构建,因此通过删除所有属性,您可以同步构建并运行正在构建的所有项目的一次构建。缺点是:您必须维护 RemoveProperties 属性 - MSBuild 没有一种方法可以删除所有全局属性。如果构建中的某些内容使用指定的自定义属性发出新的 MSBuild 任务,则会调用第二个 Target 实例。

当然,您的构建将在此目标上同步。您可以尝试通过将 CompileDependsOn 设置为依赖于 Prebuild 目标来连接目标,以允许构建中的独立进度。但是,使用 InitialTargets 让目标早期和普遍地运行似乎是更好的选择。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接