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

Traversal targets for cross-targeting #1018

Merged
merged 5 commits into from
Sep 13, 2016
Merged

Conversation

nguerrera
Copy link
Contributor

@nguerrera nguerrera commented Sep 12, 2016

This implements the portion of cross-targeting that we agreed must happen first in msbuild proper and as soon as possible to uncover any unforseen breaking impact on existing projects.

  1. Redirect Microsoft.VisualBasic/CSharp.targets to new Microsoft.Common.Traversal.targets if $(TargetFrameworks) is set, but $(TargetFramework) is empty.
  2. Implement the protocol where every project will pass its TFM down to project references and get the properties that configure the destination to the best compatible target.
  3. For now, the common traversal targets just import based on a variable that we will set in a props hook, but ultimately some general logic should probably be live there, and there should be a way for arbitrary nuget packages to participate. This needs design we have not yet done so going with a minimal, unblocking start.

@nguerrera nguerrera force-pushed the cross-targeting branch 3 times, most recently from caceff2 to e136e0a Compare September 13, 2016 17:11
@nguerrera nguerrera changed the title [WIP] Traversal targets for cross-targeting Traversal targets for cross-targeting Sep 13, 2016

<!--
============================================================
PrepareProjectReferences
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a nice improvement 👍

-->

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(CoreTraversalTargetsPath)"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What defines this?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will define it in our after-props hook. We are only redirecting targets, not props so it will work. We need to discuss the outer build extensibility and how nuget packages participate, etc. This is just enough to (1) unblock my follow up work (2) smoke test that the common targets hijacking doesn't interfere with existing projects.

@nguerrera
Copy link
Contributor Author

Ready for review, @AndyGerlicher @cdmihai @srivatsn @davkean.

@nguerrera
Copy link
Contributor Author

FYI, @dotnet/project-system

@rainersigwald
Copy link
Member

I'm not a fan of calling this "traversal". Inside Microsoft, there's a long tradition of "traversal projects" (traditionally dirs.proj) that are lightweight directory-hierarchy traversers. MSBuild has this concept as well, for instance in BuildRequestConfiguration.

That said, I'm not sure what the right name for this concept is. "Inner" and "outer" as we've been casually calling it isn't very descriptive. Maybe something like CrossTargetingCoordinating? That's certainly not elegant.

@nguerrera
Copy link
Contributor Author

I'm happy to rename but we need a quick decision if this is really going in tonight. Traversal was what we had said in Friday's design meeting and I reiterated in my notes sent immediately after that. CrossTargetCoordinating is too long. Maybe we just go with what we've been saying and use Outer. I know @srivatsn doesn't like Outer though.

@srivatsn
Copy link
Contributor

I'll defer to the MSBuild folks wrt naming here.

@@ -17,6 +17,15 @@ Copyright (C) Microsoft Corporation. All rights reserved.

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<!--
We are doing a cross-targeting traversal build if there is no list of target frameworks specified
Copy link
Contributor

@cdmihai cdmihai Sep 13, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If there's a design doc on some github SDK page about what a cross-tagetting traversal build is, this comment would be a good spot to reference it in case users want to understand the bigger picture. :)

When we run during clean phase, we would skip on this
condition and then not rerun during build phase.
@AndyGerlicher
Copy link
Contributor

How about Microsoft.Common.CrossTargeting.targets?

@nguerrera
Copy link
Contributor Author

nguerrera commented Sep 13, 2016

How about Microsoft.Common.CrossTargeting.targets?

OK.

@nguerrera
Copy link
Contributor Author

And IsCrossTargetingBuild to mean that we're in the outer build. Inner build is non cross-targeting since it is one TFM. I think this is a fine way to go.

@AndyGerlicher
Copy link
Contributor

LGTM once IsTraversalBuild is renamed.

@nguerrera
Copy link
Contributor Author

@AndyGerlicher Thanks and done.

@nguerrera
Copy link
Contributor Author

@AndyGerlicher @cdmihai @rainersigwald Thanks again! Can you also help me get this ported to xplat and published to a package that the cli can consume?

@cdmihai
Copy link
Contributor

cdmihai commented Sep 14, 2016

@nguerrera

I think this is how you get into xplat:

@jeffkl, does that look alright?

@nguerrera
Copy link
Contributor Author

@cdmihai @jeffkl I've done this as #1025.

@rainersigwald
Copy link
Member

For posterity: this change caused an error in an internal project that had a custom target defined as:

<Target Name="ValidateReferences"
        DependsOnTargets="
            $(ResolveReferencesDependsOn);
            ValidateExportsFilesExist; 
            ValidatePackageReferences; 
            ValidateBinplace"
        AfterTargets="$(ResolveReferencesDependsOn)">

Note that it hooks after (any of) $(ResolveReferencesDependsOn) but then requires (all of) $(ResolveReferencesDependsOn) to run. Adding this target created a cycle on Clean:

Clean depends on CleanReferencedProjects depends on PrepareProjectReferences depends on AssignProjectConfiguration.

ValidateReferences has an AfterTargets for AssignProjectConfiguration, so ValidateReferences attempts to run, but first we have to run its DependsOnTargets, so we try to add them to the target stack, but when we consider PrepareProjectReferences, it’s already on the stack, so trying to add it would create a cycle, and we fail.

The error was

error MSB4006: There is a circular dependency in the target dependency graph involving target "PrepareProjectReferences".

This can be fixed by changing the custom target's hook:

             ValidateExportsFilesExist; 
             ValidatePackageReferences; 
             ValidateBinplace"
-          AfterTargets="$(ResolveReferencesDependsOn)">
+          BeforeTargets="ResolveReferences">
 
     <Error Text="@(ValidationError->'&#xa;%(Identity): %(Text)','')"
            Condition="@(ValidationError) != '' and $(ValidateProjectSettings) == 'true'"/>

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

Successfully merging this pull request may close these issues.

7 participants