sbtn support

Ref https://github.com/sbt/sbt/issues/5665

This implements `--client` option to use `sbt` script as the sbtn runner. The build user can also set the env variable `SBT_NATIVE_CLIENT` to `true`.

The script will attempt to parse `project/build.properties` and use sbtn only when it's sbt 1.4 or above.
This commit is contained in:
Eugene Yokota 2020-09-19 22:03:23 -04:00
parent 50f44c7ac8
commit 2def5ef636
7 changed files with 246 additions and 27 deletions

1
.gitignore vendored
View File

@ -12,3 +12,4 @@ src_managed
*~
/citest/freshly-baked/
/upload/cookies
.bsp

View File

@ -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 <eugene.yokota@lightbend.com>",
@ -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."))

View File

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

View File

@ -1 +1 @@
sbt.version=1.3.10
sbt.version=1.4.0-RC1

View File

@ -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") })
}
()
}
}

View File

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

View File

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