MSBuild中的Directory.build.props是否会级联到每个项目?

3

执行摘要:我希望根据仅在构建管道后期存在的条件,在属性组中设置属性,并寻找一种更早解决此问题的方法。

我有一个相当简单的Directory.build.props文件。

<Project>

  <PropertyGroup>
    <MyMode>Default</MyMode>
  </PropertyGroup>

  <!-- This one overrides the default group above -->
  <PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
    <MyMode>Changed to Debug</MyMode>
  </PropertyGroup>

  <!-- This one is not applied -->
  <PropertyGroup Condition=" '$(TargetFrameworkVersion)' == 'v4.7.2' ">
    <MyMode>Framework</MyMode>
  </PropertyGroup>


  <Target Name="Stats" AfterTargets="Build">
    <Message Importance="High" Text="::::: Mode set to $(MyMode)" />
    <Message Importance="High" Text="::::: Target Framework set to $(TargetFrameworkVersion)" />
  </Target>

</Project>

一个简单的项目结构

E:.
│   Directory.build.props
│   MSBuild_Test.sln
│
├───ConsoleAppNet
│       App.config
│       ConsoleAppNet.csproj
│       Program.cs
│
└───MSBuild_Test
        Class1.cs
        LibStandard.csproj

LibStandard是一个 .net 标准库,ConsoleAppNet 是一个 .net 框架项目,同时也依赖于 LibStandard

当我执行上述的 msbuild 脚本时,我会得到如下输出。

  LibStandard -> E:\temp\MSBuild_Test\MSBuild_Test\bin\Debug\netstandard2.0\LibStandard.dll
  ::::: Mode set to Changed to Debug
  ::::: Target Framework set to v2.0
  ConsoleAppNet -> E:\temp\MSBuild_Test\ConsoleAppNet\bin\Debug\ConsoleAppNet.exe
  ::::: Mode set to Changed to Debug
  ::::: Target Framework set to v4.7.2

如您所见,控制台输出应该已触发具有条件的属性组,导致MyModeFramework,但它并没有成功。 这个从未被匹配过:
  <PropertyGroup Condition=" '$(TargetFrameworkVersion)' == 'v4.7.2' ">
    <MyMode>Framework</MyMode>
  </PropertyGroup>

是否有一种好的方法根据上述条件在加载时应用PropertyGroups

我知道可以将PropertyGroup重写放置在目标中,例如:

  <Target Name="TooLate" BeforeTargets="BeforeBuild" Condition=" '$(TargetFrameworkVersion' == 'v4.7.2' ">
    <PropertyGroup >
      <MyMode>Framework</MyMode>
    </PropertyGroup>
  </Target>

这段代码也能够正确执行,但此时我不能设置其他重要的变量。

我的意图是根据不同条件重定向输出目录。当我在一个目标中设置$(OutputPath)时,已经太晚了。该项目会在整个构建过程中忽略此输出:

  <Target Name="TooLate" BeforeTargets="BeforeBuild" Condition=" '$(TargetFrameworkVersion)' == 'v4.7.2' ">
    <PropertyGroup >
      <OutputPath>New_Output_Directory</OutputPath>
    </PropertyGroup>
  </Target>

我甚至可以打印出OutputPath变量并且它指向正确的值,但构建程序仍然使用旧值并未重定向输出。

1个回答

5

给我来个高五,我找到了解决所有即将出现的Samuel询问相同问题的方案。

快速解答

在导入Directory.build.props时,没有其他属性(例如TargetFramework)已经被导入,并将默认为空。这就是为什么对它们的检查会失败的原因。改用Directory.build.targets

  • Directory.build.props被非常地导入,允许您在开头设置属性
  • Directory.build.targets被非常地导入,允许您自定义构建链

资源

以下是有关msbuild的一些非常有用的页面

解释

下面是来自自定义页面上的段落引用(只要当前文档还存在...)

导入顺序

Directory.Build.props在Microsoft.Common.props中非常早地被导入,并且稍后定义的属性对它不可用。因此,避免引用尚未定义的属性(并将计算为空)。

Directory.Build.targets是从Microsoft.Common.targets导入的,它会在从NuGet包导入.targets文件之后导入。因此,它可以覆盖大部分构建逻辑中定义的属性和目标,但有时您可能需要在最终导入后自定义项目文件。

通过阅读这个引文,目标的暗示有些模糊,但是使用Directory.Build.targets是覆盖属性和使用条件检查的最佳位置。


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