added jlink plugin
This commit is contained in:
20
graalvm/build.gradle
Normal file
20
graalvm/build.gradle
Normal file
@@ -0,0 +1,20 @@
|
||||
plugins {
|
||||
id 'java-gradle-plugin'
|
||||
}
|
||||
|
||||
|
||||
gradlePlugin {
|
||||
plugins {
|
||||
create("NativeImagePlugin") {
|
||||
id = 'net.woggioni.gradle.graalvm.native-image'
|
||||
implementationClass = "net.woggioni.gradle.graalvm.NativeImagePlugin"
|
||||
}
|
||||
}
|
||||
|
||||
plugins {
|
||||
create("JlinkPlugin") {
|
||||
id = 'net.woggioni.gradle.graalvm.jlink'
|
||||
implementationClass = "net.woggioni.gradle.graalvm.JlinkPlugin"
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,5 @@
|
||||
package net.woggioni.gradle.graalvm;
|
||||
|
||||
public class Constants {
|
||||
public static final String GRAALVM_TASK_GROUP = "graalvm";
|
||||
}
|
@@ -0,0 +1,57 @@
|
||||
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.FileCollection;
|
||||
import org.gradle.api.file.ProjectLayout;
|
||||
import org.gradle.api.plugins.BasePlugin;
|
||||
import org.gradle.api.plugins.BasePluginExtension;
|
||||
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.provider.Provider;
|
||||
import org.gradle.api.tasks.TaskContainer;
|
||||
import org.gradle.api.tasks.bundling.Zip;
|
||||
import org.gradle.jvm.tasks.Jar;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
public class JlinkPlugin implements Plugin<Project> {
|
||||
|
||||
public static final String JLINK_TASK_NAME = "jlink";
|
||||
public static final String JLINK_DIST_TASK_NAME = "jlinkDist";
|
||||
@Override
|
||||
public void apply(Project project) {
|
||||
project.getPluginManager().apply(JavaLibraryPlugin.class);
|
||||
ExtensionContainer extensionContainer = project.getExtensions();
|
||||
BasePluginExtension basePluginExtension = extensionContainer.getByType(BasePluginExtension.class);
|
||||
JavaApplication javaApplicationExtension =
|
||||
Optional.ofNullable(extensionContainer.findByType(JavaApplication.class))
|
||||
.orElseGet(() -> extensionContainer.create("application", JavaApplication.class));
|
||||
|
||||
TaskContainer tasks = project.getTasks();
|
||||
Provider<JlinkTask> jlinTaskProvider = tasks.register(JLINK_TASK_NAME, JlinkTask.class, jlinkTask -> {
|
||||
ConfigurationContainer configurations = project.getConfigurations();
|
||||
FileCollection classpath = project.files(tasks.named(JavaPlugin.JAR_TASK_NAME),
|
||||
configurations.getByName(JavaPlugin.RUNTIME_CLASSPATH_CONFIGURATION_NAME));
|
||||
jlinkTask.getClasspath().set(classpath);
|
||||
});
|
||||
|
||||
Provider<Zip> jlinkZipTaskProvider = tasks.register(JLINK_DIST_TASK_NAME, Zip.class, zip -> {
|
||||
zip.getArchiveBaseName().set(project.getName());
|
||||
if(project.getVersion() != null) {
|
||||
zip.getArchiveVersion().set(project.getVersion().toString());
|
||||
}
|
||||
zip.getDestinationDirectory().set(basePluginExtension.getDistsDirectory());
|
||||
zip.from(jlinTaskProvider);
|
||||
});
|
||||
|
||||
tasks.named(BasePlugin.ASSEMBLE_TASK_NAME, Task.class, t -> {
|
||||
t.getInputs().files(jlinkZipTaskProvider);
|
||||
});
|
||||
|
||||
}
|
||||
}
|
158
graalvm/src/main/java/net/woggioni/gradle/graalvm/JlinkTask.java
Normal file
158
graalvm/src/main/java/net/woggioni/gradle/graalvm/JlinkTask.java
Normal file
@@ -0,0 +1,158 @@
|
||||
package net.woggioni.gradle.graalvm;
|
||||
|
||||
import lombok.SneakyThrows;
|
||||
import org.gradle.api.Project;
|
||||
import org.gradle.api.file.Directory;
|
||||
import org.gradle.api.file.DirectoryProperty;
|
||||
import org.gradle.api.file.FileCollection;
|
||||
import org.gradle.api.file.ProjectLayout;
|
||||
import org.gradle.api.file.RegularFileProperty;
|
||||
import org.gradle.api.logging.Logger;
|
||||
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.ListProperty;
|
||||
import org.gradle.api.provider.Property;
|
||||
import org.gradle.api.provider.Provider;
|
||||
import org.gradle.api.tasks.Classpath;
|
||||
import org.gradle.api.tasks.Exec;
|
||||
import org.gradle.api.tasks.Input;
|
||||
import org.gradle.api.tasks.InputDirectory;
|
||||
import org.gradle.api.tasks.Optional;
|
||||
import org.gradle.api.tasks.OutputDirectory;
|
||||
import org.gradle.api.tasks.OutputFile;
|
||||
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.process.CommandLineArgumentProvider;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import static java.util.Optional.ofNullable;
|
||||
import static net.woggioni.gradle.graalvm.Constants.GRAALVM_TASK_GROUP;
|
||||
|
||||
public abstract class JlinkTask extends Exec {
|
||||
|
||||
@Classpath
|
||||
public abstract Property<FileCollection> getClasspath();
|
||||
|
||||
@InputDirectory
|
||||
public abstract DirectoryProperty getGraalVmHome();
|
||||
|
||||
@Input
|
||||
@Optional
|
||||
public abstract Property<String> getMainClass();
|
||||
|
||||
@Input
|
||||
@Optional
|
||||
public abstract Property<String> getMainModule();
|
||||
|
||||
@Input
|
||||
public abstract ListProperty<String> getAdditionalModules();
|
||||
|
||||
@Inject
|
||||
protected abstract JavaModuleDetector getJavaModuleDetector();
|
||||
|
||||
@OutputDirectory
|
||||
public abstract DirectoryProperty getOutputDir();
|
||||
private final Logger logger;
|
||||
public JlinkTask() {
|
||||
Project project = getProject();
|
||||
logger = project.getLogger();
|
||||
setGroup(GRAALVM_TASK_GROUP);
|
||||
setDescription(
|
||||
"Generates a custom Java runtime image that contains only the platform modules" +
|
||||
" that are required for a given application");
|
||||
ExtensionContainer ext = project.getExtensions();
|
||||
JavaApplication javaApplication = ext.findByType(JavaApplication.class);
|
||||
if(!Objects.isNull(javaApplication)) {
|
||||
getMainClass().convention(javaApplication.getMainClass());
|
||||
getMainModule().convention(javaApplication.getMainModule());
|
||||
}
|
||||
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);
|
||||
getAdditionalModules().convention(new ArrayList<>());
|
||||
|
||||
BasePluginExtension basePluginExtension =
|
||||
ext.getByType(BasePluginExtension.class);
|
||||
getOutputDir().convention(
|
||||
basePluginExtension.getLibsDirectory()
|
||||
.dir(project.getName() +
|
||||
ofNullable(project.getVersion()).map(it -> "-" + it).orElse(""))
|
||||
);
|
||||
Object executableProvider = new Object() {
|
||||
@Override
|
||||
public String toString() {
|
||||
return getGraalVmHome().get() + "/bin/jlink";
|
||||
}
|
||||
};
|
||||
executable(executableProvider);
|
||||
CommandLineArgumentProvider argumentProvider = new CommandLineArgumentProvider() {
|
||||
@Override
|
||||
@SneakyThrows
|
||||
public Iterable<String> asArguments() {
|
||||
List<String> result = new ArrayList<>();
|
||||
result.add("--compress=2");
|
||||
JavaModuleDetector javaModuleDetector = getJavaModuleDetector();
|
||||
FileCollection classpath = getClasspath().get();
|
||||
FileCollection mp = javaModuleDetector.inferModulePath(true, classpath);
|
||||
if(!mp.isEmpty()) {
|
||||
result.add("-p");
|
||||
result.add(mp.getAsPath());
|
||||
}
|
||||
|
||||
if(getMainModule().isPresent()) {
|
||||
result.add("--launcher");
|
||||
String launcherArg = project.getName() + '=' +
|
||||
getMainModule().get() +
|
||||
ofNullable(getMainClass().getOrElse(null)).map(it -> '/' + it).orElse("");
|
||||
result.add(launcherArg);
|
||||
}
|
||||
result.add("--output");
|
||||
result.add(getOutputDir().get().getAsFile().toString());
|
||||
List<String> additionalModules = getAdditionalModules().get();
|
||||
if(getMainModule().isPresent() || !additionalModules.isEmpty()) {
|
||||
result.add("--add-modules");
|
||||
ofNullable(getMainModule().getOrElse(null)).ifPresent(result::add);
|
||||
additionalModules.forEach(result::add);
|
||||
}
|
||||
return Collections.unmodifiableList(result);
|
||||
}
|
||||
};
|
||||
getArgumentProviders().add(argumentProvider);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
@SneakyThrows
|
||||
protected void exec() {
|
||||
Files.walk(getOutputDir().get().getAsFile().toPath())
|
||||
.sorted(Comparator.reverseOrder())
|
||||
.forEach(new Consumer<Path>() {
|
||||
@Override
|
||||
@SneakyThrows
|
||||
public void accept(Path path) {
|
||||
Files.delete(path);
|
||||
}
|
||||
});
|
||||
super.exec();
|
||||
}
|
||||
}
|
@@ -1,14 +1,12 @@
|
||||
package net.woggioni.gradle.nativeimage;
|
||||
package net.woggioni.gradle.graalvm;
|
||||
|
||||
import org.gradle.api.artifacts.Configuration;
|
||||
import org.gradle.api.artifacts.ConfigurationContainer;
|
||||
import org.gradle.api.file.Directory;
|
||||
import org.gradle.api.file.DirectoryProperty;
|
||||
import org.gradle.api.file.ProjectLayout;
|
||||
import org.gradle.api.plugins.JavaApplication;
|
||||
import org.gradle.api.plugins.JavaPlugin;
|
||||
import org.gradle.api.provider.Provider;
|
||||
import org.gradle.api.tasks.Input;
|
||||
import org.gradle.api.tasks.JavaExec;
|
||||
import org.gradle.api.tasks.OutputDirectory;
|
||||
import org.gradle.api.tasks.TaskContainer;
|
||||
@@ -19,10 +17,9 @@ import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.StreamSupport;
|
||||
|
||||
import static net.woggioni.gradle.nativeimage.NativeImagePlugin.NATIVE_IMAGE_CONFIGURATION_FOLDER_NAME;
|
||||
import static net.woggioni.gradle.nativeimage.NativeImagePlugin.NATIVE_IMAGE_TASK_GROUP;
|
||||
import static net.woggioni.gradle.graalvm.Constants.GRAALVM_TASK_GROUP;
|
||||
import static net.woggioni.gradle.graalvm.NativeImagePlugin.NATIVE_IMAGE_CONFIGURATION_FOLDER_NAME;
|
||||
|
||||
public abstract class NativeImageConfigurationTask extends JavaExec {
|
||||
|
||||
@@ -30,7 +27,7 @@ public abstract class NativeImageConfigurationTask extends JavaExec {
|
||||
public abstract DirectoryProperty getConfigurationDir();
|
||||
|
||||
public NativeImageConfigurationTask() {
|
||||
setGroup(NATIVE_IMAGE_TASK_GROUP);
|
||||
setGroup(GRAALVM_TASK_GROUP);
|
||||
setDescription("Run the application with the native-image-agent " +
|
||||
"to create a configuration for native image creation");
|
||||
ProjectLayout layout = getProject().getLayout();
|
@@ -1,10 +1,12 @@
|
||||
package net.woggioni.gradle.nativeimage;
|
||||
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.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;
|
||||
@@ -21,8 +23,6 @@ public class NativeImagePlugin implements Plugin<Project> {
|
||||
public static final String CONFIGURE_NATIVE_IMAGE_TASK_NAME = "configureNativeImage";
|
||||
public static final String NATIVE_IMAGE_CONFIGURATION_FOLDER_NAME = "native-image";
|
||||
|
||||
public static final String NATIVE_IMAGE_TASK_GROUP = "native image";
|
||||
|
||||
@Override
|
||||
public void apply(Project project) {
|
||||
project.getPluginManager().apply(JavaLibraryPlugin.class);
|
||||
@@ -33,6 +33,7 @@ public class NativeImagePlugin implements Plugin<Project> {
|
||||
.orElseGet(() -> extensionContainer.create("application", JavaApplication.class));
|
||||
|
||||
TaskContainer tasks = project.getTasks();
|
||||
|
||||
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(
|
||||
@@ -43,12 +44,20 @@ public class NativeImagePlugin implements Plugin<Project> {
|
||||
);
|
||||
});
|
||||
});
|
||||
tasks.register(CONFIGURE_NATIVE_IMAGE_TASK_NAME, NativeImageConfigurationTask.class);
|
||||
tasks.register(NATIVE_IMAGE_TASK_NAME, NativeImageTask.class, nativeImageTask -> {
|
||||
|
||||
Provider<NativeImageConfigurationTask> nativeImageConfigurationTaskProvider =
|
||||
tasks.register(CONFIGURE_NATIVE_IMAGE_TASK_NAME, NativeImageConfigurationTask.class);
|
||||
|
||||
Provider<NativeImageTask> 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);
|
||||
});
|
||||
|
||||
tasks.named(BasePlugin.ASSEMBLE_TASK_NAME, Task.class, t -> {
|
||||
t.getInputs().files(nativeImageTaskProvider);
|
||||
});
|
||||
}
|
||||
}
|
@@ -1,4 +1,4 @@
|
||||
package net.woggioni.gradle.nativeimage;
|
||||
package net.woggioni.gradle.graalvm;
|
||||
|
||||
import org.gradle.api.Project;
|
||||
import org.gradle.api.file.Directory;
|
||||
@@ -32,7 +32,7 @@ import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
import static java.util.Optional.ofNullable;
|
||||
import static net.woggioni.gradle.nativeimage.NativeImagePlugin.NATIVE_IMAGE_TASK_GROUP;
|
||||
import static net.woggioni.gradle.graalvm.Constants.GRAALVM_TASK_GROUP;
|
||||
|
||||
public abstract class NativeImageTask extends Exec {
|
||||
|
||||
@@ -45,6 +45,10 @@ public abstract class NativeImageTask extends Exec {
|
||||
@Input
|
||||
public abstract Property<Boolean> getUseJpms();
|
||||
@Input
|
||||
public abstract Property<Boolean> getUseMusl();
|
||||
@Input
|
||||
public abstract Property<Boolean> getBuildStaticImage();
|
||||
@Input
|
||||
public abstract Property<Boolean> getEnableFallback();
|
||||
|
||||
@Input
|
||||
@@ -63,9 +67,11 @@ public abstract class NativeImageTask extends Exec {
|
||||
public NativeImageTask() {
|
||||
Project project = getProject();
|
||||
logger = project.getLogger();
|
||||
setGroup(NATIVE_IMAGE_TASK_GROUP);
|
||||
setGroup(GRAALVM_TASK_GROUP);
|
||||
setDescription("Create a native image of the application using GraalVM");
|
||||
getUseJpms().convention(false);
|
||||
getUseMusl().convention(false);
|
||||
getBuildStaticImage().convention(false);
|
||||
getEnableFallback().convention(false);
|
||||
ExtensionContainer ext = project.getExtensions();
|
||||
JavaApplication javaApplication = ext.findByType(JavaApplication.class);
|
||||
@@ -102,6 +108,12 @@ public abstract class NativeImageTask extends Exec {
|
||||
if(!getEnableFallback().get()) {
|
||||
result.add("--no-fallback");
|
||||
}
|
||||
if(getBuildStaticImage().get()) {
|
||||
result.add("--static");
|
||||
}
|
||||
if(getUseMusl().get()) {
|
||||
result.add("--libc=musl");
|
||||
}
|
||||
JavaModuleDetector javaModuleDetector = getJavaModuleDetector();
|
||||
boolean useJpms = getUseJpms().get();
|
||||
FileCollection classpath = getClasspath().get();
|
||||
@@ -118,7 +130,6 @@ public abstract class NativeImageTask extends Exec {
|
||||
result.add("-o");
|
||||
result.add(getOutputFile().get().getAsFile().toString());
|
||||
result.add(getMainClass().get());
|
||||
logger.info("Native image arguments: " + String.join(" ", result));
|
||||
return Collections.unmodifiableList(result);
|
||||
}
|
||||
};
|
@@ -2,7 +2,7 @@ woggioniMavenRepositoryUrl=https://mvn.woggioni.net/
|
||||
|
||||
lys.catalog.version=2023.10.01
|
||||
|
||||
version.myGradlePlugins=2023.10.05
|
||||
version.myGradlePlugins=2023.10.06
|
||||
version.gradle=7.6
|
||||
version.felix.config.admin=1.9.26
|
||||
version.felix=7.0.5
|
||||
|
@@ -1,13 +0,0 @@
|
||||
plugins {
|
||||
id 'java-gradle-plugin'
|
||||
}
|
||||
|
||||
|
||||
gradlePlugin {
|
||||
plugins {
|
||||
create("NativeImagePlugin") {
|
||||
id = "net.woggioni.gradle.native-image"
|
||||
implementationClass = "net.woggioni.gradle.nativeimage.NativeImagePlugin"
|
||||
}
|
||||
}
|
||||
}
|
@@ -26,4 +26,4 @@ include 'osgi-app:osgi-simple-bootstrapper-api'
|
||||
include 'osgi-app:osgi-simple-bootstrapper-application'
|
||||
include 'wildfly'
|
||||
include 'sambal'
|
||||
include 'native-image'
|
||||
include 'graalvm'
|
||||
|
Reference in New Issue
Block a user