From 40eba07f289129633f8c5d16ffc3e246012d8e35 Mon Sep 17 00:00:00 2001 From: Andrew Stanton-Nurse Date: Thu, 15 Oct 2015 12:18:45 -0700 Subject: [PATCH] add some bootstrap scripting --- Microsoft.DotNet.Cli.sln | 26 ++--- NuGet.Config | 3 + bootstrap.cmd | 55 ---------- scripts/bootstrap.cmd | 100 ++++++++++++++++++ scripts/{bootstrap => dnxhost}/dotnet-compile | 0 .../{bootstrap => dnxhost}/dotnet-compile.cmd | 0 scripts/{bootstrap => dnxhost}/dotnet-publish | 0 .../{bootstrap => dnxhost}/dotnet-publish.cmd | 0 src/Microsoft.DotNet.Cli.Utils/Command.cs | 57 ++++++++-- src/Microsoft.DotNet.Tools.Publish/Program.cs | 8 ++ 10 files changed, 169 insertions(+), 80 deletions(-) delete mode 100644 bootstrap.cmd create mode 100644 scripts/bootstrap.cmd rename scripts/{bootstrap => dnxhost}/dotnet-compile (100%) rename scripts/{bootstrap => dnxhost}/dotnet-compile.cmd (100%) rename scripts/{bootstrap => dnxhost}/dotnet-publish (100%) rename scripts/{bootstrap => dnxhost}/dotnet-publish.cmd (100%) diff --git a/Microsoft.DotNet.Cli.sln b/Microsoft.DotNet.Cli.sln index 525d8e8e4..e51673c71 100644 --- a/Microsoft.DotNet.Cli.sln +++ b/Microsoft.DotNet.Cli.sln @@ -19,26 +19,21 @@ Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.DotNet.Tools.Comp EndProject Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.DotNet.Tools.Publish", "src\Microsoft.DotNet.Tools.Publish\Microsoft.DotNet.Tools.Publish.xproj", "{391D6AD6-0FD5-4E1E-A4C8-6B5439D197B5}" EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "samples", "samples", "{13F8C30C-1011-459C-82B2-0ACDD73EDA18}" +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "scripts", "scripts", "{13F8C30C-1011-459C-82B2-0ACDD73EDA18}" ProjectSection(SolutionItems) = preProject - scripts\dotnet = scripts\dotnet - scripts\dotnet-compile = scripts\dotnet-compile - scripts\dotnet-compile.cmd = scripts\dotnet-compile.cmd - scripts\dotnet-publish = scripts\dotnet-publish - scripts\dotnet-publish.cmd = scripts\dotnet-publish.cmd - scripts\dotnet-resolve-references = scripts\dotnet-resolve-references - scripts\dotnet-resolve-references.cmd = scripts\dotnet-resolve-references.cmd - scripts\dotnet-resolve-sources = scripts\dotnet-resolve-sources - scripts\dotnet-resolve-sources.cmd = scripts\dotnet-resolve-sources.cmd - scripts\dotnet-restore = scripts\dotnet-restore - scripts\dotnet-restore.cmd = scripts\dotnet-restore.cmd - scripts\dotnet-run = scripts\dotnet-run - scripts\dotnet-run.cmd = scripts\dotnet-run.cmd - scripts\dotnet.cmd = scripts\dotnet.cmd + scripts\bootstrap.cmd = scripts\bootstrap.cmd EndProjectSection EndProject Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.Extensions.ProjectModel", "src\Microsoft.Extensions.ProjectModel\Microsoft.Extensions.ProjectModel.xproj", "{303677D5-7312-4C3F-BAEE-BEB1A9BD9FE6}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "bootstrap", "bootstrap", "{07731125-77D7-4B83-B7B2-C865C6B8A6E8}" + ProjectSection(SolutionItems) = preProject + scripts\bootstrap\dotnet-compile = scripts\bootstrap\dotnet-compile + scripts\bootstrap\dotnet-compile.cmd = scripts\bootstrap\dotnet-compile.cmd + scripts\bootstrap\dotnet-publish = scripts\bootstrap\dotnet-publish + scripts\bootstrap\dotnet-publish.cmd = scripts\bootstrap\dotnet-publish.cmd + EndProjectSection +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -75,5 +70,6 @@ Global {0A309227-A9D8-4DDF-88DD-326B57B04378} = {ED2FE3E2-F7E7-4389-8231-B65123F2076F} {391D6AD6-0FD5-4E1E-A4C8-6B5439D197B5} = {ED2FE3E2-F7E7-4389-8231-B65123F2076F} {303677D5-7312-4C3F-BAEE-BEB1A9BD9FE6} = {ED2FE3E2-F7E7-4389-8231-B65123F2076F} + {07731125-77D7-4B83-B7B2-C865C6B8A6E8} = {13F8C30C-1011-459C-82B2-0ACDD73EDA18} EndGlobalSection EndGlobal diff --git a/NuGet.Config b/NuGet.Config index 3bd706bd8..892f7c825 100644 --- a/NuGet.Config +++ b/NuGet.Config @@ -7,4 +7,7 @@ + + + diff --git a/bootstrap.cmd b/bootstrap.cmd deleted file mode 100644 index a89daa802..000000000 --- a/bootstrap.cmd +++ /dev/null @@ -1,55 +0,0 @@ -@echo off - -REM Build 'dotnet' using a version of 'dotnet' hosted on the DNX -REM The output of this is independent of DNX - -where dnvm >nul 2>nul -if %errorlevel% == 0 goto have_dnvm - -REM download dnvm -echo Installing dnvm (DNX is needed to bootstrap currently) ... -powershell -NoProfile -ExecutionPolicy unrestricted -Command "&{$Branch='dev';$wc=New-Object System.Net.WebClient;$wc.Proxy=[System.Net.WebRequest]::DefaultWebProxy;$wc.Proxy.Credentials=[System.Net.CredentialCache]::DefaultNetworkCredentials;Invoke-Expression ($wc.DownloadString('https://raw.githubusercontent.com/aspnet/Home/dev/dnvminstall.ps1'))}" - -:have_dnvm -echo Installing and use-ing the latest CoreCLR x64 DNX ... -call dnvm install -u latest -r coreclr -arch x64 -alias dotnet_bootstrap -if errorlevel 1 goto fail - -call dnvm use dotnet_bootstrap -r coreclr -arch x64 -if errorlevel 1 goto fail - -rd /s /q %~dp0artifacts\bootstrap -if errorlevel 1 goto fail - -echo Running 'dnu restore' to restore packages for DNX-hosted projects -call dnu restore "%~dp0src\Microsoft.DotNet.Cli" -if errorlevel 1 goto fail - -call dnu restore "%~dp0src\Microsoft.DotNet.Tools.Compiler" -if errorlevel 1 goto fail - -call dnu restore "%~dp0src\Microsoft.DotNet.Tools.Publish" -if errorlevel 1 goto fail - -echo Building basic dotnet tools using DNX-hosted version - -echo Building dotnet.exe ... -call "%~dp0scripts\bootstrap\dotnet-publish" --framework dnxcore50 --runtime win7-x64 --output "%~dp0artifacts\bootstrap" "%~dp0src\Microsoft.DotNet.Cli" -if errorlevel 1 goto fail - -echo Building dotnet-compile.exe ... -call "%~dp0scripts\bootstrap\dotnet-publish" --framework dnxcore50 --runtime win7-x64 --output "%~dp0artifacts\bootstrap" "%~dp0src\Microsoft.DotNet.Tools.Compiler" -if errorlevel 1 goto fail - -echo Building dotnet-publish.exe ... -call "%~dp0scripts\bootstrap\dotnet-publish" --framework dnxcore50 --runtime win7-x64 --output "%~dp0artifacts\bootstrap" "%~dp0src\Microsoft.DotNet.Tools.Publish" -if errorlevel 1 goto fail - -echo Bootstrapped 'dotnet' command is available in %~dp0artifacts\bootstrap -goto end - -:fail -echo Bootstrapping failed... -exit /B 1 - -:end \ No newline at end of file diff --git a/scripts/bootstrap.cmd b/scripts/bootstrap.cmd new file mode 100644 index 000000000..3a434e587 --- /dev/null +++ b/scripts/bootstrap.cmd @@ -0,0 +1,100 @@ +@echo off + +setlocal + +REM Build 'dotnet' using a version of itself hosted on the DNX +REM The output of this is independent of DNX + +REM This trick gets the absolute path from a relative path +pushd %~dp0.. +set REPOROOT=%CD% +popd + +set STAGE1_DIR=%REPOROOT%\artifacts\stage1 +set STAGE2_DIR=%REPOROOT%\artifacts\stage2 +set DOTNET_PUBLISH=%REPOROOT%\scripts\dnxhost\dotnet-publish.cmd + +REM TEMPORARY! +if not defined DOTNET_CORE_CONSOLE_PATH ( + if exist "%REPOROOT%\..\coreclr" ( + set DOTNET_CORE_CONSOLE_PATH=%REPOROOT%\..\coreclr\bin\Product\Windows_NT.x64.Debug\CoreConsole.exe + ) +) +if not exist "%DOTNET_CORE_CONSOLE_PATH%" goto missing_coreconsole + +where dnvm >nul 2>nul +if %errorlevel% == 0 goto have_dnvm + +REM download dnvm +echo Installing dnvm (DNX is needed to bootstrap currently) ... +powershell -NoProfile -ExecutionPolicy Unrestricted -Command "&{$Branch='dev';$wc=New-Object System.Net.WebClient;$wc.Proxy=[System.Net.WebRequest]::DefaultWebProxy;$wc.Proxy.Credentials=[System.Net.CredentialCache]::DefaultNetworkCredentials;Invoke-Expression ($wc.DownloadString('https://raw.githubusercontent.com/aspnet/Home/dev/dnvminstall.ps1'))}" + +:have_dnvm +echo Installing and use-ing the latest CoreCLR x64 DNX ... +call dnvm install -u latest -r coreclr -arch x64 -alias dotnet_bootstrap +if errorlevel 1 goto fail + +call dnvm use dotnet_bootstrap -r coreclr -arch x64 +if errorlevel 1 goto fail + +if exist %STAGE1_DIR% rd /s /q %STAGE1_DIR% + +echo Running 'dnu restore' to restore packages for DNX-hosted projects +call dnu restore "%REPOROOT%\src\Microsoft.DotNet.Cli" +if errorlevel 1 goto fail + +call dnu restore "%REPOROOT%\src\Microsoft.DotNet.Tools.Compiler" +if errorlevel 1 goto fail + +call dnu restore "%REPOROOT%\src\Microsoft.DotNet.Tools.Publish" +if errorlevel 1 goto fail + +echo Building basic dotnet tools using DNX-hosted version + +echo Building stage1 dotnet.exe ... +call "%DOTNET_PUBLISH%" --framework dnxcore50 --runtime win7-x64 --output "%STAGE1_DIR%" "%REPOROOT%\src\Microsoft.DotNet.Cli" +if errorlevel 1 goto fail + +echo Building stage1 dotnet-compile.exe ... +call "%DOTNET_PUBLISH%" --framework dnxcore50 --runtime win7-x64 --output "%STAGE1_DIR%" "%REPOROOT%\src\Microsoft.DotNet.Tools.Compiler" +if errorlevel 1 goto fail + +echo Building stage1 dotnet-publish.exe ... +call "%DOTNET_PUBLISH%" --framework dnxcore50 --runtime win7-x64 --output "%STAGE1_DIR%" "%REPOROOT%\src\Microsoft.DotNet.Tools.Publish" +if errorlevel 1 goto fail + +echo Re-building dotnet tools with the bootstrapped version +REM This should move into a proper build script of some kind once we are bootstrapped +set PATH=%STAGE1_DIR%;%PATH% + +if exist %STAGE2_DIR% rd /s /q %STAGE2_DIR% + +echo Building stage2 dotnet.exe ... +dotnet publish --framework dnxcore50 --runtime win7-x64 --output "%STAGE2_DIR%" "%REPOROOT%\src\Microsoft.DotNet.Cli" +if errorlevel 1 goto fail + +echo Building stage2 dotnet-compile.exe ... +dotnet publish --framework dnxcore50 --runtime win7-x64 --output "%STAGE2_DIR%" "%REPOROOT%\src\Microsoft.DotNet.Tools.Compiler" +if errorlevel 1 goto fail + +echo Building stage2 dotnet-publish.exe ... +dotnet publish --framework dnxcore50 --runtime win7-x64 --output "%STAGE2_DIR%" "%REPOROOT%\src\Microsoft.DotNet.Tools.Publish" +if errorlevel 1 goto fail + +echo Bootstrapped dotnet to %STAGE2_DIR% + +goto end + +:fail +echo Bootstrapping failed... +exit /B 1 + +:missing_coreconsole +echo Bootstrapping temporarily requires a patched CoreConsole to workaround +echo this issue: https://github.com/dotnet/coreclr/issues/1771 +echo Either clone dotnet/coreclr to a sibling directory of this repo called +echo "coreclr" and build it, or put the path to the patched version of +echo CoreConsole in the DOTNET_CORE_CONSOLE_PATH environment variable +exit /B 1 + +:end \ No newline at end of file diff --git a/scripts/bootstrap/dotnet-compile b/scripts/dnxhost/dotnet-compile similarity index 100% rename from scripts/bootstrap/dotnet-compile rename to scripts/dnxhost/dotnet-compile diff --git a/scripts/bootstrap/dotnet-compile.cmd b/scripts/dnxhost/dotnet-compile.cmd similarity index 100% rename from scripts/bootstrap/dotnet-compile.cmd rename to scripts/dnxhost/dotnet-compile.cmd diff --git a/scripts/bootstrap/dotnet-publish b/scripts/dnxhost/dotnet-publish similarity index 100% rename from scripts/bootstrap/dotnet-publish rename to scripts/dnxhost/dotnet-publish diff --git a/scripts/bootstrap/dotnet-publish.cmd b/scripts/dnxhost/dotnet-publish.cmd similarity index 100% rename from scripts/bootstrap/dotnet-publish.cmd rename to scripts/dnxhost/dotnet-publish.cmd diff --git a/src/Microsoft.DotNet.Cli.Utils/Command.cs b/src/Microsoft.DotNet.Cli.Utils/Command.cs index baf40a800..69caf84c6 100644 --- a/src/Microsoft.DotNet.Cli.Utils/Command.cs +++ b/src/Microsoft.DotNet.Cli.Utils/Command.cs @@ -11,8 +11,6 @@ namespace Microsoft.DotNet.Cli.Utils { public class Command { - private static readonly string[] WindowsExecutableExtensions = new[] { "exe", "cmd", "bat" }; - private TaskCompletionSource _processTcs; private Process _process; @@ -53,9 +51,14 @@ namespace Microsoft.DotNet.Cli.Utils public static Command Create(string executable, string args) { - var comSpec = Environment.GetEnvironmentVariable("ComSpec"); - if (!string.IsNullOrEmpty(comSpec)) + // On Windows, we want to avoid using "cmd" if possible (it mangles the colors, and a bunch of other things) + // So, do a quick path search to see if we can just directly invoke it + var useCmd = ShouldUseCmd(executable); + + if (useCmd) { + var comSpec = Environment.GetEnvironmentVariable("ComSpec"); + // cmd doesn't like "foo.exe ", so we need to ensure that if // args is empty, we just run "foo.exe" if (!string.IsNullOrEmpty(args)) @@ -67,16 +70,50 @@ namespace Microsoft.DotNet.Cli.Utils args = $"/C \"{executable}{args}\""; executable = comSpec; } - else - { - // Temporary, we're doing this so that redirecting the output works - args = $"bash -c \"{executable} {args.Replace("\"", "\\\"")}\""; - executable = "/usr/bin/env"; - } return new Command(executable, args); } + private static bool ShouldUseCmd(string executable) + { + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + var extension = Path.GetExtension(executable); + if (!string.IsNullOrEmpty(executable)) + { + return string.Equals(executable, ".exe", StringComparison.Ordinal); + } + else if (executable.Contains(Path.DirectorySeparatorChar)) + { + // It's a relative path without an extension + if (File.Exists(executable + ".exe")) + { + // It refers to an exe! + return false; + } + } + else + { + // Search the path to see if we can find it + foreach (var path in Environment.GetEnvironmentVariable("PATH").Split(Path.PathSeparator)) + { + var candidate = Path.Combine(path, executable + ".exe"); + if (File.Exists(candidate)) + { + // We found an exe! + return false; + } + } + } + + // It's a non-exe :( + return true; + } + + // Non-windows never uses cmd + return false; + } + public async Task RunAsync() { ThrowIfRunning(); diff --git a/src/Microsoft.DotNet.Tools.Publish/Program.cs b/src/Microsoft.DotNet.Tools.Publish/Program.cs index b7e749815..e38f6269e 100644 --- a/src/Microsoft.DotNet.Tools.Publish/Program.cs +++ b/src/Microsoft.DotNet.Tools.Publish/Program.cs @@ -115,6 +115,14 @@ namespace Microsoft.DotNet.Tools.Publish return 1; } + // Allow CoreConsole to be replaced + string overrideCoreConsole = Environment.GetEnvironmentVariable("DOTNET_CORE_CONSOLE_PATH"); + if(!string.IsNullOrEmpty(overrideCoreConsole) && File.Exists(overrideCoreConsole)) + { + Console.WriteLine($"Using CoreConsole override: {overrideCoreConsole}"); + File.Copy(overrideCoreConsole, coreConsole, overwrite: true); + } + // Use the 'command' field to generate the name var outputExe = Path.Combine(outputPath, context.Project.Name + ".exe"); if (File.Exists(outputExe))