Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bending .NET - Corrected Common Flat Build Output #21

Closed
Stefan75 opened this issue Jan 19, 2022 · 1 comment
Closed

Bending .NET - Corrected Common Flat Build Output #21

Stefan75 opened this issue Jan 19, 2022 · 1 comment

Comments

@Stefan75
Copy link

Stefan75 commented Jan 19, 2022

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.

@nietras
Copy link
Owner

nietras commented Jan 23, 2022

Hey @Stefan75, thank you very much for your comment.

I actually saw the issue where someone (you?) commented on using BeforeTargetFrameworkInferenceTargets in a normal target and I also tried it. However, I did not try it exactly the way you describe it though with:

<PropertyGroup>		 
<BeforeTargetFrameworkInferenceTargets>$(MSBuildThisFileDirectory)BeforeTargetFrameworkInference.targets</BeforeTargetFrameworkInferenceTargets>
</PropertyGroup>

I just tried this out, and I believe it works! 🎉

I simply forward to and import the OutputBuildProject.props in BeforeTargetFrameworkInference.targets:

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

I have attached a zip with this approach.

CommonFlatBuild.zip

Comments are welcome. F12 appears to work. Build looks same.

Thanks!
Niels

PS: BeforeTargetFrameworkInferenceTargets is mentioned in dotnet/sdk#14931
PPS: dotnet/runtime appears to use this trick too in https://github.com/dotnet/runtime/blob/75c0b990ce249d6c37adfa4037ef3ba5b280085c/src/libraries/Directory.Build.props#L14, so it should be validated by that https://github.com/dotnet/runtime/blob/main/eng/BeforeTargetFrameworkInference.targets
PPPS: The target is indeed simply imported in https://github.com/dotnet/sdk/blob/main/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.TargetFrameworkInference.targets and hence the indirection is not really needed as such, the important thing is the comment:

Note that this file is only included when $(TargetFramework) is set and so we do not need to check that here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants