diff --git a/graalvm/src/main/java/net/woggioni/gradle/graalvm/NativeImageConfigurationTask.java b/graalvm/src/main/java/net/woggioni/gradle/graalvm/NativeImageConfigurationTask.java index 52ebf1c..4fd8cee 100644 --- a/graalvm/src/main/java/net/woggioni/gradle/graalvm/NativeImageConfigurationTask.java +++ b/graalvm/src/main/java/net/woggioni/gradle/graalvm/NativeImageConfigurationTask.java @@ -74,7 +74,9 @@ public abstract class NativeImageConfigurationTask extends JavaExec { } else { jvmArgs.add("-agentlib:native-image-agent=config-output-dir=" + getConfigurationDir().get()); } - for(String jvmArg : Optional.ofNullable(javaApplication.getApplicationDefaultJvmArgs()).orElse(Collections.emptyList())) { + for(String jvmArg : Optional.ofNullable(javaApplication) + .map(JavaApplication::getApplicationDefaultJvmArgs) + .orElse(Collections.emptyList())) { jvmArgs.add(jvmArg); } return jvmArgs; diff --git a/graalvm/src/main/java/net/woggioni/gradle/graalvm/NativeImageExtension.java b/graalvm/src/main/java/net/woggioni/gradle/graalvm/NativeImageExtension.java new file mode 100644 index 0000000..104ab04 --- /dev/null +++ b/graalvm/src/main/java/net/woggioni/gradle/graalvm/NativeImageExtension.java @@ -0,0 +1,26 @@ +package net.woggioni.gradle.graalvm; + +import org.gradle.api.file.DirectoryProperty; +import org.gradle.api.file.FileCollection; +import org.gradle.api.provider.Property; + +abstract public class NativeImageExtension { + public abstract Property getClasspath(); + + public abstract DirectoryProperty getGraalVmHome(); + + public abstract Property getUseMusl(); + public abstract Property getBuildStaticImage(); + public abstract Property getEnableFallback(); + public abstract Property getLinkAtBuildTime(); + + public abstract Property getMainClass(); + + public abstract Property getMainModule(); + + public abstract Property getCompressExecutable(); + + public abstract Property getUseLZMA(); + + public abstract Property getCompressionLevel(); +} diff --git a/graalvm/src/main/java/net/woggioni/gradle/graalvm/NativeImagePlugin.java b/graalvm/src/main/java/net/woggioni/gradle/graalvm/NativeImagePlugin.java index aaa0d25..f6e08a9 100644 --- a/graalvm/src/main/java/net/woggioni/gradle/graalvm/NativeImagePlugin.java +++ b/graalvm/src/main/java/net/woggioni/gradle/graalvm/NativeImagePlugin.java @@ -2,36 +2,44 @@ package net.woggioni.gradle.graalvm; import org.gradle.api.Plugin; import org.gradle.api.Project; -import org.gradle.api.Task; import org.gradle.api.artifacts.ConfigurationContainer; +import org.gradle.api.file.Directory; import org.gradle.api.file.FileCollection; import org.gradle.api.file.ProjectLayout; -import org.gradle.api.plugins.BasePlugin; import org.gradle.api.plugins.ExtensionContainer; -import org.gradle.api.plugins.JavaApplication; import org.gradle.api.plugins.JavaLibraryPlugin; import org.gradle.api.plugins.JavaPlugin; +import org.gradle.api.plugins.JavaPluginExtension; +import org.gradle.api.provider.Property; import org.gradle.api.provider.Provider; +import org.gradle.api.tasks.CacheableTask; import org.gradle.api.tasks.TaskContainer; import org.gradle.jvm.tasks.Jar; +import org.gradle.jvm.toolchain.JavaInstallationMetadata; +import org.gradle.jvm.toolchain.JavaLauncher; +import org.gradle.jvm.toolchain.JavaToolchainService; -import java.util.Optional; +import static java.util.Optional.ofNullable; +@CacheableTask public class NativeImagePlugin implements Plugin { public static final String NATIVE_IMAGE_TASK_NAME = "nativeImage"; + public static final String UPX_TASK_NAME = "upx"; public static final String CONFIGURE_NATIVE_IMAGE_TASK_NAME = "configureNativeImage"; public static final String NATIVE_IMAGE_CONFIGURATION_FOLDER_NAME = "native-image"; + private static void setIfPresent(Property p1, Provider provider) { + if(provider.isPresent()) { + p1.set(provider); + } + } + @Override public void apply(Project project) { project.getPluginManager().apply(JavaLibraryPlugin.class); ProjectLayout layout = project.getLayout(); ExtensionContainer extensionContainer = project.getExtensions(); - JavaApplication javaApplicationExtension = - Optional.ofNullable(extensionContainer.findByType(JavaApplication.class)) - .orElseGet(() -> extensionContainer.create("application", JavaApplication.class)); - TaskContainer tasks = project.getTasks(); Provider jarTaskProvider = tasks.named(JavaPlugin.JAR_TASK_NAME, Jar.class, jar -> { @@ -44,16 +52,56 @@ public class NativeImagePlugin implements Plugin { ); }); }); + NativeImageExtension nativeImageExtension = extensionContainer.create("nativeImage", NativeImageExtension.class); + + ExtensionContainer ext = project.getExtensions(); + JavaPluginExtension javaPluginExtension = ext.findByType(JavaPluginExtension.class); + JavaToolchainService javaToolchainService = ext.findByType(JavaToolchainService.class); + + Provider graalHomeDirectoryProvider = ofNullable(javaPluginExtension.getToolchain()).map(javaToolchainSpec -> + javaToolchainService.launcherFor(javaToolchainSpec) + ).map(javaLauncher -> + javaLauncher.map(JavaLauncher::getMetadata).map(JavaInstallationMetadata::getInstallationPath) + ).orElseGet(() -> layout.dir(project.provider(() -> project.file(System.getProperty("java.home"))))); + nativeImageExtension.getGraalVmHome().convention(graalHomeDirectoryProvider); + nativeImageExtension.getUseMusl().convention(false); + nativeImageExtension.getEnableFallback().convention(false); + nativeImageExtension.getLinkAtBuildTime().convention(false); + nativeImageExtension.getBuildStaticImage().convention(false); + nativeImageExtension.getCompressExecutable().convention(false); + nativeImageExtension.getUseLZMA().convention(false); + nativeImageExtension.getCompressionLevel().convention(6); + + ConfigurationContainer configurations = project.getConfigurations(); + FileCollection classpath = project.files(jarTaskProvider, + configurations.getByName(JavaPlugin.RUNTIME_CLASSPATH_CONFIGURATION_NAME)); + nativeImageExtension.getClasspath().convention(classpath); Provider nativeImageConfigurationTaskProvider = tasks.register(CONFIGURE_NATIVE_IMAGE_TASK_NAME, NativeImageConfigurationTask.class); Provider nativeImageTaskProvider = tasks.register(NATIVE_IMAGE_TASK_NAME, NativeImageTask.class, nativeImageTask -> { - nativeImageTask.getInputs().files(nativeImageConfigurationTaskProvider); - ConfigurationContainer configurations = project.getConfigurations(); - FileCollection classpath = project.files(jarTaskProvider, - configurations.getByName(JavaPlugin.RUNTIME_CLASSPATH_CONFIGURATION_NAME)); - nativeImageTask.getClasspath().set(classpath); + nativeImageTask.getClasspath().set(nativeImageExtension.getClasspath()); + nativeImageTask.getBuildStaticImage().set(nativeImageExtension.getBuildStaticImage()); + nativeImageTask.getUseMusl().set(nativeImageExtension.getUseMusl()); + nativeImageTask.getLinkAtBuildTime().set(nativeImageExtension.getLinkAtBuildTime()); + nativeImageTask.getMainClass().set(nativeImageExtension.getMainClass()); + nativeImageTask.getMainModule().set(nativeImageExtension.getMainModule()); + nativeImageTask.getEnableFallback().set(nativeImageExtension.getEnableFallback()); }); + + Provider upxTaskProvider = tasks.register(UPX_TASK_NAME, UpxTask.class, t -> { + t.getInputFile().set(nativeImageTaskProvider.flatMap(NativeImageTask::getOutputFile)); + setIfPresent(t.getUseLZMA(), nativeImageExtension.getUseLZMA()); + setIfPresent(t.getCompressionLevel(), nativeImageExtension.getCompressionLevel()); + setIfPresent(t.getCompressionLevel(), nativeImageExtension.getCompressionLevel()); + }); + + tasks.named(NATIVE_IMAGE_TASK_NAME, NativeImageTask.class, t -> { + if(nativeImageExtension.getCompressExecutable().getOrElse(false)) { + t.finalizedBy(upxTaskProvider); + } + }); + } } diff --git a/graalvm/src/main/java/net/woggioni/gradle/graalvm/UpxTask.java b/graalvm/src/main/java/net/woggioni/gradle/graalvm/UpxTask.java new file mode 100644 index 0000000..1c3aacb --- /dev/null +++ b/graalvm/src/main/java/net/woggioni/gradle/graalvm/UpxTask.java @@ -0,0 +1,108 @@ +package net.woggioni.gradle.graalvm; + +import org.gradle.api.Project; +import org.gradle.api.file.RegularFileProperty; +import org.gradle.api.plugins.BasePluginExtension; +import org.gradle.api.provider.Property; +import org.gradle.api.tasks.CacheableTask; +import org.gradle.api.tasks.Exec; +import org.gradle.api.tasks.Input; +import org.gradle.api.tasks.InputFile; +import org.gradle.api.tasks.OutputFile; +import org.gradle.api.tasks.PathSensitive; +import org.gradle.api.tasks.PathSensitivity; +import org.gradle.process.CommandLineArgumentProvider; + +import javax.inject.Inject; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +@CacheableTask +public abstract class UpxTask extends Exec { + + @InputFile + @PathSensitive(PathSensitivity.NONE) + public abstract RegularFileProperty getInputFile(); + + @OutputFile + public abstract RegularFileProperty getOutputFile(); + + @Input + public abstract Property getUseLZMA(); + + @Input + public abstract Property getCompressionLevel(); + + @Inject + public UpxTask(Project project) { + BasePluginExtension be = project.getExtensions().findByType(BasePluginExtension.class); + getOutputFile().convention( + be.getDistsDirectory().file(String.format("%s.upx", project.getName())) + ); + getUseLZMA().convention(false); + getCompressionLevel().convention(10); + + executable("upx"); + + getArgumentProviders().add(new CommandLineArgumentProvider() { + @Override + public Iterable asArguments() { + List result = new ArrayList(); + if(getUseLZMA().get()) { + result.add("--lzma"); + } else { + result.add("--no-lzma"); + } + String compressionLevel; + int cl = getCompressionLevel().get(); + switch (cl) { + case 1: + compressionLevel = "-1"; + break; + case 2: + compressionLevel = "-2"; + break; + case 3: + compressionLevel = "-3"; + break; + case 4: + compressionLevel = "-4"; + break; + case 5: + compressionLevel = "-5"; + break; + case 6: + compressionLevel = "-6"; + break; + case 7: + compressionLevel = "-7"; + break; + case 8: + compressionLevel = "-8"; + break; + case 9: + compressionLevel = "-9"; + break; + case 10: + compressionLevel = "--best"; + break; + case 11: + compressionLevel = "--brute"; + break; + case 12: + compressionLevel = "--ultra-brute"; + break; + default: + throw new IllegalArgumentException(String.format("Unsupported compression level %d", cl)); + } + result.add(compressionLevel); + result.add(getInputFile().getAsFile().get().toString()); + result.add("-f"); + result.add("-o"); + result.add(getOutputFile().getAsFile().get().toString()); + return Collections.unmodifiableList(result); + } + }); + } +} diff --git a/gradle.properties b/gradle.properties index 81b7d94..a0d412c 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,5 +1,5 @@ lys.catalog.version=2025.02.05 -version.myGradlePlugins=2025.02.08 +version.myGradlePlugins=2025.02.25 version.gradle=8.12 gitea.maven.url = https://gitea.woggioni.net/api/packages/woggioni/maven diff --git a/lombok/src/main/java/net/woggioni/gradle/lombok/LombokPlugin.java b/lombok/src/main/java/net/woggioni/gradle/lombok/LombokPlugin.java index c717ac6..f252eba 100644 --- a/lombok/src/main/java/net/woggioni/gradle/lombok/LombokPlugin.java +++ b/lombok/src/main/java/net/woggioni/gradle/lombok/LombokPlugin.java @@ -28,7 +28,6 @@ public class LombokPlugin implements Plugin { @Override public void apply(Project project) { project.getPluginManager().apply(JavaPlugin.class); - ObjectFactory objectFactory = project.getObjects(); LombokExtension ext = project.getExtensions().create("lombok", LombokExtension.class); ExtraPropertiesExtension epe = project.getExtensions().getExtraProperties(); if(epe.has("version.lombok")) { diff --git a/sambal/src/main/java/net/woggioni/gradle/sambal/SambalPlugin.java b/sambal/src/main/java/net/woggioni/gradle/sambal/SambalPlugin.java index 612f195..b3e1867 100644 --- a/sambal/src/main/java/net/woggioni/gradle/sambal/SambalPlugin.java +++ b/sambal/src/main/java/net/woggioni/gradle/sambal/SambalPlugin.java @@ -224,6 +224,7 @@ public class SambalPlugin implements Plugin { it.parameters( params -> params.setRootDirectory(project.getRootDir())); }); ext.set("gitRevision", gitRevisionProvider); + ext.set("which", new MethodClosure(this, "which").curry(project)); PluginManager pluginManager = project.getPluginManager(); pluginManager.withPlugin("java-library", (AppliedPlugin plugin) -> {