added Gradle toolchain support to NativeImage task
All checks were successful
CI / build (push) Successful in 1m32s

This commit is contained in:
2025-03-03 15:49:28 +08:00
parent d580161d01
commit bd548dfd01
4 changed files with 89 additions and 48 deletions

View File

@@ -0,0 +1,22 @@
package net.woggioni.gradle.graalvm;
import org.gradle.api.Action;
import org.gradle.api.model.ObjectFactory;
import org.gradle.jvm.toolchain.JavaToolchainSpec;
import javax.inject.Inject;
abstract class DefaultNativeImageExtension implements NativeImageExtension {
@Inject
public DefaultNativeImageExtension(ObjectFactory objects) {
}
@Override
public JavaToolchainSpec toolchain(Action<? super JavaToolchainSpec> action) {
JavaToolchainSpec jts = getToolchain();
action.execute(getToolchain());
return jts;
}
}

View File

@@ -1,26 +1,32 @@
package net.woggioni.gradle.graalvm;
import org.gradle.api.file.DirectoryProperty;
import org.gradle.api.Action;
import org.gradle.api.file.FileCollection;
import org.gradle.api.provider.Property;
import org.gradle.api.tasks.Nested;
import org.gradle.jvm.toolchain.JavaToolchainSpec;
abstract public class NativeImageExtension {
public abstract Property<FileCollection> getClasspath();
public abstract DirectoryProperty getGraalVmHome();
public interface NativeImageExtension {
Property<FileCollection> getClasspath();
public abstract Property<Boolean> getUseMusl();
public abstract Property<Boolean> getBuildStaticImage();
public abstract Property<Boolean> getEnableFallback();
public abstract Property<Boolean> getLinkAtBuildTime();
@Nested
JavaToolchainSpec getToolchain();
public abstract Property<String> getMainClass();
JavaToolchainSpec toolchain(Action<? super JavaToolchainSpec> action);
public abstract Property<String> getMainModule();
Property<Boolean> getUseMusl();
Property<Boolean> getBuildStaticImage();
Property<Boolean> getEnableFallback();
Property<Boolean> getLinkAtBuildTime();
public abstract Property<Boolean> getCompressExecutable();
Property<String> getMainClass();
public abstract Property<Boolean> getUseLZMA();
Property<String> getMainModule();
public abstract Property<Integer> getCompressionLevel();
Property<Boolean> getCompressExecutable();
Property<Boolean> getUseLZMA();
Property<Integer> getCompressionLevel();
}

View File

@@ -3,9 +3,9 @@ package net.woggioni.gradle.graalvm;
import org.gradle.api.Plugin;
import org.gradle.api.Project;
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.model.ObjectFactory;
import org.gradle.api.plugins.ExtensionContainer;
import org.gradle.api.plugins.JavaLibraryPlugin;
import org.gradle.api.plugins.JavaPlugin;
@@ -15,11 +15,8 @@ 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 static java.util.Optional.ofNullable;
import org.gradle.jvm.toolchain.JavaToolchainSpec;
import org.gradle.jvm.toolchain.internal.DefaultToolchainSpec;
@CacheableTask
public class NativeImagePlugin implements Plugin<Project> {
@@ -30,7 +27,7 @@ public class NativeImagePlugin implements Plugin<Project> {
public static final String NATIVE_IMAGE_CONFIGURATION_FOLDER_NAME = "native-image";
private static <T> void setIfPresent(Property<T> p1, Provider<T> provider) {
if(provider.isPresent()) {
if (provider.isPresent()) {
p1.set(provider);
}
}
@@ -45,25 +42,25 @@ public class NativeImagePlugin implements Plugin<Project> {
Provider<Jar> jarTaskProvider = tasks.named(JavaPlugin.JAR_TASK_NAME, Jar.class, jar -> {
jar.from(layout.getProjectDirectory().dir(NATIVE_IMAGE_CONFIGURATION_FOLDER_NAME), copySpec -> {
copySpec.into(
String.format("META-INF/native-image/%s/%s/",
project.getName(),
project.getGroup()
)
String.format("META-INF/native-image/%s/%s/",
project.getName(),
project.getGroup()
)
);
});
});
NativeImageExtension nativeImageExtension = extensionContainer.create("nativeImage", NativeImageExtension.class);
ExtensionContainer ext = project.getExtensions();
JavaPluginExtension javaPluginExtension = ext.findByType(JavaPluginExtension.class);
JavaToolchainService javaToolchainService = ext.findByType(JavaToolchainService.class);
ObjectFactory objects = project.getObjects();
NativeImageExtension nativeImageExtension = objects.newInstance(DefaultNativeImageExtension.class);
extensionContainer.add("nativeImage", nativeImageExtension);
nativeImageExtension.toolchain(jts -> {
jts.getImplementation().convention(javaPluginExtension.getToolchain().getImplementation());
jts.getVendor().convention(javaPluginExtension.getToolchain().getVendor());
jts.getLanguageVersion().convention(javaPluginExtension.getToolchain().getLanguageVersion());
});
Provider<Directory> 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);
@@ -78,10 +75,16 @@ public class NativeImagePlugin implements Plugin<Project> {
nativeImageExtension.getClasspath().convention(classpath);
Provider<NativeImageConfigurationTask> nativeImageConfigurationTaskProvider =
tasks.register(CONFIGURE_NATIVE_IMAGE_TASK_NAME, NativeImageConfigurationTask.class);
tasks.register(CONFIGURE_NATIVE_IMAGE_TASK_NAME, NativeImageConfigurationTask.class);
Provider<NativeImageTask> nativeImageTaskProvider = tasks.register(NATIVE_IMAGE_TASK_NAME, NativeImageTask.class, nativeImageTask -> {
nativeImageTask.getClasspath().set(nativeImageExtension.getClasspath());
nativeImageTask.toolchain(jts -> {
jts.getImplementation().convention(nativeImageExtension.getToolchain().getImplementation());
jts.getVendor().convention(nativeImageExtension.getToolchain().getVendor());
jts.getLanguageVersion().convention(nativeImageExtension.getToolchain().getLanguageVersion());
});
nativeImageTask.getBuildStaticImage().set(nativeImageExtension.getBuildStaticImage());
nativeImageTask.getUseMusl().set(nativeImageExtension.getUseMusl());
nativeImageTask.getLinkAtBuildTime().set(nativeImageExtension.getLinkAtBuildTime());
@@ -98,7 +101,7 @@ public class NativeImagePlugin implements Plugin<Project> {
});
tasks.named(NATIVE_IMAGE_TASK_NAME, NativeImageTask.class, t -> {
if(nativeImageExtension.getCompressExecutable().getOrElse(false)) {
if (nativeImageExtension.getCompressExecutable().getOrElse(false)) {
t.finalizedBy(upxTaskProvider);
}
});

View File

@@ -1,5 +1,6 @@
package net.woggioni.gradle.graalvm;
import org.gradle.api.Action;
import org.gradle.api.Project;
import org.gradle.api.file.Directory;
import org.gradle.api.file.DirectoryProperty;
@@ -8,10 +9,10 @@ import org.gradle.api.file.ProjectLayout;
import org.gradle.api.file.RegularFileProperty;
import org.gradle.api.logging.Logger;
import org.gradle.api.logging.Logging;
import org.gradle.api.model.ObjectFactory;
import org.gradle.api.plugins.BasePluginExtension;
import org.gradle.api.plugins.ExtensionContainer;
import org.gradle.api.plugins.JavaApplication;
import org.gradle.api.plugins.JavaPluginExtension;
import org.gradle.api.provider.Property;
import org.gradle.api.provider.Provider;
import org.gradle.api.tasks.CacheableTask;
@@ -25,9 +26,9 @@ import org.gradle.api.tasks.OutputFile;
import org.gradle.api.tasks.PathSensitive;
import org.gradle.api.tasks.PathSensitivity;
import org.gradle.internal.jvm.JavaModuleDetector;
import org.gradle.jvm.toolchain.JavaInstallationMetadata;
import org.gradle.jvm.toolchain.JavaLauncher;
import org.gradle.jvm.toolchain.JavaToolchainService;
import org.gradle.jvm.toolchain.JavaToolchainSpec;
import org.gradle.jvm.toolchain.internal.DefaultToolchainSpec;
import org.gradle.process.CommandLineArgumentProvider;
import javax.inject.Inject;
@@ -37,7 +38,6 @@ import java.util.Collections;
import java.util.List;
import java.util.Objects;
import static java.util.Optional.ofNullable;
import static net.woggioni.gradle.graalvm.Constants.GRAALVM_TASK_GROUP;
@CacheableTask
@@ -53,6 +53,13 @@ public abstract class NativeImageTask extends Exec {
@PathSensitive(PathSensitivity.RELATIVE)
public abstract DirectoryProperty getGraalVmHome();
private final JavaToolchainSpec toolchain;
public JavaToolchainSpec toolchain(Action<? super JavaToolchainSpec> action) {
action.execute(toolchain);
return toolchain;
}
@InputFile
@PathSensitive(PathSensitivity.ABSOLUTE)
public abstract RegularFileProperty getNativeCompilerPath();
@@ -81,10 +88,12 @@ public abstract class NativeImageTask extends Exec {
private static final Logger log = Logging.getLogger(NativeImageTask.class);
public NativeImageTask() {
@Inject
public NativeImageTask(ObjectFactory objects) {
Project project = getProject();
setGroup(GRAALVM_TASK_GROUP);
setDescription("Create a native image of the application using GraalVM");
toolchain = objects.newInstance(DefaultToolchainSpec.class);
getUseMusl().convention(false);
getBuildStaticImage().convention(false);
getEnableFallback().convention(false);
@@ -108,15 +117,16 @@ public abstract class NativeImageTask extends Exec {
}
getClasspath().convention(project.files());
ProjectLayout layout = project.getLayout();
JavaToolchainService javaToolchainService = ext.findByType(JavaToolchainService.class);
JavaPluginExtension javaPluginExtension = ext.findByType(JavaPluginExtension.class);
Provider<Directory> 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")))));
getGraalVmHome().convention(graalHomeDirectoryProvider);
JavaToolchainService javaToolchainService = ext.findByType(JavaToolchainService.class);
Provider<Directory> graalHomeDirectoryProvider = javaToolchainService.launcherFor(it -> {
it.getLanguageVersion().set(toolchain.getLanguageVersion());
it.getVendor().set(toolchain.getVendor());
it.getImplementation().set(toolchain.getImplementation());
}).map(javaLauncher ->
javaLauncher.getMetadata().getInstallationPath()
).orElse(layout.dir(project.provider(() -> project.file(System.getProperty("java.home")))));
getGraalVmHome().convention(graalHomeDirectoryProvider);
BasePluginExtension basePluginExtension =
ext.getByType(BasePluginExtension.class);
getOutputFile().convention(basePluginExtension.getLibsDirectory().file(project.getName()));