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

Perform nearest-TFM query in parallel #1785

Closed
rainersigwald opened this issue Mar 2, 2017 · 2 comments
Closed

Perform nearest-TFM query in parallel #1785

rainersigwald opened this issue Mar 2, 2017 · 2 comments
Labels
Milestone

Comments

@rainersigwald
Copy link
Member

Work in progress notes on moving from batching to parallelizable invocations of GetTargetFrameworkProperties

Working diff
diff --git "a/C:\\Program Files\\dotnet\\sdk\\1.0.0/Microsoft.Common.CurrentVersion.targets" "b/S:\\work\\single-eval\\cli_paralleltfquery\\sdk\\1.0.0/Microsoft.Common.CurrentVersion.targets"
index 80fbf5a..c6b0e86 100644
--- "a/C:\\Program Files\\dotnet\\sdk\\1.0.0/Microsoft.Common.CurrentVersion.targets"	
+++ "b/S:\\work\\single-eval\\cli_paralleltfquery\\sdk\\1.0.0/Microsoft.Common.CurrentVersion.targets"
@@ -1510,8 +1510,7 @@ Copyright (C) Microsoft Corporation. All rights reserved.
 
     ======================================================================================
   -->
-  <Target Name="_GetProjectReferenceTargetFrameworkProperties"
-          Outputs="%(_MSBuildProjectReferenceExistent.Identity)">
+  <Target Name="_GetProjectReferenceTargetFrameworkProperties">
     <!--
       Honor SkipGetTargetFrameworkProperties=true metadata on project references
       to mean that the project reference is known not to target multiple frameworks
@@ -1555,7 +1554,7 @@ Copyright (C) Microsoft Corporation. All rights reserved.
     </PropertyGroup>
 
     <MSBuild
-        Projects="%(_MSBuildProjectReferenceExistent.Identity)"
+        Projects="@(_MSBuildProjectReferenceExistent)"
         Targets="GetTargetFrameworkProperties"
         BuildInParallel="$(BuildInParallel)"
         Properties="%(_MSBuildProjectReferenceExistent.SetConfiguration); %(_MSBuildProjectReferenceExistent.SetPlatform); ReferringTargetFramework=$(ReferringTargetFrameworkForProjectReferences)"
@@ -1563,30 +1562,41 @@ Copyright (C) Microsoft Corporation. All rights reserved.
         RemoveProperties="%(_MSBuildProjectReferenceExistent.GlobalPropertiesToRemove);TargetFramework;RuntimeIdentifier"
         Condition="'%(_MSBuildProjectReferenceExistent.SkipGetTargetFrameworkProperties)' != 'true'">
 
-      <Output TaskParameter="TargetOutputs" PropertyName="_ProjectReferenceTargetFrameworkProperties" />
+      <Output TaskParameter="TargetOutputs" ItemName="_ProjectReferenceTargetFrameworkProperties" />
     </MSBuild>
 
     <ItemGroup>
-      <_MSBuildProjectReferenceExistent Condition="'%(_MSBuildProjectReferenceExistent.Identity)' == '%(Identity)' and '$(_ProjectReferenceTargetFrameworkProperties)' != ''">
-        <SetTargetFramework>$(_ProjectReferenceTargetFrameworkProperties)</SetTargetFramework>
-
-        <UndefineProperties Condition="$(_ProjectReferenceTargetFrameworkProperties.Contains(`ProjectHasSingleTargetFramework=true`))">%(_MSBuildProjectReferenceExistent.UndefineProperties);TargetFramework;ProjectHasSingleTargetFramework</UndefineProperties>
-        <!-- Unconditionally remove the property that was set as a marker to indicate that for this call we should remove TargetFramework -->
-        <UndefineProperties Condition="!$(_ProjectReferenceTargetFrameworkProperties.Contains(`ProjectHasSingleTargetFramework=true`))">%(_MSBuildProjectReferenceExistent.UndefineProperties);ProjectHasSingleTargetFramework</UndefineProperties>
-      </_MSBuildProjectReferenceExistent>
+      <!-- Build an item that has Identity matching _MSBuildProjectReferenceExistent and metadata for properties to set. -->
+      <_ProjectReferencesWithTargetFrameworkProperties Include="@(_ProjectReferenceTargetFrameworkProperties->'%(OriginalItemSpec)')">
+        <!--<DesiredTargetFrameworkProperties>$([System.String]::Copy('%(Identity)').Replace('ProjectHasSingleTargetFramework=true','').Replace('ProjectIsRidAgnostic=true','').TrimEnd(';'))</DesiredTargetFrameworkProperties>
+        <HasSingleTargetFramework>$([System.String]::Copy('%(Identity)').Contains('ProjectHasSingleTargetFramework=true'))</HasSingleTargetFramework>
+        <IsRidAgnostic>$([System.String]::Copy('%(Identity)').Contains('ProjectIsRidAgnostic=true'))</IsRidAgnostic>-->
+      </_ProjectReferencesWithTargetFrameworkProperties>
     </ItemGroup>
+    <!--<FindInList List="@(_ProjectReferencesWithTargetFrameworkProperties)" ItemSpecToFind="foo" />
+    <FindInList List="@(_MSBuildProjectReferenceExistent)" ItemSpecToFind="foo" />
 
+    <Message Importance="High" Text="'@(_ProjectReferencesWithTargetFrameworkProperties)' == '%(Identity)' and '%(_ProjectReferencesWithTargetFrameworkProperties.HasSingleTargetFramework)' != 'true' : %(_ProjectReferencesWithTargetFrameworkProperties.DesiredTargetFrameworkProperties)" />-->
     <ItemGroup>
-      <_MSBuildProjectReferenceExistent Condition="'%(_MSBuildProjectReferenceExistent.Identity)' == '%(Identity)' and '$(_ProjectReferenceTargetFrameworkProperties)' != ''">
-        <UndefineProperties Condition="$(_ProjectReferenceTargetFrameworkProperties.Contains(`ProjectIsRidAgnostic=true`))">%(_MSBuildProjectReferenceExistent.UndefineProperties);RuntimeIdentifier;ProjectIsRidAgnostic</UndefineProperties>
-        <!-- Unconditionally remove the property that was set as a marker to indicate that for this call we should remove RuntimeIdentifier -->
-        <UndefineProperties Condition="!$(_ProjectReferenceTargetFrameworkProperties.Contains(`ProjectIsRidAgnostic=true`))">%(_MSBuildProjectReferenceExistent.UndefineProperties);ProjectIsRidAgnostic</UndefineProperties>
+
+      <!-- Set the project's returned TargetFramework -->
+      <_MSBuildProjectReferenceExistent Condition="'@(_ProjectReferencesWithTargetFrameworkProperties)' == '%(Identity)' and '@(_ProjectReferencesWithTargetFrameworkProperties->'%(HasSingleTargetFramework)')' != 'true'">
+        <SetTargetFramework>@(_ProjectReferencesWithTargetFrameworkProperties->'%(DesiredTargetFrameworkProperties)')</SetTargetFramework>
+      </_MSBuildProjectReferenceExistent>
+
+      <!-- If the project has only one TF, don't specify it. It will go directly to the inner build anyway and we don't want to redundantly specify a global property, which can cause a race. -->
+      <_MSBuildProjectReferenceExistent Condition="'@(_ProjectReferencesWithTargetFrameworkProperties)' == '%(Identity)' and '@(_ProjectReferencesWithTargetFrameworkProperties->'%(HasSingleTargetFramework)')' == 'true'">
+        <UndefineProperties>@(_MSBuildProjectReferenceExistent->'%(UndefineProperties)');TargetFramework</UndefineProperties>
+      </_MSBuildProjectReferenceExistent>
+
+      <!-- If the project has only one RID, assume it's compatible with the current project and don't pass this one along. -->
+      <_MSBuildProjectReferenceExistent Condition="'@(_ProjectReferencesWithTargetFrameworkProperties)' == '%(Identity)' and '@(_ProjectReferencesWithTargetFrameworkProperties->'%(IsRidAgnostic)')' == 'true'">
+        <UndefineProperties>@(_MSBuildProjectReferenceExistent->'%(UndefineProperties)');RuntimeIdentifier</UndefineProperties>
       </_MSBuildProjectReferenceExistent>
     </ItemGroup>
 
-    <PropertyGroup>
-      <_ProjectReferenceTargetFrameworkProperties />
-    </PropertyGroup>
+    <FindInList List="@(_MSBuildProjectReferenceExistent)" ItemSpecToFind="foo" />
+
   </Target>
 
   <!--
diff --git "a/C:\\Program Files\\dotnet\\sdk\\1.0.0/Sdks/Microsoft.NET.Sdk/build/Microsoft.NET.Sdk.Common.targets" "b/S:\\work\\single-eval\\cli_paralleltfquery\\sdk\\1.0.0/Sdks/Microsoft.NET.Sdk/build/Microsoft.NET.Sdk.Common.targets"
index 1cdc34e..d7599ce 100644
--- "a/C:\\Program Files\\dotnet\\sdk\\1.0.0/Sdks/Microsoft.NET.Sdk/build/Microsoft.NET.Sdk.Common.targets"	
+++ "b/S:\\work\\single-eval\\cli_paralleltfquery\\sdk\\1.0.0/Sdks/Microsoft.NET.Sdk/build/Microsoft.NET.Sdk.Common.targets"
@@ -51,7 +51,7 @@ Copyright (c) .NET Foundation. All rights reserved.
     with the referencing project's target framework.
   ============================================================
    -->
-  <Target Name="GetTargetFrameworkProperties" Returns="TargetFramework=$(NearestTargetFramework);ProjectHasSingleTargetFramework=$(_HasSingleTargetFramework);ProjectIsRidAgnostic=$(_IsRidAgnostic)">
+  <Target Name="GetTargetFrameworkProperties" Returns="@(ProjectBuildInstructions)">
 
     <PropertyGroup>
       <!-- indicate to caller that project is RID agnostic so that a global property RuntimeIdentifier value can be removed -->
@@ -76,6 +76,23 @@ Copyright (c) .NET Foundation. All rights reserved.
                                Condition="'$(_SkipNearestTargetFrameworkResolution)' != 'true'">
       <Output PropertyName="NearestTargetFramework" TaskParameter="NearestTargetFramework" />
     </GetNearestTargetFramework>
+
+    <PropertyGroup>
+      <PropertiesToBeBuiltWith>TargetFramework=$(NearestTargetFramework)</PropertiesToBeBuiltWith>
+      <PropertiesToBeBuiltWith Condition="$(_HasSingleTargetFramework)">$(PropertiesToBeBuiltWith);ProjectHasSingleTargetFramework=true</PropertiesToBeBuiltWith>
+      <PropertiesToBeBuiltWith Condition="$(_IsRidAgnostic)">$(PropertiesToBeBuiltWith);ProjectIsRidAgnostic=true</PropertiesToBeBuiltWith>
+
+      <!-- The return value from this target will be treated as an item, so it must be escaped to transfer semicolons.-->
+      <PropertiesToBeBuiltWithEscaped>$([MSBuild]::Escape($(PropertiesToBeBuiltWith)))</PropertiesToBeBuiltWithEscaped>
+    </PropertyGroup>
+
+    <ItemGroup>
+      <ProjectBuildInstructions Include="$(MSBuildThisFileFullPath)">
+        <DesiredTargetFrameworkProperties>TargetFramework=$(NearestTargetFramework)</DesiredTargetFrameworkProperties>
+        <HasSingleTargetFramework>$(_HasSingleTargetFramework)</HasSingleTargetFramework>
+        <IsRidAgnostic>$(_IsRidAgnostic)</IsRidAgnostic>
+      </ProjectBuildInstructions>
+    </ItemGroup>
   </Target>
   
 </Project>
@rainersigwald rainersigwald self-assigned this Mar 2, 2017
@rainersigwald
Copy link
Member Author

cleaned up diff:

diff --git "a/C:\\Program Files\\dotnet\\sdk\\1.0.0/Microsoft.Common.CurrentVersion.targets" "b/S:\\work\\single-eval\\cli_paralleltfquery\\sdk\\1.0.0/Microsoft.Common.CurrentVersion.targets"
index 80fbf5a..0aeba60 100644
--- "a/C:\\Program Files\\dotnet\\sdk\\1.0.0/Microsoft.Common.CurrentVersion.targets"	
+++ "b/S:\\work\\single-eval\\cli_paralleltfquery\\sdk\\1.0.0/Microsoft.Common.CurrentVersion.targets"
@@ -1510,8 +1510,7 @@ Copyright (C) Microsoft Corporation. All rights reserved.
 
     ======================================================================================
   -->
-  <Target Name="_GetProjectReferenceTargetFrameworkProperties"
-          Outputs="%(_MSBuildProjectReferenceExistent.Identity)">
+  <Target Name="_GetProjectReferenceTargetFrameworkProperties">
     <!--
       Honor SkipGetTargetFrameworkProperties=true metadata on project references
       to mean that the project reference is known not to target multiple frameworks
@@ -1555,7 +1554,7 @@ Copyright (C) Microsoft Corporation. All rights reserved.
     </PropertyGroup>
 
     <MSBuild
-        Projects="%(_MSBuildProjectReferenceExistent.Identity)"
+        Projects="@(_MSBuildProjectReferenceExistent)"
         Targets="GetTargetFrameworkProperties"
         BuildInParallel="$(BuildInParallel)"
         Properties="%(_MSBuildProjectReferenceExistent.SetConfiguration); %(_MSBuildProjectReferenceExistent.SetPlatform); ReferringTargetFramework=$(ReferringTargetFrameworkForProjectReferences)"
@@ -1563,30 +1562,32 @@ Copyright (C) Microsoft Corporation. All rights reserved.
         RemoveProperties="%(_MSBuildProjectReferenceExistent.GlobalPropertiesToRemove);TargetFramework;RuntimeIdentifier"
         Condition="'%(_MSBuildProjectReferenceExistent.SkipGetTargetFrameworkProperties)' != 'true'">
 
-      <Output TaskParameter="TargetOutputs" PropertyName="_ProjectReferenceTargetFrameworkProperties" />
+      <Output TaskParameter="TargetOutputs" ItemName="_ProjectReferenceTargetFrameworkProperties" />
     </MSBuild>
 
     <ItemGroup>
-      <_MSBuildProjectReferenceExistent Condition="'%(_MSBuildProjectReferenceExistent.Identity)' == '%(Identity)' and '$(_ProjectReferenceTargetFrameworkProperties)' != ''">
-        <SetTargetFramework>$(_ProjectReferenceTargetFrameworkProperties)</SetTargetFramework>
+      <!-- Build an item that has Identity matching _MSBuildProjectReferenceExistent and metadata for properties to set. -->
+      <_ProjectReferencesWithTargetFrameworkProperties Include="@(_ProjectReferenceTargetFrameworkProperties->'%(OriginalItemSpec)')">
+        <!--<DesiredTargetFrameworkProperties>$([System.String]::Copy('%(Identity)').Replace('ProjectHasSingleTargetFramework=true','').Replace('ProjectIsRidAgnostic=true','').TrimEnd(';'))</DesiredTargetFrameworkProperties>
+        <HasSingleTargetFramework>$([System.String]::Copy('%(Identity)').Contains('ProjectHasSingleTargetFramework=true'))</HasSingleTargetFramework>
+        <IsRidAgnostic>$([System.String]::Copy('%(Identity)').Contains('ProjectIsRidAgnostic=true'))</IsRidAgnostic>-->
+      </_ProjectReferencesWithTargetFrameworkProperties>
+
+      <!-- Set the project's returned TargetFramework -->
+      <_MSBuildProjectReferenceExistent Condition="'@(_ProjectReferencesWithTargetFrameworkProperties)' == '%(Identity)' and '@(_ProjectReferencesWithTargetFrameworkProperties->'%(HasSingleTargetFramework)')' != 'true'">
+        <SetTargetFramework>@(_ProjectReferencesWithTargetFrameworkProperties->'%(DesiredTargetFrameworkProperties)')</SetTargetFramework>
+      </_MSBuildProjectReferenceExistent>
 
-        <UndefineProperties Condition="$(_ProjectReferenceTargetFrameworkProperties.Contains(`ProjectHasSingleTargetFramework=true`))">%(_MSBuildProjectReferenceExistent.UndefineProperties);TargetFramework;ProjectHasSingleTargetFramework</UndefineProperties>
-        <!-- Unconditionally remove the property that was set as a marker to indicate that for this call we should remove TargetFramework -->
-        <UndefineProperties Condition="!$(_ProjectReferenceTargetFrameworkProperties.Contains(`ProjectHasSingleTargetFramework=true`))">%(_MSBuildProjectReferenceExistent.UndefineProperties);ProjectHasSingleTargetFramework</UndefineProperties>
+      <!-- If the project has only one TF, don't specify it. It will go directly to the inner build anyway and we don't want to redundantly specify a global property, which can cause a race. -->
+      <_MSBuildProjectReferenceExistent Condition="'@(_ProjectReferencesWithTargetFrameworkProperties)' == '%(Identity)' and '@(_ProjectReferencesWithTargetFrameworkProperties->'%(HasSingleTargetFramework)')' == 'true'">
+        <UndefineProperties>@(_MSBuildProjectReferenceExistent->'%(UndefineProperties)');TargetFramework</UndefineProperties>
       </_MSBuildProjectReferenceExistent>
-    </ItemGroup>
 
-    <ItemGroup>
-      <_MSBuildProjectReferenceExistent Condition="'%(_MSBuildProjectReferenceExistent.Identity)' == '%(Identity)' and '$(_ProjectReferenceTargetFrameworkProperties)' != ''">
-        <UndefineProperties Condition="$(_ProjectReferenceTargetFrameworkProperties.Contains(`ProjectIsRidAgnostic=true`))">%(_MSBuildProjectReferenceExistent.UndefineProperties);RuntimeIdentifier;ProjectIsRidAgnostic</UndefineProperties>
-        <!-- Unconditionally remove the property that was set as a marker to indicate that for this call we should remove RuntimeIdentifier -->
-        <UndefineProperties Condition="!$(_ProjectReferenceTargetFrameworkProperties.Contains(`ProjectIsRidAgnostic=true`))">%(_MSBuildProjectReferenceExistent.UndefineProperties);ProjectIsRidAgnostic</UndefineProperties>
+      <!-- If the project has only one RID, assume it's compatible with the current project and don't pass this one along. -->
+      <_MSBuildProjectReferenceExistent Condition="'@(_ProjectReferencesWithTargetFrameworkProperties)' == '%(Identity)' and '@(_ProjectReferencesWithTargetFrameworkProperties->'%(IsRidAgnostic)')' == 'true'">
+        <UndefineProperties>@(_MSBuildProjectReferenceExistent->'%(UndefineProperties)');RuntimeIdentifier</UndefineProperties>
       </_MSBuildProjectReferenceExistent>
     </ItemGroup>
-
-    <PropertyGroup>
-      <_ProjectReferenceTargetFrameworkProperties />
-    </PropertyGroup>
   </Target>
 
   <!--
diff --git "a/C:\\Program Files\\dotnet\\sdk\\1.0.0/Sdks/Microsoft.NET.Sdk/build/Microsoft.NET.Sdk.Common.targets" "b/S:\\work\\single-eval\\cli_paralleltfquery\\sdk\\1.0.0/Sdks/Microsoft.NET.Sdk/build/Microsoft.NET.Sdk.Common.targets"
index 1cdc34e..70486fb 100644
--- "a/C:\\Program Files\\dotnet\\sdk\\1.0.0/Sdks/Microsoft.NET.Sdk/build/Microsoft.NET.Sdk.Common.targets"	
+++ "b/S:\\work\\single-eval\\cli_paralleltfquery\\sdk\\1.0.0/Sdks/Microsoft.NET.Sdk/build/Microsoft.NET.Sdk.Common.targets"
@@ -51,7 +51,7 @@ Copyright (c) .NET Foundation. All rights reserved.
     with the referencing project's target framework.
   ============================================================
    -->
-  <Target Name="GetTargetFrameworkProperties" Returns="TargetFramework=$(NearestTargetFramework);ProjectHasSingleTargetFramework=$(_HasSingleTargetFramework);ProjectIsRidAgnostic=$(_IsRidAgnostic)">
+  <Target Name="GetTargetFrameworkProperties" Returns="@(ProjectBuildInstructions)">
 
     <PropertyGroup>
       <!-- indicate to caller that project is RID agnostic so that a global property RuntimeIdentifier value can be removed -->
@@ -76,6 +76,14 @@ Copyright (c) .NET Foundation. All rights reserved.
                                Condition="'$(_SkipNearestTargetFrameworkResolution)' != 'true'">
       <Output PropertyName="NearestTargetFramework" TaskParameter="NearestTargetFramework" />
     </GetNearestTargetFramework>
+
+    <ItemGroup>
+      <ProjectBuildInstructions Include="$(MSBuildThisFileFullPath)">
+        <DesiredTargetFrameworkProperties>TargetFramework=$(NearestTargetFramework)</DesiredTargetFrameworkProperties>
+        <HasSingleTargetFramework>$(_HasSingleTargetFramework)</HasSingleTargetFramework>
+        <IsRidAgnostic>$(_IsRidAgnostic)</IsRidAgnostic>
+      </ProjectBuildInstructions>
+    </ItemGroup>
   </Target>
   
 </Project>

@rainersigwald
Copy link
Member Author

I'm looking at this again because it seems likely to be the foundation of any good path to fixing #1276.

As implemented above, this would break backward compatibility with older SDKs on the new common targets (like SDK 2.0.0 on MSBuild 15.5 would presumably have).

But that can be fixed. Working on that now.

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

Successfully merging a pull request may close this issue.

3 participants