From 4d19e4d86644fd5cebacd9dbe9213f43996288ad Mon Sep 17 00:00:00 2001 From: Sridhar Periyasamy Date: Wed, 16 Mar 2016 15:54:02 -0700 Subject: [PATCH 01/14] Layout CLI SDK, Shared Fx and Muxer in stage1 and stage2. --- scripts/dotnet-cli-build/CompileTargets.cs | 247 ++++++++++++++++++-- scripts/dotnet-cli-build/Utils/DotNetCli.cs | 6 +- 2 files changed, 225 insertions(+), 28 deletions(-) diff --git a/scripts/dotnet-cli-build/CompileTargets.cs b/scripts/dotnet-cli-build/CompileTargets.cs index 7c6c80bb4..f78b0a2a8 100644 --- a/scripts/dotnet-cli-build/CompileTargets.cs +++ b/scripts/dotnet-cli-build/CompileTargets.cs @@ -7,6 +7,8 @@ using Microsoft.Extensions.PlatformAbstractions; using static Microsoft.DotNet.Cli.Build.FS; using static Microsoft.DotNet.Cli.Build.Framework.BuildHelpers; +using System.Text.RegularExpressions; +using System.Reflection.PortableExecutable; namespace Microsoft.DotNet.Cli.Build { @@ -45,6 +47,12 @@ namespace Microsoft.DotNet.Cli.Build "Microsoft.Extensions.Testing.Abstractions" }; + public const string SharedFrameworkName = "Microsoft.NETCore.App"; + + private static string CoreHostBaseName => $"corehost{Constants.ExeSuffix}"; + private static string DotnetHostFxrBaseName => $"{Constants.DynamicLibPrefix}hostfxr{Constants.DynamicLibSuffix}"; + private static string HostPolicyBaseName => $"{Constants.DynamicLibPrefix}hostpolicy{Constants.DynamicLibSuffix}"; + // Updates the stage 2 with recent changes. [Target(nameof(PrepareTargets.Init), nameof(CompileStage2))] public static BuildTargetResult UpdateBuild(BuildTargetContext c) @@ -118,9 +126,9 @@ namespace Microsoft.DotNet.Cli.Build rid); // Copy the output out - File.Copy(Path.Combine(cmakeOut, "cli", "corehost"), Path.Combine(Dirs.Corehost, "corehost"), overwrite: true); - File.Copy(Path.Combine(cmakeOut, "cli", "dll", $"{Constants.DynamicLibPrefix}hostpolicy{Constants.DynamicLibSuffix}"), Path.Combine(Dirs.Corehost, $"{Constants.DynamicLibPrefix}hostpolicy{Constants.DynamicLibSuffix}"), overwrite: true); - File.Copy(Path.Combine(cmakeOut, "cli", "fxr", $"{Constants.DynamicLibPrefix}hostfxr{Constants.DynamicLibSuffix}"), Path.Combine(Dirs.Corehost, $"{Constants.DynamicLibPrefix}hostfxr{Constants.DynamicLibSuffix}"), overwrite: true); + File.Copy(Path.Combine(cmakeOut, "cli", "corehost"), Path.Combine(Dirs.Corehost, CoreHostBaseName), overwrite: true); + File.Copy(Path.Combine(cmakeOut, "cli", "dll", DotnetHostFxrBaseName), Path.Combine(Dirs.Corehost, DotnetHostFxrBaseName), overwrite: true); + File.Copy(Path.Combine(cmakeOut, "cli", "fxr", HostPolicyBaseName), Path.Combine(Dirs.Corehost, HostPolicyBaseName), overwrite: true); } return c.Success(); @@ -131,7 +139,16 @@ namespace Microsoft.DotNet.Cli.Build { CleanBinObj(c, Path.Combine(c.BuildContext.BuildDirectory, "src")); CleanBinObj(c, Path.Combine(c.BuildContext.BuildDirectory, "test")); - return CompileStage(c, + + if (Directory.Exists(Dirs.Stage1)) + { + Utils.DeleteDirectory(Dirs.Stage1); + } + Directory.CreateDirectory(Dirs.Stage1); + + CopySharedHost(Dirs.Stage1); + PackageSharedFramework(c, Dirs.Stage1, DotNetCli.Stage0); + return CompileCliSdk(c, dotnet: DotNetCli.Stage0, outputDir: Dirs.Stage1); } @@ -143,7 +160,16 @@ namespace Microsoft.DotNet.Cli.Build CleanBinObj(c, Path.Combine(c.BuildContext.BuildDirectory, "src")); CleanBinObj(c, Path.Combine(c.BuildContext.BuildDirectory, "test")); - var result = CompileStage(c, + + if (Directory.Exists(Dirs.Stage2)) + { + Utils.DeleteDirectory(Dirs.Stage2); + } + Directory.CreateDirectory(Dirs.Stage2); + + PackageSharedFramework(c, Dirs.Stage2, DotNetCli.Stage1); + CopySharedHost(Dirs.Stage2); + var result = CompileCliSdk(c, dotnet: DotNetCli.Stage1, outputDir: Dirs.Stage2); @@ -174,15 +200,134 @@ namespace Microsoft.DotNet.Cli.Build return c.Success(); } - private static BuildTargetResult CompileStage(BuildTargetContext c, DotNetCli dotnet, string outputDir) + private static void CopySharedHost(string outputDir) { - Rmdir(outputDir); + // corehost will be renamed to dotnet at some point and then this can be removed. + File.Copy( + Path.Combine(Dirs.Corehost, CoreHostBaseName), + Path.Combine(outputDir, $"dotnet{Constants.ExeSuffix}"), true); + File.Copy( + Path.Combine(Dirs.Corehost, DotnetHostFxrBaseName), + Path.Combine(outputDir, DotnetHostFxrBaseName), true); + } + public static void PackageSharedFramework(BuildTargetContext c, string outputDir, DotNetCli dotnetCli) + { + string SharedFrameworkSourceRoot = Path.Combine(Dirs.RepoRoot, "src", "sharedframework", "framework"); + string SharedFrameworkNugetVersion = GetVersionFromProjectJson(Path.Combine(Path.Combine(Dirs.RepoRoot, "src", "sharedframework", "framework"), "project.json")); + + // We publish to a sub folder of the PublishRoot so tools like heat and zip can generate folder structures easier. + string SharedFrameworkNameAndVersionRoot = Path.Combine(outputDir, "shared", SharedFrameworkName, SharedFrameworkNugetVersion); + + if (Directory.Exists(SharedFrameworkNameAndVersionRoot)) + { + Utils.DeleteDirectory(SharedFrameworkNameAndVersionRoot); + } + + string publishFramework = "dnxcore50"; // Temporary, use "netcoreapp" when we update nuget. + string publishRuntime; + if (PlatformServices.Default.Runtime.OperatingSystemPlatform == Platform.Windows) + { + publishRuntime = $"win7-{PlatformServices.Default.Runtime.RuntimeArchitecture}"; + } + else + { + publishRuntime = PlatformServices.Default.Runtime.GetRuntimeIdentifier(); + } + + dotnetCli.Publish( + "--output", SharedFrameworkNameAndVersionRoot, + "-r", publishRuntime, + "-f", publishFramework, + SharedFrameworkSourceRoot).Execute().EnsureSuccessful(); + + // Clean up artifacts that dotnet-publish generates which we don't need + File.Delete(Path.Combine(SharedFrameworkNameAndVersionRoot, $"framework{Constants.ExeSuffix}")); + File.Delete(Path.Combine(SharedFrameworkNameAndVersionRoot, "framework.dll")); + File.Delete(Path.Combine(SharedFrameworkNameAndVersionRoot, "framework.pdb")); + File.Delete(Path.Combine(SharedFrameworkNameAndVersionRoot, "framework.runtimeconfig.json")); + + // Rename the .deps file + var destinationDeps = Path.Combine(SharedFrameworkNameAndVersionRoot, $"{SharedFrameworkName}.deps.json"); + File.Move(Path.Combine(SharedFrameworkNameAndVersionRoot, "framework.deps"), Path.Combine(SharedFrameworkNameAndVersionRoot, $"{SharedFrameworkName}.deps")); + File.Move(Path.Combine(SharedFrameworkNameAndVersionRoot, "framework.deps.json"), destinationDeps); + + // Generate RID fallback graph + string runtimeGraphGeneratorRuntime = null; + switch (PlatformServices.Default.Runtime.OperatingSystemPlatform) + { + case Platform.Windows: + runtimeGraphGeneratorRuntime = "win"; + break; + case Platform.Linux: + runtimeGraphGeneratorRuntime = "linux"; + break; + case Platform.Darwin: + runtimeGraphGeneratorRuntime = "osx"; + break; + } + if (!string.IsNullOrEmpty(runtimeGraphGeneratorRuntime)) + { + var runtimeGraphGeneratorName = "RuntimeGraphGenerator"; + var runtimeGraphGeneratorProject = Path.Combine(Dirs.RepoRoot, "tools", runtimeGraphGeneratorName); + var runtimeGraphGeneratorOutput = Path.Combine(Dirs.Output, "tools", runtimeGraphGeneratorName); + + dotnetCli.Publish( + "--output", runtimeGraphGeneratorOutput, + runtimeGraphGeneratorProject).Execute().EnsureSuccessful(); + var runtimeGraphGeneratorExe = Path.Combine(runtimeGraphGeneratorOutput, $"{runtimeGraphGeneratorName}{Constants.ExeSuffix}"); + + Cmd(runtimeGraphGeneratorExe, "--project", SharedFrameworkSourceRoot, "--deps", destinationDeps, runtimeGraphGeneratorRuntime) + .Execute(); + } + else + { + c.Error($"Could not determine rid graph generation runtime for platform {PlatformServices.Default.Runtime.OperatingSystemPlatform}"); + } + + // corehost will be renamed to dotnet at some point and then we will not need to rename it here. + File.Copy( + Path.Combine(Dirs.Corehost, CoreHostBaseName), + Path.Combine(SharedFrameworkNameAndVersionRoot, $"dotnet{Constants.ExeSuffix}")); + File.Copy( + Path.Combine(Dirs.Corehost, HostPolicyBaseName), + Path.Combine(SharedFrameworkNameAndVersionRoot, HostPolicyBaseName), true); + + if (File.Exists(Path.Combine(SharedFrameworkNameAndVersionRoot, "mscorlib.ni.dll"))) + { + // Publish already places the crossgen'd version of mscorlib into the output, so we can + // remove the IL version + File.Delete(Path.Combine(SharedFrameworkNameAndVersionRoot, "mscorlib.dll")); + } + + CrossgenSharedFx(c, SharedFrameworkNameAndVersionRoot); + } + + private static string GetVersionFromProjectJson(string pathToProjectJson) + { + Regex r = new Regex($"\"{Regex.Escape(SharedFrameworkName)}\"\\s*:\\s*\"(?'version'[^\"]*)\""); + + foreach (var line in File.ReadAllLines(pathToProjectJson)) + { + var m = r.Match(line); + + if (m.Success) + { + return m.Groups["version"].Value; + } + } + + throw new InvalidOperationException("Unable to match the version name from " + pathToProjectJson); + } + + private static BuildTargetResult CompileCliSdk(BuildTargetContext c, DotNetCli dotnet, string outputDir) + { var configuration = c.BuildContext.Get("Configuration"); - var binDir = Path.Combine(outputDir, "bin"); - var buildVesion = c.BuildContext.Get("BuildVersion"); + var buildVersion = c.BuildContext.Get("BuildVersion"); + outputDir = Path.Combine(outputDir, "sdk", buildVersion.NuGetVersion); - Mkdirp(binDir); + Rmdir(outputDir); + Mkdirp(outputDir); foreach (var project in ProjectsToPublish) { @@ -191,11 +336,11 @@ namespace Microsoft.DotNet.Cli.Build dotnet.Publish( "--native-subdirectory", "--output", - binDir, + outputDir, "--configuration", configuration, Path.Combine(c.BuildContext.BuildDirectory, "src", project)) - .Environment("DOTNET_BUILD_VERSION", buildVesion.VersionSuffix) + .Environment("DOTNET_BUILD_VERSION", buildVersion.VersionSuffix) .Execute() .EnsureSuccessful(); } @@ -203,9 +348,9 @@ namespace Microsoft.DotNet.Cli.Build FixModeFlags(outputDir); // Copy corehost - File.Copy(Path.Combine(Dirs.Corehost, $"corehost{Constants.ExeSuffix}"), Path.Combine(binDir, $"corehost{Constants.ExeSuffix}"), overwrite: true); - File.Copy(Path.Combine(Dirs.Corehost, $"{Constants.DynamicLibPrefix}hostpolicy{Constants.DynamicLibSuffix}"), Path.Combine(binDir, $"{Constants.DynamicLibPrefix}hostpolicy{Constants.DynamicLibSuffix}"), overwrite: true); - File.Copy(Path.Combine(Dirs.Corehost, $"{Constants.DynamicLibPrefix}hostfxr{Constants.DynamicLibSuffix}"), Path.Combine(binDir, $"{Constants.DynamicLibPrefix}hostfxr{Constants.DynamicLibSuffix}"), overwrite: true); + File.Copy(Path.Combine(Dirs.Corehost, $"corehost{Constants.ExeSuffix}"), Path.Combine(outputDir, $"corehost{Constants.ExeSuffix}"), overwrite: true); + File.Copy(Path.Combine(Dirs.Corehost, $"{Constants.DynamicLibPrefix}hostpolicy{Constants.DynamicLibSuffix}"), Path.Combine(outputDir, $"{Constants.DynamicLibPrefix}hostpolicy{Constants.DynamicLibSuffix}"), overwrite: true); + File.Copy(Path.Combine(Dirs.Corehost, $"{Constants.DynamicLibPrefix}hostfxr{Constants.DynamicLibSuffix}"), Path.Combine(outputDir, $"{Constants.DynamicLibPrefix}hostfxr{Constants.DynamicLibSuffix}"), overwrite: true); // Corehostify binaries foreach (var binaryToCorehostify in BinariesForCoreHost) @@ -213,9 +358,9 @@ namespace Microsoft.DotNet.Cli.Build try { // Yes, it is .exe even on Linux. This is the managed exe we're working with - File.Copy(Path.Combine(binDir, $"{binaryToCorehostify}.exe"), Path.Combine(binDir, $"{binaryToCorehostify}.dll")); - File.Delete(Path.Combine(binDir, $"{binaryToCorehostify}.exe")); - File.Copy(Path.Combine(binDir, $"corehost{Constants.ExeSuffix}"), Path.Combine(binDir, binaryToCorehostify + Constants.ExeSuffix)); + File.Copy(Path.Combine(outputDir, $"{binaryToCorehostify}.exe"), Path.Combine(outputDir, $"{binaryToCorehostify}.dll")); + File.Delete(Path.Combine(outputDir, $"{binaryToCorehostify}.exe")); + File.Copy(Path.Combine(outputDir, $"corehost{Constants.ExeSuffix}"), Path.Combine(outputDir, binaryToCorehostify + Constants.ExeSuffix)); } catch (Exception ex) { @@ -224,25 +369,25 @@ namespace Microsoft.DotNet.Cli.Build } // dotnet.exe is from stage0. But we must be using the newly built corehost in stage1 - File.Delete(Path.Combine(binDir, $"dotnet{Constants.ExeSuffix}")); - File.Copy(Path.Combine(binDir, $"corehost{Constants.ExeSuffix}"), Path.Combine(binDir, $"dotnet{Constants.ExeSuffix}")); + File.Delete(Path.Combine(outputDir, $"dotnet{Constants.ExeSuffix}")); + File.Copy(Path.Combine(outputDir, $"corehost{Constants.ExeSuffix}"), Path.Combine(outputDir, $"dotnet{Constants.ExeSuffix}")); // Crossgen Roslyn - var result = Crossgen(c, binDir); + var result = CrossgenCliSdk(c, outputDir); if (!result.Success) { return result; } // Copy AppDeps - result = CopyAppDeps(c, binDir); + result = CopyAppDeps(c, outputDir); if (!result.Success) { return result; } // Generate .version file - var version = buildVesion.SimpleVersion; + var version = buildVersion.SimpleVersion; var content = $@"{c.BuildContext["CommitHash"]}{Environment.NewLine}{version}{Environment.NewLine}"; File.WriteAllText(Path.Combine(outputDir, ".version"), content); @@ -296,12 +441,12 @@ namespace Microsoft.DotNet.Cli.Build return c.Success(); } - private static BuildTargetResult Crossgen(BuildTargetContext c, string outputDir) + private static BuildTargetResult CrossgenCliSdk(BuildTargetContext c, string outputDir) { // Check if we need to skip crossgen if (string.Equals(Environment.GetEnvironmentVariable("DOTNET_BUILD_SKIP_CROSSGEN"), "1")) { - c.Warn("Skipping crossgen because DOTNET_BUILD_SKIP_CROSSGEN is set"); + c.Warn("Skipping crossgen for Cli Sdk because DOTNET_BUILD_SKIP_CROSSGEN is set"); return c.Success(); } @@ -346,6 +491,58 @@ namespace Microsoft.DotNet.Cli.Build return c.Success(); } + public static BuildTargetResult CrossgenSharedFx(BuildTargetContext c, string pathToAssemblies) + { + // Check if we need to skip crossgen + if (!string.Equals(Environment.GetEnvironmentVariable("CROSSGEN_SHAREDFRAMEWORK"), "1")) + { + c.Warn("Skipping crossgen for SharedFx because CROSSGEN_SHAREDFRAMEWORK is not set to 1"); + return c.Success(); + } + + foreach (var file in Directory.GetFiles(pathToAssemblies)) + { + string fileName = Path.GetFileName(file); + + if (fileName == "mscorlib.dll" || fileName == "mscorlib.ni.dll" || !HasMetadata(file)) + { + continue; + } + + string tempPathName = Path.ChangeExtension(file, "readytorun"); + + // This is not always correct. The version of crossgen we need to pick up is whatever one was restored as part + // of the Microsoft.NETCore.Runtime.CoreCLR package that is part of the shared library. For now, the version hardcoded + // in CompileTargets and the one in the shared library project.json match and are updated in lock step, but long term + // we need to be able to look at the project.lock.json file and figure out what version of Microsoft.NETCore.Runtime.CoreCLR + // was used, and then select that version. + ExecSilent(Crossgen.GetCrossgenPathForVersion(CompileTargets.CoreCLRVersion), + "-readytorun", "-in", file, "-out", tempPathName, "-platform_assemblies_paths", pathToAssemblies); + + File.Delete(file); + File.Move(tempPathName, file); + } + + return c.Success(); + } + + private static bool HasMetadata(string pathToFile) + { + try + { + using (var inStream = File.OpenRead(pathToFile)) + { + using (var peReader = new PEReader(inStream)) + { + return peReader.HasMetadata; + } + } + } + catch (BadImageFormatException) { } + + return false; + } + private static List GetAssembliesToCrossGen() { return new List diff --git a/scripts/dotnet-cli-build/Utils/DotNetCli.cs b/scripts/dotnet-cli-build/Utils/DotNetCli.cs index a84ec89dc..01e618fac 100644 --- a/scripts/dotnet-cli-build/Utils/DotNetCli.cs +++ b/scripts/dotnet-cli-build/Utils/DotNetCli.cs @@ -7,11 +7,11 @@ using Microsoft.Extensions.PlatformAbstractions; namespace Microsoft.DotNet.Cli.Build { - internal class DotNetCli + public class DotNetCli { public static readonly DotNetCli Stage0 = new DotNetCli(GetStage0Path()); - public static readonly DotNetCli Stage1 = new DotNetCli(Path.Combine(Dirs.Stage1, "bin")); - public static readonly DotNetCli Stage2 = new DotNetCli(Path.Combine(Dirs.Stage2, "bin")); + public static readonly DotNetCli Stage1 = new DotNetCli(Dirs.Stage1); + public static readonly DotNetCli Stage2 = new DotNetCli(Dirs.Stage2); public string BinPath { get; } From 5150bae60c405bcb71d4a97bb13cbb92202233a0 Mon Sep 17 00:00:00 2001 From: Sridhar Periyasamy Date: Wed, 16 Mar 2016 17:54:44 -0700 Subject: [PATCH 02/14] Fix Package targets to respect the new CLI SDK layout. --- scripts/dotnet-cli-build/CompileTargets.cs | 31 +-- scripts/dotnet-cli-build/InstallerTargets.cs | 2 +- scripts/dotnet-cli-build/MsiTargets.cs | 4 +- scripts/dotnet-cli-build/PackageTargets.cs | 84 ++++--- scripts/dotnet-cli-build/PkgTargets.cs | 10 +- scripts/dotnet-cli-build/PrepareTargets.cs | 25 +- .../SharedFrameworkTargets.cs | 218 ------------------ scripts/dotnet-cli-build/Utils/Monikers.cs | 6 +- scripts/dotnet-cli-build/Utils/Utils.cs | 9 +- test/Installer/testmsi.ps1 | 2 +- 10 files changed, 100 insertions(+), 291 deletions(-) delete mode 100644 scripts/dotnet-cli-build/SharedFrameworkTargets.cs diff --git a/scripts/dotnet-cli-build/CompileTargets.cs b/scripts/dotnet-cli-build/CompileTargets.cs index f78b0a2a8..d05bf4e2c 100644 --- a/scripts/dotnet-cli-build/CompileTargets.cs +++ b/scripts/dotnet-cli-build/CompileTargets.cs @@ -139,7 +139,7 @@ namespace Microsoft.DotNet.Cli.Build { CleanBinObj(c, Path.Combine(c.BuildContext.BuildDirectory, "src")); CleanBinObj(c, Path.Combine(c.BuildContext.BuildDirectory, "test")); - + if (Directory.Exists(Dirs.Stage1)) { Utils.DeleteDirectory(Dirs.Stage1); @@ -147,7 +147,7 @@ namespace Microsoft.DotNet.Cli.Build Directory.CreateDirectory(Dirs.Stage1); CopySharedHost(Dirs.Stage1); - PackageSharedFramework(c, Dirs.Stage1, DotNetCli.Stage0); + PublishSharedFramework(c, Dirs.Stage1, DotNetCli.Stage0); return CompileCliSdk(c, dotnet: DotNetCli.Stage0, outputDir: Dirs.Stage1); @@ -160,14 +160,14 @@ namespace Microsoft.DotNet.Cli.Build CleanBinObj(c, Path.Combine(c.BuildContext.BuildDirectory, "src")); CleanBinObj(c, Path.Combine(c.BuildContext.BuildDirectory, "test")); - + if (Directory.Exists(Dirs.Stage2)) { Utils.DeleteDirectory(Dirs.Stage2); } Directory.CreateDirectory(Dirs.Stage2); - PackageSharedFramework(c, Dirs.Stage2, DotNetCli.Stage1); + PublishSharedFramework(c, Dirs.Stage2, DotNetCli.Stage1); CopySharedHost(Dirs.Stage2); var result = CompileCliSdk(c, dotnet: DotNetCli.Stage1, @@ -211,10 +211,10 @@ namespace Microsoft.DotNet.Cli.Build Path.Combine(outputDir, DotnetHostFxrBaseName), true); } - public static void PackageSharedFramework(BuildTargetContext c, string outputDir, DotNetCli dotnetCli) + public static void PublishSharedFramework(BuildTargetContext c, string outputDir, DotNetCli dotnetCli) { string SharedFrameworkSourceRoot = Path.Combine(Dirs.RepoRoot, "src", "sharedframework", "framework"); - string SharedFrameworkNugetVersion = GetVersionFromProjectJson(Path.Combine(Path.Combine(Dirs.RepoRoot, "src", "sharedframework", "framework"), "project.json")); + string SharedFrameworkNugetVersion = c.BuildContext.Get("SharedFrameworkNugetVersion"); // We publish to a sub folder of the PublishRoot so tools like heat and zip can generate folder structures easier. string SharedFrameworkNameAndVersionRoot = Path.Combine(outputDir, "shared", SharedFrameworkName, SharedFrameworkNugetVersion); @@ -303,23 +303,6 @@ namespace Microsoft.DotNet.Cli.Build CrossgenSharedFx(c, SharedFrameworkNameAndVersionRoot); } - private static string GetVersionFromProjectJson(string pathToProjectJson) - { - Regex r = new Regex($"\"{Regex.Escape(SharedFrameworkName)}\"\\s*:\\s*\"(?'version'[^\"]*)\""); - - foreach (var line in File.ReadAllLines(pathToProjectJson)) - { - var m = r.Match(line); - - if (m.Success) - { - return m.Groups["version"].Value; - } - } - - throw new InvalidOperationException("Unable to match the version name from " + pathToProjectJson); - } - private static BuildTargetResult CompileCliSdk(BuildTargetContext c, DotNetCli dotnet, string outputDir) { var configuration = c.BuildContext.Get("Configuration"); @@ -499,7 +482,7 @@ namespace Microsoft.DotNet.Cli.Build c.Warn("Skipping crossgen for SharedFx because CROSSGEN_SHAREDFRAMEWORK is not set to 1"); return c.Success(); } - + foreach (var file in Directory.GetFiles(pathToAssemblies)) { string fileName = Path.GetFileName(file); diff --git a/scripts/dotnet-cli-build/InstallerTargets.cs b/scripts/dotnet-cli-build/InstallerTargets.cs index 097d37f18..ba657769f 100644 --- a/scripts/dotnet-cli-build/InstallerTargets.cs +++ b/scripts/dotnet-cli-build/InstallerTargets.cs @@ -99,7 +99,7 @@ namespace Microsoft.DotNet.Cli.Build Cmd(Path.Combine(Dirs.RepoRoot, "scripts", "package", "package-sharedframework-debian.sh"), "--input", inputRoot, "--output", debFile, "--package-name", packageName, - "--framework-nuget-name", SharedFrameworkTargets.SharedFrameworkName, + "--framework-nuget-name", Monikers.SharedFrameworkName, "--framework-nuget-version", c.BuildContext.Get("SharedFrameworkNugetVersion"), "--obj-root", objRoot, "--version", version) .Execute() diff --git a/scripts/dotnet-cli-build/MsiTargets.cs b/scripts/dotnet-cli-build/MsiTargets.cs index f4f82f695..5d2adf871 100644 --- a/scripts/dotnet-cli-build/MsiTargets.cs +++ b/scripts/dotnet-cli-build/MsiTargets.cs @@ -64,7 +64,7 @@ namespace Microsoft.DotNet.Cli.Build [BuildPlatforms(BuildPlatform.Windows)] public static BuildTargetResult InitMsi(BuildTargetContext c) { - SdkBundle = c.BuildContext.Get("SdkInstallerFile"); + SdkBundle = c.BuildContext.Get("CombinedFrameworkSDKHostInstallerFile"); SdkMsi = Path.ChangeExtension(SdkBundle, "msi"); Engine = Path.Combine(Path.GetDirectoryName(SdkBundle), ENGINE); @@ -129,7 +129,7 @@ namespace Microsoft.DotNet.Cli.Build public static BuildTargetResult GenerateDotnetSharedFrameworkMsi(BuildTargetContext c) { var inputDir = c.BuildContext.Get("SharedFrameworkPublishRoot"); - var sharedFrameworkNuGetName = SharedFrameworkTargets.SharedFrameworkName; + var sharedFrameworkNuGetName = Monikers.SharedFrameworkName; var sharedFrameworkNuGetVersion = c.BuildContext.Get("SharedFrameworkNugetVersion"); var upgradeCode = Utils.GenerateGuidFromName($"{sharedFrameworkNuGetName}-{sharedFrameworkNuGetVersion}-{Arch}").ToString().ToUpper(); var wixObjRoot = Path.Combine(Dirs.Output, "obj", "wix", "sharedframework"); diff --git a/scripts/dotnet-cli-build/PackageTargets.cs b/scripts/dotnet-cli-build/PackageTargets.cs index 0ef59c1f2..2719439e4 100644 --- a/scripts/dotnet-cli-build/PackageTargets.cs +++ b/scripts/dotnet-cli-build/PackageTargets.cs @@ -13,8 +13,8 @@ namespace Microsoft.DotNet.Cli.Build public static class PackageTargets { [Target(nameof(PackageTargets.CopyCLISDKLayout), - nameof(SharedFrameworkTargets.PublishSharedHost), - nameof(SharedFrameworkTargets.PublishSharedFramework), + nameof(PackageTargets.CopySharedHostLayout), + nameof(PackageTargets.CopySharedFxLayout), nameof(PackageTargets.CopyCombinedFrameworkSDKHostLayout), nameof(PackageTargets.CopyCombinedFrameworkHostLayout))] public static BuildTargetResult InitPackage(BuildTargetContext c) @@ -52,45 +52,62 @@ namespace Microsoft.DotNet.Cli.Build [Target] public static BuildTargetResult CopyCLISDKLayout(BuildTargetContext c) { - var nugetVersion = c.BuildContext.Get("BuildVersion").NuGetVersion; var cliSdkRoot = Path.Combine(Dirs.Output, "obj", "clisdk"); - var cliSdk = Path.Combine(cliSdkRoot, "sdk", nugetVersion); - if (Directory.Exists(cliSdkRoot)) { Utils.DeleteDirectory(cliSdkRoot); } - Directory.CreateDirectory(cliSdk); - - var binPath = Path.Combine(Dirs.Stage2, "bin"); - foreach (var file in Directory.GetFiles(binPath, "*", SearchOption.AllDirectories)) - { - string destFile = file.Replace(binPath, cliSdk); - Directory.CreateDirectory(Path.GetDirectoryName(destFile)); - File.Copy(file, destFile, true); - } - - File.Copy(Path.Combine(Dirs.Stage2, ".version"), Path.Combine(cliSdk, ".version"), true); - - // copy stage2 to "cliSdkRoot\bin". - // this is a temp hack until we fix the build scripts to use the new shared fx and shared host - // the current build scripts need the CLI sdk to be in the bin folder. - - foreach (var file in Directory.GetFiles(Dirs.Stage2, "*", SearchOption.AllDirectories)) - { - string destFile = file.Replace(Dirs.Stage2, cliSdkRoot); - Directory.CreateDirectory(Path.GetDirectoryName(destFile)); - File.Copy(file, destFile, true); - } + Directory.CreateDirectory(cliSdkRoot); + Utils.CopyDirectoryRecursively(Path.Combine(Dirs.Stage2, "sdk"), cliSdkRoot, true); c.BuildContext["CLISDKRoot"] = cliSdkRoot; return c.Success(); } + [Target] + public static BuildTargetResult CopySharedHostLayout(BuildTargetContext c) + { + var sharedHostRoot = Path.Combine(Dirs.Output, "obj", "sharedHost"); + if (Directory.Exists(sharedHostRoot)) + { + Utils.DeleteDirectory(sharedHostRoot); + } + + Directory.CreateDirectory(sharedHostRoot); + + foreach (var file in Directory.GetFiles(Dirs.Stage2, "*", SearchOption.TopDirectoryOnly)) + { + var destFile = file.Replace(Dirs.Stage2, sharedHostRoot); + File.Copy(file, destFile, true); + } + + c.BuildContext["SharedHostPublishRoot"] = sharedHostRoot; + return c.Success(); + } + + [Target] + public static BuildTargetResult CopySharedFxLayout(BuildTargetContext c) + { + var sharedFxRoot = Path.Combine(Dirs.Output, "obj", "sharedFx"); + if (Directory.Exists(sharedFxRoot)) + { + Utils.DeleteDirectory(sharedFxRoot); + } + + Directory.CreateDirectory(sharedFxRoot); + Utils.CopyDirectoryRecursively(Path.Combine(Dirs.Stage2, "shared"), sharedFxRoot, true); + c.BuildContext["SharedFrameworkPublishRoot"] = sharedFxRoot; + return c.Success(); + } + [Target] public static BuildTargetResult CopyCombinedFrameworkSDKHostLayout(BuildTargetContext c) { var combinedRoot = Path.Combine(Dirs.Output, "obj", "combined-framework-sdk-host"); + if (Directory.Exists(combinedRoot)) + { + Utils.DeleteDirectory(combinedRoot); + } string sdkPublishRoot = c.BuildContext.Get("CLISDKRoot"); Utils.CopyDirectoryRecursively(sdkPublishRoot, combinedRoot); @@ -109,6 +126,11 @@ namespace Microsoft.DotNet.Cli.Build public static BuildTargetResult CopyCombinedFrameworkHostLayout(BuildTargetContext c) { var combinedRoot = Path.Combine(Dirs.Output, "obj", "combined-framework-host"); + if (Directory.Exists(combinedRoot)) + { + Utils.DeleteDirectory(combinedRoot); + } + string sharedFrameworkPublishRoot = c.BuildContext.Get("SharedFrameworkPublishRoot"); Utils.CopyDirectoryRecursively(sharedFrameworkPublishRoot, combinedRoot); @@ -130,9 +152,6 @@ namespace Microsoft.DotNet.Cli.Build [BuildPlatforms(BuildPlatform.Windows)] public static BuildTargetResult GenerateZip(BuildTargetContext c) { - CreateZipFromDirectory(c.BuildContext.Get("SharedHostPublishRoot"), c.BuildContext.Get("SharedHostCompressedFile")); - CreateZipFromDirectory(c.BuildContext.Get("SharedFrameworkPublishRoot"), c.BuildContext.Get("SharedFrameworkCompressedFile")); - CreateZipFromDirectory(c.BuildContext.Get("CLISDKRoot"), c.BuildContext.Get("SdkCompressedFile")); CreateZipFromDirectory(c.BuildContext.Get("CombinedFrameworkSDKHostRoot"), c.BuildContext.Get("CombinedFrameworkSDKHostCompressedFile")); CreateZipFromDirectory(c.BuildContext.Get("CombinedFrameworkHostRoot"), c.BuildContext.Get("CombinedFrameworkHostCompressedFile")); @@ -143,9 +162,6 @@ namespace Microsoft.DotNet.Cli.Build [BuildPlatforms(BuildPlatform.Unix)] public static BuildTargetResult GenerateTarBall(BuildTargetContext c) { - CreateTarBallFromDirectory(c.BuildContext.Get("SharedHostPublishRoot"), c.BuildContext.Get("SharedHostCompressedFile")); - CreateTarBallFromDirectory(c.BuildContext.Get("SharedFrameworkPublishRoot"), c.BuildContext.Get("SharedFrameworkCompressedFile")); - CreateTarBallFromDirectory(c.BuildContext.Get("CLISDKRoot"), c.BuildContext.Get("SdkCompressedFile")); CreateTarBallFromDirectory(c.BuildContext.Get("CombinedFrameworkSDKHostRoot"), c.BuildContext.Get("CombinedFrameworkSDKHostCompressedFile")); CreateTarBallFromDirectory(c.BuildContext.Get("CombinedFrameworkHostRoot"), c.BuildContext.Get("CombinedFrameworkHostCompressedFile")); @@ -159,7 +175,7 @@ namespace Microsoft.DotNet.Cli.Build var versionSuffix = c.BuildContext.Get("BuildVersion").VersionSuffix; var env = GetCommonEnvVars(c); Cmd("powershell", "-NoProfile", "-NoLogo", - Path.Combine(Dirs.RepoRoot, "packaging", "nuget", "package.ps1"), Path.Combine(Dirs.Stage2, "bin"), versionSuffix) + Path.Combine(Dirs.RepoRoot, "packaging", "nuget", "package.ps1"), Dirs.Stage2, versionSuffix) .Environment(env) .Execute() .EnsureSuccessful(); diff --git a/scripts/dotnet-cli-build/PkgTargets.cs b/scripts/dotnet-cli-build/PkgTargets.cs index 1f082b069..56b37026f 100644 --- a/scripts/dotnet-cli-build/PkgTargets.cs +++ b/scripts/dotnet-cli-build/PkgTargets.cs @@ -37,7 +37,7 @@ namespace Microsoft.DotNet.Cli.Build [BuildPlatforms(BuildPlatform.OSX)] public static BuildTargetResult GenerateSharedFrameworkProductArchive(BuildTargetContext c) { - string sharedFrameworkNugetName = SharedFrameworkTargets.SharedFrameworkName; + string sharedFrameworkNugetName = Monikers.SharedFrameworkName; string sharedFrameworkNugetVersion = c.BuildContext.Get("SharedFrameworkNugetVersion"); string version = c.BuildContext.Get("BuildVersion").SimpleVersion; string id = $"com.microsoft.dotnet.sharedframework.{sharedFrameworkNugetName}.{sharedFrameworkNugetVersion}.osx.x64"; @@ -53,9 +53,9 @@ namespace Microsoft.DotNet.Cli.Build "shared-framework-distribution-template.xml"); string distTemplate = File.ReadAllText(inputDistTemplatePath); string distributionPath = Path.Combine(packageIntermediatesPath, "shared-framework-formatted-distribution.xml"); - string formattedDistContents = + string formattedDistContents = distTemplate.Replace("{SharedFrameworkNugetVersion}", sharedFrameworkNugetVersion) - .Replace("{SharedFrameworkNugetName}", SharedFrameworkTargets.SharedFrameworkName) + .Replace("{SharedFrameworkNugetName}", Monikers.SharedFrameworkName) .Replace("{VERSION}", version); File.WriteAllText(distributionPath, formattedDistContents); @@ -63,7 +63,7 @@ namespace Microsoft.DotNet.Cli.Build "--version", version, "--identifier", id, "--package-path", packageIntermediatesPath, - "--resources", resourcePath, + "--resources", resourcePath, "--distribution", distributionPath, outFilePath) .Execute() @@ -76,7 +76,7 @@ namespace Microsoft.DotNet.Cli.Build [BuildPlatforms(BuildPlatform.OSX)] public static BuildTargetResult GenerateSharedFrameworkPkg(BuildTargetContext c) { - string sharedFrameworkNugetName = SharedFrameworkTargets.SharedFrameworkName; + string sharedFrameworkNugetName = Monikers.SharedFrameworkName; string sharedFrameworkNugetVersion = c.BuildContext.Get("SharedFrameworkNugetVersion"); Directory.CreateDirectory(Path.Combine(Dirs.Output, "obj", "pkg")); string version = c.BuildContext.Get("BuildVersion").SimpleVersion; diff --git a/scripts/dotnet-cli-build/PrepareTargets.cs b/scripts/dotnet-cli-build/PrepareTargets.cs index 0dcfa1538..33a2eaf43 100644 --- a/scripts/dotnet-cli-build/PrepareTargets.cs +++ b/scripts/dotnet-cli-build/PrepareTargets.cs @@ -10,6 +10,7 @@ using System.Text; using static Microsoft.DotNet.Cli.Build.FS; using static Microsoft.DotNet.Cli.Build.Utils; using static Microsoft.DotNet.Cli.Build.Framework.BuildHelpers; +using System.Text.RegularExpressions; namespace Microsoft.DotNet.Cli.Build { @@ -45,6 +46,7 @@ namespace Microsoft.DotNet.Cli.Build c.BuildContext["Configuration"] = configEnv; c.BuildContext["Channel"] = Environment.GetEnvironmentVariable("CHANNEL"); + c.BuildContext["SharedFrameworkNugetVersion"] = GetVersionFromProjectJson(Path.Combine(Dirs.RepoRoot, "src", "sharedframework", "framework", "project.json")); c.Info($"Building {c.BuildContext["Configuration"]} to: {Dirs.Output}"); c.Info("Build Environment:"); @@ -112,11 +114,11 @@ namespace Microsoft.DotNet.Cli.Build var versionBadgeName = $"{CurrentPlatform.Current}_{CurrentArchitecture.Current}_{config}_version_badge.svg"; c.BuildContext["VersionBadge"] = Path.Combine(Dirs.Output, versionBadgeName); - AddInstallerArtifactToContext(c, "dotnet", "Sdk"); + AddInstallerArtifactToContext(c, "dotnet-sdk", "Sdk"); AddInstallerArtifactToContext(c, "dotnet-host", "SharedHost"); AddInstallerArtifactToContext(c, "dotnet-sharedframework", "SharedFramework"); - AddInstallerArtifactToContext(c, "dotnet-combined-framework-sdk-host", "CombinedFrameworkSDKHost"); - AddInstallerArtifactToContext(c, "dotnet-combined-framework-host", "CombinedFrameworkHost"); + AddInstallerArtifactToContext(c, "dotnet-dev", "CombinedFrameworkSDKHost"); + AddInstallerArtifactToContext(c, "dotnet", "CombinedFrameworkHost"); return c.Success(); } @@ -315,6 +317,23 @@ cmake is required to build the native host 'corehost'"; return c.Success(); } + private static string GetVersionFromProjectJson(string pathToProjectJson) + { + Regex r = new Regex($"\"{Regex.Escape(Monikers.SharedFrameworkName)}\"\\s*:\\s*\"(?'version'[^\"]*)\""); + + foreach (var line in File.ReadAllLines(pathToProjectJson)) + { + var m = r.Match(line); + + if (m.Success) + { + return m.Groups["version"].Value; + } + } + + throw new InvalidOperationException("Unable to match the version name from " + pathToProjectJson); + } + private static bool AptPackageIsInstalled(string packageName) { var result = Command.Create("dpkg", "-s", packageName) diff --git a/scripts/dotnet-cli-build/SharedFrameworkTargets.cs b/scripts/dotnet-cli-build/SharedFrameworkTargets.cs deleted file mode 100644 index 7dffd64c4..000000000 --- a/scripts/dotnet-cli-build/SharedFrameworkTargets.cs +++ /dev/null @@ -1,218 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.IO.Compression; -using System.Text.RegularExpressions; -using System.Reflection.PortableExecutable; -using System.Runtime.InteropServices; -using Microsoft.DotNet.Cli.Build.Framework; -using Microsoft.Extensions.PlatformAbstractions; - -using static Microsoft.DotNet.Cli.Build.Framework.BuildHelpers; -using Newtonsoft.Json.Linq; -using Newtonsoft.Json; - -namespace Microsoft.DotNet.Cli.Build -{ - public class SharedFrameworkTargets - { - public const string SharedFrameworkName = "Microsoft.NETCore.App"; - - private const string CoreHostBaseName = "corehost"; - private const string DotnetHostFxrBaseName = "hostfxr"; - private const string HostPolicyBaseName = "hostpolicy"; - - [Target(nameof(PackageSharedFramework), nameof(CrossGenAllManagedAssemblies))] - public static BuildTargetResult PublishSharedFramework(BuildTargetContext c) - { - return c.Success(); - } - - [Target] - public static BuildTargetResult PackageSharedFramework(BuildTargetContext c) - { - string SharedFrameworkPublishRoot = Path.Combine(Dirs.Output, "obj", "sharedframework"); - string SharedFrameworkSourceRoot = Path.Combine(Dirs.RepoRoot, "src", "sharedframework", "framework"); - string SharedFrameworkNugetVersion = GetVersionFromProjectJson(Path.Combine(Path.Combine(Dirs.RepoRoot, "src", "sharedframework", "framework"), "project.json")); - - if (Directory.Exists(SharedFrameworkPublishRoot)) - { - Utils.DeleteDirectory(SharedFrameworkPublishRoot); - } - - // We publish to a sub folder of the PublishRoot so tools like heat and zip can generate folder structures easier. - string SharedFrameworkNameAndVersionRoot = Path.Combine(SharedFrameworkPublishRoot, "shared", SharedFrameworkName, SharedFrameworkNugetVersion); - - string publishFramework = "dnxcore50"; // Temporary, use "netcoreapp" when we update nuget. - string publishRuntime; - if (PlatformServices.Default.Runtime.OperatingSystemPlatform == Platform.Windows) - { - publishRuntime = $"win7-{PlatformServices.Default.Runtime.RuntimeArchitecture}"; - } - else - { - publishRuntime = PlatformServices.Default.Runtime.GetRuntimeIdentifier(); - } - - DotNetCli.Stage2.Publish( - "--output", SharedFrameworkNameAndVersionRoot, - "-r", publishRuntime, - "-f", publishFramework, - SharedFrameworkSourceRoot).Execute().EnsureSuccessful(); - - c.BuildContext["SharedFrameworkPublishRoot"] = SharedFrameworkPublishRoot; - c.BuildContext["SharedFrameworkNugetVersion"] = SharedFrameworkNugetVersion; - - // Clean up artifacts that dotnet-publish generates which we don't need - File.Delete(Path.Combine(SharedFrameworkNameAndVersionRoot, $"framework{Constants.ExeSuffix}")); - File.Delete(Path.Combine(SharedFrameworkNameAndVersionRoot, "framework.dll")); - File.Delete(Path.Combine(SharedFrameworkNameAndVersionRoot, "framework.pdb")); - File.Delete(Path.Combine(SharedFrameworkNameAndVersionRoot, "framework.runtimeconfig.json")); - - // Rename the .deps file - var destinationDeps = Path.Combine(SharedFrameworkNameAndVersionRoot, $"{SharedFrameworkName}.deps.json"); - File.Move(Path.Combine(SharedFrameworkNameAndVersionRoot, "framework.deps"), Path.Combine(SharedFrameworkNameAndVersionRoot, $"{SharedFrameworkName}.deps")); - File.Move(Path.Combine(SharedFrameworkNameAndVersionRoot, "framework.deps.json"), destinationDeps); - - // Generate RID fallback graph - string runtimeGraphGeneratorRuntime = null; - switch (PlatformServices.Default.Runtime.OperatingSystemPlatform) - { - case Platform.Windows: - runtimeGraphGeneratorRuntime = "win"; - break; - case Platform.Linux: - runtimeGraphGeneratorRuntime = "linux"; - break; - case Platform.Darwin: - runtimeGraphGeneratorRuntime = "osx"; - break; - } - if (!string.IsNullOrEmpty(runtimeGraphGeneratorRuntime)) - { - var runtimeGraphGeneratorName = "RuntimeGraphGenerator"; - var runtimeGraphGeneratorProject = Path.Combine(c.BuildContext.BuildDirectory, "tools", runtimeGraphGeneratorName); - var runtimeGraphGeneratorOutput = Path.Combine(Dirs.Output, "tools", runtimeGraphGeneratorName); - - DotNetCli.Stage2.Publish( - "--output", runtimeGraphGeneratorOutput, - runtimeGraphGeneratorProject).Execute().EnsureSuccessful(); - var runtimeGraphGeneratorExe = Path.Combine(runtimeGraphGeneratorOutput, $"{runtimeGraphGeneratorName}{Constants.ExeSuffix}"); - - Cmd(runtimeGraphGeneratorExe, "--project", SharedFrameworkSourceRoot, "--deps", destinationDeps, runtimeGraphGeneratorRuntime) - .Execute(); - } - else - { - c.Error($"Could not determine rid graph generation runtime for platform {PlatformServices.Default.Runtime.OperatingSystemPlatform}"); - } - - // corehost will be renamed to dotnet at some point and then we will not need to rename it here. - File.Copy( - Path.Combine(Dirs.Corehost, $"{CoreHostBaseName}{Constants.ExeSuffix}"), - Path.Combine(SharedFrameworkNameAndVersionRoot, $"dotnet{Constants.ExeSuffix}")); - File.Copy( - Path.Combine(Dirs.Corehost, $"{Constants.DynamicLibPrefix}{HostPolicyBaseName}{Constants.DynamicLibSuffix}"), - Path.Combine(SharedFrameworkNameAndVersionRoot, $"{Constants.DynamicLibPrefix}{HostPolicyBaseName}{Constants.DynamicLibSuffix}"), true); - - if (File.Exists(Path.Combine(SharedFrameworkNameAndVersionRoot, "mscorlib.ni.dll"))) - { - // Publish already places the crossgen'd version of mscorlib into the output, so we can - // remove the IL version - File.Delete(Path.Combine(SharedFrameworkNameAndVersionRoot, "mscorlib.dll")); - c.BuildContext["SharedFrameworkNameAndVersionRoot"] = SharedFrameworkNameAndVersionRoot; - } - - return c.Success(); - } - - [Target] - public static BuildTargetResult PublishSharedHost(BuildTargetContext c) - { - string SharedHostPublishRoot = Path.Combine(Dirs.Output, "obj", "sharedhost"); - - if (Directory.Exists(SharedHostPublishRoot)) - { - Utils.DeleteDirectory(SharedHostPublishRoot); - } - Directory.CreateDirectory(SharedHostPublishRoot); - - // corehost will be renamed to dotnet at some point and then this can be removed. - File.Copy( - Path.Combine(Dirs.Corehost, $"{CoreHostBaseName}{Constants.ExeSuffix}"), - Path.Combine(SharedHostPublishRoot, $"dotnet{Constants.ExeSuffix}")); - File.Copy( - Path.Combine(Dirs.Corehost, $"{Constants.DynamicLibPrefix}{DotnetHostFxrBaseName}{Constants.DynamicLibSuffix}"), - Path.Combine(SharedHostPublishRoot, $"{Constants.DynamicLibPrefix}{DotnetHostFxrBaseName}{Constants.DynamicLibSuffix}")); - - c.BuildContext["SharedHostPublishRoot"] = SharedHostPublishRoot; - - return c.Success(); - } - - private static string GetVersionFromProjectJson(string pathToProjectJson) - { - Regex r = new Regex($"\"{Regex.Escape(SharedFrameworkName)}\"\\s*:\\s*\"(?'version'[^\"]*)\""); - - foreach(var line in File.ReadAllLines(pathToProjectJson)) - { - var m = r.Match(line); - - if (m.Success) - { - return m.Groups["version"].Value; - } - } - - throw new InvalidOperationException("Unable to match the version name from " + pathToProjectJson); - } - - [Target] - [Environment("CROSSGEN_SHAREDFRAMEWORK", "1", "true")] - public static BuildTargetResult CrossGenAllManagedAssemblies(BuildTargetContext c) - { - string pathToAssemblies = c.BuildContext.Get("SharedFrameworkNameAndVersionRoot"); - - foreach (var file in Directory.GetFiles(pathToAssemblies)) - { - string fileName = Path.GetFileName(file); - - if (fileName == "mscorlib.dll" || fileName == "mscorlib.ni.dll" || !HasMetadata(file)) - { - continue; - } - - string tempPathName = Path.ChangeExtension(file, "readytorun"); - - // This is not always correct. The version of crossgen we need to pick up is whatever one was restored as part - // of the Microsoft.NETCore.Runtime.CoreCLR package that is part of the shared library. For now, the version hardcoded - // in CompileTargets and the one in the shared library project.json match and are updated in lock step, but long term - // we need to be able to look at the project.lock.json file and figure out what version of Microsoft.NETCore.Runtime.CoreCLR - // was used, and then select that version. - ExecSilent(Crossgen.GetCrossgenPathForVersion(CompileTargets.CoreCLRVersion), - "-readytorun", "-in", file, "-out", tempPathName, "-platform_assemblies_paths", pathToAssemblies); - - File.Delete(file); - File.Move(tempPathName, file); - } - - return c.Success(); - } - - private static bool HasMetadata(string pathToFile) - { - try - { - using (var inStream = File.OpenRead(pathToFile)) - { - using (var peReader = new PEReader(inStream)) - { - return peReader.HasMetadata; - } - } - } catch (BadImageFormatException) { } - - return false; - } - } -} diff --git a/scripts/dotnet-cli-build/Utils/Monikers.cs b/scripts/dotnet-cli-build/Utils/Monikers.cs index b69c0d05b..7fb3562e4 100644 --- a/scripts/dotnet-cli-build/Utils/Monikers.cs +++ b/scripts/dotnet-cli-build/Utils/Monikers.cs @@ -8,6 +8,8 @@ namespace Microsoft.DotNet.Cli.Build { public class Monikers { + public const string SharedFrameworkName = "Microsoft.NETCore.App"; + public static string GetProductMoniker(BuildTargetContext c, string artifactPrefix) { string osname = GetOSShortName(); @@ -31,7 +33,7 @@ namespace Microsoft.DotNet.Cli.Build case "rtm": packageName = "dotnet"; break; - default: + default: throw new Exception($"Unknown channel - {channel}"); } @@ -42,7 +44,7 @@ namespace Microsoft.DotNet.Cli.Build { var sharedFrameworkNugetVersion = c.BuildContext.Get("SharedFrameworkNugetVersion"); - return $"dotnet-sharedframework-{SharedFrameworkTargets.SharedFrameworkName}-{sharedFrameworkNugetVersion}".ToLower(); + return $"dotnet-sharedframework-{SharedFrameworkName}-{sharedFrameworkNugetVersion}".ToLower(); } public static string GetOSShortName() diff --git a/scripts/dotnet-cli-build/Utils/Utils.cs b/scripts/dotnet-cli-build/Utils/Utils.cs index d9dd937a0..b94343249 100644 --- a/scripts/dotnet-cli-build/Utils/Utils.cs +++ b/scripts/dotnet-cli-build/Utils/Utils.cs @@ -101,8 +101,15 @@ namespace Microsoft.DotNet.Cli.Build } } - public static void CopyDirectoryRecursively(string path, string destination) + public static void CopyDirectoryRecursively(string path, string destination, bool keepParentDir = false) { + if (keepParentDir) + { + path = path.TrimEnd(Path.DirectorySeparatorChar); + destination = Path.Combine(destination, Path.GetFileName(path)); + Directory.CreateDirectory(destination); + } + foreach (var file in Directory.GetFiles(path, "*", SearchOption.AllDirectories)) { string destFile = file.Replace(path, destination); diff --git a/test/Installer/testmsi.ps1 b/test/Installer/testmsi.ps1 index 3f4f0d3cc..d1b82f67b 100644 --- a/test/Installer/testmsi.ps1 +++ b/test/Installer/testmsi.ps1 @@ -38,7 +38,7 @@ $testName = "Microsoft.DotNet.Cli.Msi.Tests" $testDir="$PSScriptRoot\$testName" $testBin="$RepoRoot\artifacts\tests\$testName" -pushd "$Stage2Dir\bin" +pushd "$Stage2Dir" try { .\dotnet restore ` From 9602d926346c6da97dc7301fd2abda93726b4029 Mon Sep 17 00:00:00 2001 From: Sridhar Periyasamy Date: Wed, 16 Mar 2016 18:16:51 -0700 Subject: [PATCH 03/14] Publish and Pkg, Deb fixes - Publish only combined SharedFx,SharedHost and combined SharedFx,SharedHost,CLISDK tarballs and zips. --- scripts/dotnet-cli-build/InstallerTargets.cs | 5 +- scripts/dotnet-cli-build/PkgTargets.cs | 5 +- scripts/dotnet-cli-build/PublishTargets.cs | 58 +++----------------- 3 files changed, 14 insertions(+), 54 deletions(-) diff --git a/scripts/dotnet-cli-build/InstallerTargets.cs b/scripts/dotnet-cli-build/InstallerTargets.cs index ba657769f..feef6e319 100644 --- a/scripts/dotnet-cli-build/InstallerTargets.cs +++ b/scripts/dotnet-cli-build/InstallerTargets.cs @@ -37,7 +37,8 @@ namespace Microsoft.DotNet.Cli.Build var channel = c.BuildContext.Get("Channel").ToLower(); var packageName = Monikers.GetDebianPackageName(c); var version = c.BuildContext.Get("BuildVersion").SimpleVersion; - var debFile = c.BuildContext.Get("SdkInstallerFile"); + var debFile = c.BuildContext.Get("CombinedFrameworkSDKHostInstallerFile"); + var input = c.BuildContext.Get("CLISDKRoot"); var manPagesDir = Path.Combine(Dirs.RepoRoot, "Documentation", "manpages"); var previousVersionURL = $"https://dotnetcli.blob.core.windows.net/dotnet/{channel}/Installers/Latest/dotnet-ubuntu-x64.latest.deb"; @@ -51,7 +52,7 @@ namespace Microsoft.DotNet.Cli.Build Directory.CreateDirectory(objRoot); Cmd(Path.Combine(Dirs.RepoRoot, "scripts", "package", "package-debian.sh"), - "-v", version, "-i", Dirs.Stage2, "-o", debFile, "-p", packageName, "-m", manPagesDir, "--previous-version-url", previousVersionURL, "--obj-root", objRoot) + "-v", version, "-i", input, "-o", debFile, "-p", packageName, "-m", manPagesDir, "--previous-version-url", previousVersionURL, "--obj-root", objRoot) .Execute() .EnsureSuccessful(); return c.Success(); diff --git a/scripts/dotnet-cli-build/PkgTargets.cs b/scripts/dotnet-cli-build/PkgTargets.cs index 56b37026f..55b1ebe33 100644 --- a/scripts/dotnet-cli-build/PkgTargets.cs +++ b/scripts/dotnet-cli-build/PkgTargets.cs @@ -24,10 +24,11 @@ namespace Microsoft.DotNet.Cli.Build public static BuildTargetResult GenerateSdkProductArchive(BuildTargetContext c) { var version = c.BuildContext.Get("BuildVersion").SimpleVersion; - var pkg = c.BuildContext.Get("SdkInstallerFile"); + var pkg = c.BuildContext.Get("CombinedFrameworkSDKHostInstallerFile"); + var input = c.BuildContext.Get("CLISDKRoot"); Cmd(Path.Combine(Dirs.RepoRoot, "packaging", "osx", "package-osx.sh"), - "-v", version, "-i", Dirs.Stage2, "-o", pkg) + "-v", version, "-i", input, "-o", pkg) .Execute() .EnsureSuccessful(); return c.Success(); diff --git a/scripts/dotnet-cli-build/PublishTargets.cs b/scripts/dotnet-cli-build/PublishTargets.cs index 04af2b35c..0894ade05 100644 --- a/scripts/dotnet-cli-build/PublishTargets.cs +++ b/scripts/dotnet-cli-build/PublishTargets.cs @@ -44,11 +44,8 @@ namespace Microsoft.DotNet.Cli.Build } [Target(nameof(PublishTargets.PublishVersionBadge), - nameof(PublishTargets.PublishCompressedFile), nameof(PublishTargets.PublishSdkInstallerFile), nameof(PublishTargets.PublishDebFileToDebianRepo), - nameof(PublishTargets.PublishSharedFrameworkCompressedFile), - nameof(PublishTargets.PublishSharedHostCompressedFile), nameof(PublishTargets.PublishCombinedFrameworkSDKHostFile), nameof(PublishTargets.PublishCombinedFrameworkHostFile), nameof(PublishTargets.PublishLatestVersionTextFile))] @@ -69,24 +66,11 @@ namespace Microsoft.DotNet.Cli.Build return c.Success(); } - [Target] - public static BuildTargetResult PublishCompressedFile(BuildTargetContext c) - { - var compressedFile = c.BuildContext.Get("SdkCompressedFile"); - var compressedFileBlob = $"{Channel}/Binaries/{Version}/{Path.GetFileName(compressedFile)}"; - var latestCompressedFile = compressedFile.Replace(Version, "latest"); - var latestCompressedFileBlob = $"{Channel}/Binaries/Latest/{Path.GetFileName(latestCompressedFile)}"; - - PublishFileAzure(compressedFileBlob, compressedFile); - PublishFileAzure(latestCompressedFileBlob, compressedFile); - return c.Success(); - } - [Target] [BuildPlatforms(BuildPlatform.Windows, BuildPlatform.OSX, BuildPlatform.Ubuntu)] public static BuildTargetResult PublishSdkInstallerFile(BuildTargetContext c) { - var installerFile = c.BuildContext.Get("SdkInstallerFile"); + var installerFile = c.BuildContext.Get("CombinedFrameworkSDKHostInstallerFile"); var installerFileBlob = $"{Channel}/Installers/{Version}/{Path.GetFileName(installerFile)}"; var latestInstallerFile = installerFile.Replace(Version, "latest"); var latestInstallerFileBlob = $"{Channel}/Installers/Latest/{Path.GetFileName(latestInstallerFile)}"; @@ -113,7 +97,7 @@ namespace Microsoft.DotNet.Cli.Build { var packageName = Monikers.GetDebianPackageName(c); var installerFile = c.BuildContext.Get("SdkInstallerFile"); - var uploadUrl = $"https://dotnetcli.blob.core.windows.net/dotnet/{Channel}/Installers/{Version}/{Path.GetFileName(installerFile)}"; + var uploadUrl = $"https://dotnetcli.blob.core.windows.net/dotnet/{Channel}/Installers/{Version}/{Path.GetFileName(installerFile)}"; var uploadJson = GenerateUploadJsonFile(packageName, Version, uploadUrl); Cmd(Path.Combine(Dirs.RepoRoot, "scripts", "publish", "repoapi_client.sh"), "-addpkg", uploadJson) @@ -133,44 +117,18 @@ namespace Microsoft.DotNet.Cli.Build { using (StreamWriter sw = new StreamWriter(fileStream)) { - sw.WriteLine("{"); - sw.WriteLine($" \"name\":\"{packageName}\","); - sw.WriteLine($" \"version\":\"{version}\","); - sw.WriteLine($" \"repositoryId\":\"{repoID}\","); - sw.WriteLine($" \"sourceUrl\":\"{uploadUrl}\""); - sw.WriteLine("}"); + sw.WriteLine("{"); + sw.WriteLine($" \"name\":\"{packageName}\","); + sw.WriteLine($" \"version\":\"{version}\","); + sw.WriteLine($" \"repositoryId\":\"{repoID}\","); + sw.WriteLine($" \"sourceUrl\":\"{uploadUrl}\""); + sw.WriteLine("}"); } } return uploadJson; } - [Target] - public static BuildTargetResult PublishSharedFrameworkCompressedFile(BuildTargetContext c) - { - var compressedFile = c.BuildContext.Get("SharedFrameworkCompressedFile"); - var compressedFileBlob = $"{Channel}/Binaries/{Version}/{Path.GetFileName(compressedFile)}"; - var latestCompressedFile = compressedFile.Replace(Version, "latest"); - var latestCompressedFileBlob = $"{Channel}/Binaries/Latest/{Path.GetFileName(latestCompressedFile)}"; - - PublishFileAzure(compressedFileBlob, compressedFile); - PublishFileAzure(latestCompressedFileBlob, compressedFile); - return c.Success(); - } - - [Target] - public static BuildTargetResult PublishSharedHostCompressedFile(BuildTargetContext c) - { - var compressedFile = c.BuildContext.Get("SharedHostCompressedFile"); - var compressedFileBlob = $"{Channel}/Binaries/{Version}/{Path.GetFileName(compressedFile)}"; - var latestCompressedFile = compressedFile.Replace(Version, "latest"); - var latestCompressedFileBlob = $"{Channel}/Binaries/Latest/{Path.GetFileName(latestCompressedFile)}"; - - PublishFileAzure(compressedFileBlob, compressedFile); - PublishFileAzure(latestCompressedFileBlob, compressedFile); - return c.Success(); - } - [Target] public static BuildTargetResult PublishCombinedFrameworkSDKHostFile(BuildTargetContext c) { From 75d49d99f3e722dbe361e718106124c5e3fc2087 Mon Sep 17 00:00:00 2001 From: Sridhar Periyasamy Date: Thu, 17 Mar 2016 10:07:03 -0700 Subject: [PATCH 04/14] Bug fix to copy the hostpolicy and hostfxr binaries from the correct location. --- scripts/dotnet-cli-build/CompileTargets.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/dotnet-cli-build/CompileTargets.cs b/scripts/dotnet-cli-build/CompileTargets.cs index d05bf4e2c..13f0a53c0 100644 --- a/scripts/dotnet-cli-build/CompileTargets.cs +++ b/scripts/dotnet-cli-build/CompileTargets.cs @@ -127,8 +127,8 @@ namespace Microsoft.DotNet.Cli.Build // Copy the output out File.Copy(Path.Combine(cmakeOut, "cli", "corehost"), Path.Combine(Dirs.Corehost, CoreHostBaseName), overwrite: true); - File.Copy(Path.Combine(cmakeOut, "cli", "dll", DotnetHostFxrBaseName), Path.Combine(Dirs.Corehost, DotnetHostFxrBaseName), overwrite: true); - File.Copy(Path.Combine(cmakeOut, "cli", "fxr", HostPolicyBaseName), Path.Combine(Dirs.Corehost, HostPolicyBaseName), overwrite: true); + File.Copy(Path.Combine(cmakeOut, "cli", "dll", HostPolicyBaseName), Path.Combine(Dirs.Corehost, HostPolicyBaseName), overwrite: true); + File.Copy(Path.Combine(cmakeOut, "cli", "fxr", DotnetHostFxrBaseName), Path.Combine(Dirs.Corehost, DotnetHostFxrBaseName), overwrite: true); } return c.Success(); From ae83a73e3507fc090f2b91755fcef07dc16ec570 Mon Sep 17 00:00:00 2001 From: Sridhar Periyasamy Date: Thu, 17 Mar 2016 13:19:27 -0700 Subject: [PATCH 05/14] Create 'dotnet-dev' and 'dotnet' pkg. - 'dotnet-dev' contains the sharedfx, shared host and CLI SDK. - 'dotnet' contains the sharedfx and the shared host. --- packaging/osx/Distribution-Template | 22 ----- packaging/osx/clisdk/Distribution-Template | 33 +++++++ .../osx/{ => clisdk}/scripts/postinstall | 2 +- packaging/osx/package-osx.sh | 86 ------------------ scripts/dotnet-cli-build/PkgTargets.cs | 90 +++++++++++++++---- 5 files changed, 105 insertions(+), 128 deletions(-) delete mode 100644 packaging/osx/Distribution-Template create mode 100644 packaging/osx/clisdk/Distribution-Template rename packaging/osx/{ => clisdk}/scripts/postinstall (86%) delete mode 100755 packaging/osx/package-osx.sh diff --git a/packaging/osx/Distribution-Template b/packaging/osx/Distribution-Template deleted file mode 100644 index c220fa5ac..000000000 --- a/packaging/osx/Distribution-Template +++ /dev/null @@ -1,22 +0,0 @@ - - - .NET CLI {VERSION} - - - - - - - - - - - - - - - - - - dotnet-osx-x64.{VERSION}.pkg - diff --git a/packaging/osx/clisdk/Distribution-Template b/packaging/osx/clisdk/Distribution-Template new file mode 100644 index 000000000..7e3f3b7ad --- /dev/null +++ b/packaging/osx/clisdk/Distribution-Template @@ -0,0 +1,33 @@ + + + .NET CLI {VERSION} + + + + + + + + + + + + + + + + + + + + + + + + + + + com.microsoft.dotnet.sharedframework.{SharedFrameworkNugetName}.{SharedFrameworkNugetVersion}.component.osx.x64.pkg + com.microsoft.dotnet.sharedhost.osx.x64.pkg + com.microsoft.dotnet.sdk.osx.x64.pkg + diff --git a/packaging/osx/scripts/postinstall b/packaging/osx/clisdk/scripts/postinstall similarity index 86% rename from packaging/osx/scripts/postinstall rename to packaging/osx/clisdk/scripts/postinstall index 0a649953a..428b79064 100755 --- a/packaging/osx/scripts/postinstall +++ b/packaging/osx/clisdk/scripts/postinstall @@ -12,7 +12,7 @@ INSTALL_DESTINATION=$2 chmod -R 755 $INSTALL_DESTINATION # Add the installation bin directory to the system-wide paths -echo $INSTALL_DESTINATION/bin | tee -a /etc/paths.d/dotnet +echo $INSTALL_DESTINATION | tee -a /etc/paths.d/dotnet exit 0 diff --git a/packaging/osx/package-osx.sh b/packaging/osx/package-osx.sh deleted file mode 100755 index 819a7e1f6..000000000 --- a/packaging/osx/package-osx.sh +++ /dev/null @@ -1,86 +0,0 @@ -#!/bin/bash -# -# 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. -# - -SOURCE="${BASH_SOURCE[0]}" -while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink - DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" - SOURCE="$(readlink "$SOURCE")" - [[ "$SOURCE" != /* ]] && SOURCE="$DIR/$SOURCE" # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located -done -DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" - -help(){ - echo "Usage: $0 [--version ] [--input ] [--output ] [--help]" - echo "" - echo "Options:" - echo " --version Specify a version for the package. Version format is 4 '.' separated numbers - ..." - echo " --input Package the entire contents of the directory tree." - echo " --output The path to where the package will be written." - exit 1 -} - -while [[ $# > 0 ]]; do - lowerI="$(echo $1 | awk '{print tolower($0)}')" - case $lowerI in - -v|--version) - DOTNET_CLI_VERSION=$2 - shift - ;; - -o|--output) - OUTPUT_PKG=$2 - shift - ;; - -i|--input) - INPUT_DIR=$2 - shift - ;; - --help) - help - ;; - *) - break - ;; - esac - shift -done - -if [ -z "$DOTNET_CLI_VERSION" ]; then - echo "Provide a version number. Missing option '--version'" && help -fi - -if [ -z "$OUTPUT_PKG" ]; then - echo "Provide an output pkg. Missing option '--output'" && help -fi - -if [ -z "$INPUT_DIR" ]; then - echo "Provide an input directory. Missing option '--input'" && help -fi - -if [ ! -d "$INPUT_DIR" ]; then - echo "'$INPUT_DIR' - is either missing or not a directory" 1>&2 - exit 1 -fi - -PACKAGE_DIR=$(dirname "${OUTPUT_PKG}") -[ -d "$PACKAGE_DIR" ] || mkdir -p $PACKAGE_DIR - -PACKAGE_ID=$(basename "${OUTPUT_PKG}") - -#chmod -R 755 $INPUT_DIR -pkgbuild --root $INPUT_DIR \ - --version $DOTNET_CLI_VERSION \ - --scripts $DIR/scripts \ - --identifier com.microsoft.dotnet.cli.pkg.dotnet-osx-x64 \ - --install-location /usr/local/share/dotnet \ - $DIR/$PACKAGE_ID - -cat $DIR/Distribution-Template | sed "/{VERSION}/s//$DOTNET_CLI_VERSION/g" > $DIR/Dist - -productbuild --version $DOTNET_CLI_VERSION --identifier com.microsoft.dotnet.cli --package-path $DIR --resources $DIR/resources --distribution $DIR/Dist $OUTPUT_PKG - -#Clean temp files -rm $DIR/$PACKAGE_ID -rm $DIR/Dist diff --git a/scripts/dotnet-cli-build/PkgTargets.cs b/scripts/dotnet-cli-build/PkgTargets.cs index 55b1ebe33..34220aac1 100644 --- a/scripts/dotnet-cli-build/PkgTargets.cs +++ b/scripts/dotnet-cli-build/PkgTargets.cs @@ -12,25 +12,80 @@ namespace Microsoft.DotNet.Cli.Build { public class PkgTargets { - [Target(nameof(GenerateSdkProductArchive), nameof(GenerateSharedFrameworkProductArchive))] + public static string PkgsIntermediateDir { get; set; } + [Target] + [BuildPlatforms(BuildPlatform.OSX)] + public static BuildTargetResult InitPkg(BuildTargetContext c) + { + PkgsIntermediateDir = Path.Combine(Dirs.Packages, "intermediate"); + Directory.CreateDirectory(PkgsIntermediateDir); + return c.Success(); + } + + [Target(nameof(InitPkg), nameof(GenerateSharedFrameworkProductArchive), nameof(GenerateCLISdkProductArchive))] [BuildPlatforms(BuildPlatform.OSX)] public static BuildTargetResult GeneratePkgs(BuildTargetContext c) { return c.Success(); } + [Target(nameof(GenerateCLISdkPkg))] + [BuildPlatforms(BuildPlatform.OSX)] + public static BuildTargetResult GenerateCLISdkProductArchive(BuildTargetContext c) + { + string sharedFrameworkNugetVersion = c.BuildContext.Get("SharedFrameworkNugetVersion"); + string version = c.BuildContext.Get("BuildVersion").SimpleVersion; + string id = $"com.microsoft.dotnet.dev.{version}.osx.x64"; + string resourcePath = Path.Combine(Dirs.RepoRoot, "packaging", "osx", "resources"); + string outFilePath = Path.Combine(Dirs.Packages, c.BuildContext.Get("CombinedFrameworkSDKHostInstallerFile")); + + string inputDistTemplatePath = Path.Combine( + Dirs.RepoRoot, + "packaging", + "osx", + "clisdk", + "Distribution-Template"); + string distTemplate = File.ReadAllText(inputDistTemplatePath); + string distributionPath = Path.Combine(PkgsIntermediateDir, "CLI-SDK-Formatted-Distribution-Template.xml"); + string formattedDistContents = + distTemplate.Replace("{SharedFrameworkNugetVersion}", sharedFrameworkNugetVersion) + .Replace("{SharedFrameworkNugetName}", Monikers.SharedFrameworkName) + .Replace("{VERSION}", version); + File.WriteAllText(distributionPath, formattedDistContents); + + Cmd("productbuild", + "--version", version, + "--identifier", id, + "--package-path", PkgsIntermediateDir, + "--resources", resourcePath, + "--distribution", distributionPath, + outFilePath) + .Execute() + .EnsureSuccessful(); + + return c.Success(); + } + [Target] [BuildPlatforms(BuildPlatform.OSX)] - public static BuildTargetResult GenerateSdkProductArchive(BuildTargetContext c) + public static BuildTargetResult GenerateCLISdkPkg(BuildTargetContext c) { - var version = c.BuildContext.Get("BuildVersion").SimpleVersion; - var pkg = c.BuildContext.Get("CombinedFrameworkSDKHostInstallerFile"); - var input = c.BuildContext.Get("CLISDKRoot"); + string version = c.BuildContext.Get("BuildVersion").SimpleVersion; + string id = $"com.microsoft.dotnet.sdk.osx.x64"; + string outFilePath = Path.Combine(PkgsIntermediateDir, id + ".pkg"); + string installLocation = "/usr/local/share/dotnet"; + string scriptsLocation = Path.Combine(Dirs.RepoRoot, "packaging", "osx", "clisdk", "scripts"); + + Cmd("pkgbuild", + "--root", c.BuildContext.Get("CLISDKRoot"), + "--identifier", id, + "--version", version, + "--install-location", installLocation, + "--scripts", scriptsLocation, + outFilePath) + .Execute() + .EnsureSuccessful(); - Cmd(Path.Combine(Dirs.RepoRoot, "packaging", "osx", "package-osx.sh"), - "-v", version, "-i", input, "-o", pkg) - .Execute() - .EnsureSuccessful(); return c.Success(); } @@ -41,10 +96,9 @@ namespace Microsoft.DotNet.Cli.Build string sharedFrameworkNugetName = Monikers.SharedFrameworkName; string sharedFrameworkNugetVersion = c.BuildContext.Get("SharedFrameworkNugetVersion"); string version = c.BuildContext.Get("BuildVersion").SimpleVersion; - string id = $"com.microsoft.dotnet.sharedframework.{sharedFrameworkNugetName}.{sharedFrameworkNugetVersion}.osx.x64"; - string packageIntermediatesPath = Path.Combine(Dirs.Output, "obj", "pkg"); + string id = $"com.microsoft.dotnet.{sharedFrameworkNugetName}.{sharedFrameworkNugetVersion}.osx.x64"; string resourcePath = Path.Combine(Dirs.RepoRoot, "packaging", "osx", "resources"); - string outFilePath = Path.Combine(packageIntermediatesPath, id + ".pkg"); + string outFilePath = Path.Combine(PkgsIntermediateDir, c.BuildContext.Get("CombinedFrameworkHostInstallerFile")); string inputDistTemplatePath = Path.Combine( Dirs.RepoRoot, @@ -53,7 +107,7 @@ namespace Microsoft.DotNet.Cli.Build "sharedframework", "shared-framework-distribution-template.xml"); string distTemplate = File.ReadAllText(inputDistTemplatePath); - string distributionPath = Path.Combine(packageIntermediatesPath, "shared-framework-formatted-distribution.xml"); + string distributionPath = Path.Combine(PkgsIntermediateDir, "shared-framework-formatted-distribution.xml"); string formattedDistContents = distTemplate.Replace("{SharedFrameworkNugetVersion}", sharedFrameworkNugetVersion) .Replace("{SharedFrameworkNugetName}", Monikers.SharedFrameworkName) @@ -63,7 +117,7 @@ namespace Microsoft.DotNet.Cli.Build Cmd("productbuild", "--version", version, "--identifier", id, - "--package-path", packageIntermediatesPath, + "--package-path", PkgsIntermediateDir, "--resources", resourcePath, "--distribution", distributionPath, outFilePath) @@ -79,10 +133,9 @@ namespace Microsoft.DotNet.Cli.Build { string sharedFrameworkNugetName = Monikers.SharedFrameworkName; string sharedFrameworkNugetVersion = c.BuildContext.Get("SharedFrameworkNugetVersion"); - Directory.CreateDirectory(Path.Combine(Dirs.Output, "obj", "pkg")); string version = c.BuildContext.Get("BuildVersion").SimpleVersion; string id = $"com.microsoft.dotnet.sharedframework.{sharedFrameworkNugetName}.{sharedFrameworkNugetVersion}.component.osx.x64"; - string outFilePath = Path.Combine(Dirs.Output, "obj", "pkg", id + ".pkg"); + string outFilePath = Path.Combine(PkgsIntermediateDir, id + ".pkg"); string installLocation = "/usr/local/share/dotnet"; string scriptsLocation = Path.Combine(Dirs.RepoRoot, "packaging", "osx", "sharedframework", "scripts"); @@ -103,10 +156,9 @@ namespace Microsoft.DotNet.Cli.Build [BuildPlatforms(BuildPlatform.OSX)] public static BuildTargetResult GenerateSharedHostPkg(BuildTargetContext c) { - Directory.CreateDirectory(Path.Combine(Dirs.Output, "obj", "pkg")); string version = c.BuildContext.Get("BuildVersion").SimpleVersion; string id = $"com.microsoft.dotnet.sharedhost.osx.x64"; - string outFilePath = Path.Combine(Dirs.Output, "obj", "pkg", id + ".pkg"); + string outFilePath = Path.Combine(PkgsIntermediateDir, id + ".pkg"); string installLocation = "/usr/local/share/dotnet"; string scriptsLocation = Path.Combine(Dirs.RepoRoot, "packaging", "osx", "sharedhost", "scripts"); @@ -123,4 +175,4 @@ namespace Microsoft.DotNet.Cli.Build return c.Success(); } } -} \ No newline at end of file +} From 51dcb6063f5142dd3269813a1fcb6af313fe3a4e Mon Sep 17 00:00:00 2001 From: Bryan Thornbury Date: Thu, 17 Mar 2016 11:43:01 -0700 Subject: [PATCH 06/14] Add Portable Test Package Asset --- .../TestPackages/dotnet-portable/Program.cs | 12 ++++++++++++ .../TestPackages/dotnet-portable/project.json | 18 ++++++++++++++++++ .../project.json | 4 ++-- .../AppWithToolDependency/project.json | 4 ++-- scripts/dotnet-cli-build/TestTargets.cs | 3 ++- 5 files changed, 36 insertions(+), 5 deletions(-) create mode 100644 TestAssets/TestPackages/dotnet-portable/Program.cs create mode 100644 TestAssets/TestPackages/dotnet-portable/project.json diff --git a/TestAssets/TestPackages/dotnet-portable/Program.cs b/TestAssets/TestPackages/dotnet-portable/Program.cs new file mode 100644 index 000000000..58d61b1bc --- /dev/null +++ b/TestAssets/TestPackages/dotnet-portable/Program.cs @@ -0,0 +1,12 @@ +using System; + +namespace ConsoleApplication +{ + public class Program + { + public static void Main(string[] args) + { + Console.WriteLine("Hello Portable World!"); + } + } +} diff --git a/TestAssets/TestPackages/dotnet-portable/project.json b/TestAssets/TestPackages/dotnet-portable/project.json new file mode 100644 index 000000000..0f9d20ba9 --- /dev/null +++ b/TestAssets/TestPackages/dotnet-portable/project.json @@ -0,0 +1,18 @@ +{ + "version": "1.0.0", + "compilationOptions": { + "emitEntryPoint": true + }, + + "frameworks": { + "netstandard1.5": { + "imports": [ + "dnxcore50", + "portable-net45+win8" + ], + "dependencies": { + "Microsoft.NETCore.App": "1.0.0-rc2-23911" + } + } + } +} diff --git a/TestAssets/TestProjects/AppWithDirectAndToolDependency/project.json b/TestAssets/TestProjects/AppWithDirectAndToolDependency/project.json index 7bcb08e63..c888180eb 100644 --- a/TestAssets/TestProjects/AppWithDirectAndToolDependency/project.json +++ b/TestAssets/TestProjects/AppWithDirectAndToolDependency/project.json @@ -17,8 +17,8 @@ }, "testRunner": "must-be-specified-to-generate-deps", "tools": { - "dotnet-hello": { - "version": "2.0.0", + "dotnet-portable": { + "version": "1.0.0", "target": "package" } } diff --git a/TestAssets/TestProjects/AppWithToolDependency/project.json b/TestAssets/TestProjects/AppWithToolDependency/project.json index 4628c7718..b25c0b2a3 100644 --- a/TestAssets/TestProjects/AppWithToolDependency/project.json +++ b/TestAssets/TestProjects/AppWithToolDependency/project.json @@ -12,8 +12,8 @@ } }, "tools": { - "dotnet-hello": { - "version": "2.0.0", + "dotnet-portable": { + "version": "1.0.0", "target": "package" } } diff --git a/scripts/dotnet-cli-build/TestTargets.cs b/scripts/dotnet-cli-build/TestTargets.cs index 5d0e3c31f..abedc6663 100644 --- a/scripts/dotnet-cli-build/TestTargets.cs +++ b/scripts/dotnet-cli-build/TestTargets.cs @@ -16,7 +16,8 @@ namespace Microsoft.DotNet.Cli.Build public static readonly string[] TestPackageProjects = new[] { "dotnet-hello/v1/dotnet-hello", - "dotnet-hello/v2/dotnet-hello" + "dotnet-hello/v2/dotnet-hello", + "dotnet-portable" }; public static readonly string[] TestProjects = new[] From bd3ba0bd41149ffea5d8fe1504e22fd3795a03a4 Mon Sep 17 00:00:00 2001 From: Bryan Thornbury Date: Thu, 17 Mar 2016 11:43:17 -0700 Subject: [PATCH 07/14] Update tests to reflect portable tools --- .../GivenAProjectToolsCommandResolver.cs | 57 +++++++++++++++++-- .../project.json | 5 ++ test/dotnet.Tests/PackagedCommandTests.cs | 24 +++++++- 3 files changed, 78 insertions(+), 8 deletions(-) diff --git a/test/Microsoft.DotNet.Cli.Utils.Tests/GivenAProjectToolsCommandResolver.cs b/test/Microsoft.DotNet.Cli.Utils.Tests/GivenAProjectToolsCommandResolver.cs index c414b1345..9ad2c8b66 100644 --- a/test/Microsoft.DotNet.Cli.Utils.Tests/GivenAProjectToolsCommandResolver.cs +++ b/test/Microsoft.DotNet.Cli.Utils.Tests/GivenAProjectToolsCommandResolver.cs @@ -16,11 +16,14 @@ using Microsoft.Extensions.PlatformAbstractions; using System.Threading; using FluentAssertions; using NuGet.Frameworks; +using NuGet.Versioning; +using NuGet.ProjectModel; namespace Microsoft.DotNet.Cli.Utils.Tests { public class GivenAProjectToolsCommandResolver { + private static readonly NuGetFramework s_toolPackageFramework = FrameworkConstants.CommonFrameworks.NetStandardApp15; private static readonly string s_liveProjectDirectory = Path.Combine(AppContext.BaseDirectory, "TestAssets/TestProjects/AppWithToolDependency"); @@ -83,7 +86,7 @@ namespace Microsoft.DotNet.Cli.Utils.Tests var commandResolverArguments = new CommandResolverArguments() { - CommandName = "dotnet-hello", + CommandName = "dotnet-portable", CommandArguments = null, ProjectDirectory = s_liveProjectDirectory }; @@ -106,7 +109,7 @@ namespace Microsoft.DotNet.Cli.Utils.Tests var commandResolverArguments = new CommandResolverArguments() { - CommandName = "dotnet-hello", + CommandName = "dotnet-portable", CommandArguments = new [] { "arg with space"}, ProjectDirectory = s_liveProjectDirectory }; @@ -118,13 +121,13 @@ namespace Microsoft.DotNet.Cli.Utils.Tests } [Fact] - public void It_returns_a_CommandSpec_with_Args_as_CommandPath_when_returning_a_CommandSpec_and_CommandArguments_are_null() + public void It_returns_a_CommandSpec_with_Args_containing_CommandPath_when_returning_a_CommandSpec_and_CommandArguments_are_null() { var projectToolsCommandResolver = SetupProjectToolsCommandResolver(); var commandResolverArguments = new CommandResolverArguments() { - CommandName = "dotnet-hello", + CommandName = "dotnet-portable", CommandArguments = null, ProjectDirectory = s_liveProjectDirectory }; @@ -134,9 +137,51 @@ namespace Microsoft.DotNet.Cli.Utils.Tests result.Should().NotBeNull(); var commandPath = result.Args.Trim('"'); - commandPath.Should().Contain("dotnet-hello"); + commandPath.Should().Contain("dotnet-portable.dll"); + } - File.Exists(commandPath).Should().BeTrue(); + [Fact] + public void It_writes_a_deps_json_file_next_to_the_lockfile() + { + var projectToolsCommandResolver = SetupProjectToolsCommandResolver(); + + var commandResolverArguments = new CommandResolverArguments() + { + CommandName = "dotnet-portable", + CommandArguments = null, + ProjectDirectory = s_liveProjectDirectory + }; + + var context = ProjectContext.Create(Path.Combine(s_liveProjectDirectory, "project.json"), s_toolPackageFramework); + + var nugetPackagesRoot = context.PackagesDirectory; + var toolPathCalculator = new ToolPathCalculator(nugetPackagesRoot); + + var lockFilePath = toolPathCalculator.GetLockFilePath( + "dotnet-portable", + new NuGetVersion("1.0.0"), + s_toolPackageFramework); + + var directory = Path.GetDirectoryName(lockFilePath); + + var depsJsonFile = Directory + .EnumerateFiles(directory) + .FirstOrDefault(p => Path.GetFileName(p).EndsWith(FileNameSuffixes.DepsJson)); + + if (depsJsonFile != null) + { + File.Delete(depsJsonFile); + } + + var result = projectToolsCommandResolver.Resolve(commandResolverArguments); + result.Should().NotBeNull(); + + + depsJsonFile = Directory + .EnumerateFiles(directory) + .FirstOrDefault(p => Path.GetFileName(p).EndsWith(FileNameSuffixes.DepsJson)); + + depsJsonFile.Should().NotBeNull(); } private ProjectToolsCommandResolver SetupProjectToolsCommandResolver( diff --git a/test/Microsoft.DotNet.Cli.Utils.Tests/project.json b/test/Microsoft.DotNet.Cli.Utils.Tests/project.json index 03dc29205..7be15c9ff 100644 --- a/test/Microsoft.DotNet.Cli.Utils.Tests/project.json +++ b/test/Microsoft.DotNet.Cli.Utils.Tests/project.json @@ -5,6 +5,11 @@ }, "dependencies": { "NETStandard.Library": "1.5.0-rc2-23911", + "NuGet.Versioning": "3.4.0-rtm-0763", + "NuGet.Packaging": "3.4.0-rtm-0763", + "NuGet.Frameworks": "3.4.0-rtm-0763", + "NuGet.ProjectModel": "3.4.0-rtm-0763", + "Microsoft.DotNet.ProjectModel": { "target": "project" }, diff --git a/test/dotnet.Tests/PackagedCommandTests.cs b/test/dotnet.Tests/PackagedCommandTests.cs index 941d3f258..7b4a91b28 100644 --- a/test/dotnet.Tests/PackagedCommandTests.cs +++ b/test/dotnet.Tests/PackagedCommandTests.cs @@ -36,9 +36,9 @@ namespace Microsoft.DotNet.Tests try { - CommandResult result = new HelloCommand().ExecuteWithCapturedOutput(); + CommandResult result = new PortableCommand().ExecuteWithCapturedOutput(); - result.Should().HaveStdOut("Hello World!" + Environment.NewLine); + result.Should().HaveStdOut("Hello Portable World!" + Environment.NewLine); result.Should().NotHaveStdErr(); result.Should().Pass(); } @@ -94,5 +94,25 @@ namespace Microsoft.DotNet.Tests return base.ExecuteWithCapturedOutput(args); } } + + class PortableCommand : TestCommand + { + public PortableCommand() + : base("dotnet") + { + } + + public override CommandResult Execute(string args = "") + { + args = $"portable {args}"; + return base.Execute(args); + } + + public override CommandResult ExecuteWithCapturedOutput(string args = "") + { + args = $"portable {args}"; + return base.ExecuteWithCapturedOutput(args); + } + } } } From b59c4333eaca5bb7a175bc059d9bab31d8bf3c7b Mon Sep 17 00:00:00 2001 From: Bryan Thornbury Date: Thu, 17 Mar 2016 11:44:18 -0700 Subject: [PATCH 08/14] Remove tool restore from dotnet restore, use nuget tool restore --- src/dotnet/commands/dotnet-restore/Program.cs | 155 +----------------- .../commands/dotnet-restore/RestoreTask.cs | 18 -- 2 files changed, 1 insertion(+), 172 deletions(-) delete mode 100644 src/dotnet/commands/dotnet-restore/RestoreTask.cs diff --git a/src/dotnet/commands/dotnet-restore/Program.cs b/src/dotnet/commands/dotnet-restore/Program.cs index 806604cf6..7cf615663 100644 --- a/src/dotnet/commands/dotnet-restore/Program.cs +++ b/src/dotnet/commands/dotnet-restore/Program.cs @@ -40,18 +40,7 @@ namespace Microsoft.DotNet.Tools.Restore { try { - var projectRestoreResult = NuGet3.Restore(args, quiet); - - var restoreTasks = GetRestoreTasks(args); - - foreach (var restoreTask in restoreTasks) - { - var project = ProjectReader.GetProject(restoreTask.ProjectPath); - - RestoreTools(project, restoreTask, quiet); - } - - return projectRestoreResult; + return NuGet3.Restore(args, quiet); } catch (InvalidOperationException e) { @@ -69,147 +58,5 @@ namespace Microsoft.DotNet.Tools.Restore return app.Execute(args); } - - private static IEnumerable GetRestoreTasks(IEnumerable args) - { - var directory = Directory.GetCurrentDirectory(); - - if (args.Any()) - { - var firstArg = args.First(); - - if (IsProjectFile(firstArg)) - { - return new [] {new RestoreTask { ProjectPath = firstArg, Arguments = args.Skip(1)} }; - } - - if (Directory.Exists(firstArg)) - { - directory = firstArg; - - args = args.Skip(1); - } - } - - return GetAllProjectFiles(directory) - .Select(p => new RestoreTask {ProjectPath = p, Arguments = args}); - } - - private static string[] GetAllProjectFiles(string directory) - { - return Directory.GetFiles(directory, Project.FileName, SearchOption.AllDirectories); - } - - private static bool IsProjectFile(string firstArg) - { - return firstArg.EndsWith(Project.FileName) && File.Exists(firstArg); - } - - private static void RestoreTools(Project project, RestoreTask restoreTask, bool quiet) - { - foreach (var tooldep in project.Tools) - { - RestoreTool(tooldep, restoreTask, quiet); - } - } - - private static void RestoreTool(LibraryRange tooldep, RestoreTask restoreTask, bool quiet) - { - var tempRoot = Path.Combine(restoreTask.ProjectDirectory, "obj"); - try - { - var tempPath = Path.Combine(tempRoot, Guid.NewGuid().ToString(), "bin"); - - var restoreSucceded = RestoreToolToPath(tooldep, restoreTask.Arguments, tempPath, quiet); - if (restoreSucceded) - { - CreateDepsInPackageCache(tooldep, tempPath); - PersistLockFile(tooldep, tempPath, restoreTask.ProjectDirectory); - } - } - finally - { - Directory.Delete(tempRoot, true); - } - } - - private static void PersistLockFile(LibraryRange tooldep, string tempPath, string projectPath) - { - var sourcePath = Path.Combine(tempPath, "project.lock.json"); - var targetDir = Path.Combine(projectPath, "artifacts", "Tools", tooldep.Name); - var targetPath = Path.Combine(targetDir, "project.lock.json"); - - if (Directory.Exists(targetDir)) Directory.Delete(targetDir, true); - Directory.CreateDirectory(targetDir); - - Console.WriteLine($"Writing '{sourcePath}' to '{targetPath}'"); - - File.Move(sourcePath, targetPath); - } - - private static void CreateDepsInPackageCache(LibraryRange toolLibrary, string projectPath) - { - var context = ProjectContext.Create(projectPath, - FrameworkConstants.CommonFrameworks.NetStandardApp15, new[] { DefaultRid }); - - var toolDescription = context.LibraryManager.GetLibraries() - .Select(l => l as PackageDescription) - .Where(l => l != null) - .FirstOrDefault(l => l.Identity.Name == toolLibrary.Name); - - var depsPath = Path.Combine( - toolDescription.Path, - Path.GetDirectoryName(toolDescription.RuntimeAssemblies.First().Path), - toolDescription.Identity.Name + FileNameSuffixes.Deps); - - var depsJsonPath = Path.Combine( - toolDescription.Path, - Path.GetDirectoryName(toolDescription.RuntimeAssemblies.First().Path), - toolDescription.Identity.Name + FileNameSuffixes.DepsJson); - - var calculator = context.GetOutputPaths(Constants.DefaultConfiguration, buidBasePath: null, outputPath: context.ProjectDirectory); - var executable = new Executable(context, calculator, context.CreateExporter(Constants.DefaultConfiguration), null); - - executable.MakeCompilationOutputRunnable(); - - if (File.Exists(depsPath)) File.Delete(depsPath); - if (File.Exists(depsJsonPath)) File.Delete(depsJsonPath); - - File.Move(Path.Combine(calculator.RuntimeOutputPath, "bin" + FileNameSuffixes.Deps), depsPath); - File.Move(Path.Combine(calculator.RuntimeOutputPath, "bin" + FileNameSuffixes.DepsJson), depsJsonPath); - } - - private static bool RestoreToolToPath(LibraryRange tooldep, IEnumerable args, string tempPath, bool quiet) - { - Directory.CreateDirectory(tempPath); - var projectPath = Path.Combine(tempPath, Project.FileName); - - Console.WriteLine($"Restoring Tool '{tooldep.Name}' for '{projectPath}' in '{tempPath}'"); - - File.WriteAllText(projectPath, GenerateProjectJsonContents(new[] {"netstandardapp1.5"}, tooldep)); - return NuGet3.Restore(new[] { $"{projectPath}" }.Concat(args), quiet) == 0; - } - - private static string GenerateProjectJsonContents(IEnumerable frameworks, LibraryRange tooldep) - { - var sb = new StringBuilder(); - sb.AppendLine("{"); - sb.AppendLine(" \"dependencies\": {"); - sb.AppendLine($" \"{tooldep.Name}\": \"{tooldep.VersionRange.OriginalString}\""); - sb.AppendLine(" },"); - sb.AppendLine(" \"frameworks\": {"); - foreach (var framework in frameworks) - { - var importsStatement = "\"imports\": [ \"dnxcore50\", \"portable-net452+win81\" ]"; - sb.AppendLine($" \"{framework}\": {{ {importsStatement} }}"); - } - sb.AppendLine(" },"); - sb.AppendLine(" \"runtimes\": { "); - sb.AppendLine($" \"{DefaultRid}\": {{}}"); - sb.AppendLine(" }"); - sb.AppendLine("}"); - var pjContents = sb.ToString(); - return pjContents; - } } } diff --git a/src/dotnet/commands/dotnet-restore/RestoreTask.cs b/src/dotnet/commands/dotnet-restore/RestoreTask.cs deleted file mode 100644 index 04de31d79..000000000 --- a/src/dotnet/commands/dotnet-restore/RestoreTask.cs +++ /dev/null @@ -1,18 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using Microsoft.DotNet.ProjectModel; - -namespace Microsoft.DotNet.Tools.Restore -{ - public struct RestoreTask - { - public string ProjectPath { get; set; } - - public IEnumerable Arguments { get; set; } - - public string ProjectDirectory => ProjectPath.EndsWith(Project.FileName, StringComparison.OrdinalIgnoreCase) - ? Path.GetDirectoryName(ProjectPath) - : ProjectPath; - } -} \ No newline at end of file From f0c2cb2c1806b8c699352d0a15fbdf45672dbf07 Mon Sep 17 00:00:00 2001 From: Bryan Thornbury Date: Thu, 17 Mar 2016 11:45:13 -0700 Subject: [PATCH 09/14] product changes to support portable tools --- .../IPackagedCommandSpecFactory.cs | 6 +- .../PackagedCommandSpecFactory.cs | 61 +++++++-- .../ProjectToolsCommandResolver.cs | 122 +++++++++++++++--- .../CommandResolution/ToolPathCalculator.cs | 70 ++++++++++ src/Microsoft.DotNet.Cli.Utils/Muxer.cs | 34 +++++ .../RuntimeConfigGenerator.cs | 53 ++++++++ src/Microsoft.DotNet.Cli.Utils/project.json | 6 +- .../Executable.cs | 26 +--- .../ProjectContext.cs | 2 +- .../ProjectContextBuilder.cs | 26 ++-- .../commands/dotnet-build/CompileContext.cs | 32 +++-- .../commands/dotnet-compile/CompilerUtil.cs | 2 +- .../commands/dotnet-pack/PackageGenerator.cs | 1 + 13 files changed, 363 insertions(+), 78 deletions(-) create mode 100644 src/Microsoft.DotNet.Cli.Utils/CommandResolution/ToolPathCalculator.cs create mode 100644 src/Microsoft.DotNet.Cli.Utils/Muxer.cs create mode 100644 src/Microsoft.DotNet.Cli.Utils/RuntimeConfigGenerator.cs diff --git a/src/Microsoft.DotNet.Cli.Utils/CommandResolution/IPackagedCommandSpecFactory.cs b/src/Microsoft.DotNet.Cli.Utils/CommandResolution/IPackagedCommandSpecFactory.cs index 34c14e56c..c285654da 100644 --- a/src/Microsoft.DotNet.Cli.Utils/CommandResolution/IPackagedCommandSpecFactory.cs +++ b/src/Microsoft.DotNet.Cli.Utils/CommandResolution/IPackagedCommandSpecFactory.cs @@ -2,7 +2,9 @@ using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; +using Microsoft.DotNet.ProjectModel; using Microsoft.DotNet.ProjectModel.Graph; +using Microsoft.DotNet.ProjectModel.Compilation; namespace Microsoft.DotNet.Cli.Utils { @@ -15,7 +17,9 @@ namespace Microsoft.DotNet.Cli.Utils IEnumerable allowedExtensions, string nugetPackagesRoot, CommandResolutionStrategy commandResolutionStrategy, - string depsFilePath); + string depsFilePath, + LibraryExporter exporter = null, + bool generateRuntimeConfig = false); } } diff --git a/src/Microsoft.DotNet.Cli.Utils/CommandResolution/PackagedCommandSpecFactory.cs b/src/Microsoft.DotNet.Cli.Utils/CommandResolution/PackagedCommandSpecFactory.cs index 8129fa2e5..9302d05d0 100644 --- a/src/Microsoft.DotNet.Cli.Utils/CommandResolution/PackagedCommandSpecFactory.cs +++ b/src/Microsoft.DotNet.Cli.Utils/CommandResolution/PackagedCommandSpecFactory.cs @@ -5,6 +5,7 @@ using System.Linq; using System.Runtime.InteropServices; using Microsoft.DotNet.ProjectModel; using Microsoft.DotNet.ProjectModel.Graph; +using Microsoft.DotNet.ProjectModel.Compilation; using Microsoft.Extensions.PlatformAbstractions; using NuGet.Frameworks; using NuGet.Packaging; @@ -20,7 +21,9 @@ namespace Microsoft.DotNet.Cli.Utils IEnumerable allowedExtensions, string nugetPackagesRoot, CommandResolutionStrategy commandResolutionStrategy, - string depsFilePath) + string depsFilePath, + LibraryExporter exporter = null, + bool generateRuntimeConfig = false) { var packageDirectory = GetPackageDirectoryFullPath(library, nugetPackagesRoot); @@ -38,11 +41,15 @@ namespace Microsoft.DotNet.Cli.Utils var commandPath = Path.Combine(packageDirectory, commandFile); + var isPortable = DetermineIfPortableApp(commandPath); + return CreateCommandSpecWrappingWithCorehostfDll( commandPath, commandArguments, depsFilePath, - commandResolutionStrategy); + commandResolutionStrategy, + nugetPackagesRoot, + isPortable); } private string GetPackageDirectoryFullPath(LockFilePackageLibrary library, string nugetPackagesRoot) @@ -69,7 +76,9 @@ namespace Microsoft.DotNet.Cli.Utils string commandPath, IEnumerable commandArguments, string depsFilePath, - CommandResolutionStrategy commandResolutionStrategy) + CommandResolutionStrategy commandResolutionStrategy, + string nugetPackagesRoot, + bool isPortable) { var commandExtension = Path.GetExtension(commandPath); @@ -79,7 +88,9 @@ namespace Microsoft.DotNet.Cli.Utils commandPath, commandArguments, depsFilePath, - commandResolutionStrategy); + commandResolutionStrategy, + nugetPackagesRoot, + isPortable); } return CreateCommandSpec(commandPath, commandArguments, commandResolutionStrategy); @@ -89,11 +100,30 @@ namespace Microsoft.DotNet.Cli.Utils string commandPath, IEnumerable commandArguments, string depsFilePath, - CommandResolutionStrategy commandResolutionStrategy) + CommandResolutionStrategy commandResolutionStrategy, + string nugetPackagesRoot, + bool isPortable) { - var corehost = CoreHost.HostExePath; - + string host = string.Empty; var arguments = new List(); + + if (isPortable) + { + var muxer = new Muxer(); + + host = muxer.MuxerPath; + if (host == null) + { + throw new Exception("Unable to locate dotnet multiplexer"); + } + + arguments.Add("exec"); + } + else + { + host = CoreHost.LocalHostExePath; + } + arguments.Add(commandPath); if (depsFilePath != null) @@ -102,9 +132,12 @@ namespace Microsoft.DotNet.Cli.Utils arguments.Add(depsFilePath); } + arguments.Add("--additionalprobingpath"); + arguments.Add(nugetPackagesRoot); + arguments.AddRange(commandArguments); - return CreateCommandSpec(corehost, arguments, commandResolutionStrategy); + return CreateCommandSpec(host, arguments, commandResolutionStrategy); } private CommandSpec CreateCommandSpec( @@ -115,6 +148,16 @@ namespace Microsoft.DotNet.Cli.Utils var escapedArgs = ArgumentEscaper.EscapeAndConcatenateArgArrayForProcessStart(commandArguments); return new CommandSpec(commandPath, escapedArgs, commandResolutionStrategy); - } + } + + private bool DetermineIfPortableApp(string commandPath) + { + var commandDir = Path.GetDirectoryName(commandPath); + + var runtimeConfig = Directory.EnumerateFiles(commandDir) + .FirstOrDefault(x => x.EndsWith("runtimeconfig.json")); + + return runtimeConfig != null; + } } } diff --git a/src/Microsoft.DotNet.Cli.Utils/CommandResolution/ProjectToolsCommandResolver.cs b/src/Microsoft.DotNet.Cli.Utils/CommandResolution/ProjectToolsCommandResolver.cs index 906d660e9..e49c4192e 100644 --- a/src/Microsoft.DotNet.Cli.Utils/CommandResolution/ProjectToolsCommandResolver.cs +++ b/src/Microsoft.DotNet.Cli.Utils/CommandResolution/ProjectToolsCommandResolver.cs @@ -5,18 +5,28 @@ using System.Linq; using System.Runtime.InteropServices; using Microsoft.DotNet.ProjectModel; using Microsoft.DotNet.ProjectModel.Graph; +using Microsoft.DotNet.ProjectModel.Compilation; +using Microsoft.Extensions.DependencyModel; using Microsoft.Extensions.PlatformAbstractions; using NuGet.Frameworks; using NuGet.Packaging; +using NuGet.ProjectModel; + +using LockFile = Microsoft.DotNet.ProjectModel.Graph.LockFile; +using FileFormatException = Microsoft.DotNet.ProjectModel.FileFormatException; namespace Microsoft.DotNet.Cli.Utils { public class ProjectToolsCommandResolver : ICommandResolver { private static readonly NuGetFramework s_toolPackageFramework = FrameworkConstants.CommonFrameworks.NetStandardApp15; + private static readonly CommandResolutionStrategy s_commandResolutionStrategy = CommandResolutionStrategy.ProjectToolsPackage; + private static readonly string s_currentRuntimeIdentifier = PlatformServices.Default.Runtime.GetLegacyRestoreRuntimeIdentifier(); + + private List _allowedCommandExtensions; private IPackagedCommandSpecFactory _packagedCommandSpecFactory; @@ -90,23 +100,21 @@ namespace Microsoft.DotNet.Cli.Utils IEnumerable args, ProjectContext projectContext) { - //todo: change this for new resolution strategy - var lockFilePath = Path.Combine( - projectContext.ProjectDirectory, - "artifacts", "Tools", toolLibrary.Name, - "project.lock.json"); - - if (!File.Exists(lockFilePath)) - { - return null; - } - - var lockFile = LockFileReader.Read(lockFilePath); - - var lockFilePackageLibrary = lockFile.PackageLibraries.FirstOrDefault(l => l.Name == toolLibrary.Name); - var nugetPackagesRoot = projectContext.PackagesDirectory; + var lockFile = GetToolLockFile(toolLibrary, nugetPackagesRoot); + var lockFilePackageLibrary = lockFile.PackageLibraries.FirstOrDefault(l => l.Name == toolLibrary.Name); + + var depsFileRoot = Path.GetDirectoryName(lockFile.LockFilePath); + var depsFilePath = GetToolDepsFilePath(toolLibrary, lockFile, depsFileRoot); + + var toolProjectContext = new ProjectContextBuilder() + .WithLockFile(lockFile) + .WithTargetFramework(s_toolPackageFramework.ToString()) + .Build(); + + var exporter = toolProjectContext.CreateExporter(Constants.DefaultConfiguration); + return _packagedCommandSpecFactory.CreateCommandSpecFromLibrary( lockFilePackageLibrary, commandName, @@ -114,7 +122,44 @@ namespace Microsoft.DotNet.Cli.Utils _allowedCommandExtensions, projectContext.PackagesDirectory, s_commandResolutionStrategy, - null); + depsFilePath); + } + + private LockFile GetToolLockFile( + LibraryRange toolLibrary, + string nugetPackagesRoot) + { + var lockFilePath = GetToolLockFilePath(toolLibrary, nugetPackagesRoot); + + if (!File.Exists(lockFilePath)) + { + return null; + } + + LockFile lockFile = null; + + try + { + lockFile = LockFileReader.Read(lockFilePath); + } + catch (FileFormatException ex) + { + throw ex; + } + + return lockFile; + } + + private string GetToolLockFilePath( + LibraryRange toolLibrary, + string nugetPackagesRoot) + { + var toolPathCalculator = new ToolPathCalculator(nugetPackagesRoot); + + return toolPathCalculator.GetBestLockFilePath( + toolLibrary.Name, + toolLibrary.VersionRange, + s_toolPackageFramework); } private ProjectContext GetProjectContextFromDirectory(string directory, NuGetFramework framework) @@ -143,5 +188,50 @@ namespace Microsoft.DotNet.Cli.Utils return projectContext; } + + private string GetToolDepsFilePath( + LibraryRange toolLibrary, + LockFile toolLockFile, + string depsPathRoot) + { + var depsJsonPath = Path.Combine( + depsPathRoot, + toolLibrary.Name + FileNameSuffixes.DepsJson); + + EnsureToolJsonDepsFileExists(toolLibrary, toolLockFile, depsJsonPath); + + return depsJsonPath; + } + + private void EnsureToolJsonDepsFileExists( + LibraryRange toolLibrary, + LockFile toolLockFile, + string depsPath) + { + if (!File.Exists(depsPath)) + { + var projectContext = new ProjectContextBuilder() + .WithLockFile(toolLockFile) + .WithTargetFramework(s_toolPackageFramework.ToString()) + .Build(); + + var exporter = projectContext.CreateExporter(Constants.DefaultConfiguration); + + var dependencyContext = new DependencyContextBuilder() + .Build(null, + null, + exporter.GetAllExports(), + true, + s_toolPackageFramework, + string.Empty); + + using (var fileStream = File.Create(depsPath)) + { + var dependencyContextWriter = new DependencyContextWriter(); + + dependencyContextWriter.Write(dependencyContext, fileStream); + } + } + } } } diff --git a/src/Microsoft.DotNet.Cli.Utils/CommandResolution/ToolPathCalculator.cs b/src/Microsoft.DotNet.Cli.Utils/CommandResolution/ToolPathCalculator.cs new file mode 100644 index 000000000..5dd24c0c5 --- /dev/null +++ b/src/Microsoft.DotNet.Cli.Utils/CommandResolution/ToolPathCalculator.cs @@ -0,0 +1,70 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.IO; +using System.Collections.Generic; +using NuGet.Frameworks; +using NuGet.Versioning; + +namespace Microsoft.DotNet.Cli.Utils +{ + public class ToolPathCalculator + { + private readonly string _packagesDirectory; + + public ToolPathCalculator(string packagesDirectory) + { + _packagesDirectory = packagesDirectory; + } + + public string GetBestLockFilePath(string packageId, VersionRange versionRange, NuGetFramework framework) + { + var availableToolVersions = GetAvailableToolVersions(packageId); + + var bestVersion = versionRange.FindBestMatch(availableToolVersions); + + return GetLockFilePath(packageId, bestVersion, framework); + } + + public string GetLockFilePath(string packageId, NuGetVersion version, NuGetFramework framework) + { + return Path.Combine( + GetBaseToolPath(packageId), + version.ToNormalizedString(), + framework.GetShortFolderName(), + "project.lock.json"); + } + + private string GetBaseToolPath(string packageId) + { + return Path.Combine( + _packagesDirectory, + ".tools", + packageId); + } + + private IEnumerable GetAvailableToolVersions(string packageId) + { + var availableVersions = new List(); + + var toolBase = GetBaseToolPath(packageId); + var versionDirectories = Directory.EnumerateDirectories(toolBase); + + foreach (var versionDirectory in versionDirectories) + { + var version = Path.GetFileName(versionDirectory); + + NuGetVersion nugetVersion = null; + NuGetVersion.TryParse(version, out nugetVersion); + + if (nugetVersion != null) + { + availableVersions.Add(nugetVersion); + } + } + + return availableVersions; + } + + } +} \ No newline at end of file diff --git a/src/Microsoft.DotNet.Cli.Utils/Muxer.cs b/src/Microsoft.DotNet.Cli.Utils/Muxer.cs new file mode 100644 index 000000000..516e0fdd8 --- /dev/null +++ b/src/Microsoft.DotNet.Cli.Utils/Muxer.cs @@ -0,0 +1,34 @@ +using System; +using System.IO; +using Microsoft.Extensions.PlatformAbstractions; + +namespace Microsoft.DotNet.Cli.Utils +{ + public class Muxer + { + private static readonly string s_muxerFileName = "dotnet" + Constants.ExeSuffix; + + private string _muxerPath; + + public string MuxerPath + { + get + { + return _muxerPath; + } + } + + public Muxer() + { + var appBase = new DirectoryInfo(PlatformServices.Default.Application.ApplicationBasePath); + var muxerDir = appBase.Parent.Parent; + + var muxerCandidate = Path.Combine(muxerDir.FullName, s_muxerFileName); + + if (File.Exists(muxerCandidate)) + { + _muxerPath = muxerCandidate; + } + } + } +} diff --git a/src/Microsoft.DotNet.Cli.Utils/RuntimeConfigGenerator.cs b/src/Microsoft.DotNet.Cli.Utils/RuntimeConfigGenerator.cs new file mode 100644 index 000000000..92ba1728d --- /dev/null +++ b/src/Microsoft.DotNet.Cli.Utils/RuntimeConfigGenerator.cs @@ -0,0 +1,53 @@ +// 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; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Xml.Linq; +using Microsoft.DotNet.Cli.Utils; +using Microsoft.DotNet.ProjectModel; +using Microsoft.DotNet.ProjectModel.Compilation; +using Microsoft.DotNet.ProjectModel.Graph; +using Microsoft.Extensions.DependencyModel; +using NuGet.Frameworks; +using Newtonsoft.Json.Linq; +using Newtonsoft.Json; + +namespace Microsoft.DotNet.Cli.Utils +{ + public static class RuntimeConfigGenerator + { + // GROOOOOSS + private static readonly string RedistPackageName = "Microsoft.NETCore.App"; + + public static void WriteRuntimeConfigToFile(LibraryExporter exporter, string runtimeConfigJsonFile) + { + // TODO: Suppress this file if there's nothing to write? RuntimeOutputFiles would have to be updated + // in order to prevent breaking incremental compilation... + + var json = new JObject(); + var runtimeOptions = new JObject(); + json.Add("runtimeOptions", runtimeOptions); + + var redistExport = exporter + .GetAllExports() + .FirstOrDefault(l => l.Library.Identity.Name.Equals(RedistPackageName, StringComparison.OrdinalIgnoreCase)); + if (redistExport != null) + { + var framework = new JObject( + new JProperty("name", redistExport.Library.Identity.Name), + new JProperty("version", redistExport.Library.Identity.Version.ToNormalizedString())); + runtimeOptions.Add("framework", framework); + } + + using (var writer = new JsonTextWriter(new StreamWriter(File.Create(runtimeConfigJsonFile)))) + { + writer.Formatting = Formatting.Indented; + json.WriteTo(writer); + } + + } + } +} \ No newline at end of file diff --git a/src/Microsoft.DotNet.Cli.Utils/project.json b/src/Microsoft.DotNet.Cli.Utils/project.json index 3e97e0621..e6cdae2f9 100644 --- a/src/Microsoft.DotNet.Cli.Utils/project.json +++ b/src/Microsoft.DotNet.Cli.Utils/project.json @@ -6,7 +6,11 @@ }, "dependencies": { "Microsoft.DotNet.ProjectModel": "1.0.0-*", - "Microsoft.Extensions.PlatformAbstractions": "1.0.0-rc2-16537" + "Microsoft.Extensions.PlatformAbstractions": "1.0.0-rc2-16537", + "NuGet.Versioning": "3.4.0-rtm-0763", + "NuGet.Packaging": "3.4.0-rtm-0763", + "NuGet.Frameworks": "3.4.0-rtm-0763", + "NuGet.ProjectModel": "3.4.0-rtm-0763" }, "frameworks": { "net451": { diff --git a/src/Microsoft.DotNet.Compiler.Common/Executable.cs b/src/Microsoft.DotNet.Compiler.Common/Executable.cs index 3fa63b148..431fc76fe 100644 --- a/src/Microsoft.DotNet.Compiler.Common/Executable.cs +++ b/src/Microsoft.DotNet.Compiler.Common/Executable.cs @@ -126,30 +126,9 @@ namespace Microsoft.Dotnet.Cli.Compiler.Common { if (!_context.TargetFramework.IsDesktop()) { - // TODO: Suppress this file if there's nothing to write? RuntimeOutputFiles would have to be updated - // in order to prevent breaking incremental compilation... - - var json = new JObject(); - var runtimeOptions = new JObject(); - json.Add("runtimeOptions", runtimeOptions); - - var redistExport = exporter - .GetAllExports() - .FirstOrDefault(l => l.Library.Identity.Name.Equals(RedistPackageName, StringComparison.OrdinalIgnoreCase)); - if (redistExport != null) - { - var framework = new JObject( - new JProperty("name", redistExport.Library.Identity.Name), - new JProperty("version", redistExport.Library.Identity.Version.ToNormalizedString())); - runtimeOptions.Add("framework", framework); - } - var runtimeConfigJsonFile = Path.Combine(_runtimeOutputPath, _context.ProjectFile.Name + FileNameSuffixes.RuntimeConfigJson); - using (var writer = new JsonTextWriter(new StreamWriter(File.Create(runtimeConfigJsonFile)))) - { - writer.Formatting = Formatting.Indented; - json.WriteTo(writer); - } + + RuntimeConfigGenerator.WriteRuntimeConfigToFile(exporter, runtimeConfigJsonFile); } } @@ -210,7 +189,6 @@ namespace Microsoft.Dotnet.Cli.Compiler.Common } } - private static void CreateDirectoryIfNotExists(string path) { var depsFile = new FileInfo(path); diff --git a/src/Microsoft.DotNet.ProjectModel/ProjectContext.cs b/src/Microsoft.DotNet.ProjectModel/ProjectContext.cs index c82e3927f..b920e857c 100644 --- a/src/Microsoft.DotNet.ProjectModel/ProjectContext.cs +++ b/src/Microsoft.DotNet.ProjectModel/ProjectContext.cs @@ -22,7 +22,7 @@ namespace Microsoft.DotNet.ProjectModel public string RuntimeIdentifier { get; } - public Project ProjectFile => RootProject.Project; + public Project ProjectFile => RootProject?.Project; public LockFile LockFile { get; } diff --git a/src/Microsoft.DotNet.ProjectModel/ProjectContextBuilder.cs b/src/Microsoft.DotNet.ProjectModel/ProjectContextBuilder.cs index 8d617df63..6e2d6b58f 100644 --- a/src/Microsoft.DotNet.ProjectModel/ProjectContextBuilder.cs +++ b/src/Microsoft.DotNet.ProjectModel/ProjectContextBuilder.cs @@ -140,7 +140,7 @@ namespace Microsoft.DotNet.ProjectModel { ProjectDirectory = Project?.ProjectDirectory ?? ProjectDirectory; - if (GlobalSettings == null) + if (GlobalSettings == null && ProjectDirectory != null) { RootDirectory = ProjectRootResolver.ResolveRootDirectory(ProjectDirectory); @@ -157,7 +157,6 @@ namespace Microsoft.DotNet.ProjectModel var frameworkReferenceResolver = new FrameworkReferenceResolver(ReferenceAssembliesPath); LockFileLookup lockFileLookup = null; - EnsureProjectLoaded(); LockFile = LockFile ?? LockFileResolver(ProjectDirectory); @@ -167,7 +166,10 @@ namespace Microsoft.DotNet.ProjectModel if (LockFile != null) { - validLockFile = LockFile.IsValidForProject(Project, out lockFileValidationMessage); + if (Project != null) + { + validLockFile = LockFile.IsValidForProject(Project, out lockFileValidationMessage); + } lockFileLookup = new LockFileLookup(LockFile); } @@ -175,10 +177,14 @@ namespace Microsoft.DotNet.ProjectModel var libraries = new Dictionary(); var projectResolver = new ProjectDependencyProvider(ProjectResolver); - var mainProject = projectResolver.GetDescription(TargetFramework, Project, targetLibrary: null); + ProjectDescription mainProject = null; + if (Project != null) + { + mainProject = projectResolver.GetDescription(TargetFramework, Project, targetLibrary: null); - // Add the main project - libraries.Add(new LibraryKey(mainProject.Identity.Name), mainProject); + // Add the main project + libraries.Add(new LibraryKey(mainProject.Identity.Name), mainProject); + } LockFileTarget target = null; if (lockFileLookup != null) @@ -251,7 +257,7 @@ namespace Microsoft.DotNet.ProjectModel } // Create a library manager - var libraryManager = new LibraryManager(libraries.Values.ToList(), diagnostics, Project.ProjectFilePath); + var libraryManager = new LibraryManager(libraries.Values.ToList(), diagnostics, Project?.ProjectFilePath); return new ProjectContext( GlobalSettings, @@ -375,13 +381,9 @@ namespace Microsoft.DotNet.ProjectModel private void EnsureProjectLoaded() { - if (Project == null) + if (Project == null && ProjectDirectory != null) { Project = ProjectResolver(ProjectDirectory); - if (Project == null) - { - throw new InvalidOperationException($"Unable to resolve project from {ProjectDirectory}"); - } } } diff --git a/src/dotnet/commands/dotnet-build/CompileContext.cs b/src/dotnet/commands/dotnet-build/CompileContext.cs index 4768f12e7..229c5af15 100644 --- a/src/dotnet/commands/dotnet-build/CompileContext.cs +++ b/src/dotnet/commands/dotnet-build/CompileContext.cs @@ -255,27 +255,33 @@ namespace Microsoft.DotNet.Tools.Build private void CollectCompilerNamePreconditions(ProjectContext project, IncrementalPreconditions preconditions) { - var projectCompiler = project.ProjectFile.CompilerName; - - if (!KnownCompilers.Any(knownCompiler => knownCompiler.Equals(projectCompiler, StringComparison.Ordinal))) + if (project.ProjectFile != null) { - preconditions.AddUnknownCompilerPrecondition(project.ProjectName(), projectCompiler); + var projectCompiler = project.ProjectFile.CompilerName; + + if (!KnownCompilers.Any(knownCompiler => knownCompiler.Equals(projectCompiler, StringComparison.Ordinal))) + { + preconditions.AddUnknownCompilerPrecondition(project.ProjectName(), projectCompiler); + } } } private void CollectScriptPreconditions(ProjectContext project, IncrementalPreconditions preconditions) { - var preCompileScripts = project.ProjectFile.Scripts.GetOrEmpty(ScriptNames.PreCompile); - var postCompileScripts = project.ProjectFile.Scripts.GetOrEmpty(ScriptNames.PostCompile); - - if (preCompileScripts.Any()) + if (project.ProjectFile != null) { - preconditions.AddPrePostScriptPrecondition(project.ProjectName(), ScriptNames.PreCompile); - } + var preCompileScripts = project.ProjectFile.Scripts.GetOrEmpty(ScriptNames.PreCompile); + var postCompileScripts = project.ProjectFile.Scripts.GetOrEmpty(ScriptNames.PostCompile); - if (postCompileScripts.Any()) - { - preconditions.AddPrePostScriptPrecondition(project.ProjectName(), ScriptNames.PostCompile); + if (preCompileScripts.Any()) + { + preconditions.AddPrePostScriptPrecondition(project.ProjectName(), ScriptNames.PreCompile); + } + + if (postCompileScripts.Any()) + { + preconditions.AddPrePostScriptPrecondition(project.ProjectName(), ScriptNames.PostCompile); + } } } diff --git a/src/dotnet/commands/dotnet-compile/CompilerUtil.cs b/src/dotnet/commands/dotnet-compile/CompilerUtil.cs index 739e46dfe..f258dc43c 100644 --- a/src/dotnet/commands/dotnet-compile/CompilerUtil.cs +++ b/src/dotnet/commands/dotnet-compile/CompilerUtil.cs @@ -122,7 +122,7 @@ namespace Microsoft.DotNet.Tools.Compiler //used in incremental precondition checks public static IEnumerable GetCommandsInvokedByCompile(ProjectContext project) { - return new List {project.ProjectFile.CompilerName, "compile"}; + return new List {project.ProjectFile?.CompilerName, "compile"}; } } } \ No newline at end of file diff --git a/src/dotnet/commands/dotnet-pack/PackageGenerator.cs b/src/dotnet/commands/dotnet-pack/PackageGenerator.cs index 8995e2025..44a793b6f 100644 --- a/src/dotnet/commands/dotnet-pack/PackageGenerator.cs +++ b/src/dotnet/commands/dotnet-pack/PackageGenerator.cs @@ -94,6 +94,7 @@ namespace Microsoft.DotNet.Tools.Compiler TryAddOutputFile(context, inputFolder, outputName); TryAddOutputFile(context, inputFolder, $"{Project.Name}.xml"); + TryAddOutputFile(context, inputFolder, $"{Project.Name}.runtimeconfig.json"); } protected virtual bool GeneratePackage(string nupkg, List packDiagnostics) From 937141c6a5e4c1f67f5c490550004a14a9f427d7 Mon Sep 17 00:00:00 2001 From: Bryan Thornbury Date: Thu, 17 Mar 2016 13:43:53 -0700 Subject: [PATCH 10/14] Cleanup --- .../IPackagedCommandSpecFactory.cs | 4 +- .../PackagedCommandSpecFactory.cs | 8 ++- src/Microsoft.DotNet.Cli.Utils/Muxer.cs | 39 ++++++++++++-- .../RuntimeConfigGenerator.cs | 53 ------------------- .../Executable.cs | 26 ++++++++- 5 files changed, 63 insertions(+), 67 deletions(-) delete mode 100644 src/Microsoft.DotNet.Cli.Utils/RuntimeConfigGenerator.cs diff --git a/src/Microsoft.DotNet.Cli.Utils/CommandResolution/IPackagedCommandSpecFactory.cs b/src/Microsoft.DotNet.Cli.Utils/CommandResolution/IPackagedCommandSpecFactory.cs index c285654da..626dcf9cc 100644 --- a/src/Microsoft.DotNet.Cli.Utils/CommandResolution/IPackagedCommandSpecFactory.cs +++ b/src/Microsoft.DotNet.Cli.Utils/CommandResolution/IPackagedCommandSpecFactory.cs @@ -17,9 +17,7 @@ namespace Microsoft.DotNet.Cli.Utils IEnumerable allowedExtensions, string nugetPackagesRoot, CommandResolutionStrategy commandResolutionStrategy, - string depsFilePath, - LibraryExporter exporter = null, - bool generateRuntimeConfig = false); + string depsFilePath); } } diff --git a/src/Microsoft.DotNet.Cli.Utils/CommandResolution/PackagedCommandSpecFactory.cs b/src/Microsoft.DotNet.Cli.Utils/CommandResolution/PackagedCommandSpecFactory.cs index 9302d05d0..1d95c8ddd 100644 --- a/src/Microsoft.DotNet.Cli.Utils/CommandResolution/PackagedCommandSpecFactory.cs +++ b/src/Microsoft.DotNet.Cli.Utils/CommandResolution/PackagedCommandSpecFactory.cs @@ -21,9 +21,7 @@ namespace Microsoft.DotNet.Cli.Utils IEnumerable allowedExtensions, string nugetPackagesRoot, CommandResolutionStrategy commandResolutionStrategy, - string depsFilePath, - LibraryExporter exporter = null, - bool generateRuntimeConfig = false) + string depsFilePath) { var packageDirectory = GetPackageDirectoryFullPath(library, nugetPackagesRoot); @@ -124,8 +122,6 @@ namespace Microsoft.DotNet.Cli.Utils host = CoreHost.LocalHostExePath; } - arguments.Add(commandPath); - if (depsFilePath != null) { arguments.Add("--depsfile"); @@ -135,6 +131,8 @@ namespace Microsoft.DotNet.Cli.Utils arguments.Add("--additionalprobingpath"); arguments.Add(nugetPackagesRoot); + arguments.Add(commandPath); + arguments.AddRange(commandArguments); return CreateCommandSpec(host, arguments, commandResolutionStrategy); diff --git a/src/Microsoft.DotNet.Cli.Utils/Muxer.cs b/src/Microsoft.DotNet.Cli.Utils/Muxer.cs index 516e0fdd8..c279f3e5a 100644 --- a/src/Microsoft.DotNet.Cli.Utils/Muxer.cs +++ b/src/Microsoft.DotNet.Cli.Utils/Muxer.cs @@ -6,7 +6,8 @@ namespace Microsoft.DotNet.Cli.Utils { public class Muxer { - private static readonly string s_muxerFileName = "dotnet" + Constants.ExeSuffix; + private static readonly string s_muxerName = "dotnet"; + private static readonly string s_muxerFileName = s_muxerName + Constants.ExeSuffix; private string _muxerPath; @@ -19,16 +20,46 @@ namespace Microsoft.DotNet.Cli.Utils } public Muxer() + { + if (!TryResolveMuxerFromParentDirectories()) + { + TryResolverMuxerFromPath(); + } + } + + private bool TryResolveMuxerFromParentDirectories() { var appBase = new DirectoryInfo(PlatformServices.Default.Application.ApplicationBasePath); - var muxerDir = appBase.Parent.Parent; + var muxerDir = appBase.Parent?.Parent; + + if (muxerDir == null) + { + return false; + } var muxerCandidate = Path.Combine(muxerDir.FullName, s_muxerFileName); - if (File.Exists(muxerCandidate)) + if (!File.Exists(muxerCandidate)) { - _muxerPath = muxerCandidate; + return false; } + + _muxerPath = muxerCandidate; + return true; + } + + private bool TryResolverMuxerFromPath() + { + var muxerPath = Env.GetCommandPath(s_muxerName, Constants.ExeSuffix); + + if (muxerPath == null || !File.Exists(muxerPath)) + { + return false; + } + + _muxerPath = muxerPath; + + return true; } } } diff --git a/src/Microsoft.DotNet.Cli.Utils/RuntimeConfigGenerator.cs b/src/Microsoft.DotNet.Cli.Utils/RuntimeConfigGenerator.cs deleted file mode 100644 index 92ba1728d..000000000 --- a/src/Microsoft.DotNet.Cli.Utils/RuntimeConfigGenerator.cs +++ /dev/null @@ -1,53 +0,0 @@ -// 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; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Xml.Linq; -using Microsoft.DotNet.Cli.Utils; -using Microsoft.DotNet.ProjectModel; -using Microsoft.DotNet.ProjectModel.Compilation; -using Microsoft.DotNet.ProjectModel.Graph; -using Microsoft.Extensions.DependencyModel; -using NuGet.Frameworks; -using Newtonsoft.Json.Linq; -using Newtonsoft.Json; - -namespace Microsoft.DotNet.Cli.Utils -{ - public static class RuntimeConfigGenerator - { - // GROOOOOSS - private static readonly string RedistPackageName = "Microsoft.NETCore.App"; - - public static void WriteRuntimeConfigToFile(LibraryExporter exporter, string runtimeConfigJsonFile) - { - // TODO: Suppress this file if there's nothing to write? RuntimeOutputFiles would have to be updated - // in order to prevent breaking incremental compilation... - - var json = new JObject(); - var runtimeOptions = new JObject(); - json.Add("runtimeOptions", runtimeOptions); - - var redistExport = exporter - .GetAllExports() - .FirstOrDefault(l => l.Library.Identity.Name.Equals(RedistPackageName, StringComparison.OrdinalIgnoreCase)); - if (redistExport != null) - { - var framework = new JObject( - new JProperty("name", redistExport.Library.Identity.Name), - new JProperty("version", redistExport.Library.Identity.Version.ToNormalizedString())); - runtimeOptions.Add("framework", framework); - } - - using (var writer = new JsonTextWriter(new StreamWriter(File.Create(runtimeConfigJsonFile)))) - { - writer.Formatting = Formatting.Indented; - json.WriteTo(writer); - } - - } - } -} \ No newline at end of file diff --git a/src/Microsoft.DotNet.Compiler.Common/Executable.cs b/src/Microsoft.DotNet.Compiler.Common/Executable.cs index 431fc76fe..3fa63b148 100644 --- a/src/Microsoft.DotNet.Compiler.Common/Executable.cs +++ b/src/Microsoft.DotNet.Compiler.Common/Executable.cs @@ -126,9 +126,30 @@ namespace Microsoft.Dotnet.Cli.Compiler.Common { if (!_context.TargetFramework.IsDesktop()) { - var runtimeConfigJsonFile = Path.Combine(_runtimeOutputPath, _context.ProjectFile.Name + FileNameSuffixes.RuntimeConfigJson); + // TODO: Suppress this file if there's nothing to write? RuntimeOutputFiles would have to be updated + // in order to prevent breaking incremental compilation... - RuntimeConfigGenerator.WriteRuntimeConfigToFile(exporter, runtimeConfigJsonFile); + var json = new JObject(); + var runtimeOptions = new JObject(); + json.Add("runtimeOptions", runtimeOptions); + + var redistExport = exporter + .GetAllExports() + .FirstOrDefault(l => l.Library.Identity.Name.Equals(RedistPackageName, StringComparison.OrdinalIgnoreCase)); + if (redistExport != null) + { + var framework = new JObject( + new JProperty("name", redistExport.Library.Identity.Name), + new JProperty("version", redistExport.Library.Identity.Version.ToNormalizedString())); + runtimeOptions.Add("framework", framework); + } + + var runtimeConfigJsonFile = Path.Combine(_runtimeOutputPath, _context.ProjectFile.Name + FileNameSuffixes.RuntimeConfigJson); + using (var writer = new JsonTextWriter(new StreamWriter(File.Create(runtimeConfigJsonFile)))) + { + writer.Formatting = Formatting.Indented; + json.WriteTo(writer); + } } } @@ -189,6 +210,7 @@ namespace Microsoft.Dotnet.Cli.Compiler.Common } } + private static void CreateDirectoryIfNotExists(string path) { var depsFile = new FileInfo(path); From 873310f8f463c1c04e6fca80f94f39000516077a Mon Sep 17 00:00:00 2001 From: Bryan Thornbury Date: Thu, 17 Mar 2016 14:06:15 -0700 Subject: [PATCH 11/14] fix commandPath ordering for corehost --- .../CommandResolution/PackagedCommandSpecFactory.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Microsoft.DotNet.Cli.Utils/CommandResolution/PackagedCommandSpecFactory.cs b/src/Microsoft.DotNet.Cli.Utils/CommandResolution/PackagedCommandSpecFactory.cs index 1d95c8ddd..dc2cfed2a 100644 --- a/src/Microsoft.DotNet.Cli.Utils/CommandResolution/PackagedCommandSpecFactory.cs +++ b/src/Microsoft.DotNet.Cli.Utils/CommandResolution/PackagedCommandSpecFactory.cs @@ -122,6 +122,8 @@ namespace Microsoft.DotNet.Cli.Utils host = CoreHost.LocalHostExePath; } + arguments.Add(commandPath); + if (depsFilePath != null) { arguments.Add("--depsfile"); @@ -131,8 +133,6 @@ namespace Microsoft.DotNet.Cli.Utils arguments.Add("--additionalprobingpath"); arguments.Add(nugetPackagesRoot); - arguments.Add(commandPath); - arguments.AddRange(commandArguments); return CreateCommandSpec(host, arguments, commandResolutionStrategy); From 6c17d0e29ce0c0153defa440b0acff7845f7b639 Mon Sep 17 00:00:00 2001 From: Bryan Thornbury Date: Thu, 17 Mar 2016 14:41:56 -0700 Subject: [PATCH 12/14] fix test --- .../GivenAProjectToolsCommandResolver.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/Microsoft.DotNet.Cli.Utils.Tests/GivenAProjectToolsCommandResolver.cs b/test/Microsoft.DotNet.Cli.Utils.Tests/GivenAProjectToolsCommandResolver.cs index 9ad2c8b66..63a85bfc7 100644 --- a/test/Microsoft.DotNet.Cli.Utils.Tests/GivenAProjectToolsCommandResolver.cs +++ b/test/Microsoft.DotNet.Cli.Utils.Tests/GivenAProjectToolsCommandResolver.cs @@ -80,7 +80,7 @@ namespace Microsoft.DotNet.Cli.Utils.Tests } [Fact] - public void It_returns_a_CommandSpec_with_CoreHost_as_FileName_and_CommandName_in_Args_when_CommandName_exists_in_ProjectTools() + public void It_returns_a_CommandSpec_with_DOTNET_as_FileName_and_CommandName_in_Args_when_CommandName_exists_in_ProjectTools() { var projectToolsCommandResolver = SetupProjectToolsCommandResolver(); @@ -97,7 +97,7 @@ namespace Microsoft.DotNet.Cli.Utils.Tests var commandFile = Path.GetFileNameWithoutExtension(result.Path); - commandFile.Should().Be("corehost"); + commandFile.Should().Be("dotnet"); result.Args.Should().Contain(commandResolverArguments.CommandName); } From d878331a5e1c96f6527d09c11caefe4cc0bae103 Mon Sep 17 00:00:00 2001 From: Bryan Thornbury Date: Thu, 17 Mar 2016 15:24:36 -0700 Subject: [PATCH 13/14] Fix EndToEnd Tests for portable build and publish --- .../TestBase.cs | 21 ++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/test/Microsoft.DotNet.Tools.Tests.Utilities/TestBase.cs b/test/Microsoft.DotNet.Tools.Tests.Utilities/TestBase.cs index 2db36724b..bb016d900 100644 --- a/test/Microsoft.DotNet.Tools.Tests.Utilities/TestBase.cs +++ b/test/Microsoft.DotNet.Tools.Tests.Utilities/TestBase.cs @@ -107,10 +107,19 @@ namespace Microsoft.DotNet.Tools.Test.Utilities string expectedOutput) { var executablePath = Path.Combine(outputDir, executableName); + var args = new List(); + + if (IsPortable(executablePath)) + { + args.Add(ArgumentEscaper.EscapeSingleArg(executablePath)); + + var muxer = new Muxer(); + executablePath = muxer.MuxerPath; + } var executableCommand = new TestCommand(executablePath); - var result = executableCommand.ExecuteWithCapturedOutput(""); + var result = executableCommand.ExecuteWithCapturedOutput(string.Join(" ", args)); result.Should().HaveStdOut(expectedOutput); result.Should().NotHaveStdErr(); @@ -141,5 +150,15 @@ namespace Microsoft.DotNet.Tools.Test.Utilities return executablePath; } + + private bool IsPortable(string executablePath) + { + var executableDir = Path.GetDirectoryName(executablePath); + + var runtimeConfig = Directory.EnumerateFiles(executableDir) + .FirstOrDefault(x => x.EndsWith("runtimeconfig.json")); + + return runtimeConfig != null; + } } } From 861b7494d3994b9f5be4b4f40c384cca61937758 Mon Sep 17 00:00:00 2001 From: Bryan Thornbury Date: Thu, 17 Mar 2016 16:39:48 -0700 Subject: [PATCH 14/14] Add hacky abstraction for quickly parsing RuntimeConfig.json and determining if it's a portable app --- .../PackagedCommandSpecFactory.cs | 11 ++++- .../RuntimeConfig/RuntimeConfig.cs | 49 +++++++++++++++++++ .../RuntimeConfig/RuntimeConfigFramework.cs | 36 ++++++++++++++ .../TestBase.cs | 15 ++++-- .../project.json | 1 + 5 files changed, 107 insertions(+), 5 deletions(-) create mode 100644 src/Microsoft.DotNet.ProjectModel/RuntimeConfig/RuntimeConfig.cs create mode 100644 src/Microsoft.DotNet.ProjectModel/RuntimeConfig/RuntimeConfigFramework.cs diff --git a/src/Microsoft.DotNet.Cli.Utils/CommandResolution/PackagedCommandSpecFactory.cs b/src/Microsoft.DotNet.Cli.Utils/CommandResolution/PackagedCommandSpecFactory.cs index dc2cfed2a..8b3ff0ca3 100644 --- a/src/Microsoft.DotNet.Cli.Utils/CommandResolution/PackagedCommandSpecFactory.cs +++ b/src/Microsoft.DotNet.Cli.Utils/CommandResolution/PackagedCommandSpecFactory.cs @@ -152,10 +152,17 @@ namespace Microsoft.DotNet.Cli.Utils { var commandDir = Path.GetDirectoryName(commandPath); - var runtimeConfig = Directory.EnumerateFiles(commandDir) + var runtimeConfigPath = Directory.EnumerateFiles(commandDir) .FirstOrDefault(x => x.EndsWith("runtimeconfig.json")); - return runtimeConfig != null; + if (runtimeConfigPath == null) + { + return false; + } + + var runtimeConfig = new RuntimeConfig(runtimeConfigPath); + + return runtimeConfig.IsPortable; } } } diff --git a/src/Microsoft.DotNet.ProjectModel/RuntimeConfig/RuntimeConfig.cs b/src/Microsoft.DotNet.ProjectModel/RuntimeConfig/RuntimeConfig.cs new file mode 100644 index 000000000..0d2d7431d --- /dev/null +++ b/src/Microsoft.DotNet.ProjectModel/RuntimeConfig/RuntimeConfig.cs @@ -0,0 +1,49 @@ +// 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; +using System.Collections.Generic; +using System.Linq; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using System.IO; + +namespace Microsoft.DotNet.ProjectModel +{ + public class RuntimeConfig + { + public bool IsPortable { get; } + public RuntimeConfigFramework Framework { get; } + + public RuntimeConfig(string runtimeConfigPath) + { + var runtimeConfigJson = OpenRuntimeConfig(runtimeConfigPath); + + Framework = ParseFramework(runtimeConfigJson); + + IsPortable = Framework != null; + } + + private JObject OpenRuntimeConfig(string runtimeConfigPath) + { + return JObject.Parse(File.ReadAllText(runtimeConfigPath)); + } + + private RuntimeConfigFramework ParseFramework(JObject runtimeConfigRoot) + { + var runtimeOptionsRoot = runtimeConfigRoot["runtimeOptions"]; + if (runtimeOptionsRoot == null) + { + return null; + } + + var framework = (JObject) runtimeOptionsRoot["framework"]; + if (framework == null) + { + return null; + } + + return RuntimeConfigFramework.ParseFromFrameworkRoot(framework); + } + } +} \ No newline at end of file diff --git a/src/Microsoft.DotNet.ProjectModel/RuntimeConfig/RuntimeConfigFramework.cs b/src/Microsoft.DotNet.ProjectModel/RuntimeConfig/RuntimeConfigFramework.cs new file mode 100644 index 000000000..d6a0c6f63 --- /dev/null +++ b/src/Microsoft.DotNet.ProjectModel/RuntimeConfig/RuntimeConfigFramework.cs @@ -0,0 +1,36 @@ +// 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; +using System.Collections.Generic; +using System.Linq; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; + +namespace Microsoft.DotNet.ProjectModel +{ + public class RuntimeConfigFramework + { + public string Name { get; set; } + public string Version { get; set; } + + public static RuntimeConfigFramework ParseFromFrameworkRoot(JObject framework) + { + var properties = framework.Properties(); + + var name = properties.FirstOrDefault(p => p.Name.Equals("name", StringComparison.OrdinalIgnoreCase)); + var version = properties.FirstOrDefault(p => p.Name.Equals("version", StringComparison.OrdinalIgnoreCase)); + + if (name == null || version == null) + { + return null; + } + + return new RuntimeConfigFramework + { + Name = name.Value.ToString(), + Version = version.Value.ToString() + }; + } + } +} \ No newline at end of file diff --git a/test/Microsoft.DotNet.Tools.Tests.Utilities/TestBase.cs b/test/Microsoft.DotNet.Tools.Tests.Utilities/TestBase.cs index bb016d900..0d5f4a0a0 100644 --- a/test/Microsoft.DotNet.Tools.Tests.Utilities/TestBase.cs +++ b/test/Microsoft.DotNet.Tools.Tests.Utilities/TestBase.cs @@ -8,6 +8,7 @@ using System.Linq; using System.Threading.Tasks; using Microsoft.DotNet.Cli.Utils; using Microsoft.DotNet.TestFramework; +using Microsoft.DotNet.ProjectModel; namespace Microsoft.DotNet.Tools.Test.Utilities { @@ -111,6 +112,7 @@ namespace Microsoft.DotNet.Tools.Test.Utilities if (IsPortable(executablePath)) { + args.Add("exec"); args.Add(ArgumentEscaper.EscapeSingleArg(executablePath)); var muxer = new Muxer(); @@ -153,12 +155,19 @@ namespace Microsoft.DotNet.Tools.Test.Utilities private bool IsPortable(string executablePath) { - var executableDir = Path.GetDirectoryName(executablePath); + var commandDir = Path.GetDirectoryName(executablePath); - var runtimeConfig = Directory.EnumerateFiles(executableDir) + var runtimeConfigPath = Directory.EnumerateFiles(commandDir) .FirstOrDefault(x => x.EndsWith("runtimeconfig.json")); - return runtimeConfig != null; + if (runtimeConfigPath == null) + { + return false; + } + + var runtimeConfig = new RuntimeConfig(runtimeConfigPath); + Console.WriteLine(runtimeConfig.Framework); + return runtimeConfig.IsPortable; } } } diff --git a/test/Microsoft.DotNet.Tools.Tests.Utilities/project.json b/test/Microsoft.DotNet.Tools.Tests.Utilities/project.json index ac4cff52e..2463caa8f 100644 --- a/test/Microsoft.DotNet.Tools.Tests.Utilities/project.json +++ b/test/Microsoft.DotNet.Tools.Tests.Utilities/project.json @@ -12,6 +12,7 @@ "dotnet-test-xunit": "1.0.0-dev-91790-12", "Microsoft.DotNet.TestFramework": "1.0.0-*", "Microsoft.DotNet.Cli.Utils": "1.0.0-*", + "Microsoft.DotNet.ProjectModel": "1.0.0-*", "Microsoft.Extensions.PlatformAbstractions": "1.0.0-rc2-16537", "Microsoft.DotNet.InternalAbstractions": { "target": "project",