diff --git a/src/Microsoft.DotNet.Cli.Utils/DotnetRuntimeIdentifiers.cs b/src/Microsoft.DotNet.Cli.Utils/DotnetRuntimeIdentifiers.cs index cb84f2542..d88a70175 100644 --- a/src/Microsoft.DotNet.Cli.Utils/DotnetRuntimeIdentifiers.cs +++ b/src/Microsoft.DotNet.Cli.Utils/DotnetRuntimeIdentifiers.cs @@ -10,17 +10,22 @@ namespace Microsoft.DotNet.Cli.Utils { public static IEnumerable InferCurrentRuntimeIdentifiers() { - // On non-Windows machines, the CLI may be used on a newer version of a supported OS - // and the current RID may not be available in the runtime.* NuGet packages, yet. - // so fallback to the RID that was used to build the CLI - which will have the correct - // runtime.* NuGet packages available. IEnumerable fallbackIdentifiers = null; - if (RuntimeEnvironment.OperatingSystemPlatform != Platform.Windows) + + // If the machine's RID isn't supported by the shared framework (i.e. the CLI + // is being used on a newer version of an OS), add the RID that the CLI was built + // with as a fallback. The RID the CLI was built with will have the correct + // runtime.* NuGet packages available. + // For example, when a user is using osx.10.12, but we only support osx.10.10 and + // osx.10.11, the project.json "runtimes" section cannot contain osx.10.12, since + // that RID isn't contained in the runtime graph - users will get a restore error. + FrameworkDependencyFile fxDepsFile = new FrameworkDependencyFile(); + if (!fxDepsFile.IsCurrentRuntimeSupported()) { string buildRid = DotnetFiles.VersionFileObject.BuildRid; if (!string.IsNullOrEmpty(buildRid)) { - fallbackIdentifiers = new string[] { DotnetFiles.VersionFileObject.BuildRid }; + fallbackIdentifiers = new string[] { buildRid }; } } diff --git a/src/Microsoft.DotNet.Cli.Utils/FrameworkDependencyFile.cs b/src/Microsoft.DotNet.Cli.Utils/FrameworkDependencyFile.cs new file mode 100644 index 000000000..01064450b --- /dev/null +++ b/src/Microsoft.DotNet.Cli.Utils/FrameworkDependencyFile.cs @@ -0,0 +1,45 @@ +// Copyright (c) .NET Foundation and contributors. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System.IO; +using System.Linq; +using Microsoft.DotNet.InternalAbstractions; +using Microsoft.Extensions.DependencyModel; + +namespace Microsoft.DotNet.Cli.Utils +{ + /// + /// Represents the .deps.json file in the shared framework + /// that the CLI is running against. + /// + internal class FrameworkDependencyFile + { + private readonly string _depsFilePath; + + public FrameworkDependencyFile() + { + _depsFilePath = Muxer.GetDataFromAppDomain("FX_DEPS_FILE"); + } + + public bool IsCurrentRuntimeSupported() + { + return IsRuntimeSupported(RuntimeEnvironment.GetRuntimeIdentifier()); + } + + public bool IsRuntimeSupported(string runtimeIdentifier) + { + DependencyContext fxDependencyContext = CreateDependencyContext(); + + return fxDependencyContext.RuntimeGraph.Any(g => g.Runtime == runtimeIdentifier); + } + + private DependencyContext CreateDependencyContext() + { + using (Stream depsFileStream = File.OpenRead(_depsFilePath)) + using (DependencyContextJsonReader reader = new DependencyContextJsonReader()) + { + return reader.Read(depsFileStream); + } + } + } +} diff --git a/src/dotnet/Program.cs b/src/dotnet/Program.cs index f80d1c2b8..eb8809cb3 100644 --- a/src/dotnet/Program.cs +++ b/src/dotnet/Program.cs @@ -220,9 +220,7 @@ namespace Microsoft.DotNet.Cli Reporter.Output.WriteLine($" OS Name: {RuntimeEnvironment.OperatingSystem}"); Reporter.Output.WriteLine($" OS Version: {RuntimeEnvironment.OperatingSystemVersion}"); Reporter.Output.WriteLine($" OS Platform: {RuntimeEnvironment.OperatingSystemPlatform}"); - - // report the BuildRid instead of the current RID, so the user knows which RID they should put in their "runtimes" section. - Reporter.Output.WriteLine($" RID: {versionFile.BuildRid ?? RuntimeEnvironment.GetRuntimeIdentifier()}"); + Reporter.Output.WriteLine($" RID: {GetDisplayRid(versionFile)}"); } private static bool IsArg(string candidate, string longName) @@ -234,5 +232,18 @@ namespace Microsoft.DotNet.Cli { return (shortName != null && candidate.Equals("-" + shortName)) || (longName != null && candidate.Equals("--" + longName)); } + + private static string GetDisplayRid(DotnetVersionFile versionFile) + { + FrameworkDependencyFile fxDepsFile = new FrameworkDependencyFile(); + + string currentRid = RuntimeEnvironment.GetRuntimeIdentifier(); + + // if the current RID isn't supported by the shared framework, display the RID the CLI was + // built with instead, so the user knows which RID they should put in their "runtimes" section. + return fxDepsFile.IsRuntimeSupported(currentRid) ? + currentRid : + versionFile.BuildRid; + } } }