-
Notifications
You must be signed in to change notification settings - Fork 1.1k
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
Report that a project only has one TFM #797
Conversation
@@ -55,13 +55,16 @@ Copyright (c) .NET Foundation. All rights reserved. | |||
with the referencing project's target framework. | |||
============================================================ | |||
--> | |||
<Target Name="GetTargetFrameworkProperties" Returns="TargetFramework=$(NearestTargetFramework)"> | |||
<Target Name="GetTargetFrameworkProperties" Returns="TargetFramework=$(NearestTargetFramework);ProjectHasSingleTargetFramework=$(_HasSingleTargetFramework)"> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we use metadata to indicate ProjectHasSingleTargetFramework? Seems like it would simplify the consuming side.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Indeed it would, but it requires returning an item rather than a property which seemed more invasive.
|
||
<PropertyGroup> | ||
<!-- If a ReferringTargetFramework was not specified, and we only have one TargetFramework, then don't try to check compatibility --> | ||
<_SkipNearestTargetFrameworkResolution Condition="'$(TargetFramework)' != '' and '$(ReferringTargetFramework)' == ''">true</_SkipNearestTargetFrameworkResolution> | ||
<NearestTargetFramework Condition="'$(_SkipNearestTargetFrameworkResolution)' == 'true'">$(TargetFramework)</NearestTargetFramework> | ||
|
||
<_HasSingleTargetFramework Condition="'$(TargetFramework)' != '' and '$(TargetFrameworks)' == ''">true</_HasSingleTargetFramework> | ||
<_HasSingleTargetFramework Condition="'$(_HasSingleTargetFramework)' == ''">false</_HasSingleTargetFramework> | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe everywhere else we consider TargetFramework to win over TargetFrameworks, so this might be better as TargetFramework != ''
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think I understand. Can you rephrase?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If I have a project that sets both TargetFramework and TargetFrameworks, TargetFramework will win (we won't go to cross-targeting targets), but this won't report it as such.
Alternative with an item + metadata instead: diff --git "a/c:\\Program Files\\dotnet - Copy\\sdk\\1.0.0-rc4-004689/Microsoft.Common.CurrentVersion.targets" "b/C:\\Program Files\\dotnet\\sdk\\1.0.0-rc4-004689/Microsoft.Common.CurrentVersion.targets"
index da772b0..96e8fb4 100644
--- "a/c:\\Program Files\\dotnet - Copy\\sdk\\1.0.0-rc4-004689/Microsoft.Common.CurrentVersion.targets"
+++ "b/C:\\Program Files\\dotnet\\sdk\\1.0.0-rc4-004689/Microsoft.Common.CurrentVersion.targets"
@@ -1524,13 +1524,20 @@ Copyright (C) Microsoft Corporation. All rights reserved.
RemoveProperties="%(_MSBuildProjectReferenceExistent.GlobalPropertiesToRemove);TargetFramework"
Condition="'%(_MSBuildProjectReferenceExistent.Extension)' != '.vcxproj'">
- <Output TaskParameter="TargetOutputs" PropertyName="_ProjectReferenceTargetFrameworkProperties" />
+ <Output TaskParameter="TargetOutputs" ItemName="_ProjectReferenceTargetFrameworkProperties" />
</MSBuild>
+ <Error Condition="@(_ProjectReferenceTargetFrameworkProperties->Count()) != 1" Text="Assertion failed: @(_ProjectReferenceTargetFrameworkProperties->Count()) @(_ProjectReferenceTargetFrameworkProperties)" />
+
<ItemGroup>
<_MSBuildProjectReferenceExistent Condition="'%(_MSBuildProjectReferenceExistent.Identity)' == '%(Identity)'">
<SetTargetFramework>$(_ProjectReferenceTargetFrameworkProperties)</SetTargetFramework>
+
+ <UndefineProperties Condition="'@(_ProjectReferenceTargetFrameworkProperties->'%(HasSingleTargetFramework)')' == 'true'">%(_MSBuildProjectReferenceExistent.UndefineProperties);TargetFramework</UndefineProperties>
</_MSBuildProjectReferenceExistent>
+
+ <!-- Clear the list so the next iteration through the loop has a single item again. -->
+ <_ProjectReferenceTargetFrameworkProperties Remove="@(_ProjectReferenceTargetFrameworkProperties)" />
</ItemGroup>
<PropertyGroup>
diff --git "a/c:\\Program Files\\dotnet - Copy\\sdk\\1.0.0-rc4-004689/Sdks/Microsoft.NET.Sdk/build/Microsoft.NET.Sdk.Common.targets" "b/C:\\Program Files\\dotnet\\sdk\\1.0.0-rc4-004689/Sdks/Microsoft.NET.Sdk/build/Microsoft.NET.Sdk.Common.targets"
index c1c71c2..ae43aa0 100644
--- "a/c:\\Program Files\\dotnet - Copy\\sdk\\1.0.0-rc4-004689/Sdks/Microsoft.NET.Sdk/build/Microsoft.NET.Sdk.Common.targets"
+++ "b/C:\\Program Files\\dotnet\\sdk\\1.0.0-rc4-004689/Sdks/Microsoft.NET.Sdk/build/Microsoft.NET.Sdk.Common.targets"
@@ -55,7 +55,7 @@ Copyright (c) .NET Foundation. All rights reserved.
with the referencing project's target framework.
============================================================
-->
- <Target Name="GetTargetFrameworkProperties" Returns="TargetFramework=$(NearestTargetFramework)">
+ <Target Name="GetTargetFrameworkProperties" Returns="@(ProjectWithTargetFrameworkProperties)">
<PropertyGroup>
<!-- If a ReferringTargetFramework was not specified, and we only have one TargetFramework, then don't try to check compatibility -->
@@ -72,6 +72,14 @@ Copyright (c) .NET Foundation. All rights reserved.
Condition="'$(_SkipNearestTargetFrameworkResolution)' != 'true'">
<Output PropertyName="NearestTargetFramework" TaskParameter="NearestTargetFramework" />
</GetNearestTargetFramework>
+
+ <ItemGroup>
+ <ProjectWithTargetFrameworkProperties Include="$(MSBuildProjectFullPath)">
+ <TargetFramework>$(NearestTargetFramework)</TargetFramework>
+ <HasSingleTargetFramework Condition="'$(TargetFrameworks)' != ''">false</HasSingleTargetFramework>
+ <HasSingleTargetFramework Condition="'$(TargetFramework)' != '' and '$(TargetFrameworks)' == ''">true</HasSingleTargetFramework>
+ </ProjectWithTargetFrameworkProperties>
+ </ItemGroup>
</Target>
</Project> I don't think I prefer it. Have to jump through hoops to operate on a single result at a time, where that's implicit with the property. Not that the property way in the PR is clean or nice . . . |
Hmm that is a lot messier than I imagined. I trust your judgement on this. |
@natidea can you test this change with whatever repros we've got? |
You'll need this change as well - dotnet/msbuild#1667 |
|
||
<PropertyGroup> | ||
<!-- If a ReferringTargetFramework was not specified, and we only have one TargetFramework, then don't try to check compatibility --> | ||
<_SkipNearestTargetFrameworkResolution Condition="'$(TargetFramework)' != '' and '$(ReferringTargetFramework)' == ''">true</_SkipNearestTargetFrameworkResolution> | ||
<NearestTargetFramework Condition="'$(_SkipNearestTargetFrameworkResolution)' == 'true'">$(TargetFramework)</NearestTargetFramework> | ||
|
||
<_HasSingleTargetFramework Condition="'$(TargetFramework)' != ''">true</_HasSingleTargetFramework> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If a SDK-based project doesn't define a TargetFramework, do we issue an error today? I'm thinking if someone takes an existing project where TFI, TFV are set and makes it use the SDK and doesn't set TargetFramework, will we now think of them as not-single-targeting projects?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point. I think we need this to be '$(IsCrossTargetingBuild)' != 'true'
. Whatever condition causes us not to use the x-targeting is the same as what should get no additional properties.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Makes perfect sense. Thanks.
@natidea MSBuild package 545 should have the common-targets side of this baked in. |
@@ -29,7 +29,7 @@ Copyright (c) .NET Foundation. All rights reserved. | |||
<Version Condition=" '$(Version)' == '' ">$(VersionPrefix)</Version> | |||
<Authors Condition=" '$(Authors)'=='' ">$(AssemblyName)</Authors> | |||
<Company Condition=" '$(Company)'=='' ">$(Authors)</Company> | |||
<AssemblyTitle Condition="'$(AssemblyTitle)' == ''">$(AssemblyName)</AssemblyTitle> | |||
- <AssemblyTitle Condition="'$(AssemblyTitle)' == ''">$(AssemblyName)</AssemblyTitle> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like there are some whitespace and extra leading character issues
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's what I get for trusting the GitHub web editor.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed.
Customer scenario: Parallel solution builds with single-targeted sdk-based projects fail intermittently (but frequently) Bugs this fixes:: #739 Workarounds, if any: None Risk: Low Performance impact: Low Is this a regression from a previous update?: No Root cause analysis:: Complicated interaction between cross-targeting P2P protocol, sln builds, and /m > 1. How was the bug found?: Customer and partner reported |
@MattGertz for approval |
@srivatsn Feel free to add this to your VSO bug now if you are comfortable. It'll be another 40 minutes before they get to us... |
Added |
Partially fixes dotnet#739. The first iteration of cross-targeting support code unconditionally queried each ProjectReference for the best TFM to build against, and then explicitly specified that TFM when building the reference. This caused a race condition when building a set of projects that had a single-TFM project and another project that had a reference to it. The entry point (probably .sln) build would build the referenced project with no TF specified, and then the referencing project would build it with an explicit TF specified. These two builds appeared different to the MSBuild engine (because they had different sets of global properties) and so were both executed, resulting in a race condition. The fix is in two parts: * Allow a project to report back through GetTargetFrameworkProperties that it only has one TF to build. * When a project reports that it has only one TF to build, issue its build request without specifying any TF (dotnet/msbuild#1667) This commit is the former.
4c6c522
to
ecc9b6c
Compare
Shiproom Update: Waiting for Weekend validation |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
After applying both patches, I no longer see the race through multiple builds of both CLI build and DependencyInjection.sln
…0190720.4 (dotnet#797) - Microsoft.AspNetCore.Mvc.Analyzers - 3.0.0-preview8.19370.4 - Microsoft.AspNetCore.Mvc.Api.Analyzers - 3.0.0-preview8.19370.4 - Microsoft.AspNetCore.Analyzers - 3.0.0-preview8.19370.4 - Microsoft.AspNetCore.Components.Analyzers - 3.0.0-preview8.19370.4
Partially fixes #739.
The first iteration of cross-targeting support code unconditionally
queried each ProjectReference for the best TFM to build against, and
then explicitly specified that TFM when building the reference. This
caused a race condition when building a set of projects that had a
single-TFM project and another project that had a reference to it. The
entry point (probably .sln) build would build the referenced project
with no TF specified, and then the referencing project would build it
with an explicit TF specified. These two builds appeared different to
the MSBuild engine (because they had different sets of global
properties) and so were both executed, resulting in a race condition.
The fix is in two parts:
that it only has one TF to build.
build request without specifying any TF. (Respect projects that say they only have one TFM msbuild#1667)
This commit is the former.