mirror of https://github.com/sbt/sbt.git
Add installNativeThinClient task
This allows a user to install the native thin client into a particular directory (e.g. /usr/local/bin). I also made buildNativeThinClient have a file dependency on the classpath so that it can be incremental if the classpath hasn't changed. This is useful if the user has run buildNativeThinClient for testing and then decides to install it once it's been validated without having to rebuild (which takes a minimum of about 30 seconds on my laptop).
This commit is contained in:
parent
26d7331283
commit
48fa28e566
|
|
@ -39,7 +39,7 @@ for:
|
||||||
- export PATH="$PATH:~/.jabba/jdk/adopt@1.8.0-222/bin"
|
- export PATH="$PATH:~/.jabba/jdk/adopt@1.8.0-222/bin"
|
||||||
- export PATH="$PATH:graalvm-ce-java8-20.1.0/bin"
|
- export PATH="$PATH:graalvm-ce-java8-20.1.0/bin"
|
||||||
- gu install native-image
|
- gu install native-image
|
||||||
- sbt -Dsbt.native-image=$(pwd)/graalvm-ce-java8-20.1.0/bin/native-image "sbtClientProj/genNativeExecutable"
|
- sbt -Dsbt.native-image=$(pwd)/graalvm-ce-java8-20.1.0/bin/native-image "sbtClientProj/buildNativeThinClient"
|
||||||
|
|
||||||
-
|
-
|
||||||
matrix:
|
matrix:
|
||||||
|
|
@ -70,7 +70,7 @@ for:
|
||||||
- export PATH="$PATH:~/.jabba/jdk/adopt@1.8.0-222/Contents/Home/bin"
|
- export PATH="$PATH:~/.jabba/jdk/adopt@1.8.0-222/Contents/Home/bin"
|
||||||
- export PATH="$PATH:graalvm-ce-java8-20.1.0/Contents/Home/bin"
|
- export PATH="$PATH:graalvm-ce-java8-20.1.0/Contents/Home/bin"
|
||||||
- gu install native-image
|
- gu install native-image
|
||||||
- sbt -Dsbt.native-image=$(pwd)/graalvm-ce-java8-20.1.0/Contents/Home/bin/native-image "sbtClientProj/genNativeExecutable"
|
- sbt -Dsbt.native-image=$(pwd)/graalvm-ce-java8-20.1.0/Contents/Home/bin/native-image "sbtClientProj/buildNativeThinClient"
|
||||||
|
|
||||||
-
|
-
|
||||||
matrix:
|
matrix:
|
||||||
|
|
@ -123,7 +123,7 @@ for:
|
||||||
- '%USERPROFILE%\.sbt'
|
- '%USERPROFILE%\.sbt'
|
||||||
|
|
||||||
test_script:
|
test_script:
|
||||||
- sbt "-Dsbt.native-image=C:\graalvm-ce-java8-20.1.0\bin\native-image.cmd" "sbtClientProj/genNativeExecutable"
|
- sbt "-Dsbt.native-image=C:\graalvm-ce-java8-20.1.0\bin\native-image.cmd" "sbtClientProj/buildNativeThinClient"
|
||||||
-
|
-
|
||||||
matrix:
|
matrix:
|
||||||
only:
|
only:
|
||||||
|
|
|
||||||
81
build.sbt
81
build.sbt
|
|
@ -206,8 +206,26 @@ lazy val sbtRoot: Project = (project in file("."))
|
||||||
.single("sbtOn")((state, dir) => s"sbtProj/test:runMain sbt.RunFromSourceMain $dir" :: state),
|
.single("sbtOn")((state, dir) => s"sbtProj/test:runMain sbt.RunFromSourceMain $dir" :: state),
|
||||||
mimaSettings,
|
mimaSettings,
|
||||||
mimaPreviousArtifacts := Set.empty,
|
mimaPreviousArtifacts := Set.empty,
|
||||||
genExecutable := (sbtClientProj / genExecutable).evaluated,
|
buildThinClient := (sbtClientProj / buildThinClient).evaluated,
|
||||||
genNativeExecutable := (sbtClientProj / genNativeExecutable).value,
|
buildNativeThinClient := (sbtClientProj / buildNativeThinClient).value,
|
||||||
|
installNativeThinClient := {
|
||||||
|
// nativeInstallDirectory can be set globally or in a gitignored local file
|
||||||
|
val dir = nativeInstallDirectory.?.value
|
||||||
|
val target = Def.spaceDelimited("").parsed.headOption match {
|
||||||
|
case Some(p) => file(p).toPath
|
||||||
|
case _ =>
|
||||||
|
dir match {
|
||||||
|
case Some(d) => d / "sbtc"
|
||||||
|
case _ =>
|
||||||
|
val msg = "Expected input parameter <path>: installNativeExecutable /usr/local/bin"
|
||||||
|
throw new IllegalStateException(msg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val base = baseDirectory.value.toPath
|
||||||
|
val exec = (sbtClientProj / buildNativeThinClient).value
|
||||||
|
streams.value.log.info(s"installing thin client ${base.relativize(exec)} to ${target}")
|
||||||
|
Files.copy(exec, target, java.nio.file.StandardCopyOption.REPLACE_EXISTING)
|
||||||
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
// This is used to configure an sbt-launcher for this version of sbt.
|
// This is used to configure an sbt-launcher for this version of sbt.
|
||||||
|
|
@ -1049,15 +1067,18 @@ lazy val serverTestProj = (project in file("server-test"))
|
||||||
)
|
)
|
||||||
|
|
||||||
val isWin = scala.util.Properties.isWin
|
val isWin = scala.util.Properties.isWin
|
||||||
val generateReflectionConfig = taskKey[Unit]("generate the graalvm reflection config")
|
val buildThinClient =
|
||||||
val genExecutable =
|
|
||||||
inputKey[JPath]("generate a java implementation of the thin client")
|
inputKey[JPath]("generate a java implementation of the thin client")
|
||||||
val graalClasspath = taskKey[String]("Generate the classpath for graal (compacted for windows)")
|
val thinClientClasspath =
|
||||||
val graalNativeImageCommand = taskKey[String]("The native image command")
|
taskKey[Seq[JPath]]("Generate the classpath for thin client (compacted for windows)")
|
||||||
val graalNativeImageOptions = settingKey[Seq[String]]("The native image options")
|
val thinClientNativeImageCommand = taskKey[String]("The native image command")
|
||||||
val graalNativeImageClass = settingKey[String]("The class for the native image")
|
val thinClientNativeImageOptions = settingKey[Seq[String]]("The native image options")
|
||||||
val genNativeExecutable = taskKey[JPath]("Generate a native executable")
|
val thinClientNativeImageClass = settingKey[String]("The class for the native image")
|
||||||
val nativeExecutablePath = settingKey[JPath]("The location of the native executable")
|
val buildNativeThinClient = taskKey[JPath]("Generate a native executable")
|
||||||
|
// Use a TaskKey rather than SettingKey for nativeInstallDirectory so it can left unset by default
|
||||||
|
val nativeInstallDirectory = taskKey[JPath]("The install directory for the native executable")
|
||||||
|
val installNativeThinClient = inputKey[JPath]("Install the native executable")
|
||||||
|
val nativeThinClientPath = settingKey[JPath]("The location of the native executable")
|
||||||
lazy val sbtClientProj = (project in file("client"))
|
lazy val sbtClientProj = (project in file("client"))
|
||||||
.dependsOn(commandProj)
|
.dependsOn(commandProj)
|
||||||
.settings(
|
.settings(
|
||||||
|
|
@ -1075,31 +1096,32 @@ lazy val sbtClientProj = (project in file("client"))
|
||||||
* external process so we create symbolic links with short names to get the
|
* external process so we create symbolic links with short names to get the
|
||||||
* classpath length under the limit.
|
* classpath length under the limit.
|
||||||
*/
|
*/
|
||||||
graalClasspath := {
|
thinClientClasspath := {
|
||||||
val original = (Compile / fullClasspathAsJars).value.map(_.data)
|
val original = (Compile / fullClasspathAsJars).value.map(_.data)
|
||||||
val outputDir = target.value / "graalcp"
|
val outputDir = target.value / "thinclientcp"
|
||||||
IO.createDirectory(outputDir)
|
IO.createDirectory(outputDir)
|
||||||
Files.walk(outputDir.toPath).forEach {
|
Files.walk(outputDir.toPath).forEach {
|
||||||
case f if f.getFileName.toString.endsWith(".jar") => Files.deleteIfExists(f)
|
case f if f.getFileName.toString.endsWith(".jar") => Files.deleteIfExists(f)
|
||||||
case _ =>
|
case _ =>
|
||||||
}
|
}
|
||||||
original.zipWithIndex
|
original.zipWithIndex.map {
|
||||||
.map {
|
case (f, i) => Files.createSymbolicLink(outputDir.toPath / s"$i.jar", f.toPath)
|
||||||
case (f, i) =>
|
|
||||||
Files.createSymbolicLink(outputDir.toPath / s"$i.jar", f.toPath)
|
|
||||||
s"$i.jar"
|
|
||||||
}
|
}
|
||||||
.mkString(java.io.File.pathSeparator)
|
|
||||||
},
|
},
|
||||||
graalNativeImageCommand := System.getProperty("sbt.native-image", "native-image").toString,
|
thinClientNativeImageCommand := System.getProperty("sbt.native-image", "native-image").toString,
|
||||||
genNativeExecutable / name := s"sbtc${if (isWin) ".exe" else ""}",
|
buildNativeThinClient / name := s"sbtc${if (isWin) ".exe" else ""}",
|
||||||
nativeExecutablePath := target.value.toPath / "bin" / (genNativeExecutable / name).value,
|
nativeThinClientPath := target.value.toPath / "bin" / (buildNativeThinClient / name).value,
|
||||||
graalNativeImageClass := "sbt.client.Client",
|
thinClientNativeImageClass := "sbt.client.Client",
|
||||||
genNativeExecutable := {
|
buildNativeThinClient := {
|
||||||
val prefix = Seq(graalNativeImageCommand.value, "-cp", graalClasspath.value)
|
val hasChanges = thinClientClasspath.outputFileChanges.hasChanges
|
||||||
val full = prefix ++ graalNativeImageOptions.value :+ graalNativeImageClass.value
|
val cpString =
|
||||||
|
thinClientClasspath.value.map(_.getFileName).mkString(java.io.File.pathSeparator)
|
||||||
|
val prefix = Seq(thinClientNativeImageCommand.value, "-cp", cpString)
|
||||||
|
val full = prefix ++ thinClientNativeImageOptions.value :+ thinClientNativeImageClass.value
|
||||||
|
val dir = target.value
|
||||||
|
if (hasChanges || !Files.exists(nativeThinClientPath.value)) {
|
||||||
val pb = new java.lang.ProcessBuilder(full: _*)
|
val pb = new java.lang.ProcessBuilder(full: _*)
|
||||||
pb.directory(target.value / "graalcp")
|
pb.directory(dir / "thinclientcp")
|
||||||
val proc = pb.start()
|
val proc = pb.start()
|
||||||
val thread = new Thread {
|
val thread = new Thread {
|
||||||
setDaemon(true)
|
setDaemon(true)
|
||||||
|
|
@ -1120,9 +1142,10 @@ lazy val sbtClientProj = (project in file("client"))
|
||||||
thread.start()
|
thread.start()
|
||||||
proc.waitFor(5, java.util.concurrent.TimeUnit.MINUTES)
|
proc.waitFor(5, java.util.concurrent.TimeUnit.MINUTES)
|
||||||
assert(proc.exitValue == 0, s"Exit value ${proc.exitValue} was nonzero")
|
assert(proc.exitValue == 0, s"Exit value ${proc.exitValue} was nonzero")
|
||||||
nativeExecutablePath.value
|
}
|
||||||
|
nativeThinClientPath.value
|
||||||
},
|
},
|
||||||
graalNativeImageOptions := Seq(
|
thinClientNativeImageOptions := Seq(
|
||||||
"--no-fallback",
|
"--no-fallback",
|
||||||
s"--initialize-at-run-time=sbt.client",
|
s"--initialize-at-run-time=sbt.client",
|
||||||
"--verbose",
|
"--verbose",
|
||||||
|
|
@ -1131,7 +1154,7 @@ lazy val sbtClientProj = (project in file("client"))
|
||||||
"-H:-ParseRuntimeOptions",
|
"-H:-ParseRuntimeOptions",
|
||||||
s"-H:Name=${target.value / "bin" / "sbtc"}",
|
s"-H:Name=${target.value / "bin" / "sbtc"}",
|
||||||
),
|
),
|
||||||
genExecutable := {
|
buildThinClient := {
|
||||||
val isFish = Def.spaceDelimited("").parsed.headOption.fold(false)(_ == "--fish")
|
val isFish = Def.spaceDelimited("").parsed.headOption.fold(false)(_ == "--fish")
|
||||||
val ext = if (isWin) ".bat" else if (isFish) ".fish" else ".sh"
|
val ext = if (isWin) ".bat" else if (isFish) ".fish" else ".sh"
|
||||||
val output = target.value.toPath / "bin" / s"${if (isFish) "fish-" else ""}client$ext"
|
val output = target.value.toPath / "bin" / s"${if (isFish) "fish-" else ""}client$ext"
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue