From b24066dd71ff2737b7be5bea080f71cbe1614420 Mon Sep 17 00:00:00 2001 From: Loic Rouchon Date: Wed, 17 Nov 2021 23:15:42 +0100 Subject: [PATCH] Remove native image and rely on the JVM at runtime The complexity of setting a build pipeline for GraalVM native image and having access to both macOs/linux for both x64 and ARM architecture is too much of an overhead for a small opensource project. This might be reconsidered in the future when availability on those OS/arch will be more widely spread or that GraalVM will offer cross compilation support. See https://github.com/oracle/graal/issues/407 --- build.gradle.kts | 159 +++++++------------ src/main/java/org/symly/cli/BeanFactory.java | 4 - src/main/java/org/symly/cli/Main.java | 25 +-- src/main/packaging/homebrew/symly | 3 + src/main/packaging/linux/symly | 3 + 5 files changed, 66 insertions(+), 128 deletions(-) create mode 100755 src/main/packaging/homebrew/symly create mode 100755 src/main/packaging/linux/symly diff --git a/build.gradle.kts b/build.gradle.kts index e80d441..4ab244b 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,11 +1,8 @@ -import org.gradle.nativeplatform.platform.internal.DefaultNativePlatform - plugins { application `jvm-test-suite` idea jacoco - id("org.graalvm.buildtools.native") version "0.9.7.1" id("org.asciidoctor.jvm.convert") version "3.3.2" id("nebula.ospackage") version "9.0.0" } @@ -99,54 +96,6 @@ tasks.jacocoTestReport { } } -graalvmNative { - binaries { - named("main") { - javaLauncher.set(javaToolchains.launcherFor { - languageVersion.set(JavaLanguageVersion.of(17)) - vendor.set(JvmVendorSpec.GRAAL_VM) - }) -// mainClass.set(null) -// classpath.from() - buildArgs.addAll( - "-Dpicocli.converters.excludes=java.sql.*,java.time.*", -// "--module-path", -// "${buildDir}/install/${project.name}/lib/", -// "--module", -// "${appModuleName}/${appMainClassName}", - // Size optimization - "-H:-AddAllCharsets", - "-H:-UseServiceLoaderFeature", - "-J-Drx.unsafe-disable=true", - "-H:+RemoveUnusedSymbols", - "-DremoveUnusedAutoconfig=true", - "--initialize-at-build-time=${appModuleName},picocli", - // Native image size debug flags -// "-H:DashboardDump=img-dump", -// "-H:+DashboardAll", -// "-H:+DashboardHeap", -// "-H:+DashboardCode", -// "-H:+DashboardPointsTo", -// "-H:+DashboardPretty", - // Native image stdout debug -// "-H:+PrintImageElementSizes", -// "-H:+PrintUniverse", -// "-H:+PrintHeapHistogram", -// "-H:+PrintAnalysisCallTree", -// "-H:+PrintImageObjectTree", -// "-H:+PrintHeapHistogram", -// "-H:+PrintMethodHistogram", -// "-H:+PrintImageHeapPartitionSizes", - ) - } - } -} - -tasks.nativeCompile { - shouldRunAfter(tasks.named("integrationTest")) -} -tasks.assemble.get().dependsOn(tasks.nativeCompile) - tasks.register("generateManpageAsciiDoc") { dependsOn(tasks.installDist) inputs.dir("${buildDir}/install/${project.name}/") @@ -203,61 +152,63 @@ tasks.register("generateShellCompletions") { } } - -val os: OperatingSystem = DefaultNativePlatform.getCurrentOperatingSystem() -if (os.isLinux()) { - ospackage { - packageName = "symly" - packageDescription = "Manages symbolic links." - url = "https://github.com/loicrouchon/symly" - - release = "1" - os = org.redline_rpm.header.Os.LINUX - user = "root" - - license = "ASL 2.0" - from("LICENSE", closureOf { - into("usr/share/doc/${project.name}") - rename("LICENSE", "copyright") - fileType = org.redline_rpm.payload.Directive.LICENSE - }) - - from("${buildDir}/native/nativeCompile/${project.name}", closureOf { - into("usr/bin/") - fileMode = 755 - }) - from("${buildDir}/docs/manpage/gz", closureOf { - into("usr/man/man1") - fileType = org.redline_rpm.payload.Directive.DOC - }) -// requires https://github.com/remkop/picocli/issues/1346 +ospackage { + packageName = "symly" + packageDescription = "Manages symbolic links." + url = "https://github.com/loicrouchon/symly" + + release = "1" + os = org.redline_rpm.header.Os.LINUX + user = "root" + + license = "ASL 2.0" + from("LICENSE", closureOf { + into("usr/share/doc/${project.name}") + rename("LICENSE", "copyright") + fileType = org.redline_rpm.payload.Directive.LICENSE + }) + from("src/main/packaging/linux/${project.name}", closureOf { + into("usr/bin") + }) + from("${buildDir}/install/${project.name}/bin/symly", closureOf { + into("usr/share/${project.name}/bin") + }) + from("${buildDir}/install/${project.name}/lib", closureOf { + into("usr/share/${project.name}/lib") + }) + from("${buildDir}/docs/manpage/gz", closureOf { + into("usr/man/man1") + fileType = org.redline_rpm.payload.Directive.DOC + }) +// requires https ://github.com/remkop/picocli/issues/1346 // from("${buildDir}/shell/completions") { // into "/usr/share/bash-completion/completions" // } - } +} - val buildDebPackage = tasks.register("buildDebPackage") { - dependsOn( - tasks.named("nativeCompile"), - tasks.named("generateManpage"), - tasks.named("generateShellCompletions") - ) - shouldRunAfter(tasks.named("integrationTest")) - maintainer = "Loic Rouchon" - setArch("amd64") - license = "ASL 2.0" - } +val buildDebPackage = tasks.register("buildDebPackage") { + dependsOn( + tasks.named("installDist"), + tasks.named("generateManpage"), + tasks.named("generateShellCompletions") + ) + shouldRunAfter(tasks.named("integrationTest")) + maintainer = "Loic Rouchon" + setArch("amd64") + license = "ASL 2.0" + requires("openjdk-17-jre-headless", "").or("java17-runtime-headless", null) +} - val buildRpmPackage = tasks.register("buildRpmPackage") { - dependsOn( - tasks.named("nativeCompile"), - tasks.named("generateManpage"), - tasks.named("generateShellCompletions") - ) - shouldRunAfter(tasks.named("integrationTest")) - packager = "Loïc Rouchon" - setArch("x86_64") - addParentDirs = false - } - tasks.assemble.get().dependsOn(buildDebPackage, buildRpmPackage) -} \ No newline at end of file +val buildRpmPackage = tasks.register("buildRpmPackage") { + dependsOn( + tasks.named("installDist"), + tasks.named("generateManpage"), + tasks.named("generateShellCompletions") + ) + shouldRunAfter(tasks.named("integrationTest")) + packager = "Loïc Rouchon" + setArch("x86_64") + requires("java-latest-openjdk-headless", "") + addParentDirs = false +} +tasks.assemble.get().dependsOn(buildDebPackage, buildRpmPackage) \ No newline at end of file diff --git a/src/main/java/org/symly/cli/BeanFactory.java b/src/main/java/org/symly/cli/BeanFactory.java index f38a1d0..e5e7243 100644 --- a/src/main/java/org/symly/cli/BeanFactory.java +++ b/src/main/java/org/symly/cli/BeanFactory.java @@ -32,10 +32,6 @@ class BeanFactory implements CommandLine.IFactory { private final CommandLine.IFactory parentFactory = CommandLine.defaultFactory(); - public void preInit() { - constructors.keySet().forEach(this::create); - } - @Override @SuppressWarnings("unchecked") public K create(Class cls) { diff --git a/src/main/java/org/symly/cli/Main.java b/src/main/java/org/symly/cli/Main.java index 17ca729..d5184d8 100644 --- a/src/main/java/org/symly/cli/Main.java +++ b/src/main/java/org/symly/cli/Main.java @@ -8,35 +8,20 @@ public class Main { - private static final BeanFactory BEAN_FACTORY = initializeBeanFactory(); - - private static final CliConsole CONSOLE = BEAN_FACTORY.create(CliConsole.class); - - /** - * Done as part of the Main class static initializer to benefit from GraalVM native-image static initialization - * optimization. - */ - private static final CommandLine COMMAND_LINE = initializeCommandLine(BEAN_FACTORY, CONSOLE); - public static void main(String... args) { int exitCode = runCommand(args); System.exit(exitCode); } private static int runCommand(String... args) { - int exitCode = COMMAND_LINE.execute(args); - CONSOLE.flush(); + BeanFactory beanFactory = new BeanFactory(); + CliConsole console = beanFactory.create(CliConsole.class); + CommandLine commandLine = initializeCommandLine(beanFactory, console); + int exitCode = commandLine.execute(args); + console.flush(); return exitCode; } - private static BeanFactory initializeBeanFactory() { - BeanFactory factory = new BeanFactory(); - // Instantiate at compile time thanks to GraalVM native-image optimization - // Doing so also avoids having to include resources in the native-image. - factory.preInit(); - return factory; - } - private static CommandLine initializeCommandLine(BeanFactory factory, CliConsole console) { CommandLine commandLine = new CommandLine(factory.create(MainCommand.class), factory); commandLine.setOut(console.writer()); diff --git a/src/main/packaging/homebrew/symly b/src/main/packaging/homebrew/symly new file mode 100755 index 0000000..d61768c --- /dev/null +++ b/src/main/packaging/homebrew/symly @@ -0,0 +1,3 @@ +#!/bin/sh +export JAVA_HOME="/usr/local/opt/openjdk" +/usr/local/Cellar/symly/bin/symly "$@" \ No newline at end of file diff --git a/src/main/packaging/linux/symly b/src/main/packaging/linux/symly new file mode 100755 index 0000000..50096c8 --- /dev/null +++ b/src/main/packaging/linux/symly @@ -0,0 +1,3 @@ +#!/bin/sh +export JAVA_HOME="/usr/lib/jvm/$(ls /usr/lib/jvm | grep -E "java-[0-9]+" | sort -V -r | head -n 1)" +/usr/share/symly/bin/symly "$@" \ No newline at end of file