diff --git a/build_projects/dotnet-cli-build/CompileTargets.cs b/build_projects/dotnet-cli-build/CompileTargets.cs index bfe5255b1..97dba4dbd 100644 --- a/build_projects/dotnet-cli-build/CompileTargets.cs +++ b/build_projects/dotnet-cli-build/CompileTargets.cs @@ -262,7 +262,8 @@ namespace Microsoft.DotNet.Cli.Build // Generate .version file var version = buildVersion.NuGetVersion; - var content = $@"{c.BuildContext["CommitHash"]}{Environment.NewLine}{version}{Environment.NewLine}"; + var buildRid = RuntimeEnvironment.GetRuntimeIdentifier(); + var content = $@"{c.BuildContext["CommitHash"]}{Environment.NewLine}{version}{Environment.NewLine}{buildRid}{Environment.NewLine}"; File.WriteAllText(Path.Combine(sdkOutputDirectory, ".version"), content); if(generateNugetPackagesArchive) diff --git a/src/Microsoft.DotNet.Cli.Utils/CommandResolution/OutputPathCommandResolver.cs b/src/Microsoft.DotNet.Cli.Utils/CommandResolution/OutputPathCommandResolver.cs index 231de29c2..37996e7bd 100644 --- a/src/Microsoft.DotNet.Cli.Utils/CommandResolution/OutputPathCommandResolver.cs +++ b/src/Microsoft.DotNet.Cli.Utils/CommandResolution/OutputPathCommandResolver.cs @@ -79,7 +79,7 @@ namespace Microsoft.DotNet.Cli.Utils var projectContext = ProjectContext.Create( projectRootPath, framework, - RuntimeEnvironmentRidExtensions.GetAllCandidateRuntimeIdentifiers()); + DotnetRuntimeIdentifiers.InferCurrentRuntimeIdentifiers()); if (projectContext.RuntimeIdentifier == null) { diff --git a/src/Microsoft.DotNet.Cli.Utils/CommandResolution/ProjectDependenciesCommandResolver.cs b/src/Microsoft.DotNet.Cli.Utils/CommandResolution/ProjectDependenciesCommandResolver.cs index 60bb1a87b..08ec98d1a 100644 --- a/src/Microsoft.DotNet.Cli.Utils/CommandResolution/ProjectDependenciesCommandResolver.cs +++ b/src/Microsoft.DotNet.Cli.Utils/CommandResolution/ProjectDependenciesCommandResolver.cs @@ -140,7 +140,7 @@ namespace Microsoft.DotNet.Cli.Utils return ProjectContext.Create( projectRootPath, framework, - RuntimeEnvironmentRidExtensions.GetAllCandidateRuntimeIdentifiers()); + DotnetRuntimeIdentifiers.InferCurrentRuntimeIdentifiers()); } diff --git a/src/Microsoft.DotNet.Cli.Utils/CommandResolution/ProjectToolsCommandResolver.cs b/src/Microsoft.DotNet.Cli.Utils/CommandResolution/ProjectToolsCommandResolver.cs index 753b079d0..f1047693f 100644 --- a/src/Microsoft.DotNet.Cli.Utils/CommandResolution/ProjectToolsCommandResolver.cs +++ b/src/Microsoft.DotNet.Cli.Utils/CommandResolution/ProjectToolsCommandResolver.cs @@ -19,9 +19,6 @@ namespace Microsoft.DotNet.Cli.Utils private static readonly CommandResolutionStrategy s_commandResolutionStrategy = CommandResolutionStrategy.ProjectToolsPackage; - private static readonly string s_currentRuntimeIdentifier = RuntimeEnvironmentRidExtensions.GetLegacyRestoreRuntimeIdentifier(); - - private List _allowedCommandExtensions; private IPackagedCommandSpecFactory _packagedCommandSpecFactory; diff --git a/src/Microsoft.DotNet.Cli.Utils/DotnetFiles.cs b/src/Microsoft.DotNet.Cli.Utils/DotnetFiles.cs index 1ff66292e..56f647101 100644 --- a/src/Microsoft.DotNet.Cli.Utils/DotnetFiles.cs +++ b/src/Microsoft.DotNet.Cli.Utils/DotnetFiles.cs @@ -12,11 +12,19 @@ namespace Microsoft.DotNet.Cli.Utils { private static string SdkRootFolder => Path.Combine(typeof(DotnetFiles).GetTypeInfo().Assembly.Location, ".."); + private static Lazy s_versionFileObject = + new Lazy(() => new DotnetVersionFile(VersionFile)); + /// /// The CLI ships with a .version file that stores the commit information and CLI version /// public static string VersionFile => Path.GetFullPath(Path.Combine(SdkRootFolder, ".version")); + internal static DotnetVersionFile VersionFileObject + { + get { return s_versionFileObject.Value; } + } + public static string NuGetPackagesArchive => Path.GetFullPath(Path.Combine(SdkRootFolder, "nuGetPackagesArchive.lzma")); diff --git a/src/Microsoft.DotNet.Cli.Utils/DotnetRuntimeIdentifiers.cs b/src/Microsoft.DotNet.Cli.Utils/DotnetRuntimeIdentifiers.cs new file mode 100644 index 000000000..7f3da4c22 --- /dev/null +++ b/src/Microsoft.DotNet.Cli.Utils/DotnetRuntimeIdentifiers.cs @@ -0,0 +1,35 @@ +// 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.Collections.Generic; +using Microsoft.DotNet.InternalAbstractions; + +namespace Microsoft.DotNet.Cli.Utils +{ + internal static class DotnetRuntimeIdentifiers + { + public static IEnumerable InferCurrentRuntimeIdentifiers() + { + IEnumerable fallbackIdentifiers = null; + + // 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.SupportsCurrentRuntime()) + { + string buildRid = DotnetFiles.VersionFileObject.BuildRid; + if (!string.IsNullOrEmpty(buildRid)) + { + fallbackIdentifiers = new string[] { buildRid }; + } + } + + return RuntimeEnvironmentRidExtensions.GetAllCandidateRuntimeIdentifiers(fallbackIdentifiers); + } + } +} diff --git a/src/Microsoft.DotNet.Cli.Utils/DotnetVersionFile.cs b/src/Microsoft.DotNet.Cli.Utils/DotnetVersionFile.cs new file mode 100644 index 000000000..1f76067f2 --- /dev/null +++ b/src/Microsoft.DotNet.Cli.Utils/DotnetVersionFile.cs @@ -0,0 +1,61 @@ +// 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.Collections.Generic; +using System.IO; + +namespace Microsoft.DotNet.Cli.Utils +{ + internal class DotnetVersionFile + { + public bool Exists { get; set; } + + public string CommitSha { get; set; } + + public string BuildNumber { get; set; } + + /// + /// The runtime identifier (rid) that this CLI was built for. + /// + /// + /// This is different than RuntimeEnvironment.GetRuntimeIdentifier() because the + /// BuildRid is a RID that is guaranteed to exist and works on the current machine. The + /// RuntimeEnvironment.GetRuntimeIdentifier() may be for a new version of the OS that + /// doesn't have full support yet. + /// + public string BuildRid { get; set; } + + public DotnetVersionFile(string versionFilePath) + { + Exists = File.Exists(versionFilePath); + + if (Exists) + { + IEnumerable lines = File.ReadLines(versionFilePath); + + int index = 0; + foreach (string line in lines) + { + if (index == 0) + { + CommitSha = line.Substring(0, 10); + } + else if (index == 1) + { + BuildNumber = line; + } + else if (index == 2) + { + BuildRid = line; + } + else + { + break; + } + + index++; + } + } + } + } +} diff --git a/src/Microsoft.DotNet.Cli.Utils/FrameworkDependencyFile.cs b/src/Microsoft.DotNet.Cli.Utils/FrameworkDependencyFile.cs new file mode 100644 index 000000000..24130ed8c --- /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 SupportsCurrentRuntime() + { + 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/Microsoft.DotNet.Cli.Utils/Properties/AssemblyInfo.cs b/src/Microsoft.DotNet.Cli.Utils/Properties/AssemblyInfo.cs index 29547d803..9b043e9dd 100644 --- a/src/Microsoft.DotNet.Cli.Utils/Properties/AssemblyInfo.cs +++ b/src/Microsoft.DotNet.Cli.Utils/Properties/AssemblyInfo.cs @@ -2,4 +2,5 @@ using System.Reflection; using System.Runtime.CompilerServices; [assembly: AssemblyMetadataAttribute("Serviceable", "True")] +[assembly: InternalsVisibleTo("dotnet, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")] [assembly: InternalsVisibleTo("Microsoft.DotNet.Cli.Utils.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")] diff --git a/src/Microsoft.DotNet.Configurer/Microsoft.DotNet.Configurer.xproj b/src/Microsoft.DotNet.Configurer/Microsoft.DotNet.Configurer.xproj index f533d0dad..223864b6b 100644 --- a/src/Microsoft.DotNet.Configurer/Microsoft.DotNet.Configurer.xproj +++ b/src/Microsoft.DotNet.Configurer/Microsoft.DotNet.Configurer.xproj @@ -8,8 +8,8 @@ e5ed47ef-bf25-4da9-a7fe-290c642cbf0f Microsoft.DotNet.Configurer - .\obj - .\bin\ + ..\..\artifacts\obj\$(MSBuildProjectName) + ..\..\artifacts\bin diff --git a/src/Microsoft.DotNet.ProjectModel/RuntimeEnvironmentRidExtensions.cs b/src/Microsoft.DotNet.ProjectModel/RuntimeEnvironmentRidExtensions.cs index f5d439157..657827745 100644 --- a/src/Microsoft.DotNet.ProjectModel/RuntimeEnvironmentRidExtensions.cs +++ b/src/Microsoft.DotNet.ProjectModel/RuntimeEnvironmentRidExtensions.cs @@ -11,20 +11,6 @@ namespace Microsoft.DotNet.InternalAbstractions // We should clean this up. Filed #619 to track. public static class RuntimeEnvironmentRidExtensions { - // Work around NuGet/Home#1941 - public static IEnumerable GetOverrideRestoreRuntimeIdentifiers() - { - if (RuntimeEnvironment.OperatingSystemPlatform != Platform.Windows) - { - yield return RuntimeEnvironment.GetRuntimeIdentifier(); - } - else - { - yield return "win7-x86"; - yield return "win7-x64"; - } - } - // Gets the identfier that is used for restore by default (this is different from the actual RID, but only on Windows) public static string GetLegacyRestoreRuntimeIdentifier() { @@ -41,36 +27,56 @@ namespace Microsoft.DotNet.InternalAbstractions public static IEnumerable GetAllCandidateRuntimeIdentifiers() { + return GetAllCandidateRuntimeIdentifiers(null); + } + + public static IEnumerable GetAllCandidateRuntimeIdentifiers(IEnumerable fallbackIdentifiers = null) + { + List result = new List(); + if (RuntimeEnvironment.OperatingSystemPlatform != Platform.Windows) { - yield return RuntimeEnvironment.GetRuntimeIdentifier(); + result.Add(RuntimeEnvironment.GetRuntimeIdentifier()); } else { var arch = RuntimeEnvironment.RuntimeArchitecture.ToLowerInvariant(); if (RuntimeEnvironment.OperatingSystemVersion.StartsWith("6.1", StringComparison.Ordinal)) { - yield return "win7-" + arch; + result.Add("win7-" + arch); } else if (RuntimeEnvironment.OperatingSystemVersion.StartsWith("6.2", StringComparison.Ordinal)) { - yield return "win8-" + arch; - yield return "win7-" + arch; + result.Add("win8-" + arch); + result.Add("win7-" + arch); } else if (RuntimeEnvironment.OperatingSystemVersion.StartsWith("6.3", StringComparison.Ordinal)) { - yield return "win81-" + arch; - yield return "win8-" + arch; - yield return "win7-" + arch; + result.Add("win81-" + arch); + result.Add("win8-" + arch); + result.Add("win7-" + arch); } else if (RuntimeEnvironment.OperatingSystemVersion.StartsWith("10.0", StringComparison.Ordinal)) { - yield return "win10-" + arch; - yield return "win81-" + arch; - yield return "win8-" + arch; - yield return "win7-" + arch; + result.Add("win10-" + arch); + result.Add("win81-" + arch); + result.Add("win8-" + arch); + result.Add("win7-" + arch); } } + + if (fallbackIdentifiers != null) + { + foreach (string fallbackIdentifier in fallbackIdentifiers) + { + if (!result.Contains(fallbackIdentifier)) + { + result.Add(fallbackIdentifier); + } + } + } + + return result; } } } diff --git a/src/dotnet/Program.cs b/src/dotnet/Program.cs index 7164727c8..eb8809cb3 100644 --- a/src/dotnet/Program.cs +++ b/src/dotnet/Program.cs @@ -209,7 +209,8 @@ namespace Microsoft.DotNet.Cli { HelpCommand.PrintVersionHeader(); - var commitSha = GetCommitSha() ?? "N/A"; + DotnetVersionFile versionFile = DotnetFiles.VersionFileObject; + var commitSha = versionFile.CommitSha ?? "N/A"; Reporter.Output.WriteLine(); Reporter.Output.WriteLine("Product Information:"); Reporter.Output.WriteLine($" Version: {Product.Version}"); @@ -219,7 +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}"); - Reporter.Output.WriteLine($" RID: {RuntimeEnvironment.GetRuntimeIdentifier()}"); + Reporter.Output.WriteLine($" RID: {GetDisplayRid(versionFile)}"); } private static bool IsArg(string candidate, string longName) @@ -232,16 +233,17 @@ namespace Microsoft.DotNet.Cli return (shortName != null && candidate.Equals("-" + shortName)) || (longName != null && candidate.Equals("--" + longName)); } - private static string GetCommitSha() + private static string GetDisplayRid(DotnetVersionFile versionFile) { - var versionFile = DotnetFiles.VersionFile; + FrameworkDependencyFile fxDepsFile = new FrameworkDependencyFile(); - if (File.Exists(versionFile)) - { - return File.ReadLines(versionFile).FirstOrDefault()?.Substring(0, 10); - } + string currentRid = RuntimeEnvironment.GetRuntimeIdentifier(); - return null; + // 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; } } } diff --git a/src/dotnet/Properties/AssemblyInfo.cs b/src/dotnet/Properties/AssemblyInfo.cs index ffdc13024..1684d65c1 100644 --- a/src/dotnet/Properties/AssemblyInfo.cs +++ b/src/dotnet/Properties/AssemblyInfo.cs @@ -2,4 +2,4 @@ using System.Reflection; using System.Runtime.CompilerServices; [assembly: AssemblyMetadataAttribute("Serviceable", "True")] -[assembly: InternalsVisibleTo("dotnet.Tests")] +[assembly: InternalsVisibleTo("dotnet.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")] diff --git a/src/dotnet/commands/dotnet-build/BuildCommandApp.cs b/src/dotnet/commands/dotnet-build/BuildCommandApp.cs index 11d7e3fde..0303ee4d4 100644 --- a/src/dotnet/commands/dotnet-build/BuildCommandApp.cs +++ b/src/dotnet/commands/dotnet-build/BuildCommandApp.cs @@ -131,7 +131,7 @@ namespace Microsoft.DotNet.Tools.Compiler var rids = new List(); if (string.IsNullOrEmpty(RuntimeValue)) { - return RuntimeEnvironmentRidExtensions.GetAllCandidateRuntimeIdentifiers(); + return DotnetRuntimeIdentifiers.InferCurrentRuntimeIdentifiers(); } else { diff --git a/src/dotnet/commands/dotnet-publish/PublishCommand.cs b/src/dotnet/commands/dotnet-publish/PublishCommand.cs index eebf24f66..e7da33394 100644 --- a/src/dotnet/commands/dotnet-publish/PublishCommand.cs +++ b/src/dotnet/commands/dotnet-publish/PublishCommand.cs @@ -425,7 +425,7 @@ namespace Microsoft.DotNet.Tools.Publish contexts.Where(c => Equals(c.TargetFramework, framework)); var rids = string.IsNullOrEmpty(runtime) ? - RuntimeEnvironmentRidExtensions.GetAllCandidateRuntimeIdentifiers() : + DotnetRuntimeIdentifiers.InferCurrentRuntimeIdentifiers() : new[] { runtime }; return contexts.Select(c => Workspace.GetRuntimeContext(c, rids)); diff --git a/src/dotnet/commands/dotnet-restore/Program.cs b/src/dotnet/commands/dotnet-restore/Program.cs index 7d45322c1..bee6b5bfc 100644 --- a/src/dotnet/commands/dotnet-restore/Program.cs +++ b/src/dotnet/commands/dotnet-restore/Program.cs @@ -11,8 +11,6 @@ namespace Microsoft.DotNet.Tools.Restore { public partial class RestoreCommand { - private static readonly string DefaultRid = RuntimeEnvironmentRidExtensions.GetLegacyRestoreRuntimeIdentifier(); - public static int Run(string[] args) { DebugHelper.HandleDebugSwitch(ref args); diff --git a/src/dotnet/commands/dotnet-run/RunCommand.cs b/src/dotnet/commands/dotnet-run/RunCommand.cs index 1eb395240..4219a8847 100644 --- a/src/dotnet/commands/dotnet-run/RunCommand.cs +++ b/src/dotnet/commands/dotnet-run/RunCommand.cs @@ -82,7 +82,7 @@ namespace Microsoft.DotNet.Tools.Run .EnsureValid(Project) .FrameworkOnlyContexts; - var rids = RuntimeEnvironmentRidExtensions.GetAllCandidateRuntimeIdentifiers(); + var rids = DotnetRuntimeIdentifiers.InferCurrentRuntimeIdentifiers(); ProjectContext frameworkContext; if (Framework == null) diff --git a/src/dotnet/commands/dotnet-test/Program.cs b/src/dotnet/commands/dotnet-test/Program.cs index 43a7e81bd..cbfbcc76e 100644 --- a/src/dotnet/commands/dotnet-test/Program.cs +++ b/src/dotnet/commands/dotnet-test/Program.cs @@ -44,7 +44,7 @@ namespace Microsoft.DotNet.Tools.Test var projectPath = GetProjectPath(dotnetTestParams.ProjectPath); var runtimeIdentifiers = !string.IsNullOrEmpty(dotnetTestParams.Runtime) ? new[] { dotnetTestParams.Runtime } : - RuntimeEnvironmentRidExtensions.GetAllCandidateRuntimeIdentifiers(); + DotnetRuntimeIdentifiers.InferCurrentRuntimeIdentifiers(); var exitCode = 0; // Create a workspace diff --git a/src/dotnet/project.json b/src/dotnet/project.json index fa4ec23f8..5c0978ea5 100644 --- a/src/dotnet/project.json +++ b/src/dotnet/project.json @@ -2,6 +2,7 @@ "version": "1.0.0-preview2-*", "buildOptions": { "emitEntryPoint": true, + "keyFile": "../../tools/Key.snk", "embed": { "include": [ "commands/dotnet-new/CSharp_Console.zip", diff --git a/test/dotnet.Tests/project.json b/test/dotnet.Tests/project.json index f479edd88..3c4394174 100644 --- a/test/dotnet.Tests/project.json +++ b/test/dotnet.Tests/project.json @@ -42,6 +42,7 @@ ] }, "buildOptions": { + "keyFile": "../../tools/Key.snk", "copyToOutput": { "include": [ "../../TestAssets/TestProjects/AppWithDependencyOnToolWithOutputName/**/*",