Skip to content

Commit

Permalink
Merge pull request #2355 from tgodzik/add-bloop-rifle
Browse files Browse the repository at this point in the history
feature: Switch to using Bloop Rifle and backport all improvements
  • Loading branch information
tgodzik authored Jul 11, 2024
2 parents 3dcee66 + 8e7645b commit 0a9bc4f
Show file tree
Hide file tree
Showing 93 changed files with 3,773 additions and 4,040 deletions.
46 changes: 12 additions & 34 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ jobs:
- uses: graalvm/setup-graalvm@v1
with:
version: '22.3.0'
java-version: '11'
java-version: '17'
github-token: ${{ secrets.GITHUB_TOKEN }}

- name: Tests
Expand All @@ -58,7 +58,7 @@ jobs:
- uses: graalvm/setup-graalvm@v1
with:
version: '22.3.0'
java-version: '11'
java-version: '17'
github-token: ${{ secrets.GITHUB_TOKEN }}

- name: Tests
Expand All @@ -74,37 +74,13 @@ jobs:
sbt nativeBridge04/test
shell: bash

launcher:
name: Launcher tests
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, windows-latest, macOS-12]
steps:
- uses: actions/checkout@v4
with:
submodules: true
- uses: graalvm/setup-graalvm@v1
with:
version: '22.3.0'
java-version: '11'
github-token: ${{ secrets.GITHUB_TOKEN }}
components: 'native-image'

- name: Tests
run: |
echo $JAVA_HOME
sbt "install; launcherTest/test"
shell: bash

test:
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, windows-latest, macOS-12]
jdk: ["22.3.0", "11"]
jdk: ["22.3.0", "17"]

name: Test ${{ matrix.os }} -- ${{ matrix.jdk }}
env:
Expand All @@ -118,15 +94,15 @@ jobs:

- uses: coursier/setup-action@v1
with:
jvm: 'temurin:11.0.18'
if: matrix.jdk == '11'
jvm: 'temurin:17'
if: matrix.jdk == '17'

- uses: coursier/cache-action@v6

- uses: graalvm/setup-graalvm@v1
with:
version: ${{ matrix.jdk }}
java-version: '11'
java-version: '17'
if: matrix.jdk == '22.3.0'

- uses: actions/setup-node@v4
Expand All @@ -146,6 +122,7 @@ jobs:
"frontend/test:compile; \
backend/test; \
docs/compile; \
bloopRifle/test; \
frontend/testOnly bloop.ScalaVersionsSpec; \
frontend/testOnly -bloop.ScalaVersionsSpec; \
frontend/runMain bloop.util.CommandsDocGenerator --test; \
Expand Down Expand Up @@ -188,23 +165,24 @@ jobs:
github-token: ${{ secrets.GITHUB_TOKEN }}

- name: Publish GraalVM Native artifacts
run: sbt "bloopgun213/graalvm-native-image:packageBin"
run: sbt "cli/graalvm-native-image:packageBin"

- name: Copy artifacts (windows)
if: matrix.os == 'windows-latest'
run: |
echo $ARTIFACT_NAME
ls bloopgun/target/bloopgun-2.13/graalvm-native-image/bloopgun-core.exe
ls cli/target/graalvm-native-image/cli.exe
mkdir -p bloop-artifacts
cp bloopgun/target/bloopgun-2.13/graalvm-native-image/bloopgun-core.exe bloop-artifacts/$ARTIFACT_NAME
cp cli/target/graalvm-native-image/cli.exe bloop-artifacts/$ARTIFACT_NAME
shell: bash

- name: Copy artifacts (not windows)
if: matrix.os != 'windows-latest'
run: |
ls cli/target/graalvm-native-image/cli
echo $ARTIFACT_NAME
mkdir -p bloop-artifacts
cp bloopgun/target/bloopgun-2.13/graalvm-native-image/bloopgun-core bloop-artifacts/$ARTIFACT_NAME
cp cli/target/graalvm-native-image/cli bloop-artifacts/$ARTIFACT_NAME
- uses: actions/upload-artifact@v4
with:
Expand Down
186 changes: 186 additions & 0 deletions bloop-rifle/src/main/scala/bloop/rifle/BloopRifle.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,186 @@
package bloop.rifle

import bloop.rifle.internal.{Operations, Util}

import java.io.{ByteArrayOutputStream, OutputStream}
import java.nio.file.Path
import java.util.concurrent.ScheduledExecutorService

import scala.concurrent.Future

object BloopRifle {

/**
* Checks whether a bloop server is running at this host / port.
*
* @param host
* @param port
* @param logger
* @return
* Whether a server is running or not.
*/
def check(
config: BloopRifleConfig,
logger: BloopRifleLogger
): Boolean = {
def check() =
Operations.check(
config.address,
logger
)
check()
}

/**
* Starts a new bloop server.
*
* @param config
* @param scheduler
* @param logger
* @return
* A future, that gets completed when the server is done starting (and can thus be used).
*/
def startServer(
config: BloopRifleConfig,
scheduler: ScheduledExecutorService,
logger: BloopRifleLogger,
version: String,
bloopJava: String
): Future[Unit] =
config.classPath(version) match {
case Left(ex) => Future.failed(new Exception("Error getting Bloop class path", ex))
case Right(cp) =>
logger.info("Starting compilation server")
logger.debug(
s"Starting Bloop $version at ${config.address.render} using JVM $bloopJava"
)
object IntValue {
def unapply(s: String): Option[Int] =
// no String.toIntOption in Scala 2.12.x
try Some(s.toInt)
catch {
case _: NumberFormatException => None
}
}
val bloopServerSupportsFileTruncating =
version.takeWhile(c => c.isDigit || c == '.').split('.') match {
case Array(IntValue(maj), IntValue(min), IntValue(patch), _ @_*) =>
import scala.math.Ordering.Implicits._
Seq(maj, min, patch) >= Seq(1, 4, 20)
case _ =>
false
}

Operations.startServer(
config.address,
bloopJava,
config.javaOpts,
cp.map(_.toPath),
config.workingDir,
scheduler,
config.startCheckPeriod,
config.startCheckTimeout,
logger,
bloopServerSupportsFileTruncating = bloopServerSupportsFileTruncating
)
}

/**
* Opens a BSP connection to a running bloop server.
*
* Starts a thread to read output from the nailgun connection, and another one to pass input to
* it.
*
* @param logger
* @return
* A [[BspConnection]] object, that can be used to close the connection.
*/
def bsp(
config: BloopRifleConfig,
workingDir: Path,
logger: BloopRifleLogger
): BspConnection = {

val bspSocketOrPort = config.bspSocketOrPort.map(_()).getOrElse {
BspConnectionAddress.Tcp("127.0.0.1", Util.randomPort())
}

val inOpt = config.bspStdin

val out = config.bspStdout.getOrElse(OutputStream.nullOutputStream())
val err = config.bspStderr.getOrElse(OutputStream.nullOutputStream())

Operations.bsp(
config.address,
bspSocketOrPort,
workingDir,
inOpt,
out,
err,
logger
)
}

def exit(
config: BloopRifleConfig,
workingDir: Path,
logger: BloopRifleLogger
): Int = {

val out = config.bspStdout.getOrElse(OutputStream.nullOutputStream())
val err = config.bspStderr.getOrElse(OutputStream.nullOutputStream())

Operations.exit(
config.address,
workingDir,
out,
err,
logger
)
}

def getCurrentBloopVersion(
config: BloopRifleConfig,
logger: BloopRifleLogger,
workdir: Path,
scheduler: ScheduledExecutorService
): Either[BloopAboutFailure, BloopServerRuntimeInfo] = {
val isRunning = BloopRifle.check(config, logger)

if (isRunning) {
val bufferedOStream = new ByteArrayOutputStream
Operations.about(
config.address,
workdir,
bufferedOStream,
OutputStream.nullOutputStream(),
logger,
scheduler
)
val bloopAboutOutput = new String(bufferedOStream.toByteArray)
VersionUtil
.parseBloopAbout(bloopAboutOutput)
.toRight(ParsingFailed(bloopAboutOutput))
} else
Left(BloopNotRunning)
}

sealed abstract class BloopAboutFailure extends Product with Serializable {
def message: String
}
case object BloopNotRunning extends BloopAboutFailure {
def message = "not running"
}
final case class ParsingFailed(bloopAboutOutput: String) extends BloopAboutFailure {
def message = s"failed to parse output: '$bloopAboutOutput'"
}

final case class BloopServerRuntimeInfo(
bloopVersion: BloopVersion,
jvmVersion: Int,
javaHome: String
) {
def message: String =
s"version $bloopVersion, JVM $jvmVersion under $javaHome"
}
}
Loading

0 comments on commit 0a9bc4f

Please sign in to comment.