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

P2Ps should be allowed when ReferenceOutputAssembly=false even given TFM incompatibilities #2661

Open
nguerrera opened this Issue Oct 23, 2017 · 28 comments

Comments

Projects
None yet
9 participants
@nguerrera
Member

nguerrera commented Oct 23, 2017

From @AArnott on March 3, 2017 18:40

With VS2015 projects, I can have a P2P from a portable library to a net46 library by setting metadata on the project reference:

<ProjectReference Include="..\SomeNet46Lib\lib.csproj">
  <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
</ProjectReference>

But with the .NET SDK projects, even with this metadata the build fails:

C:\Program Files (x86)\Microsoft Visual Studio\2017\d15rel\MSBuild\Sdks\Microsoft.NET.Sdk\build\Microsoft.NET.Sdk.Common.targets(73,5): error : Project 'C:\git\pinvoke\src\CodeGeneration\CodeGeneration.csproj'
targets '.NETFramework,Version=v4.6'. It cannot be referenced by a project that targets '.NETPortable,Version=v0.0,Profile=Profile92'. [C:\git\pinvoke\src\CodeGeneration\CodeGeneration.csproj]

This blocks scenarios where a P2P exists merely for the sake of ensuring build ordering but without the assembly reference. In my particular scenario, the referenced project provides a binary that the build of the portable library picks up for code generation purposes.

Copied from original issue: dotnet/sdk#939

@nguerrera

This comment has been minimized.

Member

nguerrera commented Oct 23, 2017

Workaround: Try also adding SkipGetTargetFrameworkProperties=true metadata to the reference.

@nguerrera

This comment has been minimized.

Member

nguerrera commented Oct 23, 2017

From @AArnott on March 7, 2017 5:58

Thanks @nguerrera. But that doesn't work either. That causes a referencing project A to build the referenced project B per A's TargetFramework value instead of B's TargetFramework.

@nguerrera

This comment has been minimized.

Member

nguerrera commented Oct 23, 2017

Ah, I believe this would only happen if A is multi targeted. Is it?

Try adding UndefineProperties="TargetFramework" metadata as well.

@nguerrera

This comment has been minimized.

Member

nguerrera commented Oct 23, 2017

From @AArnott on March 7, 2017 18:39

Yes, A is multi-targeted.
And that additional metadata did the trick. Thanks.

Should we leave the issue active for making this scenario simpler, and/or work the way it used to?

@nguerrera

This comment has been minimized.

Member

nguerrera commented Oct 23, 2017

Should we leave the issue active for making this scenario simpler, and/or work the way it used to?

Yes, this should work without the extra metadata.

@nguerrera

This comment has been minimized.

Member

nguerrera commented Oct 23, 2017

From @AArnott on April 11, 2017 13:31

This is badly broken. The workaround causes nuget restore to fail in VS (command line is fine) and also is related to a build failure that only occurs on some non-Windows machines including Travis CI Ubuntu.

I tried replacing this with a "project dependency" encoded in the solution file, and that fixed most of the symptoms, until I tried msbuild.exe my.sln when I learned that msbuild translates that solution dependency into a project reference during the build (@AndyGerlicher when did this feature get added?), with ReferenceOutputAssembly=false set (just as I wanted to do with my original ProjectReference item) and that of course repeats the original problem and the build fails because a net40 project can't depend on a netstandard1.5 project.

This inability to influence build ordering is really causing some pain here. Please fix soon!

@nguerrera

This comment has been minimized.

Member

nguerrera commented Oct 23, 2017

From @Sumo-MBryant on May 8, 2017 8:1

Has anyone found a workaround that is close to successful?

For a minimal netstandard1.X project reference to a netcoreapp1.X project:

SkipGetTargetFrameworkProperties fails in GenerateDepsFile (dotnet/sdk#1020)

Interestingly enough when I restore and build from MSBuild directly the project.assets.json file is missing the project reference and builds successfully. When building from Visual Studio, the project.assets.json contains the reference with a broken framework "framework": "Unsupported,Version=v0.0" and fails to build.

@nguerrera

This comment has been minimized.

Member

nguerrera commented Oct 23, 2017

From @AArnott on May 8, 2017 22:52

No. I finally gave up and checked the binary into git so I didn't need a project reference. I tried for days but never found a way that got dotnet build, msbuild, and VS to all work correctly at once. 😦

@nguerrera

This comment has been minimized.

Member

nguerrera commented Oct 23, 2017

From @rainersigwald on July 14, 2017 21:46

This can be worked around by adding an outside-the-norm order dependency in MSBuild, by way of a custom call to the MSBuild task.

<Target Name="WorkaroundSdk939" BeforeTargets="ResolveProjectReferences">
  <MSBuild Project="..\..\the\other.csproj" />
</Target>

Note that depending on your specific needs, you might need to be careful to preserve configuration and other normally-handled-for-you properties, or call a specific target.

@AArnott

msbuild translates that solution dependency into a project reference during the build (@AndyGerlicher when did this feature get added?)

This appears to have been added to MSBuild in the dev11 timeframe. @cdmihai went into detail on the process in #2274 (comment). The current team doesn't know why it's necessary.

@nguerrera

This comment has been minimized.

Member

nguerrera commented Oct 23, 2017

From @AArnott on July 14, 2017 22:52

Note that depending on your specific needs, you might need to be careful to preserve configuration and other normally-handled-for-you properties, or call a specific target.

Ya, that's what kills your proposed workaround in virtually all my scenarios. That would build the default configuration of the project, which could mean building all the target frameworks in debug mode, which is almost never what I would expect or need. Also, it would cause over-build, compiling twice etc. which can at least slow down the build, but also lead to symbols and DLLs not always matching up. It's a non-starter for me.
I've tried being very particular about passing in the right global properties to this call, but I guess there's a reason the ResolveProjectReferences target and its predecessors are so complicated. It's very hard to mimic.

@nguerrera

This comment has been minimized.

Member

nguerrera commented Oct 23, 2017

From @rainersigwald on August 7, 2017 13:41

@mhutch came up with an interesting workaround in #2399 (comment):

<!-- workaround for https://github.com/Microsoft/msbuild/issues/2399 -->
<Target Name="WorkaroundMSBuildIssue2399" BeforeTargets="GetTargetFrameworkProperties">
  <PropertyGroup>
    <ReferringTargetFramework>$(TargetFramework)</ReferringTargetFramework>
  </PropertyGroup>
</Target>

In the referenced project.

That essentially disables the target-framework compatibility check for the referenced project, which could be somewhat dangerous (depending on the nature of other references to the project) but avoids this problem.

@nguerrera

This comment has been minimized.

Member

nguerrera commented Oct 23, 2017

From @rainersigwald on August 23, 2017 18:47

Workaround

Set

<AddSyntheticProjectReferencesForSolutionDependencies>false</AddSyntheticProjectReferencesForSolutionDependencies>

in the project that has the ProjectReference to the incompatible project. This prevents the elevation of solution build dependencies to ProjectReferences in AssignProjectConfiguration.

(Was poking around near this target for another reason and saw this.)

@nguerrera

This comment has been minimized.

Member

nguerrera commented Oct 23, 2017

Moving to msbuild because after the double-evaluation fix, this compatibility check happens there in the context of the caller.

@nguerrera

This comment has been minimized.

Member

nguerrera commented Oct 24, 2017

I would think SkipGetTargetFrameworkProperties=true metadata on ProjectReference would work now and that we should set this automatically when ReferenceOutputAssembly=false.

@rynowak

This comment has been minimized.

rynowak commented Nov 5, 2017

I just tried SkipGetTargetFrameworkProperties workaround and it works for me. Thanks!

@rynowak

This comment has been minimized.

rynowak commented Nov 5, 2017

Actually, I spoke too soon, it fails during pack:

C:\Program Files\dotnet\sdk\2.1.1-preview-007094\Sdks\Microsoft.NET.Sdk\build\Microsoft.PackageDependencyResolution.targ
ets(167,5): error : Assets file 'C:\Users\rynowak\git\rynowak\Apparator\src\Apparator.Host\obj\project.assets.json' does
n't have a target for '.NETStandard,Version=v2.0'. Ensure that restore has run and that you have included 'netstandard2.
0' in the TargetFrameworks for your project. [C:\Users\rynowak\git\rynowak\Apparator\src\Apparator.Host\Apparator.Host.c
sproj]
@SimonCropp

This comment has been minimized.

SimonCropp commented Dec 18, 2017

my workaround

<ProjectReference Include="..\ProjectToBuildFirst\ProjectToBuildFirst.csproj"
    PrivateAssets="All"
    Condition="$(TargetFramework)=='fake'"/>
@AArnott

This comment has been minimized.

Member

AArnott commented Dec 18, 2017

@SimonCropp what does that accomplish? MSBuild would never build your project reference in that case. Is it that at least it works within the IDE that makes this workaround attractive?

@mhutch

This comment has been minimized.

Member

mhutch commented Dec 23, 2017

FYI something in 15.5 seems to have broken my workaround while not resolving the original bug.

Fortunately setting AddSyntheticProjectReferencesForSolutionDependencies to True in the dependent project seems to work.

@rainersigwald rainersigwald added this to the MSBuild 15.6 milestone Jan 9, 2018

rainersigwald added a commit to rainersigwald/msbuild that referenced this issue Jan 16, 2018

Skip tf-compat checks for solution dependencies
Explicitly opts synthetic project references injected by solution
dependencies out of the TargetFramework-compatibility/find-best-match
dance instituted in 15.x for .NET Standard support.

Fixes the most common cause of Microsoft#2661.

rainersigwald added a commit to rainersigwald/msbuild that referenced this issue Jan 16, 2018

No tfcompat check if ReferenceOutputAssembly=false
It is confusing to explicitly specify that you _don't_ want the output
of another project referenced in this project and then be told that the
output is incompatible.

This commit listens to the preexisting ProjectReference metadatum
ReferenceOutputAssembly and avoids the compatibility/best-match checks
on ProjectReferences that avoid the dependency.

Fixes Microsoft#2661 (and dotnet/sdk#939).

rainersigwald added a commit to rainersigwald/msbuild that referenced this issue Jan 19, 2018

No tfcompat check if ReferenceOutputAssembly=false
It is confusing to explicitly specify that you _don't_ want the output
of another project referenced in this project and then be told that the
output is incompatible.

This commit listens to the preexisting ProjectReference metadatum
ReferenceOutputAssembly and avoids the compatibility/best-match checks
on ProjectReferences that avoid the dependency.

Fixes Microsoft#2661 (and dotnet/sdk#939).

rainersigwald added a commit that referenced this issue Jan 19, 2018

No tfcompat check if ReferenceOutputAssembly=false (#2867)
It is confusing to explicitly specify that you _don't_ want the output
of another project referenced in this project and then be told that the
output is incompatible.

This commit listens to the preexisting ProjectReference metadatum
ReferenceOutputAssembly and avoids the compatibility/best-match checks
on ProjectReferences that avoid the dependency.

Fixes #2661 (and dotnet/sdk#939).
@rainersigwald

This comment has been minimized.

Contributor

rainersigwald commented Jan 31, 2018

Unfortunately, #2867 broke existing code, so reopening this.

@rainersigwald rainersigwald reopened this Jan 31, 2018

@cdmihai

This comment has been minimized.

Member

cdmihai commented Jan 31, 2018

Could it be that the smallest fix is to call GetTargetFrameworks with the new msbuild task argument to ignore the call if the target does not exist? That way _GetProjectReferenceTargetFrameworkProperties only picks a TFM for the dependencies that respond back. See #2935 (comment)

@rainersigwald

This comment has been minimized.

Contributor

rainersigwald commented Jan 31, 2018

@cdmihai we already do that; the problem arises when the project (correctly) responds with a list, but nothing in that list matches the current referencing TF.

@cdmihai

This comment has been minimized.

Member

cdmihai commented Feb 1, 2018

Oh, ok. @AndyGerlicher suggested a new metadata on ProjectReference telling the sdk what to do.

AutoTargetFrameworkOverride="true" where the sdks chooses from the returned tfm list, like pick the first one. Half joking, we could add to the p2p contract saying that projects should order the returned list from most preferred to least preferred :)
or
TargetFrameworkOverride="<user knows best tfm>"

@cdmihai

This comment has been minimized.

Member

cdmihai commented Feb 1, 2018

Apparently TargetFrameworkOverride already exists as SetTargetFramework :)

@nguerrera

This comment has been minimized.

Member

nguerrera commented Feb 1, 2018

It does, but the syntax is ugly SetTargetFramework="TargetFramework=net45". Ideally it would just be TargetFramework="net45", but I had a concern about that (potentially) tripping up the CPS project selector.

AndyGerlicher added a commit that referenced this issue Feb 1, 2018

@Joebeazelman

This comment has been minimized.

Joebeazelman commented Feb 3, 2018

I'm running VS 15.5.5 and I cannot reference a 2.0 project in a UWP app. Any workaround to this? Thanks.

xen2 added a commit to SiliconStudio/xenko that referenced this issue Apr 2, 2018

[Build] Workaround for solution dependencies with incomptable framewo…
…rks: Microsoft/msbuild#2661 (comment)


# Original commit: '0a018e90ad3bf68c273597d3c76802f28a1d8c53'
@SimonCropp

This comment has been minimized.

SimonCropp commented May 12, 2018

this is in milestone 15.6. but i can repro in 15.7.66.2115

MSBuild auto-detection: using msbuild version '15.7.66.2115' from 'C:\Program Files (x86)\Microsoft Visual Studio\Preview\Community\MSBuild\15.0\bin'.
....
(_GetProjectReferenceTargetFrameworkProperties target) -> 
  C:\Program Files (x86)\Microsoft Visual Studio\Preview\Community\MSBuild\15.0\Bin\Microsoft.Common.CurrentVersion.targets(1603,5):
error : Project 'C:\projects\costura\Costura.Fody\Costura.Fody.csproj' targets 'net46;netstandard2.0'.
It cannot be referenced by a project that targets '.NETFramework,Version=v4.5.2'. [C:\projects\costura\Costura\Costura.csproj]
  C:\Program Files (x86)\Microsoft Visual Studio\Preview\Community\MSBuild\15.0\Bin\Microsoft.Common.CurrentVersion.targets(1603,5):
error : Project 'C:\projects\costura\Costura.Tasks\Costura.Tasks.csproj' targets 'netstandard2.0;net46'.
It cannot be referenced by a project that targets '.NETFramework,Version=v4.5.2'. [C:\projects\costura\Costura\Costura.csproj]
  C:\Program Files (x86)\Microsoft Visual Studio\Preview\Community\MSBuild\15.0\Bin\Microsoft.Common.CurrentVersion.targets(1603,5):
error : Project 'C:\projects\costura\Costura.Template\Costura.Template.csproj' targets 'net46'.
It cannot be referenced by a project that targets '.NETFramework,Version=v4.5.2'. [C:\projects\costura\Costura\Costura.csproj]
    0 Warning(s)
    3 Error(s)

rainersigwald added a commit to rainersigwald/msbuild that referenced this issue May 15, 2018

Skip tf-compat checks for solution dependencies
Explicitly opts synthetic project references injected by solution
dependencies out of the TargetFramework-compatibility/find-best-match
dance instituted in 15.x for .NET Standard support.

Fixes the most common cause of Microsoft#2661.

bording added a commit to Particular/NServiceBus that referenced this issue May 17, 2018

@bording

This comment has been minimized.

bording commented May 17, 2018

@rainersigwald What's the plan for getting this fixed?

If I'm hitting this now, how am I supposed to work around it? I see #2661 (comment), but how exactly am I supposed to be using that? Does that only work if I'm using solution-level dependencies, or is there a way to use a ProjectReference as well?

I'm asking because I've been able to get it working with a solution-level dependency, but because of other, unrelated problems, I can't use solution-level dependencies right now. Is there a way to use a ProjectReference and still have my solution build with MSBuild?

rainersigwald added a commit that referenced this issue May 18, 2018

Skip tf-compat checks for solution dependencies (#3315)
Explicitly opts synthetic project references injected by solution
dependencies out of the TargetFramework-compatibility/find-best-match
dance instituted in 15.x for .NET Standard support.

Fixes the most common cause of #2661.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment