Directory.Build.targets 无法覆盖 OutputPath 属性
2024-04-20 23:19:40

在管理多个工程时,通常需要根据工程的属性并按照指定的规则来决定二进制文件的输出位置。第一直觉是在Directory.Build.targets文件中设置OutputPath属性。
然而实测发现Directory.Build.targets文件中的OutputPath并未生效。
Google 一番后找到两种解决办法。

BeforeTargetFrameworkInferenceTargets 属性

这个属性出现在 Microsoft.NET.TargetFrameworkInference.targets 文件中,并没有官方的文档。
我们可以在Directory.Build.props中设置它:

1
<BeforeTargetFrameworkInferenceTargets>$(MSBuildThisFileDirectory)OutputBuild.props</BeforeTargetFrameworkInferenceTargets>

然后在OutputBuild.props中覆盖OutputPath,这里是可以使用自定义属性的。

1
2
3
4
5
<Project>
<PropertyGroup>
<OutputPath>bin\$(Foo)</OutputPath>
</PropertyGroup>
</Project>

.props 和 .targets 文件之前和之后

比起没有文档的BeforeTargetFrameworkInferenceTargets属性,MSBuild 提供了一系列”钩子”属性,可以在Microsoft.Common.PropsMicrosoft.Common.Targets文件的前后执行。

  • CustomBeforeMicrosoftCommonProps
  • CustomBeforeMicrosoftCommonTargets
  • CustomAfterMicrosoftCommonProps
  • CustomAfterMicrosoftCommonTargets
  • CustomBeforeMicrosoftCSharpTargets
  • CustomBeforeMicrosoftVisualBasicTargets
  • CustomAfterMicrosoftCSharpTargets
  • CustomAfterMicrosoftVisualBasicTargets


从名字上看,我们只关心前面四个。测试一下:

1
2
3
4
5
6
7
8
<Project>
<PropertyGroup>
<CustomBeforeMicrosoftCommonProps>$(MSBuildThisFileDirectory)BeforeMicrosoftCommon.props</CustomBeforeMicrosoftCommonProps>
<CustomAfterMicrosoftCommonProps>$(MSBuildThisFileDirectory)AfterMicrosoftCommon.props</CustomAfterMicrosoftCommonProps>
<CustomBeforeMicrosoftCommonTargets>$(MSBuildThisFileDirectory)BeforeMicrosoftCommon.targets</CustomBeforeMicrosoftCommonTargets>
<CustomAfterMicrosoftCommonTargets>$(MSBuildThisFileDirectory)AfterMicrosoftCommon.targets</CustomAfterMicrosoftCommonTargets>
</PropertyGroup>
</Project>

这四个文件的载入顺序是:

  1. CustomBeforeMicrosoftCommonProps。可覆盖OutputPath属性,但不可以使用工程的自定义属性。
  2. CustomAfterMicrosoftCommonProps。可覆盖OutputPath属性,但不可以使用工程的自定义属性。
  3. CustomBeforeMicrosoftCommonTargets。可使用工程的自定义属性。
  4. CustomAfterMicrosoftCommonTargets。无法覆盖OutputPath属性。


所以,我们有机会在CustomBeforeMicrosoftCommonTargets中覆盖OutputPath属性。

相关阅读

setting OutputPath in a Directory.Build.targets
Bending .NET - Improved Common Flat Build Output
自定义所有 .NET 生成
Document the import order of the common msbuild extension points.