enso/project/EnvironmentCheck.scala
Hubert Plociniczak 096fcfee82
Generate native image for engine-runner (#3638)
This PR adds a possibility to generate native-image for engine-runner.
Note that due to on-demand loading of stdlib, programs that make use of it are currently not yet supported
(that will be resolved at a later point).
The purpose of this PR is only to make sure that we can generate a bare minimum runner because due to lack TruffleBoundaries or misconfiguration in reflection config, this can get broken very easily.
To generate a native image simply execute:
```
sbt> engine-runner-native/buildNativeImage
... (wait a few minutes)
```
The executable is called `runner` and can be tested via a simple test that is in the resources. To illustrate the benefits
see the timings difference between the non-native and native one:
```
>time built-distribution/enso-engine-0.0.0-dev-linux-amd64/enso-0.0.0-dev/bin/enso --no-ir-caches --in-project test/Tests/ --run engine/runner-native/src/test/resources/Factorial.enso 6
720

real	0m4.503s
user	0m9.248s
sys	0m1.494s
> time ./runner --run engine/runner-native/src/test/resources/Factorial.enso 6
720

real	0m0.176s
user	0m0.042s
sys	0m0.038s
```

# Important Notes
Notice that due to a [bug in GraalVM](https://github.com/oracle/graal/issues/4200), which is already fixed in 22.x, and us still being on 21.x for the time being, I had to add a workaround to our sbt build to build a different fat jar for native image. To workaround it I had to exclude sqlite jar. Hence native image task is on `engine-runner-native` and not on `engine-runner`.

Will need to add the above command to CI.
2022-09-22 14:45:10 +00:00

89 lines
2.8 KiB
Scala

import java.io.IOException
import sbt._
import sbt.internal.util.ManagedLogger
import scala.sys.process._
object EnvironmentCheck {
/** Compares the version of JVM running sbt with the GraalVM versions defined
* in project configuration and reports errors if the versions do not match.
*
* @param expectedGraalVersion the GraalVM version that should be used for
* building this project
* @param expectedJavaVersion the Java version of the used GraalVM
* distribution
* @param log a logger used to report errors if the versions are mismatched
*/
def graalVersionOk(
expectedGraalVersion: String,
expectedJavaVersion: String,
log: ManagedLogger
): Boolean = {
val javaSpecificationVersion =
System.getProperty("java.vm.specification.version")
val versionProperty = "java.vendor.version"
val rawGraalVersion = System.getProperty(versionProperty)
def graalVersion: Option[String] = {
val versionRegex = """GraalVM (CE|EE) ([\d.]+.*)""".r
rawGraalVersion match {
case versionRegex(_, version) => Some(version)
case _ => None
}
}
val graalOk = if (rawGraalVersion == null) {
log.error(
s"Property $versionProperty is not defined. " +
s"Make sure your current JVM is set to " +
s"GraalVM $expectedGraalVersion Java $expectedJavaVersion."
)
false
} else
graalVersion match {
case Some(version) if version == expectedGraalVersion => true
case _ =>
log.error(
s"GraalVM version mismatch - you are running $rawGraalVersion " +
s"but GraalVM $expectedGraalVersion is expected."
)
false
}
val javaOk =
if (javaSpecificationVersion != expectedJavaVersion) {
log.error(
s"Java version mismatch - you are running " +
s"Java $javaSpecificationVersion " +
s"but Java $expectedJavaVersion is expected."
)
false
} else true
graalOk && javaOk
}
/** Augments a state transition to do a Rust and GraalVM version check.
*
* @param graalVersion the GraalVM version that should be used for
* building this project
* @param javaVersion the Java version of the used GraalVM distribution
* @param oldTransition the state transition to be augmented
* @return an augmented state transition that does all the state changes of
* oldTransition but also runs the version checks
*/
def addVersionCheck(
graalVersion: String,
javaVersion: String
)(
oldTransition: State => State
): State => State =
(state: State) => {
val newState = oldTransition(state)
val logger = newState.log
newState
}
}