From 3e6551f80d7c0e7e335f33511661cecd663cde2b Mon Sep 17 00:00:00 2001 From: Victor Hurdugaci Date: Tue, 15 Dec 2015 11:53:41 -0800 Subject: [PATCH] Move KoreBuild-dotnet from release --- KoreBuild-dotnet/build/KoreBuild.cmd | 43 +++ KoreBuild-dotnet/build/KoreBuild.sh | 43 +++ KoreBuild-dotnet/build/_dnx-test.shade | 85 ++++++ KoreBuild-dotnet/build/_dnx.shade | 30 ++ KoreBuild-dotnet/build/_dotnet-publish.shade | 29 ++ KoreBuild-dotnet/build/_dotnet-test.shade | 33 +-- .../build/_k-standard-goals.shade | 23 +- KoreBuild-dotnet/build/dotnet-install.cmd | 10 + KoreBuild-dotnet/build/dotnet-install.ps1 | 91 ++++++ KoreBuild-dotnet/build/dotnet-install.sh | 262 ++++++++++++++++++ .../build}/makefile.shade | 0 build-template-dotnet/.gitignore | 1 + build-template-dotnet/build.cmd | 78 +++--- build-template-dotnet/build.sh | 47 ++-- 14 files changed, 674 insertions(+), 101 deletions(-) create mode 100644 KoreBuild-dotnet/build/KoreBuild.cmd create mode 100644 KoreBuild-dotnet/build/KoreBuild.sh create mode 100644 KoreBuild-dotnet/build/_dnx-test.shade create mode 100644 KoreBuild-dotnet/build/_dnx.shade create mode 100644 KoreBuild-dotnet/build/_dotnet-publish.shade create mode 100644 KoreBuild-dotnet/build/dotnet-install.cmd create mode 100644 KoreBuild-dotnet/build/dotnet-install.ps1 create mode 100644 KoreBuild-dotnet/build/dotnet-install.sh rename {build-template-dotnet => KoreBuild-dotnet/build}/makefile.shade (100%) diff --git a/KoreBuild-dotnet/build/KoreBuild.cmd b/KoreBuild-dotnet/build/KoreBuild.cmd new file mode 100644 index 0000000000..3d6936480e --- /dev/null +++ b/KoreBuild-dotnet/build/KoreBuild.cmd @@ -0,0 +1,43 @@ +@ECHO off +SETLOCAL + +IF "%KOREBUILD_FOLDER%"=="" ( + ECHO Error: KOREBUILD_FOLDER is not set. + EXIT /B 1 +) +IF "%NUGET_PATH%"=="" ( + ECHO Error: NUGET_PATH is not set. + EXIT /B 1 +) + +IF NOT EXIST Sake ( + "%NUGET_PATH%" install Sake -ExcludeVersion -Source https://api.nuget.org/v3/index.json -o %~dp0 +) + +SET DOTNET_LOCAL_INSTALL_FOLDER=%LOCALAPPDATA%\Microsoft\dotnet\cli\bin + +CALL %~dp0dotnet-install.cmd +ECHO Adding %DOTNET_LOCAL_INSTALL_FOLDER% to PATH +SET PATH=%DOTNET_LOCAL_INSTALL_FOLDER%;%PATH% +SET DOTNET_HOME=%DOTNET_LOCAL_INSTALL_FOLDER% + +REM ==== Temporary because we need 'dnu packages add' ==== +IF "%BUILDCMD_DNX_VERSION%"=="" ( + SET BUILDCMD_DNX_VERSION=latest +) +IF "%SKIP_DNX_INSTALL%"=="" ( + CALL %KOREBUILD_FOLDER%\build\dnvm install %BUILDCMD_DNX_VERSION% -runtime CoreCLR -arch x86 -alias default + CALL %KOREBUILD_FOLDER%\build\dnvm install default -runtime CLR -arch x86 -alias default +) ELSE ( + CALL %KOREBUILD_FOLDER%\build\dnvm use default -runtime CLR -arch x86 +) +REM ============================ + +SET MAKEFILE_PATH=makefile.shade +IF NOT EXIST %MAKEFILE_PATH% ( + SET MAKEFILE_PATH=%KOREBUILD_FOLDER%\build\makefile.shade +) +ECHO Using makefile: %MAKEFILE_PATH% + +REM Don't use full paths. Sake doesn't support them! +"%~dp0Sake\tools\Sake.exe" -I %KOREBUILD_FOLDER%\build -f %MAKEFILE_PATH% %* \ No newline at end of file diff --git a/KoreBuild-dotnet/build/KoreBuild.sh b/KoreBuild-dotnet/build/KoreBuild.sh new file mode 100644 index 0000000000..07d587b1fc --- /dev/null +++ b/KoreBuild-dotnet/build/KoreBuild.sh @@ -0,0 +1,43 @@ +#!/usr/bin/env bash + +if [ -z "$koreBuildFolder" ]; then + echo "koreBuildFolder is not set." + exit 1 +fi + +if [ -z "$nugetPath" ]; then + echo "nugetPath is not set." + exit 1 +fi + +sakeFolder=$koreBuildFolder/build/Sake + +if test ! -d $sakeFolder; then + mono $nugetPath install Sake -ExcludeVersion -o $koreBuildFolder/build -nocache -pre +fi + +# Need to set this variable because by default the install script +# requires sudo +export DOTNET_INSTALL_DIR=~/.dotnet +export PATH=$DOTNET_INSTALL_DIR/bin:$PATH +export DOTNET_HOME=DOTNET_INSTALL_DIR +source $koreBuildFolder/build/dotnet-install.sh + +makefilePath=makefile.shade +if test ! -f $makefilePath; then + makefilePath=$koreBuildFolder/build/makefile.shade +fi + +# ==== Temporary because we need 'dnu packages add' ==== +if ! type dnvm > /dev/null 2>&1; then + source $koreBuildFolder/build/dnvm.sh +fi +if ! type dnx > /dev/null 2>&1 || [ -z "$SKIP_DNX_INSTALL" ]; then + dnvm install latest -runtime coreclr -alias default + dnvm install default -runtime mono -alias default +else + dnvm use default -runtime mono +fi +# ============ + +mono $koreBuildFolder/build/Sake/tools/Sake.exe -I $koreBuildFolder/build -f $makefilePath "$@" \ No newline at end of file diff --git a/KoreBuild-dotnet/build/_dnx-test.shade b/KoreBuild-dotnet/build/_dnx-test.shade new file mode 100644 index 0000000000..3c3d9fbf37 --- /dev/null +++ b/KoreBuild-dotnet/build/_dnx-test.shade @@ -0,0 +1,85 @@ +use import="Json" +use import="Environment" + +default NO_PARALLEL_TEST_PROJECTS='${E("NO_PARALLEL_TEST_PROJECTS")}' +default KOREBUILD_TEST_DNXCORE='${E("KOREBUILD_TEST_DNXCORE")}' +default KOREBUILD_TEST_SKIPMONO='${E("KOREBUILD_TEST_SKIPMONO")}' + +@{/* + +// ====== This file shall be removed eventually ==== + +dnx-test + Run unit tests in your project. + +projectFile='' + Required. Path to the test project.json to execute + +*/} + +@{ + Console.WriteLine("Project file: " + projectFile); + + var projectText = File.ReadAllText(projectFile); + var project = (JsonObject)Json.Deserialize(projectText); + + var commands = project.ValueAsJsonObject("commands"); + + if (commands != null && commands.Keys.Contains("test")) + { + var projectFolder = Path.GetDirectoryName(projectFile); + var projectName = Path.GetFileName(projectFolder); + + var noParallelTestProjects = new HashSet(StringComparer.OrdinalIgnoreCase); + if (!string.IsNullOrEmpty(NO_PARALLEL_TEST_PROJECTS)) + { + noParallelTestProjects.UnionWith(NO_PARALLEL_TEST_PROJECTS.Split((char)',')); + } + + var configs = project.ValueAsJsonObject("frameworks"); + IEnumerable targetFrameworks; + if (configs == null) + { + // Assume dnx451 only if none specified + targetFrameworks = new[] { "dnx451" }; + } + else + { + targetFrameworks = configs.Keys; + } + + // Currently only dnx* targets are supported. See aspnet/Universe#53 + targetFrameworks = targetFrameworks.Where(k => k.StartsWith("dnx", StringComparison.OrdinalIgnoreCase)); + + foreach (var framework in targetFrameworks) + { + var testArgs = noParallelTestProjects.Contains(projectName) ? " -parallel none" : ""; + + if (!framework.StartsWith("dnxcore", StringComparison.OrdinalIgnoreCase)) + { + if (IsLinux) + { + // Work around issue with testing in parallel on Mono. + testArgs = " -parallel none"; + } + + if (!IsLinux || + (!string.Equals(KOREBUILD_TEST_SKIPMONO, "1") && + !string.Equals(KOREBUILD_TEST_SKIPMONO, "true"))) + { + Dnx("test" + testArgs, projectFolder); + } + } + /* + Core CLR tests run with the new runner + + else if (!IsLinux || + string.Equals(KOREBUILD_TEST_DNXCORE, "1") || + string.Equals(KOREBUILD_TEST_DNXCORE, "true")) + { + Dnx("test" + testArgs, projectFolder, "default -runtime coreclr"); + } + */ + } + } +} \ No newline at end of file diff --git a/KoreBuild-dotnet/build/_dnx.shade b/KoreBuild-dotnet/build/_dnx.shade new file mode 100644 index 0000000000..e68258f2ed --- /dev/null +++ b/KoreBuild-dotnet/build/_dnx.shade @@ -0,0 +1,30 @@ +@{/* + +// ====== This file shall be removed eventually ==== + +k + Run dnx commands in your project. Executes `dnx` command. + +command='' + The `dnx` subcommand to execute. +dnxDir='' + Optional. The directory in which to execute the `dnx` command. +dnvmUse='' + Optional. The DNX framework to use. Suitable for a `dnvm run` or `dnvm use` command. +*/} + +default currentDir = '${Directory.GetCurrentDirectory()}' +default dnxDir = '${ currentDir }' + +default dnvmUse='' +var dnvmPath = '${ Path.Combine(Directory.GetCurrentDirectory(), ".build", "KoreBuild-dotnet", "build", "dnvm") }' + +exec program='cmd' commandline='/C dnx ${command}' workingdir='${dnxDir}' if='!IsLinux && string.IsNullOrEmpty(dnvmUse)' + +var cmdCommand = '/S /C ""${dnvmPath}.cmd" use ${dnvmUse} && dnx ${command}"' +exec program='cmd' commandline='${ cmdCommand }' workingdir='${dnxDir}' if='!IsLinux && !string.IsNullOrEmpty(dnvmUse)' + +exec program='dnx' commandline='${command}' workingdir='${dnxDir}' if='IsLinux && string.IsNullOrEmpty(dnvmUse)' + +var envCommand = 'bash -c "source \"${dnvmPath}.sh\" && dnvm use ${dnvmUse} && dnx ${command}"' +exec program='/usr/bin/env' commandline='${ envCommand }' workingdir='${dnxDir}' if='IsLinux && !string.IsNullOrEmpty(dnvmUse)' \ No newline at end of file diff --git a/KoreBuild-dotnet/build/_dotnet-publish.shade b/KoreBuild-dotnet/build/_dotnet-publish.shade new file mode 100644 index 0000000000..64253e7098 --- /dev/null +++ b/KoreBuild-dotnet/build/_dotnet-publish.shade @@ -0,0 +1,29 @@ +@{/* + +dotnet-publish + Builds package from project. + +projectFile='' + Required. Path to the project.json to build. + +outputFolder='' + Optional. The output folder. + +configuration='' + Optional. The configuration to build in. Defaults to 'Debug'. +*/} + +default configuration = 'Debug' + +@{ + var projectFolder=Path.GetDirectoryName(projectFile); + var projectName=Path.GetFileName(projectFolder); + var projectBin=Path.Combine(projectFolder, "bin", configuration); + + var outputArg = string.IsNullOrEmpty(outputFolder)? "": "-o " + outputFolder; + + DeleteFolder(projectBin); + + var dotnetArgs=string.Format("publish --configuration {0} {1} {2}", configuration, outputArg, projectFolder); + Dotnet(dotnetArgs); +} \ No newline at end of file diff --git a/KoreBuild-dotnet/build/_dotnet-test.shade b/KoreBuild-dotnet/build/_dotnet-test.shade index b1e67c55f1..550890dda4 100644 --- a/KoreBuild-dotnet/build/_dotnet-test.shade +++ b/KoreBuild-dotnet/build/_dotnet-test.shade @@ -19,9 +19,7 @@ projectFile='' var projectText = File.ReadAllText(projectFile); var project = (JsonObject)Json.Deserialize(projectText); - var commands = project.ValueAsJsonObject("commands"); - - if (commands != null && commands.Keys.Contains("test")) + if (project.Keys.Contains("testRunner")) { var projectFolder = Path.GetDirectoryName(projectFile); var projectName = Path.GetFileName(projectFolder); @@ -49,29 +47,14 @@ projectFile='' foreach (var framework in targetFrameworks) { - var testArgs = noParallelTestProjects.Contains(projectName) ? " -parallel none" : ""; - - Console.WriteLine("!!! Tests skipped for " + projectName); - if (!framework.StartsWith("dnxcore", StringComparison.OrdinalIgnoreCase)) + if (framework.StartsWith("dnxcore")) { - if (IsLinux) - { - // Work around issue with testing in parallel on Mono. - testArgs = " -parallel none"; - } - - if (!IsLinux || - (!string.Equals(KOREBUILD_TEST_SKIPMONO, "1") && - !string.Equals(KOREBUILD_TEST_SKIPMONO, "true"))) - { - // Dotnet("test" + testArgs, projectFolder); - } - } - else if (!IsLinux || - string.Equals(KOREBUILD_TEST_DNXCORE, "1") || - string.Equals(KOREBUILD_TEST_DNXCORE, "true")) - { - // Dotnet("test" + testArgs, projectFolder, "default -runtime coreclr"); + var publishFolder = Path.Combine(projectFolder, ".testPublish", framework); + DotnetPublish(projectFile, publishFolder); + + var runnerExe = Path.Combine(publishFolder, "dotnet-test-xunit.exe"); + var targetTestDll = Path.Combine(publishFolder, projectName + ".dll"); + Exec(runnerExe, targetTestDll); } } } diff --git a/KoreBuild-dotnet/build/_k-standard-goals.shade b/KoreBuild-dotnet/build/_k-standard-goals.shade index b16e60ac7d..6b848f7fb5 100644 --- a/KoreBuild-dotnet/build/_k-standard-goals.shade +++ b/KoreBuild-dotnet/build/_k-standard-goals.shade @@ -170,10 +170,12 @@ default NUGET_FEED = 'https://api.nuget.org/v3/index.json' var projectFiles = Files.Include("test/**/project.json").Exclude("**/bin/*/app/project.json").ToList(); if (ShouldRunInParallel) { + Parallel.ForEach(projectFiles, projectFile => DnxTest(projectFile, testParallel: true)); Parallel.ForEach(projectFiles, projectFile => DotnetTest(projectFile, testParallel: true)); } else { + projectFiles.ForEach(projectFile => DnxTest(projectFile, testParallel: false)); projectFiles.ForEach(projectFile => DotnetTest(projectFile, testParallel: false)); } } @@ -340,15 +342,34 @@ macro name="UpdateResx" resxFile='string' macro name="DotnetTest" projectFile='string' testParallel='bool' dotnet-test - + macro name="DotnetCompile" projectFile='string' configuration='string' dotnet-compile macro name="DotnetPack" projectFile='string' dotnetPackOutputDir='string' configuration='string' dotnet-pack +macro name="DotnetPublish" projectFile='string' outputFolder='string' + dotnet-publish + macro name="DeleteFolder" delete='string' directory macro name="CopyFolder" sourceDir='string' outputDir='string' overwrite='bool' copy + +@{ +// === EVERYTHING BELOW THIS LINE IS TEMPORARY === +} + +macro name='Dnx' command='string' + dnx + +macro name='Dnx' command='string' dnxDir='string' + dnx + +macro name='Dnx' command='string' dnxDir='string' dnvmUse='string' + dnx + +macro name="DnxTest" projectFile='string' testParallel='bool' + dnx-test \ No newline at end of file diff --git a/KoreBuild-dotnet/build/dotnet-install.cmd b/KoreBuild-dotnet/build/dotnet-install.cmd new file mode 100644 index 0000000000..8e54519450 --- /dev/null +++ b/KoreBuild-dotnet/build/dotnet-install.cmd @@ -0,0 +1,10 @@ +@Echo off + +for /f "delims=" %%i in ('PowerShell -NoProfile -NoLogo -ExecutionPolicy unrestricted -Command "[System.IO.Path]::GetTempFileName()"') do set INSTALL_CMD_PATH_FILE="%%i.cmd" + +PowerShell -NoProfile -NoLogo -ExecutionPolicy unrestricted -Command "[System.Threading.Thread]::CurrentThread.CurrentCulture = ''; [System.Threading.Thread]::CurrentThread.CurrentUICulture = '';$CmdPathFile='%INSTALL_CMD_PATH_FILE%';& '%~dp0dotnet-install.ps1' %*" + +IF EXIST %INSTALL_CMD_PATH_FILE% ( + CALL %INSTALL_CMD_PATH_FILE% + DEL %INSTALL_CMD_PATH_FILE% +) diff --git a/KoreBuild-dotnet/build/dotnet-install.ps1 b/KoreBuild-dotnet/build/dotnet-install.ps1 new file mode 100644 index 0000000000..8c187ba5a1 --- /dev/null +++ b/KoreBuild-dotnet/build/dotnet-install.ps1 @@ -0,0 +1,91 @@ +# +# 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. +# + +$ErrorActionPreference="Stop" +$ProgressPreference="SilentlyContinue" + +$Feed="https://dotnetcli.blob.core.windows.net/dotnet" +$Channel="dev" +$DotNetFileName="dotnet-win-x64.latest.zip" +$DotNetUrl="$Feed/$Channel/Binaries/Latest" + +function say($str) +{ + Write-Host "dotnet_install: $str" +} + +$InstallDir = $env:DOTNET_INSTALL_DIR +if (!$InstallDir) { + $InstallDir = "$env:LocalAppData\Microsoft\dotnet" +} + +say "Preparing to install .NET Tools to $InstallDir" + +# Check if we need to bother +$LocalFile = "$InstallDir\cli\.version" +if (Test-Path $LocalFile) +{ + $LocalData = @(cat $LocalFile) + $LocalHash = $LocalData[0].Trim() + $LocalVersion = $LocalData[1].Trim() + if ($LocalVersion -and $LocalHash) + { + $RemoteResponse = Invoke-WebRequest -UseBasicParsing "$Feed/$Channel/dnvm/latest.win.version" + $RemoteData = @([Text.Encoding]::UTF8.GetString($RemoteResponse.Content).Split()); + $RemoteHash = $RemoteData[0].Trim() + $RemoteVersion = $RemoteData[1].Trim() + + if (!$RemoteVersion -or !$RemoteHash) { + throw "Invalid response from feed" + } + + say "Latest version: $RemoteVersion" + say "Local Version: $LocalVersion" + + if($LocalHash -eq $RemoteHash) + { + say "You already have the latest version" + exit 0 + } + } +} + +# Set up the install location +if (!(Test-Path $InstallDir)) { + mkdir $InstallDir | Out-Null +} + +# De-powershell the path before passing to .NET APIs +$InstallDir = Convert-Path $InstallDir + +say "Downloading $DotNetFileName from $DotNetUrl" +$resp = Invoke-WebRequest -UseBasicParsing "$DotNetUrl/$DotNetFileName" -OutFile "$InstallDir\$DotNetFileName" + +say "Extracting zip" + +# Create the destination +if (Test-Path "$InstallDir\cli_new") { + del -rec -for "$InstallDir\cli_new" +} +mkdir "$InstallDir\cli_new" | Out-Null + +Add-Type -Assembly System.IO.Compression.FileSystem | Out-Null +[System.IO.Compression.ZipFile]::ExtractToDirectory("$InstallDir\$DotNetFileName", "$InstallDir\cli_new") + +# Replace the old installation (if any) +if (Test-Path "$InstallDir\cli") { + del -rec -for "$InstallDir\cli" +} +mv "$InstallDir\cli_new" "$InstallDir\cli" + +# Clean the zip +if (Test-Path "$InstallDir\$DotNetFileName") { + del -for "$InstallDir\$DotNetFileName" +} + +say "The .NET Tools have been installed to $InstallDir\cli!" + +# New layout +say "Add '$InstallDir\cli\bin' to your PATH to use dotnet" diff --git a/KoreBuild-dotnet/build/dotnet-install.sh b/KoreBuild-dotnet/build/dotnet-install.sh new file mode 100644 index 0000000000..5030b9e56d --- /dev/null +++ b/KoreBuild-dotnet/build/dotnet-install.sh @@ -0,0 +1,262 @@ +#!/usr/bin/env sh +# +# 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. +# + +# Note: This script should be compatible with the dash shell used in Ubuntu. So avoid bashisms! See https://wiki.ubuntu.com/DashAsBinSh for more info + +# This is a herestring Everything from the line AFTER the "read" until the line containing ONLY "EOF" is part of the string +# The quotes around "EOF" ensure that $ is not interpreted as a variable expansion. The indentation of the herestring must be +# kept exactly consistent +LINK_SCRIPT_CONTENT=$(cat <<-"EOF" +#!/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 )" + +if [ -z "$DOTNET_TOOLS" ]; then + # We should be in $PREFIX/bin, so just get the directory above us. + PREFIX="$( cd -P "$DIR/.." && pwd)" + + # The tools are in $PREFIX/share/dotnet/cli by default + DOTNET_TOOLS_DEFAULT=$PREFIX/share/dotnet/cli + + # Check the default location + if [ -d "$DOTNET_TOOLS_DEFAULT" ]; then + export DOTNET_TOOLS=$DOTNET_TOOLS_DEFAULT + else + echo "error: the .NET tools installation appears to be corrupt!" 1>&2 + echo "error: specifically, the tools could not be located in the $DOTNET_TOOLS_DEFAULT directory" 1>&2 + exit 1 + fi +fi + +MY_NAME=$(basename ${BASH_SOURCE[0]}) +MY_TARGET=$DOTNET_TOOLS/bin/$MY_NAME + +if [ ! -e "$MY_TARGET" ]; then + echo "error: the tool $MY_TARGET cannot be found" 1>&2 + exit 1 +fi + +if [ ! -x "$MY_TARGET" ]; then + echo "error: the tool $MY_TARGET is not executable" 1>&2 + exit 1 +fi + +exec "$MY_TARGET" "$@" +EOF +) + +#set default prefix (PREFIX is a fairly standard env-var, but we also want to allow the use the specific "DOTNET_INSTALL_DIR" one) +if [ ! -z "$DOTNET_INSTALL_DIR" ]; then + PREFIX=$DOTNET_INSTALL_DIR +elif [ -z "$PREFIX" ]; then + PREFIX=/usr/local +fi + +#setup some colors to use. These need to work in fairly limited shells, like the Ubuntu Docker container where there are only 8 colors. +#See if stdout is a terminal +if [ -t 1 ]; then + # see if it supports colors + ncolors=$(tput colors) + if [ -n "$ncolors" ] && [ $ncolors -ge 8 ]; then + bold="$(tput bold)" + normal="$(tput sgr0)" + black="$(tput setaf 0)" + red="$(tput setaf 1)" + green="$(tput setaf 2)" + yellow="$(tput setaf 3)" + blue="$(tput setaf 4)" + magenta="$(tput setaf 5)" + cyan="$(tput setaf 6)" + white="$(tput setaf 7)" + fi +fi + +#Standardise OS name to what is put into filenames of the tarballs. +current_os() +{ + local uname=$(uname) + if [ "$uname" = "Darwin" ]; then + echo "osx" + else + echo "linux" + fi +} + +machine_has() { + type "$1" > /dev/null 2>&1 + return $? +} + +#Not 100% sure at the moment that these checks are enough. We might need to take version into account or do something +#more complicated. This seemed like a good beginning though as it should catch the default "clean" machine case and give +#people an appropriate hint. +check_pre_reqs() { + local os=$(current_os) + local _failing=false; + + if [ "$DOTNET_INSTALL_SKIP_PREREQS" = "1" ]; then + return 0 + fi + + if [ "$os" = "linux" ]; then + [ -z "$(ldconfig -p | grep libunwind)" ] && say_err "Unable to locate libunwind. Install libunwind to continue" && _failing=true + [ -z "$(ldconfig -p | grep libssl)" ] && say_err "Unable to locate libssl. Install libssl to continue" && _failing=true + [ -z "$(ldconfig -p | grep libcurl)" ] && say_err "Unable to locate libcurl. Install libcurl to continue" && _failing=true + [ -z "$(ldconfig -p | grep libicu)" ] && say_err "Unable to locate libicu. Install libicu to continue" && _failing=true + [ -z "$(ldconfig -p | grep gettext)" ] && say_err "Unable to locate gettext. Install gettext to continue" && _failing=true + fi + + if [ "$_failing" = true ]; then + return 1 + fi +} + +say_err() { + printf "%b\n" "${red}dotnet_install: Error: $1${normal}" >&2 +} + +say() { + printf "%b\n" "dotnet_install: $1" +} + +make_link() { + local target_name=$1 + local dest=$PREFIX/bin/$target_name + say "Linking $dest -> $PREFIX/share/dotnet/cli/$target_name" + if [ -e $dest ]; then + rm $dest + fi + + [ -d "$PREFIX/bin" ] || mkdir -p $PREFIX/bin + + echo "$LINK_SCRIPT_CONTENT" > $dest + + # Make mode: rwxr-xr-x + chmod 755 $dest +} + +install_dotnet() +{ + if ! machine_has "curl"; then + printf "%b\n" "${red}curl is required to download dotnet. Install curl to proceed. ${normal}" >&2 + return 1 + fi + + say "Preparing to install .NET Tools to $PREFIX" + + if [ -e "$PREFIX/share/dotnet/cli/dotnet" ] && [ ! -w "$PREFIX/share/dotnet/cli/dotnet" ]; then + say_err "dotnet cli is already installed and not writeable. Use 'curl -sSL | sudo sh' to force install." + say_err "If you have previously installed the cli using a package manager or installer then that is why it is write protected, and you need to run sudo to install the new version." + say_err "Alternatively, removing the '$PREFIX/share/dotnet' directory completely before running the script will also resolve the issue." + return 1 + fi + + if ! check_pre_reqs; then + say_err "Ending install due to missing pre-reqs" + return 1; + fi + local os=$(current_os) + local installLocation="$PREFIX/share/dotnet" + local dotnet_url="https://dotnetcli.blob.core.windows.net/dotnet/dev/Binaries/Latest" + local dotnet_filename="dotnet-$os-x64.latest.tar.gz" + + if [ "$RELINK" = "0" ]; then + if [ "$FORCE" = "0" ]; then + # Check if we need to bother + local remoteData="$(curl -s https://dotnetcli.blob.core.windows.net/dotnet/dev/dnvm/latest.$os.version)" + [ $? != 0 ] && say_err "Unable to determine latest version." && return 1 + + local remoteVersion=$(IFS="\n" && echo $remoteData | tail -n 1) + local remoteHash=$(IFS="\n" && echo $remoteData | head -n 1) + + local localVersion=$(tail -n 1 "$installLocation/cli/.version" 2>/dev/null) + [ -z $localVersion ] && localVersion='' + local localHash=$(head -n 1 "$installLocation/cli/.version" 2>/dev/null) + + say "Latest Version: $remoteVersion" + say "Local Version: $localVersion" + + [ "$remoteHash" = "$localHash" ] && say "${green}You already have the latest version.${normal}" && return 0 + fi + + #This should noop if the directory already exists. + mkdir -p $installLocation + + say "Downloading $dotnet_filename from $dotnet_url" + + #Download file and check status code, error and return if we cannot download a cli tar. + local httpResult=$(curl -L -D - "$dotnet_url/$dotnet_filename" -o "$installLocation/$dotnet_filename" -# | grep "^HTTP/1.1" | head -n 1 | sed "s/HTTP.1.1 \([0-9]*\).*/\1/") + [ $httpResult -ne "302" ] && [ $httpResult -ne "200" ] && echo "${Red}HTTP Error $httpResult fetching the dotnet cli from $dotnet_url ${RCol}" && return 1 + + say "Extracting tarball" + #Any of these could fail for various reasons so we will check each one and end the script there if it fails. + rm -rf "$installLocation/cli_new" + mkdir "$installLocation/cli_new" + [ $? != 0 ] && say_err "failed to clean and create temporary cli directory to extract into" && return 1 + + tar -xzf "$installLocation/$dotnet_filename" -C "$installLocation/cli_new" + [ $? != 0 ] && say_err "failed to extract tar" && return 1 + + say "Moving new CLI into install location and symlinking" + + rm -rf "$installLocation/cli" + [ $? != 0 ] && say_err "Failed to clean current dotnet install" && return 1 + + mv "$installLocation/cli_new" "$installLocation/cli" + elif [ ! -e "$installLocation/cli" ]; then + say_err "${red}cannot relink dotnet, it is not installed in $PREFIX!" + return 1 + fi + + for f in $(find "$installLocation/cli" -regex ".*/dotnet[a-z\-]*$") + do + local baseFile=$(basename $f) + make_link $baseFile + done + + if [ -e "$installLocation/$dotnet_filename" ]; then + say "Cleaning $dotnet_filename" + if ! rm "$installLocation/$dotnet_filename"; then + say_err "Failed to delete tar after extracting." + return 1 + fi + fi +} + +FORCE=0 +RELINK=0 +while [ $# -ne 0 ] +do + if [ $1 = "-f" ] || [ $1 = "--force" ]; then + FORCE=1 + elif [ $1 = "-r" ] || [ $1 = "--relink" ]; then + RELINK=1 + elif [ $1 = "-?" ] || [ $1 = "-h" ] || [ $1 = "--help" ]; then + echo ".NET Tools Installer" + echo "" + echo "Usage:" + echo " $0 [-f]" + echo " $0 -r" + echo " $0 -h" + echo "" + echo "Options:" + echo " -f Force reinstallation even if you have the most recent version installed" + echo " -r Don't re-download, just recreate the links in $PREFIX/bin" + echo " -h Show this help message" + echo "" + echo "The PREFIX environment variable can be used to affect the root installation directory" + exit 0 + fi + shift +done + +install_dotnet diff --git a/build-template-dotnet/makefile.shade b/KoreBuild-dotnet/build/makefile.shade similarity index 100% rename from build-template-dotnet/makefile.shade rename to KoreBuild-dotnet/build/makefile.shade diff --git a/build-template-dotnet/.gitignore b/build-template-dotnet/.gitignore index c2e1708217..d679b4484b 100644 --- a/build-template-dotnet/.gitignore +++ b/build-template-dotnet/.gitignore @@ -6,6 +6,7 @@ TestResults/ _ReSharper.*/ packages/ artifacts/ +.build/ PublishProfiles/ *.user *.suo diff --git a/build-template-dotnet/build.cmd b/build-template-dotnet/build.cmd index c09dcb948c..72bcdff468 100644 --- a/build-template-dotnet/build.cmd +++ b/build-template-dotnet/build.cmd @@ -1,54 +1,40 @@ -@echo off -cd %~dp0 - +@ECHO off SETLOCAL -SET REPO_FOLDER=%CD% -SET DOTNET_INSTALL_DIR=%REPO_FOLDER%\packages +SET REPO_FOLDER=%~dp0 +CD %REPO_FOLDER% + +SET BUILD_FOLDER=.build +SET KOREBUILD_FOLDER=%BUILD_FOLDER%\KoreBuild-dotnet +SET KOREBUILD_VERSION= + +SET NUGET_PATH=%BUILD_FOLDER%\NuGet.exe SET NUGET_VERSION=latest SET CACHED_NUGET=%LocalAppData%\NuGet\nuget.%NUGET_VERSION%.exe -SET BUILDCMD_KOREBUILD_VERSION= -SET BUILDCMD_DNX_VERSION= -IF EXIST %CACHED_NUGET% goto copynuget -echo Downloading latest version of NuGet.exe... -IF NOT EXIST %LocalAppData%\NuGet md %LocalAppData%\NuGet -@powershell -NoProfile -ExecutionPolicy unrestricted -Command "$ProgressPreference = 'SilentlyContinue'; Invoke-WebRequest 'https://dist.nuget.org/win-x86-commandline/%NUGET_VERSION%/nuget.exe' -OutFile '%CACHED_NUGET%'" - -:copynuget -IF EXIST .nuget\nuget.exe goto getsake -md .nuget -copy %CACHED_NUGET% .nuget\nuget.exe > nul - -:getsake -IF EXIST packages\Sake goto skipgetsake -.nuget\NuGet.exe install Sake -ExcludeVersion -Source https://www.nuget.org/api/v2/ -Out packages -:skipgetsake - -:getkorebuild -IF EXIST packages\KoreBuild-dotnet goto skipgetkorebuild -IF "%BUILDCMD_KOREBUILD_VERSION%"=="" ( - .nuget\nuget.exe install KoreBuild-dotnet -ExcludeVersion -o packages -nocache -pre -) ELSE ( - .nuget\nuget.exe install KoreBuild-dotnet -version %BUILDCMD_KOREBUILD_VERSION% -ExcludeVersion -o packages -nocache -pre -) -:skipgetkorebuild - -REM Temporary because we need 'dnu packages add' -:getdnx -IF "%BUILDCMD_DNX_VERSION%"=="" ( - SET BUILDCMD_DNX_VERSION=latest -) -IF "%SKIP_DNX_INSTALL%"=="" ( - CALL packages\KoreBuild-dotnet\build\dnvm install %BUILDCMD_DNX_VERSION% -runtime CoreCLR -arch x86 -alias default - CALL packages\KoreBuild-dotnet\build\dnvm install default -runtime CLR -arch x86 -alias default -) ELSE ( - CALL packages\KoreBuild-dotnet\build\dnvm use default -runtime CLR -arch x86 +IF NOT EXIST %BUILD_FOLDER% ( + md %BUILD_FOLDER% ) -:getdotnet -SET DOTNET_INSTALL_DIR=packages -CALL packages\KoreBuild-dotnet\build\install.cmd -SET PATH=%DOTNET_INSTALL_DIR%\cli\bin;%PATH% +IF NOT EXIST %NUGET_PATH% ( + IF NOT EXIST %CACHED_NUGET% ( + echo Downloading latest version of NuGet.exe... + IF NOT EXIST %LocalAppData%\NuGet ( + md %LocalAppData%\NuGet + ) + @powershell -NoProfile -ExecutionPolicy unrestricted -Command "$ProgressPreference = 'SilentlyContinue'; Invoke-WebRequest 'https://dist.nuget.org/win-x86-commandline/%NUGET_VERSION%/nuget.exe' -OutFile '%CACHED_NUGET%'" + ) -packages\Sake\tools\Sake.exe -I packages\KoreBuild-dotnet\build -f makefile.shade %* + copy %CACHED_NUGET% %NUGET_PATH% > nul +) + +IF NOT EXIST %KOREBUILD_FOLDER% ( + SET KOREBUILD_DOWNLOAD_ARGS= + IF NOT "%KOREBUILD_VERSION%"=="" ( + SET KOREBUILD_DOWNLOAD_ARGS=-version %KOREBUILD_VERSION% + ) + + .nuget\nuget.exe install KoreBuild-dotnet -ExcludeVersion -o %BUILD_FOLDER% -nocache -pre %KOREBUILD_DOWNLOAD_ARGS% +) + +"%KOREBUILD_FOLDER%\build\KoreBuild.cmd" %* diff --git a/build-template-dotnet/build.sh b/build-template-dotnet/build.sh index cb10f88203..7b5e25e3a8 100755 --- a/build-template-dotnet/build.sh +++ b/build-template-dotnet/build.sh @@ -6,9 +6,12 @@ while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symli 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 -REPO_FOLDER="$( cd -P "$( dirname "$SOURCE" )" && pwd )" +repoFolder="$( cd -P "$( dirname "$SOURCE" )" && pwd )" -export DOTNET_INSTALL_DIR=$REPO_FOLDER/packages/cli +buildFolder=.build +koreBuildFolder=$buildFolder/KoreBuild-dotnet + +nugetPath=$buildFolder/nuget.exe if test `uname` = Darwin; then cachedir=~/Library/Caches/KBuild @@ -21,39 +24,25 @@ else fi mkdir -p $cachedir nugetVersion=latest -cachePath=$cachedir/nuget.$nugetVersion.exe +cacheNuget=$cachedir/nuget.$nugetVersion.exe -url=https://dist.nuget.org/win-x86-commandline/$nugetVersion/nuget.exe +nugetUrl=https://dist.nuget.org/win-x86-commandline/$nugetVersion/nuget.exe -if test ! -f $cachePath; then - wget -O $cachePath $url 2>/dev/null || curl -o $cachePath --location $url /dev/null +if test ! -d $buildFolder; then + mkdir $buildFolder fi -if test ! -e .nuget; then - mkdir .nuget - cp $cachePath .nuget/nuget.exe +if test ! -f $nugetPath; then + if test ! -f $cacheNuget; then + wget -O $cacheNuget $nugetUrl 2>/dev/null || curl -o $cacheNuget --location $nugetUrl /dev/null + fi + + cp $cacheNuget $nugetPath fi -if test ! -d packages/Sake; then - mono .nuget/nuget.exe install Sake -ExcludeVersion -Source https://www.nuget.org/api/v2/ -Out packages +if test ! -d $koreBuildFolder; then + mono $nugetPath install KoreBuild-dotnet -ExcludeVersion -o $buildFolder -nocache -pre fi -if test ! -d packages/KoreBuild-dotnet; then - mono .nuget/nuget.exe install KoreBuild-dotnet -ExcludeVersion -o packages -nocache -pre -fi +source $koreBuildFolder/build/KoreBuild.sh -# Temporary because we need 'dnu packages add' -if ! type dnvm > /dev/null 2>&1; then - source packages/KoreBuild/build/dnvm.sh -fi - -if ! type dnx > /dev/null 2>&1 || [ -z "$SKIP_DNX_INSTALL" ]; then - dnvm install latest -runtime coreclr -alias default - dnvm install default -runtime mono -alias default -else - dnvm use default -runtime mono -fi - -source packages/KoreBuild-dotnet/build/install.sh -export PATH=$DOTNET_INSTALL_DIR/bin/:$PATH -mono packages/Sake/tools/Sake.exe -I packages/KoreBuild-dotnet/build -f makefile.shade "$@"