mirror of
https://github.com/enso-org/enso.git
synced 2024-10-05 17:17:50 +03:00
Support for --jvm option in Enso runner (#10374)
Addresses one of two concerns of #5298 - adds support for `--jvm` argument to allow us to switch from _native image_ built Enso binary (as developed by #10126) to regular JVM based Enso execution. This change _doesn't affect production builds_. The _native executable_ continues to be only built by `engine-runner/buildNativeImage` which is tested on CI, but not in the production jobs.
This commit is contained in:
parent
d65371096b
commit
515d8238bb
1
.gitignore
vendored
1
.gitignore
vendored
@ -133,7 +133,6 @@ build-cache/
|
||||
##################
|
||||
|
||||
*.build_artifacts.txt
|
||||
/runner
|
||||
|
||||
######################
|
||||
## Enso-Development ##
|
||||
|
@ -59,6 +59,12 @@
|
||||
[10353]: https://github.com/enso-org/enso/pull/10353
|
||||
[10396]: https://github.com/enso-org/enso/pull/10396
|
||||
|
||||
#### Enso Language & Runtime
|
||||
|
||||
- Support for [explicit --jvm option][10374] when launching `enso` CLI
|
||||
|
||||
[10374]: https://github.com/enso-org/enso/pull/10374
|
||||
|
||||
#### Enso Standard Library
|
||||
|
||||
- [Added Statistic.Product][10122]
|
||||
|
103
build.sbt
103
build.sbt
@ -2627,55 +2627,60 @@ lazy val `engine-runner` = project
|
||||
assembly := assembly
|
||||
.dependsOn(`runtime-fat-jar` / assembly)
|
||||
.value,
|
||||
rebuildNativeImage :=
|
||||
NativeImage
|
||||
.buildNativeImage(
|
||||
"runner",
|
||||
staticOnLinux = false,
|
||||
additionalOptions = Seq(
|
||||
"-Dorg.apache.commons.logging.Log=org.apache.commons.logging.impl.NoOpLog",
|
||||
"-H:IncludeResources=.*Main.enso$",
|
||||
"-H:+AddAllCharsets",
|
||||
"-H:+IncludeAllLocales",
|
||||
"-ea",
|
||||
// useful perf & debug switches:
|
||||
// "-g",
|
||||
// "-H:+SourceLevelDebug",
|
||||
// "-H:-DeleteLocalSymbols",
|
||||
// you may need to set smallJdk := None to use following flags:
|
||||
// "--trace-class-initialization=org.enso.syntax2.Parser",
|
||||
"-Dnic=nic"
|
||||
),
|
||||
mainClass = Some("org.enso.runner.Main"),
|
||||
initializeAtRuntime = Seq(
|
||||
"org.jline.nativ.JLineLibrary",
|
||||
"org.jline.terminal.impl.jna",
|
||||
"io.methvin.watchservice.jna.CarbonAPI",
|
||||
"zio.internal.ZScheduler$$anon$4",
|
||||
"org.enso.runner.Main$",
|
||||
"sun.awt",
|
||||
"sun.java2d",
|
||||
"sun.font",
|
||||
"java.awt",
|
||||
"com.sun.imageio",
|
||||
"com.sun.jna.internal.Cleaner",
|
||||
"com.sun.jna.Structure$FFIType",
|
||||
"akka.http"
|
||||
rebuildNativeImage := Def
|
||||
.taskDyn {
|
||||
NativeImage
|
||||
.buildNativeImage(
|
||||
"enso",
|
||||
targetDir = engineDistributionRoot.value / "bin",
|
||||
staticOnLinux = false,
|
||||
additionalOptions = Seq(
|
||||
"-Dorg.apache.commons.logging.Log=org.apache.commons.logging.impl.NoOpLog",
|
||||
"-H:IncludeResources=.*Main.enso$",
|
||||
"-H:+AddAllCharsets",
|
||||
"-H:+IncludeAllLocales",
|
||||
"-ea",
|
||||
// useful perf & debug switches:
|
||||
// "-g",
|
||||
// "-H:+SourceLevelDebug",
|
||||
// "-H:-DeleteLocalSymbols",
|
||||
// you may need to set smallJdk := None to use following flags:
|
||||
// "--trace-class-initialization=org.enso.syntax2.Parser",
|
||||
"-Dnic=nic"
|
||||
),
|
||||
mainClass = Some("org.enso.runner.Main"),
|
||||
initializeAtRuntime = Seq(
|
||||
"org.jline.nativ.JLineLibrary",
|
||||
"org.jline.terminal.impl.jna",
|
||||
"io.methvin.watchservice.jna.CarbonAPI",
|
||||
"zio.internal.ZScheduler$$anon$4",
|
||||
"org.enso.runner.Main$",
|
||||
"sun.awt",
|
||||
"sun.java2d",
|
||||
"sun.font",
|
||||
"java.awt",
|
||||
"com.sun.imageio",
|
||||
"com.sun.jna.internal.Cleaner",
|
||||
"com.sun.jna.Structure$FFIType",
|
||||
"akka.http"
|
||||
)
|
||||
)
|
||||
)
|
||||
.dependsOn(NativeImage.additionalCp)
|
||||
.dependsOn(NativeImage.smallJdk)
|
||||
.dependsOn(assembly)
|
||||
.dependsOn(
|
||||
buildEngineDistribution
|
||||
)
|
||||
.value,
|
||||
buildNativeImage := NativeImage
|
||||
.incrementalNativeImageBuild(
|
||||
rebuildNativeImage,
|
||||
"runner"
|
||||
}
|
||||
.dependsOn(NativeImage.additionalCp)
|
||||
.dependsOn(NativeImage.smallJdk)
|
||||
.dependsOn(assembly)
|
||||
.dependsOn(
|
||||
buildEngineDistribution
|
||||
)
|
||||
.value
|
||||
.value,
|
||||
buildNativeImage := Def.taskDyn {
|
||||
NativeImage
|
||||
.incrementalNativeImageBuild(
|
||||
rebuildNativeImage,
|
||||
"enso",
|
||||
targetDir = engineDistributionRoot.value / "bin"
|
||||
)
|
||||
}.value
|
||||
)
|
||||
.dependsOn(`version-output`)
|
||||
.dependsOn(yaml)
|
||||
@ -3575,6 +3580,10 @@ ThisBuild / buildEngineDistribution := {
|
||||
buildEngineDistribution.result.value
|
||||
}
|
||||
|
||||
ThisBuild / engineDistributionRoot := {
|
||||
engineDistributionRoot.value
|
||||
}
|
||||
|
||||
lazy val buildEngineDistributionNoIndex =
|
||||
taskKey[Unit]("Builds the engine distribution without generating indexes")
|
||||
buildEngineDistributionNoIndex := {
|
||||
|
@ -123,7 +123,6 @@
|
||||
bench-report.xml:
|
||||
build.sbt:
|
||||
run:
|
||||
runner: # The runner native image (Linux only).
|
||||
CHANGELOG.md:
|
||||
|
||||
# Launcher Package
|
||||
|
@ -483,7 +483,15 @@ impl RunContext {
|
||||
if self.config.build_native_runner {
|
||||
debug!("Building and testing native engine runners");
|
||||
runner_sanity_test(&self.repo_root, None).await?;
|
||||
ide_ci::fs::remove_file_if_exists(&self.repo_root.runner)?;
|
||||
let enso = self
|
||||
.repo_root
|
||||
.built_distribution
|
||||
.enso_engine_triple
|
||||
.engine_package
|
||||
.bin
|
||||
.join("enso")
|
||||
.with_executable_extension();
|
||||
ide_ci::fs::remove_file_if_exists(&enso)?;
|
||||
if self.config.build_espresso_runner {
|
||||
let enso_java = "espresso";
|
||||
sbt.command()?
|
||||
@ -636,7 +644,14 @@ pub async fn runner_sanity_test(
|
||||
// The engine package is necessary for running the native runner.
|
||||
ide_ci::fs::tokio::require_exist(engine_package).await?;
|
||||
if enso_java.is_none() {
|
||||
let test_base = Command::new(&repo_root.runner)
|
||||
let enso = repo_root
|
||||
.built_distribution
|
||||
.enso_engine_triple
|
||||
.engine_package
|
||||
.bin
|
||||
.join("enso")
|
||||
.with_executable_extension();
|
||||
let test_base = Command::new(&enso)
|
||||
.args(["--run", repo_root.test.join("Base_Tests").as_str()])
|
||||
.set_env_opt(ENSO_JAVA, enso_java)?
|
||||
.set_env(ENSO_DATA_DIRECTORY, engine_package)?
|
||||
|
@ -73,11 +73,21 @@ impl BuiltEnso {
|
||||
}
|
||||
|
||||
pub async fn run_benchmarks(&self, opt: BenchmarkOptions) -> Result {
|
||||
self.cmd()?
|
||||
.with_args(["--run", self.paths.repo_root.test.benchmarks.as_str()])
|
||||
let filename = format!("enso{}", if TARGET_OS == OS::Windows { ".exe" } else { "" });
|
||||
let enso = self
|
||||
.paths
|
||||
.repo_root
|
||||
.built_distribution
|
||||
.enso_engine_triple
|
||||
.engine_package
|
||||
.bin
|
||||
.join(filename);
|
||||
let benchmarks = Command::new(&enso)
|
||||
.args(["--jvm", "--run", self.paths.repo_root.test.benchmarks.as_str()])
|
||||
.set_env(ENSO_BENCHMARK_TEST_DRY_RUN, &Boolean::from(opt.dry_run))?
|
||||
.run_ok()
|
||||
.await
|
||||
.await;
|
||||
benchmarks
|
||||
}
|
||||
|
||||
pub fn run_test(&self, test_path: impl AsRef<Path>, ir_caches: IrCaches) -> Result<Command> {
|
||||
|
@ -8,5 +8,5 @@ for opt in "$@"; do
|
||||
done
|
||||
|
||||
JAVA_OPTS="--add-opens=java.base/java.nio=ALL-UNNAMED $JAVA_OPTS"
|
||||
exec java --module-path $COMP_PATH -Dorg.graalvm.language.enso.home=$COMP_PATH $EXTRA_OPTS $JAVA_OPTS -m org.enso.runtime/org.enso.EngineRunnerBootLoader "$@"
|
||||
exec java --module-path $COMP_PATH $EXTRA_OPTS $JAVA_OPTS -m org.enso.runtime/org.enso.EngineRunnerBootLoader "$@"
|
||||
exit
|
||||
|
@ -7,5 +7,5 @@ set EXTRA_OPTS=%EXTRA_OPTS% -Dgraal.Dump=Truffle:1
|
||||
)
|
||||
)
|
||||
set JAVA_OPTS=%JAVA_OPTS% --add-opens=java.base/java.nio=ALL-UNNAMED
|
||||
java --module-path %comp-dir% -Dorg.graalvm.language.enso.home=%comp-dir% -Dpolyglot.compiler.IterativePartialEscape=true %EXTRA_OPTS% %JAVA_OPTS% -m org.enso.runtime/org.enso.EngineRunnerBootLoader %*
|
||||
java --module-path %comp-dir% -Dpolyglot.compiler.IterativePartialEscape=true %EXTRA_OPTS% %JAVA_OPTS% -m org.enso.runtime/org.enso.EngineRunnerBootLoader %*
|
||||
exit /B %errorlevel%
|
||||
|
@ -111,7 +111,7 @@ For example, to update settings for the Launcher:
|
||||
java -agentlib:native-image-agent=config-merge-dir=engine/launcher/src/main/resources/META-INF/native-image/org/enso/launcher -jar launcher.jar <arguments>
|
||||
```
|
||||
|
||||
Note that for convenience, you can run the launcher/engine runner via
|
||||
Note that for convenience, you can run the launcher/engine runtime via
|
||||
`bin/enso`, e.g.
|
||||
|
||||
```bash
|
||||
@ -210,7 +210,7 @@ sbt> engine-runner/buildNativeImage
|
||||
and execute any program with that binary - for example `test/Base_Tests`
|
||||
|
||||
```bash
|
||||
$ runner --run test/Base_Tests
|
||||
$ ./built-distribution/enso-engine-*/enso-*/bin/enso --run test/Base_Tests
|
||||
```
|
||||
|
||||
The task that generates the Native Image, along with all the necessary
|
||||
@ -224,7 +224,7 @@ Since [PR-6966](https://github.com/enso-org/enso/pull/6966) there is an
|
||||
experimental support for including
|
||||
[Espresso Java interpreter](https://www.graalvm.org/jdk17/reference-manual/java-on-truffle/)
|
||||
to allow use of some library functions (like `IO.println`) in the _Native Image_
|
||||
built runner.
|
||||
built runtime.
|
||||
|
||||
The support can be enabled by setting environment variable `ENSO_JAVA=espresso`
|
||||
and making sure Espresso is installed in the Enso engine `component` directory:
|
||||
@ -278,7 +278,7 @@ Espresso support works also with
|
||||
`ENSO_JAVA=espresso` is specified when building the `runner` executable:
|
||||
|
||||
```bash
|
||||
enso$ rm runner
|
||||
enso$ rm ./built-distribution/enso-engine-*/enso-*/bin/enso
|
||||
enso$ ENSO_JAVA=espresso sbt --java-home /graalvm
|
||||
sbt> engine-runner/buildNativeImage
|
||||
```
|
||||
@ -288,7 +288,7 @@ build script detects presence of Espresso and automatically adds
|
||||
`--language:java` when creating the image. Then you can use
|
||||
|
||||
```bash
|
||||
$ ENSO_JAVA=espresso ./runner --run hello.enso
|
||||
$ ENSO_JAVA=espresso ./built-distribution/enso-engine-*/enso-*/bin/enso --run hello.enso
|
||||
```
|
||||
|
||||
to execute native image `runner` build of Enso together with Espresso.
|
||||
to execute native image build of Enso together with Espresso.
|
||||
|
@ -8,6 +8,7 @@ import java.net.URISyntaxException;
|
||||
import java.nio.file.InvalidPathException;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
@ -53,6 +54,7 @@ import scala.runtime.BoxedUnit;
|
||||
|
||||
/** The main CLI entry point class. */
|
||||
public final class Main {
|
||||
private static final String JVM_OPTION = "jvm";
|
||||
private static final String RUN_OPTION = "run";
|
||||
private static final String INSPECT_OPTION = "inspect";
|
||||
private static final String DUMP_GRAPHS_OPTION = "dump-graphs";
|
||||
@ -127,6 +129,15 @@ public final class Main {
|
||||
.longOpt(RUN_OPTION)
|
||||
.desc("Runs a specified Enso file.")
|
||||
.build();
|
||||
var jvm =
|
||||
cliOptionBuilder()
|
||||
.hasArg(true)
|
||||
.numberOfArgs(1)
|
||||
.optionalArg(true)
|
||||
.argName("jvm")
|
||||
.longOpt(JVM_OPTION)
|
||||
.desc("Specifies whether to run JVM mode and optionally selects a JVM to run with.")
|
||||
.build();
|
||||
var inspect =
|
||||
cliOptionBuilder()
|
||||
.longOpt(INSPECT_OPTION)
|
||||
@ -451,6 +462,7 @@ public final class Main {
|
||||
options
|
||||
.addOption(help)
|
||||
.addOption(repl)
|
||||
.addOption(jvm)
|
||||
.addOption(run)
|
||||
.addOption(inspect)
|
||||
.addOption(dumpGraphs)
|
||||
@ -508,17 +520,17 @@ public final class Main {
|
||||
}
|
||||
|
||||
/** Terminates the process with a failure exit code. */
|
||||
private RuntimeException exitFail() {
|
||||
private static RuntimeException exitFail() {
|
||||
return doExit(1);
|
||||
}
|
||||
|
||||
/** Terminates the process with a success exit code. */
|
||||
private RuntimeException exitSuccess() {
|
||||
private static RuntimeException exitSuccess() {
|
||||
return doExit(0);
|
||||
}
|
||||
|
||||
/** Shuts down the logging service and terminates the process. */
|
||||
private RuntimeException doExit(int exitCode) {
|
||||
private static RuntimeException doExit(int exitCode) {
|
||||
RunnerLogging.tearDown();
|
||||
System.exit(exitCode);
|
||||
return null;
|
||||
@ -932,7 +944,7 @@ public final class Main {
|
||||
}
|
||||
|
||||
/** Parses the log level option. */
|
||||
private Level parseLogLevel(String levelOption) {
|
||||
private static Level parseLogLevel(String levelOption) {
|
||||
var name = levelOption.toLowerCase();
|
||||
var found =
|
||||
Stream.of(Level.values()).filter(x -> name.equals(x.name().toLowerCase())).findFirst();
|
||||
@ -949,7 +961,7 @@ public final class Main {
|
||||
}
|
||||
|
||||
/** Parses an URI that specifies the logging service connection. */
|
||||
private URI parseUri(String string) {
|
||||
private static URI parseUri(String string) {
|
||||
try {
|
||||
return new URI(string);
|
||||
} catch (URISyntaxException ex) {
|
||||
@ -966,7 +978,7 @@ public final class Main {
|
||||
*
|
||||
* @param args the command line arguments
|
||||
*/
|
||||
public static void main(String[] args) throws IOException {
|
||||
public static void main(String[] args) throws Exception {
|
||||
new Main().launch(args);
|
||||
}
|
||||
|
||||
@ -1294,10 +1306,95 @@ public final class Main {
|
||||
System.out.println(msg);
|
||||
}
|
||||
|
||||
private void launch(String[] args) {
|
||||
private void launch(String[] args) throws IOException, InterruptedException, URISyntaxException {
|
||||
var options = buildOptions();
|
||||
var line = preprocessArguments(options, args);
|
||||
launch(options, line);
|
||||
|
||||
var logMasking = new boolean[1];
|
||||
var logLevel = setupLogging(options, line, logMasking);
|
||||
|
||||
if (line.hasOption(JVM_OPTION)) {
|
||||
var jvm = line.getOptionValue(JVM_OPTION);
|
||||
var current = System.getProperty("java.home");
|
||||
if (jvm == null) {
|
||||
jvm = current;
|
||||
}
|
||||
if (current == null || !current.equals(jvm)) {
|
||||
var loc = Main.class.getProtectionDomain().getCodeSource().getLocation();
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
commandAndArgs.add("java");
|
||||
} else {
|
||||
commandAndArgs.add(new File(new File(new File(jvm), "bin"), "java").getAbsolutePath());
|
||||
}
|
||||
var jvmOptions = System.getenv("JAVA_OPTS");
|
||||
if (jvmOptions != null) {
|
||||
for (var op : jvmOptions.split(" ")) {
|
||||
if (op.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
commandAndArgs.add(op);
|
||||
}
|
||||
}
|
||||
|
||||
commandAndArgs.add("--add-opens=java.base/java.nio=ALL-UNNAMED");
|
||||
commandAndArgs.add("--module-path");
|
||||
var component = new File(loc.toURI().resolve("..")).getAbsoluteFile();
|
||||
if (!component.getName().equals("component")) {
|
||||
component = new File(component, "component");
|
||||
}
|
||||
if (!component.isDirectory()) {
|
||||
throw new IOException("Cannot find " + component + " directory");
|
||||
}
|
||||
commandAndArgs.add(component.getPath());
|
||||
commandAndArgs.add("-m");
|
||||
commandAndArgs.add("org.enso.runtime/org.enso.EngineRunnerBootLoader");
|
||||
var it = line.iterator();
|
||||
while (it.hasNext()) {
|
||||
var op = it.next();
|
||||
if (JVM_OPTION.equals(op.getLongOpt())) {
|
||||
continue;
|
||||
}
|
||||
var longName = op.getLongOpt();
|
||||
if (longName != null) {
|
||||
commandAndArgs.add("--" + longName);
|
||||
} else {
|
||||
commandAndArgs.add("-" + op.getOpt());
|
||||
}
|
||||
var values = op.getValuesList();
|
||||
if (values != null) {
|
||||
commandAndArgs.addAll(values);
|
||||
}
|
||||
}
|
||||
commandAndArgs.addAll(line.getArgList());
|
||||
var pb = new ProcessBuilder();
|
||||
pb.inheritIO();
|
||||
pb.command(commandAndArgs);
|
||||
var p = pb.start();
|
||||
var exitCode = p.waitFor();
|
||||
if (exitCode == 0) {
|
||||
throw exitSuccess();
|
||||
} else {
|
||||
throw doExit(exitCode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
launch(options, line, logLevel, logMasking[0]);
|
||||
}
|
||||
|
||||
protected CommandLine preprocessArguments(Options options, String[] args) {
|
||||
@ -1315,15 +1412,18 @@ public final class Main {
|
||||
}
|
||||
}
|
||||
|
||||
protected void launch(Options options, CommandLine line) {
|
||||
private static Level setupLogging(Options options, CommandLine line, boolean[] logMasking) {
|
||||
var logLevel =
|
||||
scala.Option.apply(line.getOptionValue(LOG_LEVEL))
|
||||
.map(this::parseLogLevel)
|
||||
.map(Main::parseLogLevel)
|
||||
.getOrElse(() -> defaultLogLevel);
|
||||
var connectionUri = scala.Option.apply(line.getOptionValue(LOGGER_CONNECT)).map(this::parseUri);
|
||||
var logMasking = !line.hasOption(NO_LOG_MASKING);
|
||||
RunnerLogging.setup(connectionUri, logLevel, logMasking);
|
||||
var connectionUri = scala.Option.apply(line.getOptionValue(LOGGER_CONNECT)).map(Main::parseUri);
|
||||
logMasking[0] = !line.hasOption(NO_LOG_MASKING);
|
||||
RunnerLogging.setup(connectionUri, logLevel, logMasking[0]);
|
||||
return logLevel;
|
||||
}
|
||||
|
||||
private void launch(Options options, CommandLine line, Level logLevel, boolean logMasking) {
|
||||
if (line.hasOption(LANGUAGE_SERVER_OPTION)) {
|
||||
runLanguageServer(line, logLevel);
|
||||
} else {
|
||||
|
@ -2,10 +2,14 @@ package org.enso.interpreter;
|
||||
|
||||
import com.oracle.truffle.api.TruffleFile;
|
||||
import com.oracle.truffle.api.TruffleLanguage;
|
||||
import java.io.File;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.Optional;
|
||||
import org.enso.polyglot.RuntimeOptions;
|
||||
|
||||
public class OptionsHelper {
|
||||
public final class OptionsHelper {
|
||||
private OptionsHelper() {}
|
||||
|
||||
/**
|
||||
* Gets the location of the project that is the context of the current run.
|
||||
*
|
||||
@ -22,17 +26,29 @@ public class OptionsHelper {
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an optional override for the language home directory.
|
||||
* Finds location of language home directory. It checks {@link
|
||||
* RuntimeOptions#LANGUAGE_HOME_OVERRIDE} and uses it. If it is not specified, it derives the
|
||||
* location from code source location of the JAR file.
|
||||
*
|
||||
* <p>This is used mostly for the runtime tests, as language home is not normally defined there.
|
||||
*/
|
||||
public static Optional<String> getLanguageHomeOverride(TruffleLanguage.Env env) {
|
||||
public static Optional<String> findLanguageHome(TruffleLanguage.Env env) {
|
||||
String option = env.getOptions().get(RuntimeOptions.LANGUAGE_HOME_OVERRIDE_KEY);
|
||||
if (option.equals("")) {
|
||||
return Optional.empty();
|
||||
} else {
|
||||
if (!option.equals("")) {
|
||||
return Optional.of(option);
|
||||
}
|
||||
try {
|
||||
var cs = OptionsHelper.class.getProtectionDomain().getCodeSource();
|
||||
var runtimeJarUri = cs.getLocation().toURI();
|
||||
var runtimeJar = new File(runtimeJarUri);
|
||||
var componentDir = runtimeJar.getParentFile();
|
||||
if (componentDir != null && componentDir.isDirectory()) {
|
||||
return Optional.of(componentDir.getPath());
|
||||
}
|
||||
} catch (IllegalStateException | URISyntaxException ex) {
|
||||
// cannot derive the location
|
||||
}
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
public static Optional<String> getEditionOverride(TruffleLanguage.Env env) {
|
||||
|
@ -174,8 +174,7 @@ public final class EnsoContext {
|
||||
},
|
||||
res -> res));
|
||||
|
||||
Optional<String> languageHome =
|
||||
OptionsHelper.getLanguageHomeOverride(environment).or(() -> Optional.ofNullable(home));
|
||||
var languageHome = OptionsHelper.findLanguageHome(environment);
|
||||
var editionOverride = OptionsHelper.getEditionOverride(environment);
|
||||
var resourceManager = new org.enso.distribution.locking.ResourceManager(lockManager);
|
||||
|
||||
|
@ -35,7 +35,7 @@ public final class Parser implements AutoCloseable {
|
||||
var d = root;
|
||||
File path = null;
|
||||
while (d != null) {
|
||||
path = new File(d, name);
|
||||
path = new File(new File(d, "component"), name);
|
||||
if (path.exists()) break;
|
||||
d = d.getParentFile();
|
||||
}
|
||||
@ -44,12 +44,13 @@ public final class Parser implements AutoCloseable {
|
||||
}
|
||||
System.load(path.getAbsolutePath());
|
||||
} catch (NullPointerException | IllegalArgumentException | LinkageError e) {
|
||||
if (!searchFromDirToTop(e, root, "target", "rust", "debug", name)) {
|
||||
if (!searchFromDirToTop(
|
||||
e, new File(".").getAbsoluteFile(), "target", "rust", "debug", name)) {
|
||||
throw new IllegalStateException("Cannot load parser from " + root, e);
|
||||
}
|
||||
if (searchFromDirToTop(e, root, "target", "rust", "debug", name)) {
|
||||
return;
|
||||
}
|
||||
if (searchFromDirToTop(e, new File(".").getAbsoluteFile(), "target", "rust", "debug", name)) {
|
||||
return;
|
||||
}
|
||||
throw new IllegalStateException("Cannot load parser from " + root, e);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -192,11 +192,8 @@ class Runner(
|
||||
val shouldInvokeViaModulePath = engine.graalRuntimeVersion.isUnchained
|
||||
|
||||
val componentPath = engine.componentDirPath.toAbsolutePath.normalize
|
||||
val langHomeOption = Seq(
|
||||
s"-Dorg.graalvm.language.enso.home=$componentPath"
|
||||
)
|
||||
var jvmArguments =
|
||||
manifestOptions ++ environmentOptions ++ commandLineOptions ++ langHomeOption
|
||||
manifestOptions ++ environmentOptions ++ commandLineOptions
|
||||
if (shouldInvokeViaModulePath) {
|
||||
jvmArguments = jvmArguments :++ Seq(
|
||||
"--module-path",
|
||||
|
@ -83,8 +83,9 @@ object NativeImage {
|
||||
* @param verbose whether to print verbose output from the native image.
|
||||
*/
|
||||
def buildNativeImage(
|
||||
artifactName: String,
|
||||
name: String,
|
||||
staticOnLinux: Boolean,
|
||||
targetDir: File = null,
|
||||
additionalOptions: Seq[String] = Seq.empty,
|
||||
buildMemoryLimitMegabytes: Option[Int] = Some(15608),
|
||||
runtimeThreadStackMegabytes: Option[Int] = Some(2),
|
||||
@ -95,7 +96,8 @@ object NativeImage {
|
||||
includeRuntime: Boolean = true
|
||||
): Def.Initialize[Task[Unit]] = Def
|
||||
.task {
|
||||
val log = state.value.log
|
||||
val log = state.value.log
|
||||
val targetLoc = artifactFile(targetDir, name, false)
|
||||
|
||||
def nativeImagePath(prefix: Path)(path: Path): Path = {
|
||||
val base = path.resolve(prefix)
|
||||
@ -138,7 +140,7 @@ object NativeImage {
|
||||
}
|
||||
if (additionalOptions.contains("--language:java")) {
|
||||
log.warn(
|
||||
s"Building ${artifactName} image with experimental Espresso support!"
|
||||
s"Building ${targetLoc} image with experimental Espresso support!"
|
||||
)
|
||||
|
||||
}
|
||||
@ -229,7 +231,7 @@ object NativeImage {
|
||||
buildMemoryLimitOptions ++
|
||||
runtimeMemoryOptions ++
|
||||
additionalOptions ++
|
||||
Seq("-o", artifactName)
|
||||
Seq("-o", targetLoc.toString())
|
||||
|
||||
args = mainClass match {
|
||||
case Some(main) =>
|
||||
@ -240,8 +242,8 @@ object NativeImage {
|
||||
Seq("-jar", pathToJAR.toString)
|
||||
}
|
||||
|
||||
val targetDir = (Compile / target).value
|
||||
val argFile = targetDir.toPath.resolve(NATIVE_IMAGE_ARG_FILE)
|
||||
val targetDirValue = (Compile / target).value
|
||||
val argFile = targetDirValue.toPath.resolve(NATIVE_IMAGE_ARG_FILE)
|
||||
IO.writeLines(argFile.toFile, args, append = false)
|
||||
|
||||
val pathParts = pathExts ++ Option(System.getenv("PATH")).toSeq
|
||||
@ -266,15 +268,16 @@ object NativeImage {
|
||||
sb.append(str + System.lineSeparator())
|
||||
})
|
||||
log.info(
|
||||
s"Started building $artifactName native image. The output is captured."
|
||||
s"Started building $targetLoc native image. The output is captured."
|
||||
)
|
||||
val retCode = process.!(processLogger)
|
||||
if (retCode != 0) {
|
||||
log.error("Native Image build failed, with output: ")
|
||||
val retCode = process.!(processLogger)
|
||||
val targetFile = artifactFile(targetDir, name, true)
|
||||
if (retCode != 0 || !targetFile.exists()) {
|
||||
log.error("Native Image build of $targetFile failed, with output: ")
|
||||
println(sb.toString())
|
||||
throw new RuntimeException("Native Image build failed")
|
||||
}
|
||||
log.info(s"$artifactName native image build successful.")
|
||||
log.info(s"$targetLoc native image build successful.")
|
||||
}
|
||||
.dependsOn(Compile / compile)
|
||||
|
||||
@ -289,14 +292,15 @@ object NativeImage {
|
||||
*/
|
||||
def incrementalNativeImageBuild(
|
||||
actualBuild: TaskKey[Unit],
|
||||
artifactName: String
|
||||
name: String,
|
||||
targetDir: File = null
|
||||
): Def.Initialize[Task[Unit]] =
|
||||
Def.taskDyn {
|
||||
def rebuild(reason: String) = {
|
||||
streams.value.log.info(
|
||||
s"$reason, forcing a rebuild."
|
||||
)
|
||||
val artifact = artifactFile(artifactName)
|
||||
val artifact = artifactFile(targetDir, name)
|
||||
if (artifact.exists()) {
|
||||
artifact.delete()
|
||||
}
|
||||
@ -314,7 +318,7 @@ object NativeImage {
|
||||
sourcesDiff: ChangeReport[File] =>
|
||||
if (sourcesDiff.modified.nonEmpty)
|
||||
rebuild(s"Native Image is not up to date")
|
||||
else if (!artifactFile(artifactName).exists())
|
||||
else if (!artifactFile(targetDir, name).exists())
|
||||
rebuild("Native Image does not exist")
|
||||
else
|
||||
Def.task {
|
||||
@ -328,9 +332,20 @@ object NativeImage {
|
||||
/** [[File]] representing the artifact called `name` built with the Native
|
||||
* Image.
|
||||
*/
|
||||
def artifactFile(name: String): File =
|
||||
if (Platform.isWindows) file(name + ".exe")
|
||||
else file(name)
|
||||
def artifactFile(
|
||||
targetDir: File,
|
||||
name: String,
|
||||
withExtension: Boolean = false
|
||||
): File = {
|
||||
val artifactName =
|
||||
if (withExtension && Platform.isWindows) name + ".exe"
|
||||
else name
|
||||
if (targetDir == null) {
|
||||
new File(artifactName).getAbsoluteFile()
|
||||
} else {
|
||||
new File(targetDir, artifactName)
|
||||
}
|
||||
}
|
||||
|
||||
private val muslBundleUrl =
|
||||
"https://github.com/gradinac/musl-bundle-example/releases/download/" +
|
||||
|
Loading…
Reference in New Issue
Block a user