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

Specify which target framework you want to use from a dependency #2280

Closed
davkean opened this issue May 28, 2018 · 14 comments
Closed

Specify which target framework you want to use from a dependency #2280

davkean opened this issue May 28, 2018 · 14 comments

Comments

@davkean
Copy link
Member

davkean commented May 28, 2018

From @JamesNK on September 14, 2016 0:32

With project.json there is no way to specify the target framework you want to use from a dependency. It is automatically chosen for you. I would like a way to specify this manually.

For example I have MyLibrary that has netstandard1.0 and netstandard1.1 frameworks.

I want to be able to explicitly say which framework I use from MyLibrary in another project that will run unit tests. That way I can run tests against the netstandard1.0 assembly and netstandard1.1 assembly.

Copied from original issue: dotnet/project-system#477

@davkean
Copy link
Member Author

davkean commented May 28, 2018

Great suggestion. @nguerrera Can we put some metadata on the reference to influence this?

@davkean
Copy link
Member Author

davkean commented May 28, 2018

From @nguerrera on September 14, 2016 16:20

Sure! With dotnet/msbuild#1018, we ask the dependency's project for the properties that configure it to best match. We can change this to honor SetTargetFramework metadata that you already set on the reference. So it's trivial for project-to-project refs. Do we need parity for package refs?

@davkean
Copy link
Member Author

davkean commented May 28, 2018

From @benaadams on May 23, 2018 8:52

This is also useful; for example currently a net452 package will always take prescience over a netstandard2.0 for net471. However may want to force the netstandard2.0 package as it uses newer apis etc

@rainersigwald
Copy link
Member

rainersigwald commented May 29, 2018

You can do this today for p2ps with

    <ProjectReference Include="..\multitargeted_lib\multitargeted_lib.csproj">
      <SetTargetFramework>TargetFramework=netstandard2.0</SetTargetFramework>
    </ProjectReference>

I agree with @nguerrera that we should imply SkipGetTargetFrameworkProperties from the presence of a SetTargetFramework: dotnet/msbuild#3356

Overriding the TF of a NuGet package is a request for NuGet which I vaguely recall has gotten some pushback from the NuGet team, but I couldn't find a NuGet bug for it.

Edit: removed reference to SkipGetTargetFrameworkProperties to avoid confusing folks in the future.

@nguerrera
Copy link
Contributor

nguerrera commented May 29, 2018

Note that dotnet/msbuild#3356 is closed and it is already redundant to specify SkipGetTargetFrameworkProperties=true if you've specified SetTargetFramework.

@benaadams
Copy link
Member

Have this issue with corert dotnet/corert#5720 using a netcorapp2.1 package that uses Reflection.Emit will cause it to choke (in native compilation); whereas forcing that package onto netstandard2.0 that doesn't use Emit will work - however the csproj/sdk doesn't allow you to override the framework for an individual package so it will always choke.

@NightOwl888
Copy link

NightOwl888 commented Mar 27, 2020

Referring to Is There a Way to Force a Project Reference to .NET Standard Project to a Specific TargetFramework, could someone please clarify which approach is the recommended one?

  <ProjectReference Include="..\..\src\ExtendedXmlSerializer\ExtendedXmlSerializer.csproj" 
                    AdditionalProperties="TargetFramework=netstandard2.0" />

Or

<ProjectReference Include="..\multitargeted_lib\multitargeted_lib.csproj">
  <SetTargetFramework>TargetFramework=netstandard2.0</SetTargetFramework>
</ProjectReference>

I am using VS2019 and the first option (the accepted answer on StackOverflow) seems to work. But there are others claiming that only the second option (which is also specified in this issue) works on VS2017. So which is the recommended option going forward?

@rainersigwald
Copy link
Member

@NightOwl888 They're quite similar in the current implementation, but I continue to recommend SetTargetFramework, primarily because it's harder to accidentally override it since it's more explicit.

@rainersigwald
Copy link
Member

Also that's the solution to this issue, so I'm going to close this.

@xenoverse-us
Copy link

@NightOwl888 They're quite similar in the current implementation, but I continue to recommend SetTargetFramework, primarily because it's harder to accidentally override it since it's more explicit.

Does this still work with Visual Studio 2019?

I'm using VS 2019 Version 16.5.4. I have a library project that is multi-targeting net462 and netstandard2.0. Another console project is net472 and has a project reference on the library project. I used SetTargetFramework but it had no effect.

The build artifact still consists of the net462 version of the library.

@NightOwl888
Copy link

NightOwl888 commented May 4, 2020

I used SetTargetFramework but it had no effect.

What method did you use do determine that it had no effect? I was able to confirm it was working in VS2019 by adding a conditional compilation section (in the library) for the target framework I was overriding and setting a breakpoint within it.

#if NETSTANDARD2_0
// Breakpoint will be hit here if you are overriding to use netstandard2.0
#else 
// Breakpoint will be hit here if you don't override
// because by default net462 will be selected
// when targeting net472 in the consumer
#endif

If your multi-targeted code doesn't actually have any conditional sections in it or you are overriding it with the same value as the default behavior, you won't see any difference.

The build artifact still consists of the net462 version of the library.

Generally, the build artifacts contain all target versions of the library when doing a solution level dotnet build, dotnet msbuild or Visual Studio solution build. This setting only determines which one the consumer will use.

@xenoverse-us
Copy link

xenoverse-us commented May 4, 2020

I used SetTargetFramework but it had no effect.

What method did you use do determine that it had no effect? I was able to confirm it was working in VS2019 by adding a conditional compilation section (in the library) for the target framework I was overriding and setting a breakpoint within it.

#if NETSTANDARD2_0
// Breakpoint will be hit here if you are overriding to use netstandard2.0
#else 
// Breakpoint will be hit here if you don't override
// because by default net462 will be selected
// when targeting net472 in the consumer
#endif

If your multi-targeted code doesn't actually have any conditional sections in it or you are overriding it with the same value as the default behavior, you won't see any difference.

The build artifact still consists of the net462 version of the library.

Generally, the build artifacts contain all target versions of the library when doing a solution level dotnet build, dotnet msbuild or Visual Studio solution build. This setting only determines which one the consumer will use.

Here is what I have

  1. Console exe project net472
  2. MyLibrary multi-target net462 and netstandard2.0. It has conditional item groups to reference ExternalLibrary A and B depending on which target framework it is building.
  3. ExternalLibrary A that MyLibrary depends on when target is net462
  4. ExternalLibrary B that MyLibrary depends on when target is netstandard2.0

Console exe project reference MyLibrary with SetTargetFramework = netstandard2.0

Maybe I misunderstood what this means. Since my Console project is net472, by default it would pick up the net462 version of MyLibrary, along with ExternalLibrary A. However, I want to force my Console project to use the netstandard version of MyLibrary, along with ExternalLibrary B.

The reason I say it is not working is because when I check build artifacts I could only find ExternalLibraryA for my Console project. If I remove net462 from MyLibrary then ExternalLibrary B shows up in build artifact.

@AndirNotes
Copy link

AndirNotes commented Mar 31, 2021

Also that's the solution to this issue, so I'm going to close this.

@rainersigwald It seems that this is not a complete solution. Can you reopen the issue?

It looks like this SetTargetFramework ignored if project references a multitarget project via another project.
E.g.:
ConsoleProject (TargetFramework=net47) -> References NetstandardProject
NetstandardProject (TargetFramework=netstandard2.0) -> References MultiTargetProject
MultiTargetProject (TargetFrameworks=net40; netstandard2.0)

After build ConsoleProject bin/Debug/net47/ contains MultiTargetProject.dll built for .net 4.0 target (can be checked via DotPeek or any other disasm) regardless SetTargetFramework property.

Sample solution: SetTargetFrameworkSample.zip

MSBuild (16.9.0 from VS 2019 16.9.2) shows that MultiTargetProject resolved reference to net40 target:

image

@sanmuru
Copy link

sanmuru commented Feb 7, 2023

@AndirNotes Any available solution now? In my case in dotnet/msbuild#8405, Main project do reference the output assembly of correct TFM from Child project, but the files that are copied to local are faulty. I think crew members fixed the reference bug but other tasks in MSBuild were not changed compatibly.

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

9 participants