diff --git a/.gitignore b/.gitignore index 48633bd52..aa7261561 100644 --- a/.gitignore +++ b/.gitignore @@ -12,3 +12,4 @@ src_managed *~ /citest/freshly-baked/ /upload/cookies +.bsp diff --git a/build.sbt b/build.sbt index 789fc6c48..0f2fe30bc 100755 --- a/build.sbt +++ b/build.sbt @@ -41,6 +41,9 @@ val sbtLaunchJarUrl = SettingKey[String]("sbt-launch-jar-url") val sbtLaunchJarLocation = SettingKey[File]("sbt-launch-jar-location") val sbtLaunchJar = TaskKey[File]("sbt-launch-jar", "Resolves SBT launch jar") val moduleID = (organization) apply { (o) => ModuleID(o, "sbt", sbtVersionToRelease) } +val sbtnVersion = SettingKey[String]("sbtn-version") +val sbtnJarsMappings = TaskKey[Seq[(File, String)]]("sbtn-jars", "Resolves sbtn JARs") +val sbtnJarsBaseUrl = SettingKey[String]("sbtn-jars-base-url") lazy val bintrayDebianUrl = settingKey[String]("API point for Debian packages") lazy val bintrayDebianExperimentalUrl = settingKey[String]("API point for Debian experimental packages") @@ -58,6 +61,13 @@ val debianBuildId = settingKey[Int]("build id for Debian") val exportRepoUsingCoursier = taskKey[File]("export Maven style repository") val exportRepoCsrDirectory = settingKey[File]("") +val x86MacPlatform = "x86_64-apple-darwin" +val x86LinuxPlatform = "x86_64-pc-linux" +val x86WindowsPlatform = "x86_64-pc-win32" +val x86MacImageName = s"sbtn-$x86MacPlatform" +val x86LinuxImageName = s"sbtn-$x86LinuxPlatform" +val x86WindowsImageName = s"sbtn-$x86WindowsPlatform.exe" + // This build creates a SBT plugin with handy features *and* bundles the SBT script for distribution. val root = (project in file(".")). enablePlugins(UniversalPlugin, LinuxPlugin, DebianPlugin, RpmPlugin, WindowsPlugin, @@ -99,6 +109,54 @@ val root = (project in file(".")). // TODO - GPG Trust validation. file }, + sbtnVersion := "1.4.0-M2", + sbtnJarsBaseUrl := "https://github.com/sbt/sbtn-dist/releases/download", + sbtnJarsMappings := { + val baseUrl = sbtnJarsBaseUrl.value + val v = sbtnVersion.value + val macosImageTar = s"sbtn-darwin-amd64-$v.tar.gz" + val linuxImageTar = s"sbtn-linux-amd64-$v.tar.gz" + val windowsImageZip = s"sbtn-windows-amd64-$v.zip" + val t = target.value + val macosTar = t / macosImageTar + val linuxTar = t / linuxImageTar + val windowsZip = t / windowsImageZip + import dispatch.classic._ + if(!macosTar.exists && !isWindows) { + IO.touch(macosTar) + val writer = new java.io.BufferedOutputStream(new java.io.FileOutputStream(macosTar)) + try Http(url(s"$baseUrl/v$v/$macosImageTar") >>> writer) + finally writer.close() + val platformDir = t / x86MacPlatform + IO.createDirectory(platformDir) + s"tar zxvf $macosTar --directory $platformDir".! + IO.move(platformDir / "sbtn", t / x86MacImageName) + } + if(!linuxTar.exists && !isWindows) { + IO.touch(linuxTar) + val writer = new java.io.BufferedOutputStream(new java.io.FileOutputStream(linuxTar)) + try Http(url(s"$baseUrl/v$v/$linuxImageTar") >>> writer) + finally writer.close() + val platformDir = t / x86LinuxPlatform + IO.createDirectory(platformDir) + s"""tar zxvf $linuxTar --directory $platformDir""".! + IO.move(platformDir / "sbtn", t / x86LinuxImageName) + } + if(!windowsZip.exists) { + IO.touch(windowsZip) + val writer = new java.io.BufferedOutputStream(new java.io.FileOutputStream(windowsZip)) + try Http(url(s"$baseUrl/v$v/$windowsImageZip") >>> writer) + finally writer.close() + val platformDir = t / x86WindowsPlatform + IO.unzip(windowsZip, platformDir) + IO.move(platformDir / "sbtn.exe", t / x86WindowsImageName) + } + if (isWindows) Seq(t / x86WindowsImageName -> s"bin/$x86WindowsImageName") + else + Seq(t / x86MacImageName -> s"bin/$x86MacImageName", + t / x86LinuxImageName -> s"bin/$x86LinuxImageName", + t / x86WindowsImageName -> s"bin/$x86WindowsImageName") + }, // GENERAL LINUX PACKAGING STUFFS maintainer := "Eugene Yokota ", @@ -210,7 +268,10 @@ val root = (project in file(".")). mappings in Universal ++= { val launchJar = sbtLaunchJar.value val rtExportJar = ((exportRepoCsrDirectory in dist).value / "org/scala-sbt/rt/java9-rt-export" / java9rtexportVersion / s"java9-rt-export-${java9rtexportVersion}.jar") - Seq(launchJar -> "bin/sbt-launch.jar", rtExportJar -> "bin/java9-rt-export.jar") + Seq( + launchJar -> "bin/sbt-launch.jar", + rtExportJar -> "bin/java9-rt-export.jar" + ) ++ sbtnJarsMappings.value }, mappings in Universal ++= (Def.taskDyn { if (sbtOfflineInstall && sbtVersionToRelease.startsWith("1.")) diff --git a/citest/build.sbt b/citest/build.sbt index c6f2f6ac5..cd4f0ab9f 100644 --- a/citest/build.sbt +++ b/citest/build.sbt @@ -11,11 +11,9 @@ lazy val root = (project in file(".")) val xs = IO.readLines(file("output.txt")).toVector println(xs) - assert(xs(0) startsWith "[info] Loading project definition") - assert(xs(1) startsWith "[info] Loading settings") - assert(xs(2) startsWith "[info] Set current project to Hello") - assert(xs(3) startsWith "[info] This is sbt") - assert(xs(4) startsWith "[info] The current project") + assert(xs(0) contains "welcome to sbt") + assert(xs(1) contains "loading project definition") + assert(xs(2) contains "loading settings") val ys = IO.readLines(file("err.txt")).toVector.distinct diff --git a/citest/project/build.properties b/citest/project/build.properties index 797e7ccfd..ea379cf2d 100644 --- a/citest/project/build.properties +++ b/citest/project/build.properties @@ -1 +1 @@ -sbt.version=1.3.10 +sbt.version=1.4.0-RC1 diff --git a/integration-test/src/test/scala/RunnerTest.scala b/integration-test/src/test/scala/RunnerTest.scala index ff340e751..b87f723b5 100755 --- a/integration-test/src/test/scala/RunnerTest.scala +++ b/integration-test/src/test/scala/RunnerTest.scala @@ -213,4 +213,20 @@ object SbtRunnerTest extends SimpleTestSuite with PowerAssertions { assert(out.contains[String]("-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=12345")) () } + + test("sbt --client") { + val out = sbtProcess("--client", "--no-colors", "compile").!!.linesIterator.toList + if (isWindows) { + println(out) + } else { + assert(out exists { _.contains("server was not detected") }) + } + val out2 = sbtProcess("--client", "--no-colors", "shutdown").!!.linesIterator.toList + if (isWindows) { + println(out) + } else { + assert(out2 exists { _.contains("disconnected") }) + } + () + } } diff --git a/src/universal/bin/sbt b/src/universal/bin/sbt index a3f9443e3..cc8d830e8 100755 --- a/src/universal/bin/sbt +++ b/src/universal/bin/sbt @@ -9,6 +9,7 @@ declare -a sbt_options declare -a print_version declare -a print_sbt_version declare -a print_sbt_script_version +declare -a original_args declare java_cmd=java declare java_version declare init_sbt_version=_to_be_replaced @@ -17,6 +18,9 @@ declare -r default_sbt_opts="" declare -r default_java_opts="-Dfile.encoding=UTF-8" declare sbt_verbose= declare sbt_debug= +declare build_props_sbt_version= +declare use_sbtn= +declare sbtn_command="$SBTN_CMD" ### ------------------------------- ### ### Helper methods for BASH scripts ### @@ -350,25 +354,6 @@ copyRt() { } run() { - java_args=($JAVA_OPTS) - sbt_options0=(${SBT_OPTS:-$default_sbt_opts}) - - # Split SBT_OPTS into options/commands - miniscript=$(map_args "${sbt_options0[@]}") && eval "${miniscript/options/sbt_options}" && \ - eval "${miniscript/commands/sbt_additional_commands}" - - # Combine command line options/commands and commands from SBT_OPTS - miniscript=$(map_args "$@") && eval "${miniscript/options/cli_options}" && eval "${miniscript/commands/cli_commands}" - args1=( "${cli_options[@]}" "${cli_commands[@]}" "${sbt_additional_commands[@]}" ) - - # process the combined args, then reset "$@" to the residuals - process_args "${args1[@]}" - vlog "[sbt_options] $(declare -p sbt_options)" - - addDefaultMemory - set -- "${residual_args[@]}" - argumentCount=$# - # Copy preloaded repo to user's preloaded directory syncPreloaded @@ -420,6 +405,7 @@ run() { declare -r noshare_opts="-Dsbt.global.base=project/.sbtboot -Dsbt.boot.directory=project/.boot -Dsbt.ivy.home=project/.ivy" declare -r sbt_opts_file=".sbtopts" +declare -r build_props_file="$(pwd)/project/build.properties" declare -r etc_sbt_opts_file="/etc/sbt/sbtopts" # this allows /etc/sbt/sbtopts location to be changed declare -r etc_file="${SBT_ETC_FILE:-$etc_sbt_opts_file}" @@ -549,6 +535,8 @@ process_args () { --numeric-version) print_sbt_version=1 && shift ;; --script-version) print_sbt_script_version=1 && shift ;; -d|-debug|--debug) sbt_debug=1 && addSbt "-debug" && shift ;; + --client) use_sbtn=1 && shift ;; + --server) use_sbtn=0 && shift ;; -ivy|--ivy) require_arg path "$1" "$2" && addJava "-Dsbt.ivy.home=$2" && shift 2 ;; -mem|--mem) require_arg integer "$1" "$2" && addMemory "$2" && shift 2 ;; @@ -587,6 +575,60 @@ loadConfigFile() { done } +loadPropFile() { + while IFS='=' read -r k v; do + if [[ "$k" == "sbt.version" ]]; then + build_props_sbt_version="$v" + fi + done <<< "$(cat "$1" | sed $'/^\#/d;s/\r$//')" +} + +detectNativeClient() { + if [[ "$sbtn_command" != "" ]]; then + : + elif [[ "$OSTYPE" == "linux-gnu"* ]]; then + [[ -f "${sbt_bin_dir}/sbtn-x86_64-pc-linux" ]] && sbtn_command="${sbt_bin_dir}/sbtn-x86_64-pc-linux" + elif [[ "$OSTYPE" == "darwin"* ]]; then + [[ -f "${sbt_bin_dir}/sbtn-x86_64-apple-darwin" ]] && sbtn_command="${sbt_bin_dir}/sbtn-x86_64-apple-darwin" + elif [[ "$OSTYPE" == "cygwin" ]] || [[ "$OSTYPE" == "msys" ]] || [[ "$OSTYPE" == "win32" ]]; then + [[ -f "${sbt_bin_dir}/sbtn-x86_64-pc-win32.exe" ]] && sbtn_command="${sbt_bin_dir}/sbtn-x86_64-pc-win32.exe" + elif [[ "$OSTYPE" == "freebsd"* ]]; then + : + else + : + fi +} + +# Run native client if build.properties points to 1.4+ and has SBT_NATIVE_CLIENT +isRunNativeClient() { + sbtV="$build_props_sbt_version" + [[ "$sbtV" == "" ]] && sbtV="$init_sbt_version" + [[ "$sbtV" == "" ]] && sbtV="0.0.0" + sbtBinaryV_1=$(echo "$sbtV" | sed 's/^\([0-9]*\)\.\([0-9]*\).*$/\1/') + sbtBinaryV_2=$(echo "$sbtV" | sed 's/^\([0-9]*\)\.\([0-9]*\).*$/\2/') + if (( $sbtBinaryV_1 >= 2 )) || ( (( $sbtBinaryV_1 >= 1 )) && (( $sbtBinaryV_2 >= 4 )) ); then + if [[ "$use_sbtn" == "1" ]] && [[ "$sbtn_command" != "" ]]; then + echo "true" + else + echo "false" + fi + else + echo "false" + fi +} + +runNativeClient() { + vlog "[debug] running native client" + for i in "${!original_args[@]}"; do + if [[ "${original_args[i]}" = "--client" ]]; then + unset 'original_args[i]' + fi + done + execRunner "$sbtn_command" "${original_args[@]}" +} + +original_args=("$@") + # Here we pull in the default settings configuration. [[ -f "$dist_sbt_opts_file" ]] && set -- $(loadConfigFile "$dist_sbt_opts_file") "$@" @@ -602,4 +644,34 @@ loadConfigFile() { # Pull in default JAVA_OPTS [[ -z "${JAVA_OPTS// }" ]] && export JAVA_OPTS="$default_java_opts" -run "$@" +[[ -f "$build_props_file" ]] && loadPropFile "$build_props_file" + +detectNativeClient + +java_args=($JAVA_OPTS) +sbt_options0=(${SBT_OPTS:-$default_sbt_opts}) +if [[ "$SBT_NATIVE_CLIENT" == "true" ]]; then + use_sbtn=1 +fi + +# Split SBT_OPTS into options/commands +miniscript=$(map_args "${sbt_options0[@]}") && eval "${miniscript/options/sbt_options}" && \ +eval "${miniscript/commands/sbt_additional_commands}" + +# Combine command line options/commands and commands from SBT_OPTS +miniscript=$(map_args "$@") && eval "${miniscript/options/cli_options}" && eval "${miniscript/commands/cli_commands}" +args1=( "${cli_options[@]}" "${cli_commands[@]}" "${sbt_additional_commands[@]}" ) + +# process the combined args, then reset "$@" to the residuals +process_args "${args1[@]}" +vlog "[sbt_options] $(declare -p sbt_options)" + +addDefaultMemory +set -- "${residual_args[@]}" +argumentCount=$# + +if [[ "$(isRunNativeClient)" == "true" ]]; then + runNativeClient +else + run +fi diff --git a/src/universal/bin/sbt.bat b/src/universal/bin/sbt.bat index 2f09cfdd6..e868271ba 100755 --- a/src/universal/bin/sbt.bat +++ b/src/universal/bin/sbt.bat @@ -23,6 +23,8 @@ set sbt_default_mem=1024 set default_sbt_opts= set default_java_opts=-Dfile.encoding=UTF-8 set sbt_jar= +set build_props_sbt_version= +set run_native_client= set sbt_args_print_version= set sbt_args_print_sbt_version= @@ -44,6 +46,7 @@ set sbt_args_sbt_create= set sbt_args_sbt_dir= set sbt_args_sbt_version= set sbt_args_mem= +set sbt_args_client= rem users can set SBT_OPTS via .sbtopts if exist .sbtopts for /F %%A in (.sbtopts) do ( @@ -77,6 +80,14 @@ if defined JAVA_HOMES ( ) ) +if exist "project\build.properties" ( + for /F "eol=# delims== tokens=1*" %%a in (project\build.properties) do ( + if "%%a" == "sbt.version" if not "%%b" == "" ( + set build_props_sbt_version=%%b + ) + ) +) + rem must set PATH or wrong javac is used for java projects if defined JAVA_HOME set "PATH=%JAVA_HOME%\bin;%PATH%" @@ -115,6 +126,12 @@ if not defined _SBT_OPTS if defined SBT_OPTS set _SBT_OPTS=%SBT_OPTS% if not defined _SBT_OPTS if defined SBT_CFG_OPTS set _SBT_OPTS=!SBT_CFG_OPTS! if not defined _SBT_OPTS if defined default_sbt_opts set _SBT_OPTS=!default_sbt_opts! +if defined SBT_NATIVE_CLIENT ( + if "%SBT_NATIVE_CLIENT%" == "true" ( + set sbt_args_client=1 + ) +) + :args_loop shift @@ -156,6 +173,14 @@ if defined _version_arg ( goto args_loop ) +if "%~0" == "--client" set _client_arg=true + +if defined _client_arg ( + set _client_arg= + set sbt_args_client=1 + goto args_loop +) + if "%~0" == "-batch" set _batch_arg=true if "%~0" == "--batch" set _batch_arg=true @@ -495,6 +520,11 @@ if !sbt_args_print_sbt_script_version! equ 1 ( goto :eof ) +if !run_native_client! equ 1 ( + goto :runnative !SBT_ARGS! + goto :eof +) + call :checkjava call :copyrt @@ -607,6 +637,21 @@ if defined sbt_args_verbose ( goto :eof +:runnative + +set "_SBTNCMD=!SBT_BIN_DIR!sbtn-x86_64-pc-win32.exe" + +if defined sbt_args_verbose ( + echo # running native client + if not "%~1" == "" ( call :echolist %* ) +) + +rem Microsoft Visual C++ 2010 SP1 Redistributable Package (x64) is required +rem https://www.microsoft.com/en-us/download/details.aspx?id=13523 +"!_SBTNCMD!" %* + +goto :eof + rem for expression tries to interpret files, so simply loop over %* instead rem fixes dealing with quotes after = args: -Dscala.ext.dirs="C:\Users\First Last\.sbt\0.13\java9-rt-ext-adoptopenjdk_11_0_3" :echolist @@ -772,6 +817,32 @@ for /f "delims=.-_ tokens=1-2" %%v in ("!JAVA_VERSION!") do ( ) ) +rem parse the first two segments of sbt.version and set run_native_client to +rem 1 if the user has also indicated they want to use native client. +set sbtV=!build_props_sbt_version! +set sbtBinaryV_1= +set sbtBinaryV_2= +for /F "delims=.-_ tokens=1-2" %%v in ("!sbtV!") do ( + set sbtBinaryV_1=%%v + set sbtBinaryV_2=%%w +) +set native_client_ready= +if !sbtBinaryV_1! geq 2 ( + set native_client_ready=1 +) else ( + if !sbtBinaryV_1! geq 1 ( + if !sbtBinaryV_2! geq 4 ( + set native_client_ready=1 + ) + ) +) +if !native_client_ready! equ 1 ( + if !sbt_args_client! equ 1 ( + set run_native_client=1 + ) +) +set native_client_ready= + exit /B 0 :checkjava