防止 MSBuild 在不使用“解决方案配置”情况下构建 .sln 中的项目

12

我希望阻止某些解决方案中的特定项目建立(在TeamCity Build Configuration中)以优化我的提交构建反馈的速度(如果你一定要知道的话)。

我知道解决方案配置机制,但不想强制每个我想要关闭的东西的所有排列组合都要用到很多.sln文件。我有一个基于约定的规则,我想说“如果我正在进行提交构建,我不想做最终的安装包装”。(并且我不想将其分成单独的解决方案)。

我不想使用涉及在.sln文件或通过[MsBuildEmitSolution][1]创建的.proj文件中查找和替换的解决方案。我知道这里有涵盖开箱即用的解决方案这个略相关的问题的问题。

我看到MSBuild /v: diag显示:

 2>Target "Build" in file "Z.sln.metaproj" from project "Z.sln" (entry point):
   Using "MSBuild" task from assembly "Microsoft.Build.Tasks.v4.0, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a".
   Task "MSBuild"
     Global Properties:
       BuildingSolutionFile=true
         CurrentSolutionConfigurationContents=<SolutionConfiguration>
   <ProjectConfiguration Project="{C83D035D-169B-4023-9BEE-1790C9FE22AB}" AbsolutePath="X.csproj" BuildProjectInSolution="True">Debug|AnyCPU</ProjectConfiguration>
   <ProjectConfiguration Project="{15E7887D-F1DB-4D85-8454-E4EF5CBDE6D5}" AbsolutePath="Y.csproj" BuildProjectInSolution="True">Debug|AnyCPU</ProjectConfiguration>
 </SolutionConfiguration>

所以问题是:
有没有一种简洁的方法让我执行XPath替换或类似操作,以达到将Project Y中的“BuildProjectInSolution =“True””更改为“BuildProjectInSolution =“False””的效果?
如果不行,是否可以在“.ccproj”(Azure 1.4包)或“.csproj”(一般项目)文件中进行相对简单的编辑,以使在命令行“msbuild Z.sln”解决方案构建中启用该项目的效果(包括触发依赖项目)被取消?

1
使用自定义的 MSBuild 文件没有问题。我不确定为什么这不能算作一个整洁的解决方案。 - Ritch Melton
@Ritch Melton:我已经有一个非常棒的自定义msbuild文件来构建一组解决方案(并行等等,实现了极佳的吞吐量)。我需要的是产品中的子系统可以加载到VS中,并添加和删除项目-因此需要.sln文件。我想指出的是,如果我唯一能做的就是强制MSBuild发出一个等效的.proj文件,那就感觉像是在为MSBuild 5改变游戏(或者当VS团队最终意识到.sln文件不是特殊情况对于真正的项目而言是相当重要的时候)存储麻烦。 - Ruben Bartelink
我理解你的感受。sln文件的问题很荒谬。还有一些msbuild问题和它与Visual Studio的集成,我就是不明白。那个抱怨太长了,在这里无法发表。 - Ritch Melton
@Ritch Melton:通常我不会因为长度这样的小问题而阻止我发泄:D 感谢回复。 - Ruben Bartelink
3个回答

4

不确定这是否算作好的方法,但是你可以设置 CustomAfterMicrosoftCommonTargets 来导入一个 msbuild 文件,覆盖 BuildDependsOn 属性并将其指向自己的构建任务。 基本上,通过设置 CustomAfterMicrosoftCommonTargets,您可以让 msbuild 导入包含以下内容的 msbuild 文件:

<PropertyGroup>
    <OldBuildDependsOn>$(BuildDependsOn)</OldBuildDependsOn>
    <BuildDependsOn>MyBuild</BuildDependsOn>
</PropertyGroup>

<Target Name="OldBuild" DependsOnTargets="$(OldBuildDependsOn)" />

<Target Name="MyBuild">
    <CallTarget Targets="OldBuild" Condition="<IfIWantThis>" /> 
</Target>

编辑

你可以使用以下MyBuild目标,根据传入的IncludeInBuildExcludeFromBuild属性中的正则表达式来包含/排除项目。 (如果您想要复杂的正则表达式,您可能会遇到MSBuild特殊字符转义的问题,但对于简单匹配,这个方法足够好)

> msbuild /p:ExcludeFromBuild="Tests|Install|Azure"

<Target Name="MyBuild">
    <CallTarget Targets="OldBuild" Condition="('$(IncludeInBuild)'=='' OR
    '$([System.Text.RegularExpressions.Regex]::IsMatch($(MSBuildProjectFullPath),
    $(IncludeInBuild), 
    System.Text.RegularExpressions.RegexOptions.IgnoreCase))'=='True') AND 
    ('$(ExcludeFromBuild)'=='' OR 
    '$([System.Text.RegularExpressions.Regex]::IsMatch($(MSBuildProjectFullPath), 
    $(ExcludeFromBuild),  
    System.Text.RegularExpressions.RegexOptions.IgnoreCase))'=='False')" /> 
</Target>

+1 有趣的技巧。不过我并不认为它特别适合作为一种基于某些声明性规则选择性地影响解决方案中项目子集的构建或不构建的方式 - 我必须动态生成CustomAfterMicrosoftTargets才能使用这种攻击角度来实现... - Ruben Bartelink
我不确定那是正确的。我使用的方法是有一个静态的msbuild文件ShouldBuild。这个文件包含一个UsingTask(所以我可以使用c#内联,因为我讨厌msbuild),它根据一些输入属性返回true或false。目前我只取$(MSBuildProjectFullPath),如果它是一个安装程序或路径中有prototype,则返回false。但我可以取多个属性,包括正则表达式字符串、XPath字符串或任何我可以用来确定是否构建项目的东西。 - Rob
我的意思是,我省略了定义<IfIWantThis>的逻辑。我只使用了String.Contains,这相当粗糙,但你可以根据需要将其简化或复杂化。 - Rob
好的,现在有了你提供的缺失链接(如果我一直在想这个问题,我应该会想到它),可以用作通用方法的基础(可以使用String.Split然后批处理来进行匹配等)。感谢您提供的解决方案! - Ruben Bartelink

4
你可以将要构建的特定项目作为参数传递给MSBuild。
MSBuild命令行如下:
MSBuild /t:<Project Name>:Rebuild;<Another Project Name>:Rebuild

在TeamCity中,您需要在MSBuild运行器的目标字段中放置<项目名称>:<目标操作>

你是说这个(MSBuild被传递一组顶级项目)是本地的,还是(正如@Ritch Melton所说)我可以编写一些代码来代替.sln文件。首先,即使是将上述内容拆分也需要自定义任务(无论是编译后的任务还是基于PS或C# TaskFactory的任务)。我可能没有理解你的意思,如果我有5个.sln文件,我会听取如何构建其中的50个.csproj / .ccproj而不包括名为“* .AzurePackage”的项目(或者可能没有.ccproj),而不必舍弃VS slns作为分组。 - Ruben Bartelink
@Ruben Bartelink:我相信你可以在本地传递一组顶级项目。这将需要大量的打字(将50个目标传递到msbuild命令行中),但不需要创建新的目标或修改sln / csproj文件。 - Eric
我想看一个例子。就解决我的问题而言,我仍然不能拥有一个包含14个项目的sln文件,并让某人添加一个新项目并为给定配置禁用另一个项目,并在运行构建时反映出这一点。 - Ruben Bartelink

-2

我在参数下添加了一个系统参数

  • 名称:system.ExcludeFromBuild
  • 类型:系统属性(system.
  • 值:指向你的 csproj 的路径

parameter pass


1
你是在建议将该方案应用于另一个答案,还是在建议这是默认项目系统的内在能力? - Ruben Bartelink

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