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

enable support for .NET Fx 4.6.1 <-> .NET Standard 2 #3447

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions integrationtests/Paket.IntegrationTests/InstallSpecs.fs
Original file line number Diff line number Diff line change
Expand Up @@ -450,6 +450,15 @@ let ``#3062 install should use external lock file``() =
newLockFile.Groups.[GroupName "main"].Resolution.ContainsKey (PackageName "FAKE") |> shouldEqual true
newLockFile.Groups.[GroupName "main"].Resolution.[PackageName "Machine.Specifications"].Version |> shouldEqual (SemVer.Parse "0.12")

[<Test>]
let ``#3447 netfx461 should support netstandard20 if the appconfig flag is set``() =
let newLockFile = installWithNfx461compat "i003447-netfx461-ns20"
// the dependencies file contains a restriction "framework: net461". So without the flag, the lock file contains only the one package because the dependencies for ns20 have been ignored.
// If the flag works correctly, then the lock file should contain all the microsoft asp.net core packages.
// The strategy is min, so the resolution should be stable regarding the versions.
newLockFile.Groups.[GroupName "main"].Resolution.ContainsKey (PackageName "Microsoft.AspNetCore.Server.Kestrel.Core") |> shouldEqual true
newLockFile.Groups.[GroupName "main"].Resolution.[PackageName "Microsoft.AspNetCore.Server.Kestrel.Core"].Version |> shouldEqual (SemVer.Parse "2.1.2")


#if INTERACTIVE
;;
Expand Down
10 changes: 10 additions & 0 deletions integrationtests/Paket.IntegrationTests/TestHelper.fs
Original file line number Diff line number Diff line change
Expand Up @@ -214,8 +214,18 @@ let installEx checkZeroWarn scenario =
#endif
LockFile.LoadFrom(Path.Combine(scenarioTempPath scenario,"paket.lock"))

let installExWithNfx461compat checkZeroWarn scenario =
#if INTERACTIVE
paket "install --verbose" scenario |> printfn "%s"
#else
paketEx checkZeroWarn "--enablenetfx461netstandard2support install" scenario |> ignore
#endif
LockFile.LoadFrom(Path.Combine(scenarioTempPath scenario,"paket.lock"))

let install scenario = installEx false scenario

let installWithNfx461compat scenario = installExWithNfx461compat false scenario

let restore scenario = paketEx false "restore" scenario |> ignore

let updateShouldFindPackageConflict packageName scenario =
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
source https://api.nuget.org/v3/index.json
storage: none
framework: net461

nuget Microsoft.AspNetCore 2.1.2 strategy:min
9 changes: 7 additions & 2 deletions src/Paket.Bootstrapper/ArgumentParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ public static class CommandArgs
}
public static class AppSettingKeys
{
public const string EnableNetFx461NetStandard2Support = "EnableNetFx461NetStandard2Support";
public const string PreferNuget = "PreferNuget";
public const string ForceNuget = "ForceNuget";
public const string NugetSource = "NugetSource";
Expand Down Expand Up @@ -115,7 +116,7 @@ public static BootstrapperOptions ParseArgumentsAndConfigurations(IEnumerable<st

// Assume --run and that all arguments are for the real paket binary
options.Run = true;
options.RunArgs = new List<string>(commandArgs);
options.RunArgs.AddRange(new List<string>(commandArgs));
commandArgs.Clear();

// Don't check more than twice a day
Expand Down Expand Up @@ -205,6 +206,10 @@ private static NameValueCollection ReadSettings(string configFilePath)

private static void FillOptionsFromAppSettings(BootstrapperOptions options, NameValueCollection appSettings)
{
if (appSettings.IsTrue(AppSettingKeys.EnableNetFx461NetStandard2Support))
{
options.RunArgs.Add("--enablenetfx461netstandard2support");
}
if (appSettings.IsTrue(AppSettingKeys.PreferNuget))
{
options.PreferNuget = true;
Expand Down Expand Up @@ -249,7 +254,7 @@ private static void FillRunOptionsFromArguments(BootstrapperOptions options, Lis
if (runIndex != -1)
{
options.Run = true;
options.RunArgs = commandArgs.GetRange(runIndex + 1, commandArgs.Count - runIndex - 1);
options.RunArgs.AddRange(commandArgs.GetRange(runIndex + 1, commandArgs.Count - runIndex - 1));
commandArgs.RemoveRange(runIndex, commandArgs.Count - runIndex);
}
}
Expand Down
6 changes: 3 additions & 3 deletions src/Paket.Bootstrapper/BootstrapperOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,18 @@ public BootstrapperOptions()
{
Verbosity = Verbosity.Normal;
DownloadArguments = new DownloadArguments();
RunArgs = Enumerable.Empty<string>();
RunArgs = new List<string>();
UnprocessedCommandArgs = Enumerable.Empty<string>();
}

public DownloadArguments DownloadArguments { get; set; }

public Verbosity Verbosity { get; set; }
public bool ForceNuget { get; set; }
public bool PreferNuget { get; set; }
public bool ShowHelp { get; set; }
public bool Run { get; set; }
public IEnumerable<string> RunArgs { get; set; }
public List<string> RunArgs { get; set; }
public IEnumerable<string> UnprocessedCommandArgs { get; set; }
}
}
26 changes: 25 additions & 1 deletion src/Paket.Core/Versioning/FrameworkHandling.fs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,26 @@ open System.Diagnostics
open Logging


/// how to handle compatibility between .NET-FX <-> .NET
[<RequireQualifiedAccess>]
type ToolingSupportMode =

/// only support framework mappings which are in-box.
/// This means .NET Standard 2 is only supported from 4.7.1 onwards.
| NativeSupport

/// support .NET Standard 2 from .NET Framework 4.6.1 onwards.
/// This requires a supported SDK during compilation, otherwise you may get successfull compilations, but errors at runtime. Use at your own risk.
| ToolingSupportNetSDK2


module DotnetToolingSupport =
/// Change how paket handles the .NET-FX <-> .NET Standard compatibility tables.
/// Changing this flag influences resolution and lockfile generation.
/// You should only ever change it in MAIN then not touch it at runtime.
let mutable mode = ToolingSupportMode.NativeSupport


/// The .NET Standard version.
// Each time a new version is added NuGetPackageCache.CurrentCacheVersion should be bumped.
[<RequireQualifiedAccess>]
Expand Down Expand Up @@ -621,7 +641,11 @@ type FrameworkIdentifier =
| DotNetFramework FrameworkVersion.V4_5_2 -> [ DotNetFramework FrameworkVersion.V4_5_1; DotNetStandard DotNetStandardVersion.V1_2 ]
| DotNetFramework FrameworkVersion.V4_5_3 -> [ DotNetFramework FrameworkVersion.V4_5_2; DotNetStandard DotNetStandardVersion.V1_2 ]
| DotNetFramework FrameworkVersion.V4_6 -> [ DotNetFramework FrameworkVersion.V4_5_3; DotNetStandard DotNetStandardVersion.V1_3 ]
| DotNetFramework FrameworkVersion.V4_6_1 -> [ DotNetFramework FrameworkVersion.V4_6; DotNetStandard DotNetStandardVersion.V1_4 ]
| DotNetFramework FrameworkVersion.V4_6_1 ->
match DotnetToolingSupport.mode with
| ToolingSupportMode.NativeSupport -> [ DotNetFramework FrameworkVersion.V4_6; DotNetStandard DotNetStandardVersion.V1_4 ]
// .NET Standard 2.0 will propagate "down", so we don't need any switches on the subsequent frameworks
Copy link
Member

Choose a reason for hiding this comment

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

Just note that depending on this will subtly prefer netstandard1.5 in some situations over netstandard2.0 (for example in net462).
The possible impact of this is smaller as expected as we forward all packages to nuget in the final step, but the list of packages might differ.

| ToolingSupportMode.ToolingSupportNetSDK2 -> [ DotNetFramework FrameworkVersion.V4_6; DotNetStandard DotNetStandardVersion.V2_0 ]
| DotNetFramework FrameworkVersion.V4_6_2 -> [ DotNetFramework FrameworkVersion.V4_6_1; DotNetStandard DotNetStandardVersion.V1_5 ]
| DotNetFramework FrameworkVersion.V4_6_3 -> [ DotNetFramework FrameworkVersion.V4_6_2 ]
| DotNetFramework FrameworkVersion.V4_7 -> [ DotNetFramework FrameworkVersion.V4_6_3]
Expand Down
2 changes: 2 additions & 0 deletions src/Paket/Commands.fs
Original file line number Diff line number Diff line change
Expand Up @@ -665,6 +665,7 @@ type Command =
| [<AltCommandLine("-v");Inherit>] Verbose
| [<Inherit>] Log_File of path:string
| [<Hidden;Inherit>] From_Bootstrapper
| [<Hidden;Inherit;Unique;CustomCommandLine("--enablenetfx461netstandard2support")>] EnableNetFx461NetStandard2Support
// subcommands
| [<CustomCommandLine("add")>] Add of ParseResults<AddArgs>
| [<CustomCommandLine("github")>] Github of ParseResults<GithubArgs>
Expand Down Expand Up @@ -733,6 +734,7 @@ with
| Verbose -> "print detailed information to the console"
| Version -> "show Paket version"
| From_Bootstrapper -> "call coming from the '--run' feature of the bootstrapper"
| EnableNetFx461NetStandard2Support -> "enable mapping when called from the bootstrapper. do not use manually."

let commandParser = ArgumentParser.Create<Command>(programName = "paket", errorHandler = new ProcessExiter(), checkStructure = false)

Expand Down
1 change: 1 addition & 0 deletions src/Paket/Paket.fsproj
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@
<Reference Include="Microsoft.Build.Utilities.v4.0" />
<Reference Include="mscorlib" />
<Reference Include="System" />
<Reference Include="System.Configuration" />
<Reference Include="System.Core" />
<Reference Include="System.Data" />
<Reference Include="System.Data.Linq" />
Expand Down
18 changes: 18 additions & 0 deletions src/Paket/Program.fs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,16 @@ open PackageSources

let sw = Stopwatch.StartNew()

type System.Collections.Specialized.NameValueCollection with
member this.GetKey(key:string) =
if this <> null && this.AllKeys |> Array.contains key then
this.Get(key)
else
null
member this.IsTrue(key:string) =
let v = this.GetKey(key)
String.equalsIgnoreCase v "true"

type PaketExiter() =
interface IExiter with
member __.Name = "paket exiter"
Expand Down Expand Up @@ -863,6 +873,7 @@ let handleCommand silent command =
| Verbose
| Silent
| From_Bootstrapper
| EnableNetFx461NetStandard2Support
| Version
| Log_File _ -> failwithf "internal error: this code should never be reached."

Expand All @@ -879,14 +890,20 @@ let main() =

try
let args = Environment.GetCommandLineArgs()
let appSettings = System.Configuration.ConfigurationManager.AppSettings
if appSettings.IsTrue("EnableNetFx461NetStandard2Support") ||
args |> Array.contains "--enablenetfx461netstandard2support" then
DotnetToolingSupport.mode <- ToolingSupportMode.ToolingSupportNetSDK2
match args with
| [| _; "restore" |] | [| _; "--from-bootstrapper"; "--enablenetfx461netstandard2support"; "restore" |]
| [| _; "restore" |] | [| _; "--from-bootstrapper"; "restore" |] ->
// Global restore fast route, see https://github.com/fsprojects/Argu/issues/90
processWithValidationEx
ignore
false
(fun _ -> true)
(fun _ -> Dependencies.Locate().Restore()) ()
| [| _; "restore"; "--project"; project |] | [| _; "--from-bootstrapper"; "--enablenetfx461netstandard2support"; "restore"; "--project"; project |]
| [| _; "restore"; "--project"; project |] | [| _; "--from-bootstrapper"; "restore"; "--project"; project |] ->
// Project restore fast route, see https://github.com/fsprojects/Argu/issues/90
processWithValidationEx
Expand All @@ -902,6 +919,7 @@ let main() =
false
(fun _ -> true)
(fun _ -> Dependencies.Locate().Restore(false, None, project, false, false, false, Some targetFramework, Some outputPath)) ()
| [| _; "install" |] | [| _; "--from-bootstrapper"; "--enablenetfx461netstandard2support"; "install" |]
| [| _; "install" |] | [| _; "--from-bootstrapper"; "install" |] ->
// Global restore fast route, see https://github.com/fsprojects/Argu/issues/90
processWithValidationEx
Expand Down