Skip to content
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
7 changes: 5 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -167,14 +167,17 @@ the same `--jar/--uber-jar` flag that you used for training.

If you try to run the native executable, you will get errors. This is because
Javalin uses reflection, which makes native compilation trickier. Anytime you
get errors when running native executable, compile using `--reach` flag, which
functions similar to Leyden in that it runs your `classes` or `app-uber.jar`
get errors when running native executable, start your app using `start --native-reach`
flag, which functions similar to Leyden in that it runs your `classes` or `.jar`
first and uses a java agent to register everything that needs to be present in the
executable during runtime. This cache is present inside `META-INF/native-image`
directory. You should commit this to git, because not all paths might be hit
during a reachability run, so it is important that the new entries are merged
with the existing reachability data.

Now that you have updated the reachability metadata, try compiling to native
again and this time the application should start up normally.

### Formatting

This is my personal gripe with Java, but a lack of a standard formatting tool
Expand Down
15 changes: 15 additions & 0 deletions src/META-INF/native-image/veles/reachability-metadata.json
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,9 @@
}
]
},
{
"type": "commands.Start$Target"
},
{
"type": "common.VersionProvider",
"methods": [
Expand Down Expand Up @@ -4165,6 +4168,18 @@
}
]
},
{
"type": "sun.text.resources.BreakIteratorInfo"
},
{
"type": "sun.text.resources.BreakIteratorResources"
},
{
"type": "sun.text.resources.BreakIteratorResources_en"
},
{
"type": "sun.text.resources.BreakIteratorResources_en_US"
},
{
"type": {
"proxy": [
Expand Down
46 changes: 0 additions & 46 deletions src/commands/Compile.java
Original file line number Diff line number Diff line change
Expand Up @@ -58,12 +58,6 @@ public class Compile implements Runnable {
@Option(names = { "-n", "--native" }, description = { "Package classes as a native executable" })
boolean doNative;

@Option(
names = { "-r", "--native-reach" },
description = { "Used when native compilation is acting up" }
)
boolean doReach;

@Option(names = { "-z", "--zip" }, description = { "Package libs and .jar into a .zip" })
boolean doZip;

Expand Down Expand Up @@ -124,10 +118,6 @@ public void run() {
unitTestRun();
}

if (doReach) {
reach();
}

if (doJar || doZip || doDocker || doUber) {
jar();
}
Expand Down Expand Up @@ -372,42 +362,6 @@ private void docker() {
executor.executeBlocking(command);
}

/**
* Use this if your native executable has issues. This will run GraalVM JVM using
* `native-image-agent` with given arguments, which will merge the reachability metadata with
* existing metadata inside `META-INF/native-image/<artifactId>`.
*
* This metadata is then used by the `native-image` utility to generate the native executable.
*/
private void reach() {
var reachabilityDir = Config.getArtifactId().isBlank()
? "veles-generated"
: Config.getArtifactId();
var classpath = mavenDeps().add(Scope.COMPILE, Scope.PROVIDED, Scope.RUNTIME)
.classpath()
.add(Config.outputClassesDir())
.toString();

var traceCmd = new ArrayList<String>();
traceCmd.add(JdkResolver.graalJava().toString());
traceCmd.add(
"-agentlib:native-image-agent=" + "config-merge-dir=" + Config.sourceDir(entrypoint)
+ "/META-INF/native-image/" + reachabilityDir
);
traceCmd.add("-cp");
traceCmd.add(classpath);
traceCmd.add(Config.getEntrypoint(entrypoint).canonicalName());
traceCmd.addAll(args);
executor.executeBlocking(traceCmd);

Paths.ensureDirExists(Config.outputClassesDir().resolve("META-INF", "native-image"));

FilesUtil.copyDir(
Config.sourceDir(entrypoint).resolve("META-INF", "native-image"),
Config.outputClassesDir().resolve("META-INF", "native-image")
);
}

/**
* Generates the native image. You need to have GraalVM installed via SDKMAN or set GRAALVM_HOME
* environment variable, that points to the the directory where GraalVM is installed.
Expand Down
2 changes: 1 addition & 1 deletion src/commands/Dev.java
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ private void runWithArgs(String args, LogFeed logFeed) {

var run = new Start();
run.executor = executor;
run.doJar = doJar;
run.target.jar = doJar;
run.args = List.of(args.split(" "));
run.run();
});
Expand Down
27 changes: 25 additions & 2 deletions src/commands/Run.java
Original file line number Diff line number Diff line change
Expand Up @@ -37,15 +37,38 @@ public class Run implements Runnable {
)
String entrypoint;

/**
* Use this if your native executable has issues. This will run GraalVM JVM using
* `native-image-agent` with given arguments, which will merge the reachability metadata with
* existing metadata inside `META-INF/native-image/<artifactId>`.
*
* This metadata is then used by the `native-image` GraalVM utility to generate the native
* executable.
*/
@Option(
names = { "-r", "--native-reach" },
description = { "Use when native compilation is acting up" }
)
public boolean doReach;

@Option(names = { "-X", "--ignore-depfiles" }, description = { "Ignore .dep files" })
boolean ignoreDepfiles;

@Parameters
List<String> args = Collections.emptyList();

public void run() {
var entrypoint = Config.getEntrypoint(this.entrypoint);
var command = new ArrayList<String>();
command.add(JdkResolver.java().toString());
if (doReach) {
command.add(JdkResolver.graalJava().toString());
command.add(
"-agentlib:native-image-agent=" + "config-merge-dir="
+ entrypoint.sourceDir().resolve("META-INF", "native-image", Config.getArtifactId())
);
} else {
command.add(JdkResolver.java().toString());
}
if (Files.exists(Path.of(".dep.nocomp")) && !ignoreDepfiles) {
command.add("@.dep.nocomp");
} else {
Expand All @@ -60,7 +83,7 @@ public void run() {
if (Config.isPreviewEnabled()) {
command.add("--enable-preview");
}
command.add(Config.getEntrypoint(this.entrypoint).filePath().toString());
command.add(entrypoint.filePath().toString());
command.addAll(args);

if (!watch) {
Expand Down
59 changes: 43 additions & 16 deletions src/commands/Start.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,20 +23,22 @@ public class Start implements Runnable {
@Mixin
CommandExecutor executor;

@Option(names = { "-j", "--jar" }, description = { "Run compiled JAR file" })
public boolean doJar;
@ArgGroup(exclusive = true)
public Target target = new Target();

@Option(names = { "-n", "--native" }, description = { "Run compiled native executable" })
public boolean doNative;
public static class Target {
@Option(names = { "-j", "--jar" }, description = { "Run compiled JAR file" })
public boolean jar;

@Option(names = { "-u", "--uber" }, description = { "Run compiled uber JAR" })
public boolean doUber;
@Option(names = { "-n", "--native" }, description = { "Run compiled native executable" })
public boolean _native;

@Option(names = { "-U", "--exploded" }, description = { "Run the exploded directory" })
public boolean doExploded;
@Option(names = { "-u", "--uber" }, description = { "Run compiled uber JAR" })
public boolean uberJar;

@Option(names = { "-X", "--ignore-depfiles" }, description = { "Ignore .dep files" })
boolean ignoreDepfiles;
@Option(names = { "-U", "--exploded" }, description = { "Run the exploded directory" })
public boolean exploded;
}

@ArgGroup(exclusive = true)
public AOTGroup aot = new AOTGroup();
Expand All @@ -56,6 +58,20 @@ public static class AOTGroup {
required = true
)
public String useAotCache;

/**
* Use this if your native executable has issues. This will run GraalVM JVM using
* `native-image-agent` with given arguments, which will merge the reachability metadata with
* existing metadata inside `META-INF/native-image/<artifactId>`.
*
* This metadata is then used by the `native-image` GraalVM utility to generate the native
* executable.
*/
@Option(
names = { "-r", "--native-reach" },
description = { "Use when native compilation is acting up" }
)
public boolean doReach;
}

@Option(
Expand All @@ -64,6 +80,9 @@ public static class AOTGroup {
)
public String entrypoint;

@Option(names = { "-X", "--ignore-depfiles" }, description = { "Ignore .dep files" })
boolean ignoreDepfiles;

@Parameters
public List<String> args = Collections.emptyList();

Expand All @@ -72,15 +91,23 @@ public void run() {
var entrypoint = Config.getEntrypoint(this.entrypoint);

var command = new ArrayList<String>();
if (!doNative) {
command.add(JdkResolver.java().toString());
if (!target._native) {
if (aot.doReach) {
command.add(JdkResolver.graalJava().toString());
command.add(
"-agentlib:native-image-agent=" + "config-merge-dir="
+ entrypoint.sourceDir().resolve("META-INF", "native-image", Config.getArtifactId())
);
} else {
command.add(JdkResolver.java().toString());
}
if (Config.isPreviewEnabled()) {
command.add("--enable-preview");
}
if (doJar || doUber) {
if (target.jar || target.uberJar) {
var aotCacheOutput = Config.outputDir()
.resolve(
(doUber
(target.uberJar
? Config.outputJavaUberJarName()
: Config.outputJavaJarName()) + ".aot"
);
Expand All @@ -96,13 +123,13 @@ public void run() {
}

command.add("-jar");
if (doJar) {
if (target.jar) {
command.add(Config.outputDir().resolve(Config.outputJavaJarName()).toString());
} else {
command.add(Config.outputDir().resolve(Config.outputJavaUberJarName()).toString());
}
} else {
if (doExploded) {
if (target.exploded) {
command.add("-cp");
command.add(Config.outputExplodedDir().toString());
} else if (Files.exists(Path.of(".dep.runtime")) && !ignoreDepfiles) {
Expand Down