Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Install Required GraalVM Components #1651

Merged
merged 9 commits into from
Apr 7, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@ import org.enso.launcher.cli.{
GlobalCLIOptions
}
import org.enso.runtimeversionmanager.components.{
GraalVMComponentConfiguration,
InstallerKind,
RuntimeComponentConfiguration,
RuntimeComponentUpdaterFactory,
RuntimeVersionManager
}
import org.enso.runtimeversionmanager.distribution.{
Expand Down Expand Up @@ -43,6 +46,10 @@ object DefaultManagers {
lazy val temporaryDirectoryManager =
new TemporaryDirectoryManager(distributionManager, defaultResourceManager)

/** Default [[RuntimeComponentConfiguration]]. */
lazy val componentConfig: RuntimeComponentConfiguration =
new GraalVMComponentConfiguration

/** Creates a [[RuntimeVersionManager]] that uses the default distribution. */
def runtimeVersionManager(
globalCLIOptions: GlobalCLIOptions,
Expand All @@ -58,6 +65,8 @@ object DefaultManagers {
defaultResourceManager,
EngineRepository.defaultEngineReleaseProvider,
GraalCEReleaseProvider.default,
componentConfig,
RuntimeComponentUpdaterFactory.Default,
InstallerKind.Launcher
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@ package org.enso.projectmanager.versionmanagement
import com.typesafe.scalalogging.LazyLogging
import org.enso.runtimeversionmanager.Environment
import org.enso.runtimeversionmanager.components.{
GraalVMComponentConfiguration,
InstallerKind,
RuntimeComponentConfiguration,
RuntimeComponentUpdaterFactory,
RuntimeVersionManagementUserInterface,
RuntimeVersionManager
}
Expand Down Expand Up @@ -52,6 +55,12 @@ object DefaultDistributionConfiguration
lazy val temporaryDirectoryManager =
new TemporaryDirectoryManager(distributionManager, resourceManager)

lazy val componentConfiguration: RuntimeComponentConfiguration =
new GraalVMComponentConfiguration

lazy val runtimeComponentUpdaterFactory: RuntimeComponentUpdaterFactory =
RuntimeComponentUpdaterFactory.Default

/** @inheritdoc */
def engineReleaseProvider: ReleaseProvider[EngineRelease] =
EngineRepository.defaultEngineReleaseProvider
Expand All @@ -67,6 +76,8 @@ object DefaultDistributionConfiguration
resourceManager = resourceManager,
engineReleaseProvider = engineReleaseProvider,
runtimeReleaseProvider = GraalCEReleaseProvider.default,
componentConfig = componentConfiguration,
componentUpdaterFactory = runtimeComponentUpdaterFactory,
installerKind = InstallerKind.ProjectManager
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import java.nio.file.Path

import org.enso.projectmanager.versionmanagement.DistributionConfiguration
import org.enso.runtimeversionmanager.components.{
GraalVMComponentConfiguration,
InstallerKind,
RuntimeVersionManagementUserInterface,
RuntimeVersionManager
Expand All @@ -30,6 +31,7 @@ import org.enso.runtimeversionmanager.runner.{JVMSettings, JavaCommand}
import org.enso.runtimeversionmanager.test.{
FakeEnvironment,
HasTestDirectory,
NoopComponentUpdaterFactory,
TestLocalLockManager
}

Expand Down Expand Up @@ -67,6 +69,10 @@ class TestDistributionConfiguration(
lazy val temporaryDirectoryManager =
new TemporaryDirectoryManager(distributionManager, resourceManager)

lazy val componentConfig = new GraalVMComponentConfiguration

lazy val componentUpdaterFactory = NoopComponentUpdaterFactory

override def makeRuntimeVersionManager(
userInterface: RuntimeVersionManagementUserInterface
): RuntimeVersionManager = new RuntimeVersionManager(
Expand All @@ -76,6 +82,8 @@ class TestDistributionConfiguration(
resourceManager = resourceManager,
engineReleaseProvider = engineReleaseProvider,
runtimeReleaseProvider = runtimeReleaseProvider,
componentConfig = componentConfig,
componentUpdaterFactory = componentUpdaterFactory,
installerKind = InstallerKind.ProjectManager
)

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
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(())
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package org.enso.runtimeversionmanager.test

import org.enso.runtimeversionmanager.OS
import org.enso.runtimeversionmanager.components.{
GraalRuntime,
RuntimeComponentUpdater,
RuntimeComponentUpdaterFactory
}

/** Test factory creating a noop updater. */
object NoopComponentUpdaterFactory extends RuntimeComponentUpdaterFactory {

/** @inheritdoc */
override def build(runtime: GraalRuntime, os: OS): RuntimeComponentUpdater =
NoopComponentUpdater
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import nl.gn0s1s.bump.SemVer
import org.enso.pkg.{PackageManager, SemVerEnsoVersion}
import org.enso.runtimeversionmanager._
import org.enso.runtimeversionmanager.components.{
GraalVMComponentConfiguration,
InstallerKind,
RuntimeVersionManagementUserInterface,
RuntimeVersionManager
Expand Down Expand Up @@ -53,6 +54,7 @@ class RuntimeVersionManagerTest
val resourceManager = TestLocalResourceManager.create()
val temporaryDirectoryManager =
new TemporaryDirectoryManager(distributionManager, resourceManager)
val componentConfig = new GraalVMComponentConfiguration

val runtimeVersionManager = new RuntimeVersionManager(
userInterface,
Expand All @@ -61,6 +63,8 @@ class RuntimeVersionManagerTest
resourceManager,
engineProvider,
runtimeProvider,
componentConfig,
NoopComponentUpdaterFactory,
installerKind
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import org.enso.cli.task.TaskProgress
import org.enso.runtimeversionmanager.FileSystem.PathSyntax
import org.enso.runtimeversionmanager._
import org.enso.runtimeversionmanager.components.{
GraalVMComponentConfiguration,
GraalVMVersion,
InstallerKind,
Manifest,
Expand Down Expand Up @@ -146,13 +147,16 @@ class ConcurrencyTest

val temporaryDirectoryManager =
new TemporaryDirectoryManager(distributionManager, resourceManager)
val componentConfig = new GraalVMComponentConfiguration
val componentsManager = new RuntimeVersionManager(
TestRuntimeVersionManagementUserInterface.default,
distributionManager,
temporaryDirectoryManager,
resourceManager,
engineProvider,
runtimeProvider,
componentConfig,
NoopComponentUpdaterFactory,
InstallerKind.Launcher
)

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package org.enso.runtimeversionmanager.components

/** A component of the GraalVM distribution. */
case class GraalVMComponent(id: String)

object GraalVMComponent {

val js: GraalVMComponent = GraalVMComponent("js")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

JS is installed by default.

val python: GraalVMComponent = GraalVMComponent("python")
val R: GraalVMComponent = GraalVMComponent("R")
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package org.enso.runtimeversionmanager.components

import org.enso.runtimeversionmanager.OS

/** Component configuration of the GraalVM distribution. */
class GraalVMComponentConfiguration extends RuntimeComponentConfiguration {

import GraalVMComponentConfiguration._

/** @inheritdoc */
override def getRequiredComponents(
version: GraalVMVersion,
os: OS
): Seq[GraalVMComponent] =
version.graalVersion match {
case GraalVersions.Major(v) if v > 20 && os.hasSulongSupport =>
Seq(GraalVMComponent.python, GraalVMComponent.R)
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
}
}

private object GraalVersions {

/** Get the major Graal version number. */
object Major {
def unapply(version: String): Option[Int] = {
version.takeWhile(_ != '.').toIntOption
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
package org.enso.runtimeversionmanager.components

import java.nio.file.Path

import org.enso.runtimeversionmanager.OS

import scala.sys.process._
import scala.util.{Success, Try}

/** Module that manages components of the GraalVM distribution.
*
* @param runtime the GraalVM runtime
* @param os the operating system
*/
class GraalVMComponentUpdater(runtime: GraalRuntime, os: OS)
extends RuntimeComponentUpdater {

import GraalVMComponentUpdater._

/** List the installed GraalVM components.
*
* @return the list of installed GraalVM components
*/
override def list: Try[Seq[GraalVMComponent]] = {
val suppressStderr = ProcessLogger(_ => ())
val process = Process(
Seq[String](Paths.gu, "list", "-v"),
Some(runtime.path.toFile),
("JAVA_HOME", runtime.path),
("GRAALVM_HOME", runtime.path)
)

for {
lines <- Try(process.lazyLines(suppressStderr))
} yield ListOut.parse(lines)
}

/** 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 componentsList = components.map(_.id)
val process = Process(
Seq[String](Paths.gu, "install") ++ componentsList,
Some(runtime.path.toFile),
("JAVA_HOME", runtime.path),
("GRAALVM_HOME", runtime.path)
)
Try(process.!!)
} else {
Success(())
}
}

private object Paths {

/** Path to `gu` executable. */
val gu: Path = os match {
case OS.Linux => runtime.path / "bin" / "gu"
case OS.MacOS => runtime.path / "bin" / "gu"
case OS.Windows => runtime.path / "bin" / "gu.cmd"
}
}
}
object GraalVMComponentUpdater {

implicit private def pathToString(path: Path): String =
path.toAbsolutePath.toString

implicit private class PathExtensions(path: Path) {

def /(child: String): Path = path.resolve(child)
}

/** 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(_))
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package org.enso.runtimeversionmanager.components

import org.enso.runtimeversionmanager.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]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
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]
}
Loading