Skip to content

Bending .NET - Corrected Common Flat Build Output #21

@Stefan75

Description

@Stefan75

Hello,

@nietras
I read your blog post:
Blog Post

In the blog post you stated that you have to import in every cs project file a prop file:

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFrameworks>net5.0;net6.0</TargetFrameworks>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
  </PropertyGroup>

  <Import Project="$(MSBuildThisFileDirectory)..\OutputBuildProject.props" />
</Project>

Here the content of the OutputBuildProjects.props file:

<Project>
  <PropertyGroup>
    <OutDir>$(BaseOutDir)_$(TargetFramework)\</OutDir>
    <TargetDir>$(OutDir)</TargetDir>
    <PublishDir>$(BasePublishDir)$(ProjectBuildDirectoryName)</PublishDir>
    <PublishDir Condition="$(TargetFramework) != ''">$(PublishDir)_$(TargetFramework)</PublishDir>
    <PublishDir Condition="$(RuntimeIdentifier) != ''">$(PublishDir)_$(RuntimeIdentifier)</PublishDir>
  </PropertyGroup>
</Project>

I guess the reason is that some of your properties depends on the settings of the cs-project file self.
(e.g. depends on TargetFramework)

Maybe I found a solution, because I have a similar problem.

During my work I found the MS-Build Property BeforeTargetFrameworkInferenceTargets.
It is possible to set the property to a msbuild-file which is then evaluated in a very early phase of the target-file evaulation, much earlier than the Directory.Build.targets file.

Some parts of the Direcotry.Build.props file content

<!--    Hook addional targets file -->
<PropertyGroup>		 
 <BeforeTargetFrameworkInferenceTargets>$(MSBuildThisFileDirectory)BeforeTargetFrameworkInference.targets</BeforeTargetFrameworkInferenceTargets>
</PropertyGroup>

Some parts of the BeforeTargetFrameworkInference.targets file content:

<PropertyGroup Condition=" $([System.Text.RegularExpressions.Regex]::IsMatch($(TargetFramework), '^netstandard')) ">
    <DotNetStandard>true</DotNetStandard>
  </PropertyGroup>
  <PropertyGroup Condition=" $([System.Text.RegularExpressions.Regex]::IsMatch($(TargetFramework), '^net[5-9]')) ">
    <DotNet5AndLater>true</DotNet5AndLater>
  </PropertyGroup>
  <PropertyGroup Condition=" $([System.Text.RegularExpressions.Regex]::IsMatch($(TargetFramework), '^net[4]')) ">
    <DotNet4>true</DotNet4>
  </PropertyGroup>

  <Target Name="Test" AfterTargets="Build">
    <Message Text="BUILD-TEST: .NET Standard detected" Condition="'$(DotNetStandard)' == 'true'" Importance="high" />
    <Message Text="BUILD-TEST: .NET 4 detected" Condition="'$(DotNet4)' == 'true'" Importance="high" />
    <Message Text="BUILD-TEST: .NET 5 or later detected" Condition="'$(DotNet5AndLater)' == 'true'" Importance="high" />
  </Target>

Here I used the TargetFrmework value for some debug outputs.

Some remarks:

  • I found the hook with help of the MSBuild Structured Logviewer
  • I didn't find any earlier hook.
  • My wish would be to have a hook which is executed as early as possible.
    We want to use such a hook to define global defaults which depend on cs-projct-file content.
    (e.g. OutptuType, ...)
  • I hope that this hook is executed early enough for my tasks, will see.

With best regards,
stefan

PS: I hope my post helps.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions