diff --git a/ext/CLRHost/osx.10.10-x64/coreconsole b/ext/CLRHost/osx.10.10-x64/coreconsole new file mode 100755 index 000000000..582f45312 Binary files /dev/null and b/ext/CLRHost/osx.10.10-x64/coreconsole differ diff --git a/ext/CLRHost/osx.10.10-x64/corerun b/ext/CLRHost/osx.10.10-x64/corerun new file mode 100755 index 000000000..bbadef994 Binary files /dev/null and b/ext/CLRHost/osx.10.10-x64/corerun differ diff --git a/scripts/bootstrap b/scripts/bootstrap new file mode 100755 index 000000000..33b28fcb9 --- /dev/null +++ b/scripts/bootstrap @@ -0,0 +1,58 @@ +#!/usr/bin/env bash + +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 )" +REPOROOT="$( cd -P "$DIR/.." && pwd )" + +echo "Bootstrapping dotnet.exe using DNX" + +UNAME=$(uname) +if [ "$UNAME" == "Darwin" ]; then + RID=osx.10.10-x64 +elif [ "$UNAME" == "Linux" ]; then + # Detect Distro? + RID=ubuntu.14.04-x64 +else + echo "Unknown OS: $UNAME" 1>&2 + exit 1 +fi + +OUTPUT_ROOT=$REPOROOT/artifacts/$RID +STAGE1_DIR=$OUTPUT_ROOT/stage1 +STAGE2_DIR=$OUTPUT_ROOT/stage2 + +STAGE0_PUBLISH=$REPOROOT/scripts/stage0/dotnet-publish + +export DOTNET_CLR_HOSTS_PATH=$REPOROOT/ext/CLRHost/$RID +export DOTNET_CSC_PATH=$REPOROOT/src/cscthingy/bin/Debug/dnxcore50/publish + +type -p dnx >/dev/null +if [ ! $? ]; then + echo "DNX is required to bootstrap stage1" 1>&2 + exit 1 +fi + +echo "Running 'dnu restore' to restore packages for DNX-hosted projects" + +dnu restore "$REPOROOT" --runtime osx.10.10-x64 --runtime osx.10.11-x64 + +# Clean up stage1 +[ -d "$STAGE1_DIR" ] && rm -Rf "$STAGE1_DIR" + +echo "Building basic dotnet tools using Stage 0 (DNX hosted)" +$STAGE0_PUBLISH --framework dnxcore50 --runtime $RID --output "$STAGE1_DIR" "$REPOROOT/src/Microsoft.DotNet.Cli" +$STAGE0_PUBLISH --framework dnxcore50 --runtime $RID --output "$STAGE1_DIR" "$REPOROOT/src/Microsoft.DotNet.Tools.Compiler" +$STAGE0_PUBLISH --framework dnxcore50 --runtime $RID --output "$STAGE1_DIR" "$REPOROOT/src/Microsoft.DotNet.Tools.Publish" + +# Add stage1 to the path and use it to build stage2 +export PATH=$STAGE1_DIR:$PATH + +echo "Building stage2 dotnet using stage1 ..." +dotnet publish --framework dnxcore50 --runtime $RID --output "$STAGE2_DIR" "$REPOROOT/src/Microsoft.DotNet.Cli" +dotnet publish --framework dnxcore50 --runtime $RID --output "$STAGE2_DIR" "$REPOROOT/src/Microsoft.DotNet.Tools.Compiler" +dotnet publish --framework dnxcore50 --runtime $RID --output "$STAGE2_DIR" "$REPOROOT/src/Microsoft.DotNet.Tools.Publish" diff --git a/scripts/bootstrap.cmd b/scripts/bootstrap.cmd index a87b8a1ba..3278670f8 100644 --- a/scripts/bootstrap.cmd +++ b/scripts/bootstrap.cmd @@ -93,4 +93,4 @@ goto end echo Bootstrapping failed... exit /B 1 -:end \ No newline at end of file +:end diff --git a/scripts/dnxhost/dotnet-compile b/scripts/stage0/dotnet-compile old mode 100644 new mode 100755 similarity index 100% rename from scripts/dnxhost/dotnet-compile rename to scripts/stage0/dotnet-compile diff --git a/scripts/dnxhost/dotnet-compile.cmd b/scripts/stage0/dotnet-compile.cmd similarity index 100% rename from scripts/dnxhost/dotnet-compile.cmd rename to scripts/stage0/dotnet-compile.cmd diff --git a/scripts/dnxhost/dotnet-publish b/scripts/stage0/dotnet-publish old mode 100644 new mode 100755 similarity index 100% rename from scripts/dnxhost/dotnet-publish rename to scripts/stage0/dotnet-publish diff --git a/scripts/dnxhost/dotnet-publish.cmd b/scripts/stage0/dotnet-publish.cmd similarity index 100% rename from scripts/dnxhost/dotnet-publish.cmd rename to scripts/stage0/dotnet-publish.cmd diff --git a/src/Microsoft.DotNet.Cli.Utils/Constants.cs b/src/Microsoft.DotNet.Cli.Utils/Constants.cs index f7ff6d8ce..c47537c58 100644 --- a/src/Microsoft.DotNet.Cli.Utils/Constants.cs +++ b/src/Microsoft.DotNet.Cli.Utils/Constants.cs @@ -2,17 +2,20 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; +using System.Runtime.InteropServices; namespace Microsoft.DotNet.Cli.Utils { internal static class Constants { // TODO: On Unix, exe suffix is empty string... - public static readonly string ExeSuffix = ".exe"; + public static readonly string ExeSuffix = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? ".exe" : ""; public static readonly string CoreConsoleName = "coreconsole" + ExeSuffix; + public static readonly string CoreRunName = "corerun" + ExeSuffix; public static readonly string DefaultConfiguration = "Debug"; public static readonly string BinDirectoryName = "bin"; public static readonly string HostsPathEnvironmentVariable = "DOTNET_CLR_HOSTS_PATH"; + public static readonly string CSCPathEnvironmentVariable = "DOTNET_CSC_PATH"; } } diff --git a/src/Microsoft.DotNet.Tools.Compiler/Program.cs b/src/Microsoft.DotNet.Tools.Compiler/Program.cs index 3086b70b7..c6f892803 100644 --- a/src/Microsoft.DotNet.Tools.Compiler/Program.cs +++ b/src/Microsoft.DotNet.Tools.Compiler/Program.cs @@ -152,16 +152,16 @@ namespace Microsoft.DotNet.Tools.Compiler private static Command RunCsc(string cscArgs) { // Locate CoreRun - string hostRoot = Environment.GetEnvironmentVariable(Constants.HostsPathEnvironmentVariable); + string hostRoot = Environment.GetEnvironmentVariable("DOTNET_CSC_PATH"); if(string.IsNullOrEmpty(hostRoot)) { hostRoot = AppContext.BaseDirectory; } - var corerun = Path.Combine(hostRoot, "CoreRun.exe"); - var cscExe = Path.Combine(AppContext.BaseDirectory, "csc.exe"); + var corerun = Path.Combine(hostRoot, Constants.CoreRunName); + var cscExe = Path.Combine(hostRoot, "csc.exe"); return File.Exists(corerun) && File.Exists(cscExe) ? Command.Create(corerun, $@"""{cscExe}"" {cscArgs}") - : Command.Create("csc.exe", cscArgs); + : Command.Create("csc", cscArgs); } private static void ApplyCompilationOptions(CompilerOptions compilationOptions, List cscArgs) diff --git a/src/Microsoft.DotNet.Tools.Publish/Program.cs b/src/Microsoft.DotNet.Tools.Publish/Program.cs index e29a49eec..ad0e5ff0a 100644 --- a/src/Microsoft.DotNet.Tools.Publish/Program.cs +++ b/src/Microsoft.DotNet.Tools.Publish/Program.cs @@ -115,8 +115,23 @@ namespace Microsoft.DotNet.Tools.Publish } // Publishing for windows, TODO(anurse): Publish for Mac/Linux/etc. + int exitCode; + if(context.RuntimeIdentifier.Equals("win7-x64")) + { + exitCode = PublishForWindows(context, outputPath); + } + else + { + exitCode = PublishForUnix(context, outputPath); + } - // Locate CoreConsole + Reporter.Output.WriteLine($"Published to {outputPath}".Green().Bold()); + return exitCode; + } + + private static int PublishForUnix(ProjectContext context, string outputPath) + { + // Locate Hosts string hostsPath = Environment.GetEnvironmentVariable(Constants.HostsPathEnvironmentVariable); if(string.IsNullOrEmpty(hostsPath)) { @@ -125,15 +140,78 @@ namespace Microsoft.DotNet.Tools.Publish var coreConsole = Path.Combine(hostsPath, Constants.CoreConsoleName); if(!File.Exists(coreConsole)) { - Reporter.Error.WriteLine($"Unable to locate CoreConsole.exe in {coreConsole}, use {Constants.HostsPathEnvironmentVariable} to set the path to it.".Red().Bold()); + Reporter.Error.WriteLine($"Unable to locate {Constants.CoreConsoleName} in {coreConsole}, use {Constants.HostsPathEnvironmentVariable} to set the path to it.".Red().Bold()); + return 1; + } + var coreRun = Path.Combine(hostsPath, Constants.CoreRunName); + if(!File.Exists(coreRun)) + { + Reporter.Error.WriteLine($"Unable to locate {Constants.CoreRunName} in {coreConsole}, use {Constants.HostsPathEnvironmentVariable} to set the path to it.".Red().Bold()); return 1; } - // TEMPORARILY bring CoreConsole along for the ride on it's own (without renaming) + // TEMPORARILY bring CoreConsole and CoreRun along for the ride on it's own (without renaming) File.Copy(coreConsole, Path.Combine(outputPath, Constants.CoreConsoleName), overwrite: true); + File.Copy(coreRun, Path.Combine(outputPath, Constants.CoreRunName), overwrite: true); // Use the 'command' field to generate the name - var outputExe = Path.Combine(outputPath, context.ProjectFile.Name + ".exe"); + var outputExe = Path.Combine(outputPath, context.ProjectFile.Name); + var outputDll = Path.Combine(outputPath, context.ProjectFile.Name + ".dll"); + + // Check if the a command name is specified, and rename the necessary files + if(context.ProjectFile.Commands.Count == 1) + { + // Write a script that can be used to launch with CoreRun + var script = $@"#!/usr/bin/env bash +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 )"" +exec ""$DIR/corerun"" ""$DIR/{context.ProjectFile.Name}.exe"" $*"; + outputExe = Path.Combine(outputPath, context.ProjectFile.Commands.Single().Key); + File.WriteAllText(outputExe, script); + Command.Create("chmod", $"a+x {outputExe}") + .ForwardStdOut() + .ForwardStdErr() + .RunAsync() + .Wait(); + File.Copy(outputDll, Path.ChangeExtension(outputDll, ".exe")); + File.Delete(outputDll); + } + return 0; + } + + private static int PublishForWindows(ProjectContext context, string outputPath) + { + // Locate Hosts + string hostsPath = Environment.GetEnvironmentVariable(Constants.HostsPathEnvironmentVariable); + if(string.IsNullOrEmpty(hostsPath)) + { + hostsPath = AppContext.BaseDirectory; + } + var coreConsole = Path.Combine(hostsPath, Constants.CoreConsoleName); + if(!File.Exists(coreConsole)) + { + Reporter.Error.WriteLine($"Unable to locate {Constants.CoreConsoleName} in {coreConsole}, use {Constants.HostsPathEnvironmentVariable} to set the path to it.".Red().Bold()); + return 1; + } + var coreRun = Path.Combine(hostsPath, Constants.CoreRunName); + if(!File.Exists(coreRun)) + { + Reporter.Error.WriteLine($"Unable to locate {Constants.CoreRunName} in {coreConsole}, use {Constants.HostsPathEnvironmentVariable} to set the path to it.".Red().Bold()); + return 1; + } + + // TEMPORARILY bring CoreConsole and CoreRun along for the ride on it's own (without renaming) + File.Copy(coreConsole, Path.Combine(outputPath, Constants.CoreConsoleName), overwrite: true); + File.Copy(coreRun, Path.Combine(outputPath, Constants.CoreRunName), overwrite: true); + + // Use the 'command' field to generate the name + var outputExe = Path.Combine(outputPath, context.ProjectFile.Name + Constants.ExeSuffix); + var outputDll = Path.Combine(outputPath, context.ProjectFile.Name + ".dll"); File.Copy(coreConsole, outputExe, overwrite: true); // Check if the a command name is specified, and rename the necessary files @@ -149,11 +227,9 @@ namespace Microsoft.DotNet.Tools.Publish File.Delete(renamedExe); } File.Move(outputExe, renamedExe); - File.Move(Path.ChangeExtension(outputExe, ".dll"), renamedDll); + File.Move(outputDll, renamedDll); outputExe = Path.Combine(outputPath, commandName + ".exe"); } - - Reporter.Output.WriteLine($"Published to {outputExe}".Green().Bold()); return 0; } diff --git a/src/cscthingy/project.json b/src/cscthingy/project.json new file mode 100644 index 000000000..5a67941c7 --- /dev/null +++ b/src/cscthingy/project.json @@ -0,0 +1,13 @@ +{ + "version": "1.0.0-*", + "dependencies": { + "Microsoft.NETCore.TestHost": "1.0.0-*", + "Microsoft.NETCore.ConsoleHost": "1.0.0-*", + "Microsoft.NETCore.Runtime": "1.0.1-*", + "Microsoft.Net.Compilers.netcore": "1.1.0-*", + "System.Xml.ReaderWriter": "4.0.11-*" + }, + "frameworks": { + "dnxcore50": { } + } +}