enso/project/LibraryManifestGenerator.scala
Pavel Marek 5a7ad6bfe4
Upgrade enso to GraalVM for jdk 21 (#7991)
Upgrade to GraalVM JDK 21.
```
> java -version
openjdk version "21" 2023-09-19
OpenJDK Runtime Environment GraalVM CE 21+35.1 (build 21+35-jvmci-23.1-b15)
OpenJDK 64-Bit Server VM GraalVM CE 21+35.1 (build 21+35-jvmci-23.1-b15, mixed mode, sharing)
```

With SDKMan, download with `sdk install java 21-graalce`.

# Important Notes
- After this PR, one can theoretically run enso with any JRE with version at least 21.
- Removed `sbt bootstrap` hack and all the other build time related hacks related to the handling of GraalVM distribution.
- `project-manager` remains backward compatible - it can open older engines with runtimes. New engines now do no longer require a separate runtime to be downloaded.
- sbt does not support compilation of `module-info.java` files in mixed projects - https://github.com/sbt/sbt/issues/3368
- Which means that we can have `module-info.java` files only for Java-only projects.
- Anyway, we need just a single `module-info.class` in the resulting `runtime.jar` fat jar.
- `runtime.jar` is assembled in `runtime-with-instruments` with a custom merge strategy (`sbt-assembly` plugin). Caching is disabled for custom merge strategies, which means that re-assembly of `runtime.jar` will be more frequent.
- Engine distribution contains multiple JAR archives (modules) in `component` directory, along with `runner/runner.jar` that is hidden inside a nested directory.
- The new entry point to the engine runner is [EngineRunnerBootLoader](https://github.com/enso-org/enso/pull/7991/files#diff-9ab172d0566c18456472aeb95c4345f47e2db3965e77e29c11694d3a9333a2aa) that contains a custom ClassLoader - to make sure that everything that does not have to be loaded from a module is loaded from `runner.jar`, which is not a module.
- The new command line for launching the engine runner is in [distribution/bin/enso](https://github.com/enso-org/enso/pull/7991/files#diff-0b66983403b2c329febc7381cd23d45871d4d555ce98dd040d4d1e879c8f3725)
- [Newest version of Frgaal](https://repo1.maven.org/maven2/org/frgaal/compiler/20.0.1/) (20.0.1) does not recognize `--source 21` option, only `--source 20`.
2023-11-17 18:02:36 +00:00

82 lines
2.4 KiB
Scala

import sbt._
import sbt.util.CacheStoreFactory
/** A helper for generating manifests for bundled libraries. */
object LibraryManifestGenerator {
/** Represents a library that will be bundled with the engine and needs to
* have its manifest generated.
*/
case class BundledLibrary(name: String, version: String)
/** Generates manifests for the provided libraries.
*
* It assumes that the engine-runner/assembly task is up to date (as it uses
* its artifacts).
*
* @param javaOpts The java options to pass to the manifest generator.
*/
def generateManifests(
libraries: Seq[BundledLibrary],
distributionRoot: File,
log: Logger,
javaOpts: Seq[String],
cacheStoreFactory: CacheStoreFactory
): Unit =
for (BundledLibrary(qualifiedName, version) <- libraries) {
val (namespace, name) = qualifiedName.split('.') match {
case Array(namespace, name) => (namespace, name)
case _ =>
throw new IllegalArgumentException(
s"Invalid library name [$qualifiedName]."
)
}
val projectPath =
distributionRoot / "lib" / namespace / name / version
val store =
cacheStoreFactory.make(s"library-manifest-$namespace-$name-$version")
val sources = (projectPath / "src").allPaths.get
Tracked.diffInputs(store, FileInfo.hash)(sources.toSet) { diff =>
def manifestExists = (projectPath / "manifest.yaml").exists()
if (diff.modified.nonEmpty || !manifestExists) {
log.info(s"Regenerating manifest for [$projectPath].")
runGenerator(projectPath, javaOpts, log)
} else {
log.debug(s"[$projectPath] manifest is up to date.")
}
}
}
private def runGenerator(
projectPath: File,
javaOpts: Seq[String],
log: Logger
): Unit = {
val javaCommand =
ProcessHandle.current().info().command().asScala.getOrElse("java")
val command = Seq(
javaCommand
) ++ javaOpts ++ Seq(
"--update-manifest",
"--in-project",
projectPath.getCanonicalPath
)
log.debug(s"Running [$command].")
val exitCode = sys.process
.Process(
command,
None,
"ENSO_EDITION_PATH" -> file("distribution/editions").getCanonicalPath
)
.!
if (exitCode != 0) {
val message = s"Command [$command] has failed with code $exitCode."
log.error(message)
throw new RuntimeException(message)
}
}
}