mirror of
https://github.com/enso-org/enso.git
synced 2024-11-22 03:32:23 +03:00
--jvm tries to find Java executable system-wide. (#11500)
Fixes `--jvm` option, given to the native image. This was failing on my machine, because when given `--jvm` option, the runner was trying to find the `java` executable from the distribution manager's runtime (on my system located in `~/.local/share/enso/runtime`) and it used the first runtime found. But the first runtime on my system is JDK 17. The `--jvm` option now tries to: - Find a JDK from the distribution manager that has the same version as the JDK used for building the engine. - If there is not an exact version match, it tries to find a runtime from distribution manager that is *newer*. - If none, fallback to system-wide search - System-wide search tries to find `java` from `$JAVA_HOME` and from `$PATH`. But this is just a fallback. # Important Notes - Added test to Engine CI jobs that pass `--jvm` argument to a native image of engine-runner -ea3af5ffbc
- `runtime-version-manager` sbt project migrated to a JPMS module - `engine-runner` now depends on `runtime-version-manager`. - Removed unnecessary stuff in `runtime-version-manager` dealing with outdated `gu` Graal Updater utility. - Extracted [GraalVersionManager](1455b025cb/lib/scala/runtime-version-manager/src/main/java/org/enso/runtimeversionmanager/components/GraalVersionManager.java
) from [RuntimeVersionManager](d2e8994700/lib/scala/runtime-version-manager/src/main/scala/org/enso/runtimeversionmanager/components/RuntimeVersionManager.scala
)
This commit is contained in:
parent
e5da7c816c
commit
7d3a4aa76e
29
build.sbt
29
build.sbt
@ -721,6 +721,7 @@ lazy val componentModulesPaths =
|
||||
(`runtime-instrument-runtime-server` / Compile / exportedModuleBin).value,
|
||||
(`runtime-language-arrow` / Compile / exportedModuleBin).value,
|
||||
(`runtime-language-epb` / Compile / exportedModuleBin).value,
|
||||
(`runtime-version-manager` / Compile / exportedModuleBin).value,
|
||||
(`persistance` / Compile / exportedModuleBin).value,
|
||||
(`cli` / Compile / exportedModuleBin).value,
|
||||
(`json-rpc-server` / Compile / exportedModuleBin).value,
|
||||
@ -1613,7 +1614,8 @@ lazy val `version-output` = (project in file("lib/scala/version-output"))
|
||||
defaultDevEnsoVersion = defaultDevEnsoVersion,
|
||||
ensoVersion = ensoVersion,
|
||||
scalacVersion = scalacVersion,
|
||||
graalVersion = graalVersion,
|
||||
graalVersion = graalMavenPackagesVersion,
|
||||
javaVersion = graalVersion,
|
||||
currentEdition = currentEdition
|
||||
)
|
||||
}.taskValue
|
||||
@ -3525,6 +3527,7 @@ lazy val `engine-runner` = project
|
||||
(`pkg` / Compile / exportedModule).value,
|
||||
(`engine-runner-common` / Compile / exportedModule).value,
|
||||
(`runtime-parser` / Compile / exportedModule).value,
|
||||
(`runtime-version-manager` / Compile / exportedModule).value,
|
||||
(`version-output` / Compile / exportedModule).value,
|
||||
(`engine-common` / Compile / exportedModule).value,
|
||||
(`polyglot-api` / Compile / exportedModule).value,
|
||||
@ -3700,6 +3703,7 @@ lazy val `engine-runner` = project
|
||||
.dependsOn(`distribution-manager`)
|
||||
.dependsOn(`edition-updater`)
|
||||
.dependsOn(`runtime-parser`)
|
||||
.dependsOn(`runtime-version-manager`)
|
||||
.dependsOn(`logging-service`)
|
||||
.dependsOn(`logging-service-logback` % Runtime)
|
||||
.dependsOn(`engine-runner-common`)
|
||||
@ -4337,15 +4341,34 @@ lazy val `connected-lock-manager-server` = project
|
||||
|
||||
lazy val `runtime-version-manager` = project
|
||||
.in(file("lib/scala/runtime-version-manager"))
|
||||
.enablePlugins(JPMSPlugin)
|
||||
.configs(Test)
|
||||
.settings(
|
||||
frgaalJavaCompilerSetting,
|
||||
scalaModuleDependencySetting,
|
||||
mixedJavaScalaProjectSetting,
|
||||
resolvers += Resolver.bintrayRepo("gn0s1s", "releases"),
|
||||
libraryDependencies ++= Seq(
|
||||
"com.typesafe.scala-logging" %% "scala-logging" % scalaLoggingVersion,
|
||||
"org.apache.commons" % "commons-compress" % commonsCompressVersion,
|
||||
"org.scalatest" %% "scalatest" % scalatestVersion % Test,
|
||||
akkaHttp
|
||||
"org.scalatest" %% "scalatest" % scalatestVersion % Test
|
||||
),
|
||||
Compile / moduleDependencies ++= Seq(
|
||||
"org.apache.commons" % "commons-compress" % commonsCompressVersion,
|
||||
"org.slf4j" % "slf4j-api" % slf4jVersion
|
||||
),
|
||||
Compile / internalModuleDependencies := Seq(
|
||||
(`cli` / Compile / exportedModule).value,
|
||||
(`distribution-manager` / Compile / exportedModule).value,
|
||||
(`downloader` / Compile / exportedModule).value,
|
||||
(`editions` / Compile / exportedModule).value,
|
||||
(`edition-updater` / Compile / exportedModule).value,
|
||||
(`logging-utils` / Compile / exportedModule).value,
|
||||
(`pkg` / Compile / exportedModule).value,
|
||||
(`semver` / Compile / exportedModule).value,
|
||||
(`scala-libs-wrapper` / Compile / exportedModule).value,
|
||||
(`scala-yaml` / Compile / exportedModule).value,
|
||||
(`version-output` / Compile / exportedModule).value
|
||||
)
|
||||
)
|
||||
.dependsOn(pkg)
|
||||
|
@ -664,6 +664,7 @@ pub async fn runner_sanity_test(
|
||||
.bin
|
||||
.join("enso")
|
||||
.with_executable_extension();
|
||||
|
||||
let test_base = Command::new(&enso)
|
||||
.args(["--run", repo_root.test.join("Base_Tests").as_str()])
|
||||
.set_env(ENSO_DATA_DIRECTORY, engine_package)?
|
||||
@ -686,7 +687,25 @@ pub async fn runner_sanity_test(
|
||||
.run_ok()
|
||||
.await;
|
||||
|
||||
test_base.and(test_internal_base).and(test_geo)
|
||||
let all_cmds = test_base.and(test_internal_base).and(test_geo);
|
||||
|
||||
// The following test does not actually run anything, it just checks if the engine
|
||||
// can accept `--jvm` argument and evaluates something.
|
||||
if TARGET_OS != OS::Windows {
|
||||
let test_jvm_arg = Command::new(&enso)
|
||||
.args([
|
||||
"--jvm",
|
||||
"--run",
|
||||
repo_root.test.join("Base_Tests").as_str(),
|
||||
"__NON_EXISTING_TEST__",
|
||||
])
|
||||
.set_env(ENSO_DATA_DIRECTORY, engine_package)?
|
||||
.run_ok()
|
||||
.await;
|
||||
all_cmds.and(test_jvm_arg)
|
||||
} else {
|
||||
all_cmds
|
||||
}
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
|
@ -36,21 +36,6 @@ The license file can be found at `licenses/APACHE2.0`.
|
||||
Copyright notices related to this dependency can be found in the directory `com.typesafe.akka.akka-actor_2.13-2.6.20`.
|
||||
|
||||
|
||||
'akka-http-core_2.13', licensed under the Apache-2.0, is distributed with the launcher.
|
||||
The license file can be found at `licenses/APACHE2.0`.
|
||||
Copyright notices related to this dependency can be found in the directory `com.typesafe.akka.akka-http-core_2.13-10.2.10`.
|
||||
|
||||
|
||||
'akka-http_2.13', licensed under the Apache-2.0, is distributed with the launcher.
|
||||
The license file can be found at `licenses/APACHE2.0`.
|
||||
Copyright notices related to this dependency can be found in the directory `com.typesafe.akka.akka-http_2.13-10.2.10`.
|
||||
|
||||
|
||||
'akka-parsing_2.13', licensed under the Apache-2.0, is distributed with the launcher.
|
||||
The license file can be found at `licenses/APACHE2.0`.
|
||||
Copyright notices related to this dependency can be found in the directory `com.typesafe.akka.akka-parsing_2.13-10.2.10`.
|
||||
|
||||
|
||||
'akka-slf4j_2.13', licensed under the Apache-2.0, is distributed with the launcher.
|
||||
The license file can be found at `licenses/APACHE2.0`.
|
||||
Copyright notices related to this dependency can be found in the directory `com.typesafe.akka.akka-slf4j_2.13-2.6.20`.
|
||||
|
@ -1,11 +0,0 @@
|
||||
Copyright (C) 2008-2017 Bjoern Hoehrmann <bjoern@hoehrmann.de>
|
||||
|
||||
Copyright (C) 2009-2017 Mathias Doenitz, Alexander Myltsev
|
||||
|
||||
Copyright (C) 2009-2022 Lightbend Inc. <https://www.lightbend.com>
|
||||
|
||||
Copyright 2011 Mark Harrah, Eugene Yokota
|
||||
|
||||
Copyright 2014 Twitter, Inc.
|
||||
|
||||
Copyright 2015 Heiko Seeberger
|
@ -1 +0,0 @@
|
||||
Copyright (C) 2009-2020 Lightbend Inc. <http://www.lightbend.com>
|
@ -1,7 +0,0 @@
|
||||
Copyright (C) 2009-2017 Mathias Doenitz, Alexander Myltsev
|
||||
|
||||
Copyright (C) 2009-2022 Lightbend Inc. <https://www.lightbend.com>
|
||||
|
||||
Copyright (c) 2004, Mikael Grev, MiG InfoCom AB. (base64 @ miginfocom . com)
|
||||
|
||||
Copyright (c) 2011-13 Miles Sabin
|
@ -39,10 +39,6 @@ object DefaultManagers {
|
||||
lazy val temporaryDirectoryManager =
|
||||
TemporaryDirectoryManager(distributionManager, defaultResourceManager)
|
||||
|
||||
/** Default [[RuntimeComponentConfiguration]]. */
|
||||
lazy val componentConfig: RuntimeComponentConfiguration =
|
||||
new GraalVMComponentConfiguration
|
||||
|
||||
/** Creates a [[RuntimeVersionManager]] that uses the default distribution. */
|
||||
def runtimeVersionManager(
|
||||
globalCLIOptions: GlobalCLIOptions,
|
||||
@ -55,12 +51,11 @@ object DefaultManagers {
|
||||
alwaysInstallMissing
|
||||
),
|
||||
distributionManager,
|
||||
new GraalVersionManager(distributionManager, LauncherEnvironment),
|
||||
temporaryDirectoryManager,
|
||||
defaultResourceManager,
|
||||
EngineRepository.defaultEngineReleaseProvider,
|
||||
GraalCEReleaseProvider.default,
|
||||
componentConfig,
|
||||
RuntimeComponentUpdaterFactory.Default,
|
||||
InstallerKind.Launcher
|
||||
)
|
||||
}
|
||||
|
@ -9,6 +9,7 @@ module org.enso.runner {
|
||||
requires org.enso.logging.config;
|
||||
requires org.enso.logging.utils;
|
||||
requires org.enso.runtime.parser;
|
||||
requires org.enso.runtime.version.manager;
|
||||
requires org.enso.runner.common;
|
||||
requires org.enso.pkg;
|
||||
requires org.enso.polyglot.api;
|
||||
|
110
engine/runner/src/main/java/org/enso/runner/JavaFinder.java
Normal file
110
engine/runner/src/main/java/org/enso/runner/JavaFinder.java
Normal file
@ -0,0 +1,110 @@
|
||||
package org.enso.runner;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Comparator;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import org.enso.distribution.DistributionManager;
|
||||
import org.enso.distribution.Environment;
|
||||
import org.enso.runtimeversionmanager.components.GraalRuntime;
|
||||
import org.enso.runtimeversionmanager.components.GraalVMVersion;
|
||||
import org.enso.runtimeversionmanager.components.GraalVersionManager;
|
||||
import org.enso.version.BuildVersion;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/** Utility class that tries to find installed JDK on the system. */
|
||||
final class JavaFinder {
|
||||
private static final Logger logger = LoggerFactory.getLogger(JavaFinder.class);
|
||||
|
||||
private JavaFinder() {}
|
||||
|
||||
/**
|
||||
* Tries to find {@code java} executable on the system. If a system-wide JDK is not found, tries
|
||||
* to find it in the {@link DistributionManager distribution} runtimes.
|
||||
*
|
||||
* @return null if cannot be found. Otherwise, returns the absolute path to the executable, or
|
||||
* simply {@code java} if it is on the {@code PATH}.
|
||||
*/
|
||||
static String findJavaExecutable() {
|
||||
var javaInRuntime = findJavaExecutableInDistributionRuntimes();
|
||||
if (javaInRuntime != null) {
|
||||
return javaInRuntime.toAbsolutePath().toString();
|
||||
}
|
||||
logger.warn("No appropriate JDK found in the distribution runtimes. Trying system-wide JDK.");
|
||||
var javaHome = System.getenv("JAVA_HOME");
|
||||
if (javaHome != null) {
|
||||
var binDir = Path.of(javaHome).resolve("bin");
|
||||
Path javaExe;
|
||||
if (isOnWindows()) {
|
||||
javaExe = binDir.resolve("java.exe");
|
||||
} else {
|
||||
javaExe = binDir.resolve("java");
|
||||
}
|
||||
if (javaExe.toFile().exists()) {
|
||||
logger.warn("Found JDK in JAVA_HOME: {}", javaHome);
|
||||
return javaExe.toAbsolutePath().toString();
|
||||
}
|
||||
}
|
||||
logger.warn("No JDK found in JAVA_HOME. Trying java on PATH.");
|
||||
if (isJavaOnPath()) {
|
||||
var javaExe = isOnWindows() ? "java.exe" : "java";
|
||||
logger.warn("Falling back to java on PATH: {}", javaExe);
|
||||
return javaExe;
|
||||
}
|
||||
logger.warn("No JDK found on PATH. Cannot start the runtime.");
|
||||
return null;
|
||||
}
|
||||
|
||||
private static boolean isOnWindows() {
|
||||
return System.getProperty("os.name").equals("windows");
|
||||
}
|
||||
|
||||
/**
|
||||
* Tries to find {@code java} executable in the distribution runtime with the same version that
|
||||
* was used for building, or a newer one.
|
||||
*
|
||||
* @return null if not found.
|
||||
*/
|
||||
private static Path findJavaExecutableInDistributionRuntimes() {
|
||||
var env = new Environment() {};
|
||||
var distributionManager = new DistributionManager(env);
|
||||
var graalVersionManager = new GraalVersionManager(distributionManager, env);
|
||||
var versionUsedForBuild =
|
||||
new GraalVMVersion(BuildVersion.graalVersion(), BuildVersion.javaVersion());
|
||||
var runtimeWithExactVersionMatch = graalVersionManager.findGraalRuntime(versionUsedForBuild);
|
||||
if (runtimeWithExactVersionMatch != null) {
|
||||
return runtimeWithExactVersionMatch.javaExecutable();
|
||||
}
|
||||
// Try to find newer runtime (JDK).
|
||||
var newerRuntime =
|
||||
graalVersionManager.getAllRuntimes().stream()
|
||||
.sorted(Comparator.comparing(GraalRuntime::version))
|
||||
.filter(runtime -> runtime.version().compareTo(versionUsedForBuild) > 0)
|
||||
.findFirst();
|
||||
if (newerRuntime.isPresent()) {
|
||||
logger.warn(
|
||||
"Found newer JDK [{}] than the one used for build [{}]",
|
||||
newerRuntime.get().version(),
|
||||
versionUsedForBuild);
|
||||
return newerRuntime.get().javaExecutable();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static boolean isJavaOnPath() {
|
||||
try {
|
||||
ProcessBuilder processBuilder;
|
||||
if (isOnWindows()) {
|
||||
processBuilder = new ProcessBuilder("java.exe", "-h");
|
||||
} else {
|
||||
processBuilder = new ProcessBuilder("java", "-h");
|
||||
}
|
||||
Process process = processBuilder.start();
|
||||
boolean exitSucc = process.waitFor(5L, TimeUnit.SECONDS);
|
||||
return exitSucc;
|
||||
} catch (IOException | InterruptedException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
@ -1339,22 +1339,13 @@ public class Main {
|
||||
println(JVM_OPTION + " option has no effect - already running in JVM " + current);
|
||||
} else {
|
||||
var commandAndArgs = new ArrayList<String>();
|
||||
JVM_FOUND:
|
||||
if (jvm == null) {
|
||||
var env = new Environment() {};
|
||||
var dm = new DistributionManager(env);
|
||||
var paths = dm.paths();
|
||||
var files = paths.runtimes().toFile().listFiles();
|
||||
if (files != null) {
|
||||
for (var d : files) {
|
||||
var java = new File(new File(d, "bin"), "java").getAbsoluteFile();
|
||||
if (java.exists()) {
|
||||
commandAndArgs.add(java.getPath());
|
||||
break JVM_FOUND;
|
||||
}
|
||||
}
|
||||
var javaExe = JavaFinder.findJavaExecutable();
|
||||
if (javaExe == null) {
|
||||
println("Cannot find java executable");
|
||||
throw exitFail();
|
||||
}
|
||||
commandAndArgs.add("java");
|
||||
commandAndArgs.add(javaExe);
|
||||
} else {
|
||||
commandAndArgs.add(new File(new File(new File(jvm), "bin"), "java").getAbsolutePath());
|
||||
}
|
||||
|
@ -52,12 +52,6 @@ object DefaultDistributionConfiguration
|
||||
lazy val temporaryDirectoryManager =
|
||||
TemporaryDirectoryManager(distributionManager, resourceManager)
|
||||
|
||||
lazy val componentConfiguration: RuntimeComponentConfiguration =
|
||||
new GraalVMComponentConfiguration
|
||||
|
||||
lazy val runtimeComponentUpdaterFactory: RuntimeComponentUpdaterFactory =
|
||||
RuntimeComponentUpdaterFactory.Default
|
||||
|
||||
/** @inheritdoc */
|
||||
def engineReleaseProvider: ReleaseProvider[EngineRelease] =
|
||||
EngineRepository.defaultEngineReleaseProvider
|
||||
@ -67,15 +61,15 @@ object DefaultDistributionConfiguration
|
||||
userInterface: RuntimeVersionManagementUserInterface
|
||||
): RuntimeVersionManager =
|
||||
new RuntimeVersionManager(
|
||||
environment = this.environment,
|
||||
userInterface = userInterface,
|
||||
distributionManager = distributionManager,
|
||||
environment = this.environment,
|
||||
userInterface = userInterface,
|
||||
distributionManager = distributionManager,
|
||||
graalVersionManager =
|
||||
new GraalVersionManager(distributionManager, environment),
|
||||
temporaryDirectoryManager = temporaryDirectoryManager,
|
||||
resourceManager = resourceManager,
|
||||
engineReleaseProvider = engineReleaseProvider,
|
||||
runtimeReleaseProvider = GraalCEReleaseProvider.default,
|
||||
componentConfig = componentConfiguration,
|
||||
componentUpdaterFactory = runtimeComponentUpdaterFactory,
|
||||
installerKind = InstallerKind.ProjectManager
|
||||
)
|
||||
|
||||
|
@ -7,7 +7,7 @@ import org.enso.editions.updater.EditionManager
|
||||
import java.nio.file.Path
|
||||
import org.enso.projectmanager.versionmanagement.DistributionConfiguration
|
||||
import org.enso.runtimeversionmanager.components.{
|
||||
GraalVMComponentConfiguration,
|
||||
GraalVersionManager,
|
||||
InstallerKind,
|
||||
RuntimeVersionManagementUserInterface,
|
||||
RuntimeVersionManager
|
||||
@ -28,7 +28,6 @@ import org.enso.runtimeversionmanager.releases.{
|
||||
import org.enso.runtimeversionmanager.runner.{JVMSettings, JavaCommand}
|
||||
import org.enso.runtimeversionmanager.test.{
|
||||
FakeEnvironment,
|
||||
NoopComponentUpdaterFactory,
|
||||
TestLocalLockManager
|
||||
}
|
||||
import org.enso.testkit.HasTestDirectory
|
||||
@ -60,6 +59,9 @@ class TestDistributionConfiguration(
|
||||
|
||||
lazy val distributionManager = new DistributionManager(environment)
|
||||
|
||||
lazy val graalVersionManager =
|
||||
new GraalVersionManager(distributionManager, environment)
|
||||
|
||||
lazy val lockManager = new TestLocalLockManager
|
||||
|
||||
lazy val resourceManager = new ResourceManager(lockManager)
|
||||
@ -69,10 +71,6 @@ class TestDistributionConfiguration(
|
||||
lazy val temporaryDirectoryManager =
|
||||
TemporaryDirectoryManager(distributionManager, resourceManager)
|
||||
|
||||
lazy val componentConfig = new GraalVMComponentConfiguration
|
||||
|
||||
lazy val componentUpdaterFactory = NoopComponentUpdaterFactory
|
||||
|
||||
override def makeRuntimeVersionManager(
|
||||
userInterface: RuntimeVersionManagementUserInterface
|
||||
): RuntimeVersionManager = new RuntimeVersionManager(
|
||||
@ -80,11 +78,10 @@ class TestDistributionConfiguration(
|
||||
userInterface = userInterface,
|
||||
distributionManager = distributionManager,
|
||||
temporaryDirectoryManager = temporaryDirectoryManager,
|
||||
graalVersionManager = graalVersionManager,
|
||||
resourceManager = resourceManager,
|
||||
engineReleaseProvider = engineReleaseProvider,
|
||||
runtimeReleaseProvider = runtimeReleaseProvider,
|
||||
componentConfig = componentConfig,
|
||||
componentUpdaterFactory = componentUpdaterFactory,
|
||||
installerKind = InstallerKind.ProjectManager
|
||||
)
|
||||
|
||||
|
@ -1,20 +0,0 @@
|
||||
package org.enso.runtimeversionmanager.test
|
||||
|
||||
import org.enso.runtimeversionmanager.components.{
|
||||
GraalVMComponent,
|
||||
RuntimeComponentUpdater
|
||||
}
|
||||
|
||||
import scala.util.Try
|
||||
|
||||
/** Test component updater that does not do anything. */
|
||||
object NoopComponentUpdater extends RuntimeComponentUpdater {
|
||||
|
||||
/** @inheritdoc */
|
||||
override def list(): Try[Seq[GraalVMComponent]] =
|
||||
Try(Seq())
|
||||
|
||||
/** @inheritdoc */
|
||||
override def install(components: Seq[GraalVMComponent]): Try[Unit] =
|
||||
Try(())
|
||||
}
|
@ -1,15 +0,0 @@
|
||||
package org.enso.runtimeversionmanager.test
|
||||
|
||||
import org.enso.runtimeversionmanager.components.{
|
||||
GraalRuntime,
|
||||
RuntimeComponentUpdater,
|
||||
RuntimeComponentUpdaterFactory
|
||||
}
|
||||
|
||||
/** Test factory creating a noop updater. */
|
||||
object NoopComponentUpdaterFactory extends RuntimeComponentUpdaterFactory {
|
||||
|
||||
/** @inheritdoc */
|
||||
override def build(runtime: GraalRuntime): RuntimeComponentUpdater =
|
||||
NoopComponentUpdater
|
||||
}
|
@ -9,7 +9,7 @@ import org.enso.distribution.{
|
||||
}
|
||||
import org.enso.pkg.{Config, PackageManager}
|
||||
import org.enso.runtimeversionmanager.components.{
|
||||
GraalVMComponentConfiguration,
|
||||
GraalVersionManager,
|
||||
InstallerKind,
|
||||
RuntimeVersionManagementUserInterface,
|
||||
RuntimeVersionManager
|
||||
@ -51,22 +51,21 @@ class RuntimeVersionManagerTest
|
||||
): (DistributionManager, RuntimeVersionManager, Environment) = {
|
||||
val env = fakeInstalledEnvironment(environmentOverrides)
|
||||
val distributionManager = new PortableDistributionManager(env)
|
||||
val graalVersionManager = new GraalVersionManager(distributionManager, env)
|
||||
|
||||
val resourceManager = TestLocalResourceManager.create()
|
||||
val temporaryDirectoryManager =
|
||||
TemporaryDirectoryManager(distributionManager, resourceManager)
|
||||
val componentConfig = new GraalVMComponentConfiguration
|
||||
|
||||
val runtimeVersionManager = new RuntimeVersionManager(
|
||||
env,
|
||||
userInterface,
|
||||
distributionManager,
|
||||
graalVersionManager,
|
||||
temporaryDirectoryManager,
|
||||
resourceManager,
|
||||
engineProvider,
|
||||
runtimeProvider,
|
||||
componentConfig,
|
||||
NoopComponentUpdaterFactory,
|
||||
installerKind
|
||||
)
|
||||
|
||||
|
@ -9,8 +9,8 @@ import org.enso.distribution.{
|
||||
TemporaryDirectoryManager
|
||||
}
|
||||
import org.enso.runtimeversionmanager.components.{
|
||||
GraalVMComponentConfiguration,
|
||||
GraalVMVersion,
|
||||
GraalVersionManager,
|
||||
InstallerKind,
|
||||
Manifest,
|
||||
RuntimeVersionManager
|
||||
@ -140,19 +140,18 @@ class ConcurrencyTest
|
||||
}
|
||||
}
|
||||
|
||||
val graalVersionManager = new GraalVersionManager(distributionManager, env)
|
||||
val temporaryDirectoryManager =
|
||||
TemporaryDirectoryManager(distributionManager, resourceManager)
|
||||
val componentConfig = new GraalVMComponentConfiguration
|
||||
val componentsManager = new RuntimeVersionManager(
|
||||
env,
|
||||
TestRuntimeVersionManagementUserInterface.default,
|
||||
distributionManager,
|
||||
graalVersionManager,
|
||||
temporaryDirectoryManager,
|
||||
resourceManager,
|
||||
engineProvider,
|
||||
runtimeProvider,
|
||||
componentConfig,
|
||||
NoopComponentUpdaterFactory,
|
||||
InstallerKind.Launcher
|
||||
)
|
||||
|
||||
|
@ -0,0 +1,22 @@
|
||||
module org.enso.runtime.version.manager {
|
||||
requires scala.library;
|
||||
requires org.apache.commons.compress;
|
||||
requires org.slf4j;
|
||||
requires org.enso.cli;
|
||||
requires org.enso.distribution;
|
||||
requires org.enso.downloader;
|
||||
requires org.enso.editions;
|
||||
requires org.enso.editions.updater;
|
||||
requires org.enso.logging.utils;
|
||||
requires org.enso.pkg;
|
||||
requires org.enso.semver;
|
||||
requires org.enso.scala.yaml;
|
||||
// For com.typesafe.scalalogging.Logger
|
||||
requires org.enso.scala.wrapper;
|
||||
requires org.enso.version.output;
|
||||
|
||||
exports org.enso.runtimeversionmanager;
|
||||
exports org.enso.runtimeversionmanager.cli;
|
||||
exports org.enso.runtimeversionmanager.components;
|
||||
exports org.enso.runtimeversionmanager.runner;
|
||||
}
|
@ -0,0 +1,140 @@
|
||||
package org.enso.runtimeversionmanager.components;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.regex.Pattern;
|
||||
import org.enso.distribution.DistributionManager;
|
||||
import org.enso.distribution.Environment;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import scala.jdk.javaapi.CollectionConverters;
|
||||
|
||||
/**
|
||||
* Utility class that finds installed managed runtimes (Graal JDK) from {@link DistributionManager}.
|
||||
*/
|
||||
public final class GraalVersionManager {
|
||||
private final DistributionManager distributionManager;
|
||||
private final Environment environment;
|
||||
private static final Logger logger = LoggerFactory.getLogger(GraalVersionManager.class);
|
||||
|
||||
public GraalVersionManager(DistributionManager distributionManager, Environment environment) {
|
||||
this.distributionManager = distributionManager;
|
||||
this.environment = environment;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all locally installed runtimes.
|
||||
*
|
||||
* @return Possibly empty list. Not null.
|
||||
*/
|
||||
public List<GraalRuntime> getAllRuntimes() {
|
||||
var foundRuntimes = new ArrayList<GraalRuntime>();
|
||||
for (var runtimeSearchPath :
|
||||
CollectionConverters.asJava(distributionManager.paths().runtimeSearchPaths())) {
|
||||
if (runtimeSearchPath.toFile().isDirectory()) {
|
||||
var subdirs = runtimeSearchPath.toFile().listFiles();
|
||||
assert subdirs != null;
|
||||
for (var subdir : subdirs) {
|
||||
var parsedVersion = parseGraalRuntimeVersionString(subdir.getName());
|
||||
if (parsedVersion != null) {
|
||||
var foundRuntime = new GraalRuntime(parsedVersion, subdir.toPath());
|
||||
foundRuntime.ensureValid();
|
||||
foundRuntimes.add(foundRuntime);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
logger.warn("Runtime search path `{}` is not a directory", runtimeSearchPath);
|
||||
}
|
||||
}
|
||||
return foundRuntimes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tries to find a GraalVM runtime for the provided engine.
|
||||
*
|
||||
* <p>Returns null if the runtime is missing.
|
||||
*/
|
||||
public GraalRuntime findGraalRuntime(Engine engine) {
|
||||
return findGraalRuntime(engine.manifest().runtimeVersion());
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds an installed GraalVM runtime with the given {@code version}.
|
||||
*
|
||||
* <p>Returns null if that version is not installed.
|
||||
*/
|
||||
public GraalRuntime findGraalRuntime(GraalVMVersion version) {
|
||||
var explicitPathOpt = environment.getEnvPath("ENSO_JVM_PATH");
|
||||
if (explicitPathOpt.isDefined()) {
|
||||
var runtime = new GraalRuntime(version, explicitPathOpt.get());
|
||||
runtime.ensureValid();
|
||||
logger.debug("Found GraalVM runtime [{}]", runtime);
|
||||
return runtime;
|
||||
}
|
||||
var pathOpt = findGraalRuntimeOnSearchPath(version);
|
||||
if (pathOpt != null) {
|
||||
GraalRuntime runtime;
|
||||
try {
|
||||
runtime = loadGraalRuntime(pathOpt);
|
||||
} catch (Exception e) {
|
||||
throw new UnrecognizedComponentError(
|
||||
"The runtime "
|
||||
+ version
|
||||
+ "is already installed, but cannot be "
|
||||
+ "loaded due to "
|
||||
+ e.getMessage()
|
||||
+ "."
|
||||
+ "Until the launcher gets an auto-repair "
|
||||
+ "feature, please try reinstalling the runtime by "
|
||||
+ "uninstalling all engines that use it and installing them "
|
||||
+ "again, or manually removing `"
|
||||
+ pathOpt
|
||||
+ "`",
|
||||
e);
|
||||
}
|
||||
logger.debug("Found GraalVM runtime [{}]", runtime);
|
||||
return runtime;
|
||||
}
|
||||
logger.debug("GraalVM runtime [{}] not found", version);
|
||||
return null;
|
||||
}
|
||||
|
||||
public GraalRuntime loadGraalRuntime(Path path) throws UnrecognizedComponentError {
|
||||
logger.debug("Loading Graal runtime [{}]", path);
|
||||
var name = path.getFileName().toString();
|
||||
var version = parseGraalRuntimeVersionString(name);
|
||||
if (version == null) {
|
||||
throw new UnrecognizedComponentError("Invalid runtime component name `" + name + "`", null);
|
||||
}
|
||||
var runtime = new GraalRuntime(version, path);
|
||||
runtime.ensureValid();
|
||||
return runtime;
|
||||
}
|
||||
|
||||
private Path findGraalRuntimeOnSearchPath(GraalVMVersion version) {
|
||||
var name = graalRuntimeNameForVersion(version);
|
||||
for (var runtimeSearchPath :
|
||||
CollectionConverters.asJava(distributionManager.paths().runtimeSearchPaths())) {
|
||||
var path = runtimeSearchPath.resolve(name);
|
||||
if (path.toFile().exists()) {
|
||||
return path;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private GraalVMVersion parseGraalRuntimeVersionString(String name) {
|
||||
var pattern = Pattern.compile("graalvm-ce-java(.+)-(.+)");
|
||||
var matcher = pattern.matcher(name);
|
||||
if (matcher.matches()) {
|
||||
return new GraalVMVersion(matcher.group(2), matcher.group(1));
|
||||
}
|
||||
logger.warn("Unrecognized runtime name `{}`", name);
|
||||
return null;
|
||||
}
|
||||
|
||||
private static String graalRuntimeNameForVersion(GraalVMVersion version) {
|
||||
return "graalvm-ce-java" + version.javaVersion() + "-" + version.graalVersion();
|
||||
}
|
||||
}
|
@ -1 +0,0 @@
|
||||
package org.enso.runtimeversionmanager;
|
@ -1,6 +1,5 @@
|
||||
package org.enso.runtimeversionmanager.cli
|
||||
|
||||
import akka.http.scaladsl.model.{IllegalUriException, Uri}
|
||||
import org.enso.cli.arguments.{Argument, OptsParseError}
|
||||
import org.enso.logger.LoggerUtils
|
||||
|
||||
@ -9,14 +8,6 @@ import java.net.URISyntaxException
|
||||
import org.slf4j.event.Level
|
||||
|
||||
object Arguments {
|
||||
implicit val uriAkkaArgument: Argument[Uri] = (string: String) =>
|
||||
try {
|
||||
Right(Uri(string))
|
||||
} catch {
|
||||
case error: IllegalUriException =>
|
||||
Left(OptsParseError(s"`$string` is not a valid Uri: $error."))
|
||||
}
|
||||
|
||||
implicit val uriArgument: Argument[URI] = (string: String) =>
|
||||
try {
|
||||
Right(URI.create(string))
|
||||
|
@ -1,11 +0,0 @@
|
||||
package org.enso.runtimeversionmanager.components
|
||||
|
||||
/** A component of the GraalVM distribution. */
|
||||
case class GraalVMComponent(id: String)
|
||||
|
||||
object GraalVMComponent {
|
||||
|
||||
val js: GraalVMComponent = GraalVMComponent("js")
|
||||
val python: GraalVMComponent = GraalVMComponent("python")
|
||||
val R: GraalVMComponent = GraalVMComponent("R")
|
||||
}
|
@ -1,89 +0,0 @@
|
||||
package org.enso.runtimeversionmanager.components
|
||||
|
||||
import org.enso.cli.OS
|
||||
|
||||
/** Component configuration of the GraalVM distribution. */
|
||||
class GraalVMComponentConfiguration extends RuntimeComponentConfiguration {
|
||||
|
||||
import GraalVMComponentConfiguration._
|
||||
|
||||
/** @inheritdoc */
|
||||
override def getRequiredComponents(
|
||||
version: GraalVMVersion,
|
||||
os: OS
|
||||
): Seq[GraalVMComponent] = {
|
||||
val optPythonComponent =
|
||||
if (os.hasPythonSupport) Seq(GraalVMComponent.python) else Seq()
|
||||
val optRComponent =
|
||||
if (os.hasRSupport) Seq(GraalVMComponent.R) else Seq()
|
||||
if (version.isUnchained) {
|
||||
Seq()
|
||||
} else {
|
||||
version.graalVersion match {
|
||||
case GraalVersions.Major(v) if v >= 23 =>
|
||||
// Since 23.0.0, R is not bundled in the Graal release anymore.
|
||||
Seq(GraalVMComponent.js) ++ optPythonComponent
|
||||
case GraalVersions.Major(v) if v >= 22 =>
|
||||
Seq(GraalVMComponent.js) ++ optRComponent ++ optPythonComponent
|
||||
case GraalVersions.Major(v)
|
||||
if v > 20 && os.hasSulongSupport && os.hasRSupport =>
|
||||
Seq(GraalVMComponent.R) ++ optPythonComponent
|
||||
case _ =>
|
||||
Seq()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
object GraalVMComponentConfiguration {
|
||||
|
||||
/** OS extensions. */
|
||||
implicit private class OSExtensions(os: OS) {
|
||||
|
||||
/** Check if the provided OS supports Sulong runtime.
|
||||
*
|
||||
* Sulong is a Graal sub-project, providing an engine for running
|
||||
* LLVM bitcode on GraalVM.
|
||||
*
|
||||
* @return `true` if the OS supports Sulong runtime and `false` otherwise
|
||||
*/
|
||||
def hasSulongSupport: Boolean =
|
||||
os match {
|
||||
case OS.Linux => true
|
||||
case OS.MacOS => true
|
||||
case OS.Windows => false
|
||||
}
|
||||
|
||||
/** Check if the provided OS supports Python.
|
||||
* Python is currently not supported in any form on Windows.
|
||||
*
|
||||
* @return `true` if the OS supports Python runtime
|
||||
*/
|
||||
def hasPythonSupport: Boolean =
|
||||
os match {
|
||||
case OS.Windows => false
|
||||
case _ => true
|
||||
}
|
||||
|
||||
/** Check if the provided OS supports FastR.
|
||||
* FastR is currently not supported in any form on Windows.
|
||||
*
|
||||
* @return `true` if the OS supports FastR GraalVM component.
|
||||
*/
|
||||
def hasRSupport: Boolean =
|
||||
os match {
|
||||
case OS.Windows => false
|
||||
case _ => true
|
||||
}
|
||||
}
|
||||
|
||||
private object GraalVersions {
|
||||
|
||||
/** Get the major Graal version number. */
|
||||
object Major {
|
||||
def unapply(version: String): Option[Int] = {
|
||||
version.takeWhile(_ != '.').toIntOption
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,180 +0,0 @@
|
||||
package org.enso.runtimeversionmanager.components
|
||||
|
||||
import java.nio.file.Path
|
||||
import com.typesafe.scalalogging.Logger
|
||||
|
||||
import scala.sys.process._
|
||||
import scala.util.{Failure, Success, Try}
|
||||
|
||||
/** Module that manages components of the GraalVM distribution.
|
||||
*
|
||||
* @param runtime the GraalVM runtime
|
||||
*/
|
||||
class GraalVMComponentUpdater(runtime: GraalRuntime)
|
||||
extends RuntimeComponentUpdater {
|
||||
|
||||
import GraalVMComponentUpdater._
|
||||
|
||||
private val logger = Logger[GraalVMComponentUpdater]
|
||||
private val gu = runtime.findExecutable("gu")
|
||||
|
||||
/** Path to the GraalVM's updater.
|
||||
*
|
||||
* @return path that will be executed to call the updater
|
||||
*/
|
||||
protected def updaterExec: Path = gu
|
||||
|
||||
/** List the installed GraalVM components.
|
||||
*
|
||||
* @return the list of installed GraalVM components
|
||||
*/
|
||||
override def list(): Try[Seq[GraalVMComponent]] = {
|
||||
val command = Seq("list", "-v")
|
||||
|
||||
logger.trace("{} {}", gu, Properties(gu))
|
||||
logger.debug(
|
||||
"Executing: JAVA_HOME={} GRAALVM_HOME={} {} {}",
|
||||
runtime.javaHome,
|
||||
runtime.javaHome,
|
||||
gu,
|
||||
command.mkString(" ")
|
||||
)
|
||||
|
||||
val executor = new ExponentialBackoffRetry(5, logger) {
|
||||
override def cmd: String = "list"
|
||||
override def executeProcess(
|
||||
logger: ProcessLogger
|
||||
): Try[LazyList[String]] = {
|
||||
val process = Process(
|
||||
updaterExec.toAbsolutePath.toString +: command,
|
||||
Some(runtime.javaHome.toFile),
|
||||
("JAVA_HOME", runtime.javaHome),
|
||||
("GRAALVM_HOME", runtime.javaHome)
|
||||
)
|
||||
Try(process.lazyLines(logger))
|
||||
}
|
||||
}
|
||||
executor
|
||||
.execute()
|
||||
.map(stdout => if (stdout.isEmpty) Seq() else ListOut.parse(stdout))
|
||||
}
|
||||
|
||||
/** Install the provided GraalVM components.
|
||||
*
|
||||
* @param components the list of components to install
|
||||
*/
|
||||
override def install(components: Seq[GraalVMComponent]): Try[Unit] = {
|
||||
if (components.nonEmpty) {
|
||||
val command = "install" +: components.map(_.id)
|
||||
logger.trace("{} {}", gu, Properties(gu))
|
||||
logger.debug(
|
||||
"Executing: JAVA_HOME={} GRRAALVM_HOME={} {} {}",
|
||||
runtime.javaHome,
|
||||
runtime.javaHome,
|
||||
gu,
|
||||
command.mkString(" ")
|
||||
)
|
||||
val executor = new ExponentialBackoffRetry(5, logger) {
|
||||
override def cmd: String = "install"
|
||||
override def executeProcess(
|
||||
logger: ProcessLogger
|
||||
): Try[LazyList[String]] = {
|
||||
val process = Process(
|
||||
updaterExec.toAbsolutePath.toString +: command,
|
||||
Some(runtime.path.toFile),
|
||||
("JAVA_HOME", runtime.javaHome),
|
||||
("GRAALVM_HOME", runtime.javaHome)
|
||||
)
|
||||
Try(process.lazyLines(logger))
|
||||
}
|
||||
}
|
||||
executor.execute().map { stdout =>
|
||||
stdout.foreach(logger.trace(_))
|
||||
()
|
||||
}
|
||||
} else {
|
||||
Success(())
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
object GraalVMComponentUpdater {
|
||||
|
||||
abstract class ProcessWithRetries(maxRetries: Int, logger: Logger) {
|
||||
def executeProcess(logger: ProcessLogger): Try[LazyList[String]]
|
||||
|
||||
def cmd: String
|
||||
|
||||
def execute(): Try[List[String]] = execute(0)
|
||||
|
||||
protected def retryWait(retry: Int): Long
|
||||
|
||||
private def execute(retry: Int): Try[List[String]] = {
|
||||
val errors = scala.collection.mutable.ListBuffer[String]()
|
||||
val processLogger = ProcessLogger(err => errors.addOne(err))
|
||||
executeProcess(processLogger) match {
|
||||
case Success(stdout) =>
|
||||
Try(stdout.toList).recoverWith({
|
||||
case _ if retry < maxRetries =>
|
||||
try {
|
||||
Thread.sleep(retryWait(retry))
|
||||
} catch {
|
||||
case _: InterruptedException =>
|
||||
}
|
||||
execute(retry + 1)
|
||||
})
|
||||
case Failure(exception) if retry < maxRetries =>
|
||||
logger.warn("{} failed: {}. Retrying...", cmd, exception.getMessage)
|
||||
try {
|
||||
Thread.sleep(retryWait(retry))
|
||||
} catch {
|
||||
case _: InterruptedException =>
|
||||
}
|
||||
execute(retry + 1)
|
||||
case Failure(exception) =>
|
||||
errors.foreach(logger.trace("[stderr] {}", _))
|
||||
Failure(exception)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
abstract class ExponentialBackoffRetry(maxRetries: Int, logger: Logger)
|
||||
extends ProcessWithRetries(maxRetries, logger) {
|
||||
override def retryWait(retry: Int): Long = {
|
||||
200 * 2.toLong ^ retry
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
implicit private def pathToString(path: Path): String =
|
||||
path.toAbsolutePath.toString
|
||||
|
||||
/** Debug file properties. */
|
||||
private case class Properties(path: Path) {
|
||||
|
||||
private val file = path.toFile
|
||||
|
||||
override def toString: String =
|
||||
s"{ exists=${file.exists()}, " +
|
||||
s"executable=${file.canExecute} " +
|
||||
"}"
|
||||
}
|
||||
|
||||
/** Parser for the `gu list -v` command output. */
|
||||
object ListOut {
|
||||
|
||||
private val ID: String = "ID"
|
||||
private val separator: Char = ':'
|
||||
|
||||
/** Extract the GraalVM components from the gu output.
|
||||
*
|
||||
* @param lines the gu output
|
||||
* @return the list of GraalVM components.
|
||||
*/
|
||||
def parse(lines: Seq[String]): Seq[GraalVMComponent] =
|
||||
lines
|
||||
.filter(_.startsWith(ID))
|
||||
.map(_.dropWhile(_ != separator).drop(1).trim)
|
||||
.map(GraalVMComponent(_))
|
||||
}
|
||||
}
|
@ -11,7 +11,8 @@ import org.enso.semver.SemVer
|
||||
* Can be specified either as a single integer or as a
|
||||
* semantic version
|
||||
*/
|
||||
case class GraalVMVersion(graalVersion: String, javaVersion: String) {
|
||||
case class GraalVMVersion(graalVersion: String, javaVersion: String)
|
||||
extends Comparable[GraalVMVersion] {
|
||||
require(GraalVMVersion.isCorrectVersionFormat(graalVersion))
|
||||
require(GraalVMVersion.isCorrectVersionFormat(javaVersion))
|
||||
|
||||
@ -29,15 +30,35 @@ case class GraalVMVersion(graalVersion: String, javaVersion: String) {
|
||||
}
|
||||
}
|
||||
|
||||
/** The GraalVM distribution policy changed a lot since GraalVM 23.1.0 for JDK 21.
|
||||
* Most of the components for the newest GraalVM distributions are distributed as
|
||||
* artifacts from the Maven central. This mens there is no longer `gu` tool.
|
||||
*
|
||||
* @see https://medium.com/graalvm/truffle-unchained-13887b77b62c
|
||||
* @return true if this version is associated with Truffle unchained.
|
||||
*/
|
||||
def isUnchained: Boolean = {
|
||||
javaMajorVersion >= 21 && graalMajorVersion >= 23
|
||||
override def compareTo(other: GraalVMVersion): Int = {
|
||||
val javaSemVer = SemVer.parse(javaVersion)
|
||||
val otherJavaSemVer = SemVer.parse(other.javaVersion)
|
||||
if (javaSemVer.isSuccess && otherJavaSemVer.isSuccess) {
|
||||
val comp = javaSemVer.get.compareTo(otherJavaSemVer.get)
|
||||
if (comp != 0) {
|
||||
return comp
|
||||
}
|
||||
}
|
||||
|
||||
val graalSemVer = SemVer.parse(graalVersion)
|
||||
val otherGraalSemVer = SemVer.parse(other.graalVersion)
|
||||
if (graalSemVer.isSuccess && otherGraalSemVer.isSuccess) {
|
||||
val comp = graalSemVer.get.compareTo(otherGraalSemVer.get)
|
||||
if (comp != 0) {
|
||||
return comp
|
||||
}
|
||||
}
|
||||
|
||||
val javaMajorComp = javaMajorVersion.compareTo(other.javaMajorVersion)
|
||||
if (javaMajorComp != 0) {
|
||||
return javaMajorComp
|
||||
}
|
||||
val graalMajorComp = graalMajorVersion.compareTo(other.graalMajorVersion)
|
||||
if (graalMajorComp != 0) {
|
||||
return graalMajorComp
|
||||
}
|
||||
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,19 +0,0 @@
|
||||
package org.enso.runtimeversionmanager.components
|
||||
|
||||
import org.enso.cli.OS
|
||||
|
||||
/** Provides configuration of the runtime components. */
|
||||
trait RuntimeComponentConfiguration {
|
||||
|
||||
/** Return the list of components required for the provided version of
|
||||
* the runtime installed on the provided OS.
|
||||
*
|
||||
* @param version the runtime version
|
||||
* @param os the operating system
|
||||
* @return the list of required components
|
||||
*/
|
||||
def getRequiredComponents(
|
||||
version: GraalVMVersion,
|
||||
os: OS
|
||||
): Seq[GraalVMComponent]
|
||||
}
|
@ -1,19 +0,0 @@
|
||||
package org.enso.runtimeversionmanager.components
|
||||
|
||||
import scala.util.Try
|
||||
|
||||
/** Module that manages components of the runtime distribution. */
|
||||
trait RuntimeComponentUpdater {
|
||||
|
||||
/** List the installed runtime components.
|
||||
*
|
||||
* @return the list of installed runtime components
|
||||
*/
|
||||
def list(): Try[Seq[GraalVMComponent]]
|
||||
|
||||
/** Install the provided runtime components.
|
||||
*
|
||||
* @param components the list of components to install
|
||||
*/
|
||||
def install(components: Seq[GraalVMComponent]): Try[Unit]
|
||||
}
|
@ -1,30 +0,0 @@
|
||||
package org.enso.runtimeversionmanager.components
|
||||
|
||||
/** The factory that creates a runtime component updater. */
|
||||
trait RuntimeComponentUpdaterFactory {
|
||||
|
||||
/** Create a runtime component updater.
|
||||
*
|
||||
* @param runtime the GraalVM runtime
|
||||
* @return new instance of the runtime component updater
|
||||
*/
|
||||
def build(runtime: GraalRuntime): RuntimeComponentUpdater
|
||||
}
|
||||
|
||||
object RuntimeComponentUpdaterFactory {
|
||||
|
||||
/** The default runtime component updater factory creating an instance of
|
||||
* [[GraalVMComponentUpdater]].
|
||||
*/
|
||||
object Default extends RuntimeComponentUpdaterFactory {
|
||||
|
||||
/** @inheritdoc */
|
||||
override def build(runtime: GraalRuntime): RuntimeComponentUpdater = {
|
||||
if (runtime.version.isUnchained) {
|
||||
new UnchainedGraalVMComponentUpdater()
|
||||
} else {
|
||||
new GraalVMComponentUpdater(runtime)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -3,7 +3,6 @@ package org.enso.runtimeversionmanager.components
|
||||
import java.nio.file.{Files, Path, StandardOpenOption}
|
||||
import com.typesafe.scalalogging.Logger
|
||||
import org.enso.semver.SemVer
|
||||
import org.enso.cli.OS
|
||||
import org.enso.distribution.{
|
||||
DistributionManager,
|
||||
Environment,
|
||||
@ -13,7 +12,6 @@ import org.enso.distribution.{
|
||||
import org.enso.distribution.locking.{LockType, ResourceManager}
|
||||
import org.enso.runtimeversionmanager.CurrentVersion
|
||||
import org.enso.distribution.FileSystem.PathSyntax
|
||||
import org.enso.logger.masking.MaskedPath
|
||||
import org.enso.downloader.archive.Archive
|
||||
import org.enso.runtimeversionmanager.locking.Resources
|
||||
import org.enso.runtimeversionmanager.releases.ReleaseProvider
|
||||
@ -32,79 +30,36 @@ import scala.util.{Failure, Success, Try, Using}
|
||||
* @param userInterface a [[RuntimeVersionManagementUserInterface]] instance
|
||||
* that specifies how to handle user interactions
|
||||
* (displaying progress and handling corner cases)
|
||||
* @param distributionManager the [[DistributionManager]] to use
|
||||
* @param engineReleaseProvider the provider of engine releases
|
||||
* @param runtimeReleaseProvider the provider of runtime releases
|
||||
* @param componentConfig the runtime component configuration
|
||||
* @param componentUpdaterFactory the runtime component updater factory
|
||||
*/
|
||||
class RuntimeVersionManager(
|
||||
environment: Environment,
|
||||
userInterface: RuntimeVersionManagementUserInterface,
|
||||
distributionManager: DistributionManager,
|
||||
graalVersionManager: GraalVersionManager,
|
||||
temporaryDirectoryManager: TemporaryDirectoryManager,
|
||||
resourceManager: ResourceManager,
|
||||
engineReleaseProvider: ReleaseProvider[EngineRelease],
|
||||
runtimeReleaseProvider: GraalVMRuntimeReleaseProvider,
|
||||
componentConfig: RuntimeComponentConfiguration,
|
||||
componentUpdaterFactory: RuntimeComponentUpdaterFactory,
|
||||
implicit private val installerKind: InstallerKind
|
||||
) {
|
||||
private val logger = Logger[RuntimeVersionManager]
|
||||
private val os = OS.operatingSystem
|
||||
|
||||
/** Tries to find a GraalVM runtime for the provided engine.
|
||||
*
|
||||
* Returns None if the runtime is missing.
|
||||
*/
|
||||
def findGraalRuntime(engine: Engine): Option[GraalRuntime] =
|
||||
findGraalRuntime(engine.manifest.runtimeVersion)
|
||||
def findGraalRuntime(engine: Engine): Option[GraalRuntime] = {
|
||||
Option(graalVersionManager.findGraalRuntime(engine))
|
||||
}
|
||||
|
||||
/** Finds an installed GraalVM runtime with the given `version`.
|
||||
*
|
||||
* Returns None if that version is not installed.
|
||||
*/
|
||||
def findGraalRuntime(version: GraalVMVersion): Option[GraalRuntime] = {
|
||||
val explicitPathOpt = this.environment.getEnvPath("ENSO_JVM_PATH")
|
||||
val graalRuntimeOpt = explicitPathOpt
|
||||
.map(path => {
|
||||
val runtime = GraalRuntime(version, path)
|
||||
runtime.ensureValid()
|
||||
runtime
|
||||
})
|
||||
.orElse {
|
||||
val pathOpt = findGraalRuntimeOnSearchPath(version)
|
||||
pathOpt.map { path =>
|
||||
// TODO [RW] for now an exception is thrown if the installation is
|
||||
// corrupted, in #1052 offer to repair the broken installation
|
||||
loadGraalRuntime(path).recoverWith { case e: Exception =>
|
||||
Failure(
|
||||
UnrecognizedComponentError(
|
||||
s"The runtime $version is already installed, but cannot be " +
|
||||
s"loaded due to $e. Until the launcher gets an auto-repair " +
|
||||
s"feature, please try reinstalling the runtime by " +
|
||||
s"uninstalling all engines that use it and installing them " +
|
||||
s"again, or manually removing `$path`",
|
||||
e
|
||||
)
|
||||
)
|
||||
}.get
|
||||
}
|
||||
}
|
||||
graalRuntimeOpt match {
|
||||
case Some(graalRuntime) =>
|
||||
logger.debug("Found GraalVM runtime [{}]", graalRuntime)
|
||||
case None =>
|
||||
logger.debug("GraalVM runtime [{}] not found", version)
|
||||
}
|
||||
graalRuntimeOpt
|
||||
}
|
||||
|
||||
private def findGraalRuntimeOnSearchPath(
|
||||
version: GraalVMVersion
|
||||
): Option[Path] = {
|
||||
val name = graalRuntimeNameForVersion(version)
|
||||
firstExisting(distributionManager.paths.runtimeSearchPaths.map(_ / name))
|
||||
Option(graalVersionManager.findGraalRuntime(version));
|
||||
}
|
||||
|
||||
/** Executes the provided action with a requested engine version.
|
||||
@ -635,70 +590,13 @@ class RuntimeVersionManager(
|
||||
private def engineNameForVersion(version: SemVer): String =
|
||||
version.toString
|
||||
|
||||
/** Returns name of the directory containing the runtime of that version.
|
||||
*/
|
||||
private def graalRuntimeNameForVersion(version: GraalVMVersion): String = {
|
||||
s"graalvm-ce-java${version.javaVersion}-${version.graalVersion}"
|
||||
}
|
||||
|
||||
/** Loads the GraalVM runtime definition.
|
||||
*/
|
||||
private def loadGraalRuntime(path: Path): Try[GraalRuntime] = {
|
||||
logger.debug("Loading Graal runtime [{}]", path)
|
||||
val name = path.getFileName.toString
|
||||
for {
|
||||
version <- parseGraalRuntimeVersionString(name)
|
||||
.toRight(
|
||||
UnrecognizedComponentError(s"Invalid runtime component name `$name`.")
|
||||
)
|
||||
.toTry
|
||||
runtime = GraalRuntime(version, path)
|
||||
_ <- runtime.ensureValid()
|
||||
_ <- installRequiredRuntimeComponents(runtime).recover {
|
||||
case NonFatal(error) =>
|
||||
val msg = translateError(error)
|
||||
logger.warn(
|
||||
"Failed to install required components on the existing [{}]. " +
|
||||
"Some language features may be unavailable. {}",
|
||||
runtime,
|
||||
msg
|
||||
)
|
||||
}
|
||||
} yield runtime
|
||||
}
|
||||
|
||||
/** Provide human-readable error messages for OS-specific failures
|
||||
* @param cause exception thrown when executing the process
|
||||
* @return human-readable error message
|
||||
*/
|
||||
private def translateError(cause: Throwable): String = {
|
||||
val msg = cause.getMessage
|
||||
OS.operatingSystem match {
|
||||
case OS.Linux => msg
|
||||
case OS.MacOS => msg
|
||||
case OS.Windows =>
|
||||
if (msg.contains("-1073741515")) {
|
||||
"Required Microsoft Visual C++ installation is missing"
|
||||
} else {
|
||||
msg
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Gets the runtime version from its name.
|
||||
*/
|
||||
private def parseGraalRuntimeVersionString(
|
||||
name: String
|
||||
): Option[GraalVMVersion] = {
|
||||
val regex = """graalvm-ce-java(.+)-(.+)""".r
|
||||
name match {
|
||||
case regex(javaVersionString, graalVersionString) =>
|
||||
Some(GraalVMVersion(graalVersionString, javaVersionString))
|
||||
case _ =>
|
||||
logger.warn(
|
||||
s"Unrecognized runtime name `$name`"
|
||||
)
|
||||
None
|
||||
try {
|
||||
Success(graalVersionManager.loadGraalRuntime(path))
|
||||
} catch {
|
||||
case e: UnrecognizedComponentError => Failure(e)
|
||||
}
|
||||
}
|
||||
|
||||
@ -800,26 +698,16 @@ class RuntimeVersionManager(
|
||||
|
||||
try {
|
||||
logger.debug("Loading temporary runtime [{}]", runtimeTemporaryPath)
|
||||
val temporaryRuntime =
|
||||
loadGraalRuntime(runtimeTemporaryPath).recoverWith { error =>
|
||||
Failure(
|
||||
InstallationError(
|
||||
"Cannot load the installed runtime. The package may have " +
|
||||
"been corrupted. Reverting installation",
|
||||
error
|
||||
)
|
||||
|
||||
loadGraalRuntime(runtimeTemporaryPath).recoverWith { error =>
|
||||
Failure(
|
||||
InstallationError(
|
||||
"Cannot load the installed runtime. The package may have " +
|
||||
"been corrupted. Reverting installation",
|
||||
error
|
||||
)
|
||||
}.get
|
||||
logger.debug("Installing GraalVM components to [{}]", temporaryRuntime)
|
||||
installRequiredRuntimeComponents(temporaryRuntime).recoverWith {
|
||||
error =>
|
||||
Failure(
|
||||
InstallationError(
|
||||
"fatal: Cannot install the required runtime components",
|
||||
error
|
||||
)
|
||||
)
|
||||
}.get
|
||||
)
|
||||
}
|
||||
|
||||
val runtimePath =
|
||||
distributionManager.paths.runtimes / runtimeDirectoryName
|
||||
@ -849,32 +737,6 @@ class RuntimeVersionManager(
|
||||
}
|
||||
}
|
||||
|
||||
/** Install components required for the specified runtime on the specified OS.
|
||||
*
|
||||
* @param runtime the GraalVM runtime
|
||||
*/
|
||||
private def installRequiredRuntimeComponents(
|
||||
runtime: GraalRuntime
|
||||
): Try[Unit] = {
|
||||
logger.debug("Installing GraalVM components [{}, {}]", runtime, os)
|
||||
val cu = componentUpdaterFactory.build(runtime)
|
||||
val requiredComponents =
|
||||
componentConfig.getRequiredComponents(runtime.version, os)
|
||||
|
||||
if (requiredComponents.isEmpty) Success(())
|
||||
else {
|
||||
for {
|
||||
installedComponents <- cu.list()
|
||||
_ = logger.debug(
|
||||
"Available GraalVM components: [{}]",
|
||||
installedComponents
|
||||
)
|
||||
missingComponents = requiredComponents.diff(installedComponents)
|
||||
_ <- cu.install(missingComponents)
|
||||
} yield ()
|
||||
}
|
||||
}
|
||||
|
||||
private def engineDirectoryNameForVersion(version: SemVer): Path =
|
||||
Path.of(version.toString())
|
||||
|
||||
@ -931,33 +793,6 @@ class RuntimeVersionManager(
|
||||
FileSystem.removeDirectory(temporaryPath)
|
||||
}
|
||||
|
||||
/** Logs on trace level all installed engines and runtimes.
|
||||
*
|
||||
* NOTE: Useful for debugging but should not be added to production code since it may
|
||||
* cause unnecessary installations for different engine versions.
|
||||
*/
|
||||
def logAvailableComponentsForDebugging(): Unit = logger.whenTraceEnabled {
|
||||
logger.trace("Discovering available components...")
|
||||
val engines = for (engine <- listInstalledEngines()) yield {
|
||||
val runtime = findGraalRuntime(engine)
|
||||
val runtimeName = runtime
|
||||
.map(_.toString)
|
||||
.getOrElse("no runtime found")
|
||||
val broken = if (engine.isMarkedBroken) " (broken)" else ""
|
||||
s" - Enso ${engine.version}$broken [runtime: $runtimeName] " +
|
||||
s"[location: ${MaskedPath(engine.path).applyMasking()}]"
|
||||
}
|
||||
|
||||
val runtimes =
|
||||
for (runtime <- listInstalledGraalRuntimes())
|
||||
yield s" - $runtime [location: " +
|
||||
s"${MaskedPath(runtime.path).applyMasking()}]"
|
||||
|
||||
logger.trace(
|
||||
s"Installed engines (${engines.length}):\n${engines.mkString("\n")}\n\n" +
|
||||
s"Installed runtimes (${runtimes.length}):\n${runtimes.mkString("\n")}"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/* Note [RuntimeVersionManager Concurrency Model]
|
||||
|
@ -1,26 +0,0 @@
|
||||
package org.enso.runtimeversionmanager.components
|
||||
|
||||
import scala.util.{Success, Try}
|
||||
|
||||
/** A dummy component updater for [[GraalVMVersion.isUnchained unchained]] GraalVM.
|
||||
* There is no `gu` utility in unchained GraalVM, so this updater does not do anything.
|
||||
* It only lists the components that are known to be included in the unchained GraalVM.
|
||||
*/
|
||||
class UnchainedGraalVMComponentUpdater extends RuntimeComponentUpdater {
|
||||
|
||||
/** There
|
||||
*
|
||||
* @return the list of installed runtime components
|
||||
*/
|
||||
override def list(): Try[Seq[GraalVMComponent]] = Success(Seq())
|
||||
|
||||
/** Install the provided runtime components.
|
||||
*
|
||||
* @param components the list of components to install
|
||||
*/
|
||||
override def install(components: Seq[GraalVMComponent]): Try[Unit] = {
|
||||
throw new IllegalStateException(
|
||||
"Cannot install components in unchained GraalVM"
|
||||
)
|
||||
}
|
||||
}
|
@ -1,106 +0,0 @@
|
||||
package org.enso.runtimeversionmanager.components
|
||||
|
||||
import org.enso.cli.OS
|
||||
import org.scalatest.matchers.should.Matchers
|
||||
import org.scalatest.wordspec.AnyWordSpec
|
||||
|
||||
class GraalVMComponentConfigurationSpec extends AnyWordSpec with Matchers {
|
||||
|
||||
"RuntimeComponentConfiguration" should {
|
||||
|
||||
"return required components" in {
|
||||
val conf = new GraalVMComponentConfiguration
|
||||
val required = Seq(GraalVMComponent.python, GraalVMComponent.R)
|
||||
val requiredAbove22 = required ++ Seq(GraalVMComponent.js)
|
||||
|
||||
conf.getRequiredComponents(
|
||||
GraalVMVersion("21.0.0.2", "11"),
|
||||
OS.Linux
|
||||
) should contain theSameElementsAs required
|
||||
|
||||
conf.getRequiredComponents(
|
||||
GraalVMVersion("21.0.0.2", "11"),
|
||||
OS.MacOS
|
||||
) should contain theSameElementsAs required
|
||||
|
||||
conf.getRequiredComponents(
|
||||
GraalVMVersion("21.0.0.2", "11"),
|
||||
OS.Windows
|
||||
) should contain theSameElementsAs Seq()
|
||||
|
||||
conf.getRequiredComponents(
|
||||
GraalVMVersion("22.0.0.0", "11"),
|
||||
OS.Linux
|
||||
) should contain theSameElementsAs requiredAbove22
|
||||
|
||||
conf.getRequiredComponents(
|
||||
GraalVMVersion("22.3.1", "17"),
|
||||
OS.MacOS
|
||||
) should contain theSameElementsAs requiredAbove22
|
||||
|
||||
conf.getRequiredComponents(
|
||||
GraalVMVersion("22.3.1", "17"),
|
||||
OS.Windows
|
||||
) should contain theSameElementsAs Seq(
|
||||
GraalVMComponent.js
|
||||
)
|
||||
|
||||
conf.getRequiredComponents(
|
||||
GraalVMVersion("22.3.1", "17"),
|
||||
OS.Linux
|
||||
) should contain theSameElementsAs Seq(
|
||||
GraalVMComponent.js,
|
||||
GraalVMComponent.python,
|
||||
GraalVMComponent.R
|
||||
)
|
||||
|
||||
conf.getRequiredComponents(
|
||||
GraalVMVersion("20.0.0.0", "11"),
|
||||
OS.Linux
|
||||
) should contain theSameElementsAs Seq()
|
||||
|
||||
conf.getRequiredComponents(
|
||||
GraalVMVersion("23.0.0", "17.0.7+7.1"),
|
||||
OS.Linux
|
||||
) should contain theSameElementsAs Seq(
|
||||
GraalVMComponent.js,
|
||||
GraalVMComponent.python
|
||||
)
|
||||
|
||||
conf.getRequiredComponents(
|
||||
GraalVMVersion("23.0.0", "11"),
|
||||
OS.Linux
|
||||
) should contain theSameElementsAs Seq(
|
||||
GraalVMComponent.js,
|
||||
GraalVMComponent.python
|
||||
)
|
||||
|
||||
conf.getRequiredComponents(
|
||||
GraalVMVersion("23.0.0", "17.0.7+7.1"),
|
||||
OS.Windows
|
||||
) should contain theSameElementsAs Seq(
|
||||
GraalVMComponent.js
|
||||
)
|
||||
}
|
||||
|
||||
"return no required components for Truffle unchained" in {
|
||||
val conf = new GraalVMComponentConfiguration
|
||||
val versions = Seq(
|
||||
GraalVMVersion("23.0.0", "21"),
|
||||
GraalVMVersion("23.0.1", "21"),
|
||||
GraalVMVersion("23.0.0", "21.0.1"),
|
||||
GraalVMVersion("23.0.1", "21.0.1"),
|
||||
GraalVMVersion("23.0.0", "21.0.1+5.1"),
|
||||
GraalVMVersion("23.0.1", "21.0.1+5.1"),
|
||||
GraalVMVersion("23.1.0", "21")
|
||||
)
|
||||
versions.forall(_.isUnchained) shouldBe true
|
||||
versions.foreach(version => {
|
||||
conf.getRequiredComponents(
|
||||
version,
|
||||
OS.Linux
|
||||
) shouldBe empty
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
@ -1,57 +0,0 @@
|
||||
package org.enso.runtimeversionmanager.components
|
||||
|
||||
import org.scalatest.matchers.should.Matchers
|
||||
import org.scalatest.wordspec.AnyWordSpec
|
||||
|
||||
class GraalVMComponentParserSpec extends AnyWordSpec with Matchers {
|
||||
|
||||
"RuntimeComponentUpdater" should {
|
||||
|
||||
"parse list output" in {
|
||||
val listOut =
|
||||
"""
|
||||
|ID : js
|
||||
|Name : Graal.js
|
||||
|Version : 21.0.0.2
|
||||
|GraalVM : n/a
|
||||
|Stability: -
|
||||
|Origin :
|
||||
|
|
||||
|ID : graalvm
|
||||
|Name : GraalVM Core
|
||||
|Version : 21.0.0.2
|
||||
|GraalVM : n/a
|
||||
|Stability: -
|
||||
|Origin :
|
||||
|
|
||||
|ID : R
|
||||
|Name : FastR
|
||||
|Version : 21.0.0.2
|
||||
|GraalVM : 21.0.0.2
|
||||
|Stability: Experimental
|
||||
|Origin : https://github.com/oracle/fastr/releases/download/vm-21.0.0.2/r-installable-java11-linux-amd64-21.0.0.2.jar
|
||||
|
|
||||
|ID : llvm-toolchain
|
||||
|Name : LLVM.org toolchain
|
||||
|Version : 21.0.0.2
|
||||
|GraalVM : 21.0.0.2
|
||||
|Stability: Supported
|
||||
|Origin : https://github.com/graalvm/graalvm-ce-builds/releases/download/vm-21.0.0.2/llvm-toolchain-installable-java11-linux-amd64-21.0.0.2.jar
|
||||
|
|
||||
|ID : native-image
|
||||
|Name : Native Image
|
||||
|Version : 21.0.0.2
|
||||
|GraalVM : 21.0.0.2
|
||||
|Stability: Early adopter
|
||||
|Origin : https://github.com/graalvm/graalvm-ce-builds/releases/download/vm-21.0.0.2/native-image-installable-svm-java11-linux-amd64-21.0.0.2.jar
|
||||
|""".stripMargin
|
||||
|
||||
val expectedComponents =
|
||||
Seq("js", "graalvm", "R", "llvm-toolchain", "native-image")
|
||||
.map(GraalVMComponent(_))
|
||||
val components =
|
||||
GraalVMComponentUpdater.ListOut.parse(listOut.linesIterator.toSeq)
|
||||
components shouldEqual expectedComponents
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,40 @@
|
||||
package org.enso.runtimeversionmanager.components
|
||||
|
||||
import org.scalatest.matchers.should.Matchers
|
||||
import org.scalatest.wordspec.AnyWordSpec
|
||||
|
||||
class GraalVMVersionSpec extends AnyWordSpec with Matchers {
|
||||
|
||||
"GraalVM Version" should {
|
||||
"greater JDK version is considered newer" in {
|
||||
val graalVersion = "24.0.0"
|
||||
val ver1 = GraalVMVersion(graalVersion, "21.0.2")
|
||||
val ver2 = GraalVMVersion(graalVersion, "17.0.7")
|
||||
(ver1.compareTo(ver2) > 0) shouldBe true
|
||||
}
|
||||
|
||||
"If JDK version is same (semver), greater Graal version is newer" in {
|
||||
val jdkVersion = "21.0.2"
|
||||
val ver1 = GraalVMVersion("24.0.2", jdkVersion)
|
||||
val ver2 = GraalVMVersion("24.0.0", jdkVersion)
|
||||
(ver1.compareTo(ver2) > 0) shouldBe true
|
||||
}
|
||||
|
||||
"If JDK version is same (non semver), greater Graal version is newer" in {
|
||||
val jdkVersion = "21"
|
||||
val ver1 = GraalVMVersion("24.0.2", jdkVersion)
|
||||
val ver2 = GraalVMVersion("24.0.0", jdkVersion)
|
||||
(ver1.compareTo(ver2) > 0) shouldBe true
|
||||
}
|
||||
|
||||
"be correctly ordered" in {
|
||||
val ver1 = GraalVMVersion("24.0.0", "21.0.2")
|
||||
val ver2 = GraalVMVersion("23.1.2", "21.0.2")
|
||||
val ver3 = GraalVMVersion("23.1.0", "21.0.1")
|
||||
val ver4 = GraalVMVersion("23.0.0", "17.0.7")
|
||||
val lst = List(ver4, ver2, ver3, ver1)
|
||||
val sortedList = lst.sortWith((ver1, ver2) => ver1.compareTo(ver2) < 0)
|
||||
sortedList shouldEqual List(ver4, ver3, ver2, ver1)
|
||||
}
|
||||
}
|
||||
}
|
@ -12,6 +12,8 @@ public class VersionsTest {
|
||||
assertTrue(SemVer.parse("0.1.1").isSuccess());
|
||||
assertTrue(SemVer.parse("9999.0.0").isSuccess());
|
||||
assertTrue(SemVer.parse("0.1").isFailure());
|
||||
assertTrue(SemVer.parse("21.0.2").isSuccess());
|
||||
assertTrue(SemVer.parse("17.0.7").isSuccess());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -19,10 +19,23 @@ public class BuildVersion {
|
||||
return GeneratedVersion.scalacVersion();
|
||||
}
|
||||
|
||||
/**
|
||||
* Version of GraalVM, more specifically, version of the GraalVM and Truffle libraries used to
|
||||
* build the engine.
|
||||
*/
|
||||
public static String graalVersion() {
|
||||
return GeneratedVersion.graalVersion();
|
||||
}
|
||||
|
||||
/**
|
||||
* Version of Java (JDK) used to build the engine.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public static String javaVersion() {
|
||||
return GeneratedVersion.javaVersion();
|
||||
}
|
||||
|
||||
public static String currentEdition() {
|
||||
return GeneratedVersion.currentEdition();
|
||||
}
|
||||
|
@ -18,6 +18,7 @@ object BuildInfo {
|
||||
* @param ensoVersion Enso version
|
||||
* @param scalacVersion Scala compiler version used in the project
|
||||
* @param graalVersion GraalVM version used in the project
|
||||
* @param javaVersion Java language version used in the project.
|
||||
* @param currentEdition name of the edition associated with the Enso
|
||||
* version; this should be removed once #1831 is
|
||||
* implemented
|
||||
@ -30,6 +31,7 @@ object BuildInfo {
|
||||
ensoVersion: String,
|
||||
scalacVersion: String,
|
||||
graalVersion: String,
|
||||
javaVersion: String,
|
||||
currentEdition: String
|
||||
): Seq[File] = {
|
||||
val gitInfo = getGitInformation(log).getOrElse(fallbackGitInformation)
|
||||
@ -58,6 +60,10 @@ object BuildInfo {
|
||||
| return "${graalVersion}";
|
||||
| }
|
||||
|
|
||||
| static String javaVersion() {
|
||||
| return "${javaVersion}";
|
||||
| }
|
||||
|
|
||||
| static String currentEdition() {
|
||||
| return "${currentEdition}";
|
||||
| }
|
||||
|
@ -1,8 +0,0 @@
|
||||
Copyright (C) 2015-2022 Lightbend Inc. <https://www.lightbend.com>
|
||||
Copyright (C) 2016-2022 Lightbend Inc. <https://www.lightbend.com>
|
||||
Copyright (C) 2017-2022 Lightbend Inc. <https://www.lightbend.com>
|
||||
Copyright (C) 2018-2022 Lightbend Inc. <https://www.lightbend.com>
|
||||
Copyright (C) 2019-2022 Lightbend Inc. <https://www.lightbend.com>
|
||||
Copyright (C) 2020-2022 Lightbend Inc. <https://www.lightbend.com>
|
||||
Copyright (C) 2021-2022 Lightbend Inc. <https://www.lightbend.com>
|
||||
Copyright 2009-2020 Lightbend Inc. <http://www.lightbend.com>
|
@ -1,6 +0,0 @@
|
||||
Copyright (C) 2008-2017 Bjoern Hoehrmann <bjoern@hoehrmann.de>
|
||||
Copyright (C) 2009-2017 Mathias Doenitz, Alexander Myltsev
|
||||
Copyright (C) 2009-2022 Lightbend Inc. <https://www.lightbend.com>
|
||||
Copyright 2011 Mark Harrah, Eugene Yokota
|
||||
Copyright 2014 Twitter, Inc.
|
||||
Copyright 2015 Heiko Seeberger
|
@ -1,6 +0,0 @@
|
||||
Copyright (C) 2009-2020 Lightbend Inc. <https://www.lightbend.com>
|
||||
Copyright (C) 2009-2022 Lightbend Inc. <https://www.lightbend.com>
|
||||
Copyright (C) 2015-2022 Lightbend Inc. <https://www.lightbend.com>
|
||||
Copyright (C) 2017-2022 Lightbend Inc. <https://www.lightbend.com>
|
||||
Copyright (C) 2018-2022 Lightbend Inc. <https://www.lightbend.com>
|
||||
Copyright (C) 2020-2022 Lightbend Inc. <https://www.lightbend.com>
|
@ -1 +0,0 @@
|
||||
Copyright (C) 2009-2020 Lightbend Inc. <http://www.lightbend.com>
|
@ -1,2 +0,0 @@
|
||||
Copyright (C) 2019-2022 Lightbend Inc. <https://www.lightbend.com>
|
||||
Copyright (c) 2013-14 Miles Sabin
|
@ -1,4 +0,0 @@
|
||||
Copyright (C) 2009-2017 Mathias Doenitz, Alexander Myltsev
|
||||
Copyright (C) 2009-2022 Lightbend Inc. <https://www.lightbend.com>
|
||||
Copyright (c) 2004, Mikael Grev, MiG InfoCom AB. (base64 @ miginfocom . com)
|
||||
Copyright (c) 2011-13 Miles Sabin
|
@ -1,3 +1,3 @@
|
||||
5BE1C47CDA76AF7E6C42089993BEA2B8DB544C1752AE5D8055BF2B4E713B20EA
|
||||
E92B79099FF706DC1F50287D428322268954285BD62F19B0A70456E3356AE1D1
|
||||
BBB2B5E440C388A022983CB2C0B9B4BA68D04B97FC07E4C8E142952448437BE0
|
||||
CA8B1BB2992E828BA958FD6CFC0076B213170FCD454406131407ED0340EC7F2F
|
||||
0
|
||||
|
Loading…
Reference in New Issue
Block a user