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))