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

[Breaking Change] Targets that run after ResolveReferences to manipulate references are broken after upgrading to 15.3 #2134

Closed
davkean opened this issue May 25, 2017 · 6 comments

Comments

@davkean
Copy link
Member

davkean commented May 25, 2017

Version 15.3.0-pre.1.0+26524.3003.d15prerel

This target which we copied from a package that comes in the VS SDK is broken in this build:

  <!-- This is a copy of the Microsoft.VisualStudio.SDK.EmbedInteropTypes NuGet package, but only the list of
       assemblies that we need. The package includes things like EnvDTE which are reasonable for consumers, but
       strange since we actually _implement_ DTE and use it as an exchange type with generics in a few places. -->
  <Target Name="LinkVSSDKEmbeddableAssemblies" DependsOnTargets="ResolveReferences" AfterTargets="ResolveReferences">
    <ItemGroup>
      <ReferencePath Condition="
              '%(FileName)' == 'Microsoft.VisualStudio.Shell.Embeddable'
           or '%(FileName)' == 'Microsoft.VisualStudio.Shell.Interop.12.0'
           or '%(FileName)' == 'Microsoft.VisualStudio.Shell.Interop.12.1.DesignTime'
           or '%(FileName)' == 'Microsoft.VisualStudio.Shell.Interop.14.0.DesignTime'
           or '%(FileName)' == 'Microsoft.VisualStudio.Shell.Interop.15.0.DesignTime'
           or '%(Filename)' == 'Microsoft.VisualStudio.Imaging.Interop.14.0.DesignTime'
           or '%(FileName)' == 'Microsoft.VisualStudio.TextManager.Interop.12.1.DesignTime'
           or '%(FileName)' == 'Microsoft.VisualStudio.ProjectSystem.Interop'
           or '%(FileName)' == 'stdole'
           or '%(FileName)' == 'Microsoft.VisualStudio.CommandBars'
           or '%(FileName)' == 'NuGet.SolutionRestoreManager.Interop'
           or '%(FileName)' == 'NuGet.VisualStudio'
              ">
        <EmbedInteropTypes>true</EmbedInteropTypes>
      </ReferencePath>
    </ItemGroup>
  </Target>

ie Changes this target makes to the ReferencePath item are not respected at compile time.

This silently breaks the product until runtime, after building with this binary - it fails to load because Visual Studio doesn't ship with any of the .DesignTime dlls, hence why they are embedded. Manipulating ReferencePath is a pretty common extension point.

I'm guessing this was broken in the references assembly changes - haven't fully groked what changes we made there and where we landed with all this.

@davkean
Copy link
Member Author

davkean commented May 25, 2017

tag @rainersigwald @AndyGerlicher

@rainersigwald
Copy link
Member

rainersigwald commented May 25, 2017

This is indeed a consequence of #2039. I'm not sure what to do about it.

This target is arguably wrong--it's manipulating an item after the rollup target that logically produces that item. I'd rather see it as BeforeTargets="ResolveReferences" DependsOnTargets="$(ResolveReferencesDependsOn)", similar to what I did with the find-ref-assemblies target. Though ordering between two different targets that want to do related things is extremely tricky there.

Being "wrong" in a non-obvious way doesn't mean we can just break things with impunity. But we also need to be able to modify the build process.

Thinking about fixes.

@davkean You can work around for the moment by adding a BeforeTargets="FindReferenceAssembliesForReferences" to that target. EDIT: wait, that probably creates a dependency cycle. You probably have to replace the dependencies with that rather than add it.

@rainersigwald
Copy link
Member

One possibility would be to move FindReferenceAssembliesForReferences to be BeforeTargets="BeforeCompile" (or _GenerateCompileInputs?). Or to add it as an explicit named, ordered dependency in $(CompileDependsOn).

Would that make it happen too late for some uses? I can't think of any offhand, since @(ReferencePathWithRefAssemblies) is used only in CoreCompile at the moment--and it's new, so if someone wanted to take a dependency on it they'd have to deal with it wherever it is.

cc @jcouv

rainersigwald added a commit to rainersigwald/msbuild that referenced this issue May 25, 2017
e3a3d69 added a new FindReferenceAssembliesForReferences target, which
ran just before ResolveReferences. Dogfooding this revealed targets in
the VS SDK (at least) that manipulate @(ReferencePath) and are hooked in
as AfterTargets of ResolveReferences. That was silently ignored,
corrupting the user's build.

Fixes dotnet#2134 by moving FindReferenceAssembliesForReferences later in the
process, so anyone hooking ResolveReferences will see the changes they
make in the compiler.

This is not a fully general solution to the problem that someone might
hook an arbitrary point and manipulate @(ReferencePath), but it unbreaks
an obvious hook point.
@rainersigwald
Copy link
Member

Confirmed by patching my 15.3.0-pre.1.0+26524.0.d15rel install that what I'm proposing in #2139 fixes the issue for the project system repo.

@nguerrera
Copy link
Contributor

Naive question: why not just have compilation tasks use @(ReferencePath->'%(ReferenceAssembly)') and eliminate the separate item group?

AndyGerlicher pushed a commit that referenced this issue May 26, 2017
e3a3d69 added a new FindReferenceAssembliesForReferences target, which
ran just before ResolveReferences. Dogfooding this revealed targets in
the VS SDK (at least) that manipulate @(ReferencePath) and are hooked in
as AfterTargets of ResolveReferences. That was silently ignored,
corrupting the user's build.

Fixes #2134 by moving FindReferenceAssembliesForReferences later in the
process, so anyone hooking ResolveReferences will see the changes they
make in the compiler.

This is not a fully general solution to the problem that someone might
hook an arbitrary point and manipulate @(ReferencePath), but it unbreaks
an obvious hook point.
rainersigwald added a commit to rainersigwald/msbuild that referenced this issue May 30, 2017
e3a3d69 added a new FindReferenceAssembliesForReferences target, which
ran just before ResolveReferences. Dogfooding this revealed targets in
the VS SDK (at least) that manipulate @(ReferencePath) and are hooked in
as AfterTargets of ResolveReferences. That was silently ignored,
corrupting the user's build.

Fixes dotnet#2134 by moving FindReferenceAssembliesForReferences later in the
process, so anyone hooking ResolveReferences will see the changes they
make in the compiler.

This is not a fully general solution to the problem that someone might
hook an arbitrary point and manipulate @(ReferencePath), but it unbreaks
an obvious hook point.
rainersigwald added a commit that referenced this issue May 31, 2017
e3a3d69 added a new FindReferenceAssembliesForReferences target, which
ran just before ResolveReferences. Dogfooding this revealed targets in
the VS SDK (at least) that manipulate @(ReferencePath) and are hooked in
as AfterTargets of ResolveReferences. That was silently ignored,
corrupting the user's build.

Fixes #2134 by moving FindReferenceAssembliesForReferences later in the
process, so anyone hooking ResolveReferences will see the changes they
make in the compiler.

This is not a fully general solution to the problem that someone might
hook an arbitrary point and manipulate @(ReferencePath), but it unbreaks
an obvious hook point.

Port of a618289 to the release branch for 15.3 preview 2.
@rainersigwald
Copy link
Member

@nguerrera That's discussed in #1986 (comment), but the short version is "target incrementality" + "backward compat". In retrospect, it could have been done that way by applying the transform everywhere (including in the inputs) and making the compat shim in Roslyn populate that metadata on the item.

@AR-May AR-May added the triaged label Feb 21, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants