msbuild - 如何避免MSBuild中的重复?

标签 msbuild dry

我不介意在必要时偶尔重复某些内容,但在 MSBuild 中我真的不知道如何永远避免重复。它不提供通常意义上的“功能”;目标只能被调用一次,即使是通过 CallTarget ,和<Import>仅适用于 Project级别。

这是我试图消除“重复”的一个具体示例:

<Target Name="Tgt1">
  <PropertyGroup><Conf1>Twiddle</Conf1><Conf2>Thing</Conf2></PropertyGroup>

  <PropertyGroup><xxxxxxxxxxExePath>$(xxxxxxxBuildRoot)\$(Conf1)Console-xxxxxxxxed</xxxxxxxxorExePath></PropertyGroup>
  <MSBuild Projects="$(BuildSingleProj)" Targets="Build;Merge"
           Properties="Configuration=$(Conf1)$(Conf2);Platform=$(Platform);CompiledFileName=$(CompiledFileName);ProjectName=$(ProjectName);SolutionFile=$(SolutionFile);Root=$(Root);Caller=$(MSBuildProjectFullPath)"/>
  <MakeDir Directories="$(xxxxxxxxorExePath)" />
  <WriteLinesToFile File="$(xxxxxxxxorExePath)\xxxxxxx.IsPortable.txt" />
  <WriteLinesToFile File="$(xxxxxxxxorExePath)\xxxxxxx.Global.Settings.xml" Lines="@(xxxxxxxLicense)" Overwrite="true" />
  <Exec Command='$(xxxxxxxxorExePath)\xxxxxxx.exe -a "$(xxxxxxxBuildRoot)\$(Conf1)$(Conf2)-Merged\xxxxxxx.exe" "$(xxxxxxxBuildRoot)\$(Conf1)$(Conf2)-xxxxxxxxed\xxxxxxx.exe"'/>
</Target>

我有四个这样的目标,Tgt1 , Tgt2 , Tgt3 , Tgt4 。这四个目标之间唯一的区别是第一行,即定义 Conf1 的行。和Conf2 .

据我所知,唯一或多或少可行的重复数据删除想法是将共享代码移动到新目标并通过 MSBuild 调用它。任务。不幸的是,这需要手动传入一串属性,而此任务使用了相当多的属性(我数了一下,有 11 个属性和 1 个项目组)。

另一个要求是我可以使用这些目标的任意子集调用脚本,例如\t:Tgt2,Tgt3 .

除了复制/粘贴这段代码之外,是否有任何明智的替代方案 - 这不涉及复制大量的属性列表?

最佳答案

这是一个完美的使用场景 Batching

您需要创建自定义Items使用适当的元数据,然后创建单个目标来引用新项目。

您可以将每个项目包装在它自己的目标中,如下所示:

<Target Name="Tgt1">
  <ItemGroup>
    <BuildConfig Include="Tgt1">
      <Conf1>Twiddle</Conf1>
      <Conf2>Thing</Conf2>
    </BuildConfig>
  </ItemGroup>
</Target>

<Target Name="Tgt2">
  <ItemGroup>
    <BuildConfig Include="Tgt2">
      <Conf1>Twaddle</Conf1>
      <Conf2>Thing 1</Conf2>
    </BuildConfig>
  </ItemGroup>
</Target>

<Target Name="Tgt3">
  <ItemGroup>
    <BuildConfig Include="Tgt3">
      <Conf1>Tulip</Conf1>
      <Conf2>Thing 2</Conf2>
    </BuildConfig>
  </ItemGroup>
</Target>

然后,您需要调用一个核心目标来执行所有工作,如下所示:

<Target Name="CoreBuild" Outputs="%(BuildConfig.Identity)">
  <Message Text="Name  : %(BuildConfig.Identity)" />
  <Message Text="Conf1 : %(BuildConfig.Conf1)" />
  <Message Text="Conf2 : %(BuildConfig.Conf2)" />
</Target>

Outputs="%(BuildConfig.Identity)" 添加到目标将确保您在目标级别而不是任务级别进行批处理。

只要最后一个目标是您的核心目标,您就可以通过传递目标的任意组合来从 msbuild 执行此操作。例如,执行此命令 MSBuild.exe test.msbulid/t:Tgt1,Tgt3,CoreBuild 将提供以下输出:

Name  : Tgt1
Conf1 : Twiddle
Conf2 : Thing

Name  : Tgt3
Conf1 : Tulip
Conf2 : Thing 2

关于msbuild - 如何避免MSBuild中的重复?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4810732/

相关文章:

c# - 在 azure-pipelines.yml 中为 dotnetpublish 命令转义空格

.net - 数据库中的 Excel 自动化,最好的技术是什么?

perl - Catalyst:如何声明一个全局子程序

coldfusion - ColdFusion 是否支持委托(delegate)?

c# - MediatR 库 : following the DRY principle

msbuild - 子节点 "2"提前退出

c# - 如何将对 System.Data.DataSetExtensions 的引用添加到网站 ascx.cs 文件?

msbuild - 所有目标未被调用(嵌套目标未被执行)

javascript - 削减 JSON 对象以声明方式发送到 Typescript 中的客户端?

c++ - 如何让C++很好的适配DRY?