Compare commits
18 Commits
bc92b75136
...
master
Author | SHA1 | Date | |
---|---|---|---|
3f6627465c
|
|||
0d32fb5ba9
|
|||
8d9861ae75
|
|||
97df729677
|
|||
d580161d01
|
|||
2b978ddf1c
|
|||
0d5865e638
|
|||
04d50e5a52
|
|||
e0d8628188
|
|||
4565a626d6
|
|||
99f1fd16ab
|
|||
5c16f1bc13
|
|||
0c3f08bfd5
|
|||
b6fa9f2948
|
|||
d1af8ef942
|
|||
6146868f37
|
|||
9c361d0419
|
|||
bffa4f1f56
|
16
.gitea/workflows/build.yaml
Normal file
16
.gitea/workflows/build.yaml
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
name: CI
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [ master ]
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: hostinger
|
||||||
|
steps:
|
||||||
|
- name: Checkout sources
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
- name: Setup Gradle
|
||||||
|
uses: gradle/actions/setup-gradle@v3
|
||||||
|
- name: Execute Gradle build
|
||||||
|
env:
|
||||||
|
PUBLISHER_TOKEN: ${{ secrets.PUBLISHER_TOKEN }}
|
||||||
|
run: ./gradlew build publish
|
31
build.gradle
31
build.gradle
@@ -1,11 +1,13 @@
|
|||||||
subprojects { subproject ->
|
subprojects { subproject ->
|
||||||
apply plugin: 'java-library'
|
apply plugin: 'java-library'
|
||||||
|
apply plugin: 'maven-publish'
|
||||||
|
|
||||||
|
group = "net.woggioni.gradle"
|
||||||
version = getProperty('version.myGradlePlugins')
|
version = getProperty('version.myGradlePlugins')
|
||||||
|
|
||||||
java {
|
java {
|
||||||
toolchain {
|
toolchain {
|
||||||
languageVersion = JavaLanguageVersion.of(17)
|
languageVersion = JavaLanguageVersion.of(21)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -27,12 +29,6 @@ subprojects { subproject ->
|
|||||||
}
|
}
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
maven {
|
|
||||||
url = woggioniMavenRepositoryUrl
|
|
||||||
content {
|
|
||||||
includeGroup 'net.woggioni'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -45,27 +41,30 @@ subprojects { subproject ->
|
|||||||
add("testImplementation", gradleTestKit())
|
add("testImplementation", gradleTestKit())
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks.named("test", Test) {
|
tasks.withType(Test) {
|
||||||
useJUnitPlatform()
|
useJUnitPlatform()
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
childProjects.forEach { name, child ->
|
|
||||||
child.with {
|
|
||||||
apply plugin: 'maven-publish'
|
|
||||||
|
|
||||||
group = "net.woggioni.gradle"
|
|
||||||
|
|
||||||
publishing {
|
publishing {
|
||||||
repositories {
|
repositories {
|
||||||
maven {
|
maven {
|
||||||
url = woggioniMavenRepositoryUrl
|
name = "Gitea"
|
||||||
|
url = uri("https://gitea.woggioni.net/api/packages/woggioni/maven")
|
||||||
|
|
||||||
|
credentials(HttpHeaderCredentials) {
|
||||||
|
name = "Authorization"
|
||||||
|
value = "token ${System.getenv()["PUBLISHER_TOKEN"]}"
|
||||||
|
}
|
||||||
|
|
||||||
|
authentication {
|
||||||
|
header(HttpHeaderAuthentication)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
wrapper {
|
wrapper {
|
||||||
gradleVersion = getProperty("version.gradle")
|
gradleVersion = getProperty("version.gradle")
|
||||||
distributionType = Wrapper.DistributionType.ALL
|
distributionType = Wrapper.DistributionType.ALL
|
||||||
|
@@ -8,6 +8,9 @@ import org.gradle.api.plugins.ObjectConfigurationAction;
|
|||||||
import org.gradle.api.provider.Provider;
|
import org.gradle.api.provider.Provider;
|
||||||
|
|
||||||
public class DependencyExportPlugin implements Plugin<Project> {
|
public class DependencyExportPlugin implements Plugin<Project> {
|
||||||
|
|
||||||
|
public static final String DEPENDENCY_EXPORT_GROUP = "dependency-export";
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void apply(Project project) {
|
public void apply(Project project) {
|
||||||
project.apply(new Action<ObjectConfigurationAction>() {
|
project.apply(new Action<ObjectConfigurationAction>() {
|
||||||
|
@@ -24,6 +24,7 @@ import org.gradle.api.plugins.JavaPlugin;
|
|||||||
import org.gradle.api.plugins.JavaPluginConvention;
|
import org.gradle.api.plugins.JavaPluginConvention;
|
||||||
import org.gradle.api.provider.Property;
|
import org.gradle.api.provider.Property;
|
||||||
import org.gradle.api.provider.Provider;
|
import org.gradle.api.provider.Provider;
|
||||||
|
import org.gradle.api.tasks.Classpath;
|
||||||
import org.gradle.api.tasks.Input;
|
import org.gradle.api.tasks.Input;
|
||||||
import org.gradle.api.tasks.InputFiles;
|
import org.gradle.api.tasks.InputFiles;
|
||||||
import org.gradle.api.tasks.Internal;
|
import org.gradle.api.tasks.Internal;
|
||||||
@@ -49,6 +50,8 @@ import java.util.stream.Collector;
|
|||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
import static net.woggioni.gradle.dependency.export.DependencyExportPlugin.DEPENDENCY_EXPORT_GROUP;
|
||||||
|
|
||||||
public class ExportDependencies extends DefaultTask {
|
public class ExportDependencies extends DefaultTask {
|
||||||
|
|
||||||
@Getter(onMethod_ = { @Input })
|
@Getter(onMethod_ = { @Input })
|
||||||
@@ -74,6 +77,7 @@ public class ExportDependencies extends DefaultTask {
|
|||||||
private final JavaPluginConvention javaPluginConvention;
|
private final JavaPluginConvention javaPluginConvention;
|
||||||
|
|
||||||
@InputFiles
|
@InputFiles
|
||||||
|
@Classpath
|
||||||
public Provider<FileCollection> getConfigurationFiles() {
|
public Provider<FileCollection> getConfigurationFiles() {
|
||||||
return configurationName.map(this::fetchConfiguration);
|
return configurationName.map(this::fetchConfiguration);
|
||||||
}
|
}
|
||||||
@@ -96,6 +100,7 @@ public class ExportDependencies extends DefaultTask {
|
|||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public ExportDependencies(ObjectFactory objects) {
|
public ExportDependencies(ObjectFactory objects) {
|
||||||
|
setGroup(DEPENDENCY_EXPORT_GROUP);
|
||||||
javaPluginConvention = getProject().getConvention().getPlugin(JavaPluginConvention.class);
|
javaPluginConvention = getProject().getConvention().getPlugin(JavaPluginConvention.class);
|
||||||
configurationName = objects.property(String.class).convention(JavaPlugin.RUNTIME_CLASSPATH_CONFIGURATION_NAME);
|
configurationName = objects.property(String.class).convention(JavaPlugin.RUNTIME_CLASSPATH_CONFIGURATION_NAME);
|
||||||
Provider<File> defaultOutputFileProvider =
|
Provider<File> defaultOutputFileProvider =
|
||||||
|
@@ -10,29 +10,37 @@ import org.gradle.api.model.ObjectFactory;
|
|||||||
import org.gradle.api.plugins.JavaPluginConvention;
|
import org.gradle.api.plugins.JavaPluginConvention;
|
||||||
import org.gradle.api.provider.Property;
|
import org.gradle.api.provider.Property;
|
||||||
import org.gradle.api.provider.Provider;
|
import org.gradle.api.provider.Provider;
|
||||||
|
import org.gradle.api.tasks.CacheableTask;
|
||||||
import org.gradle.api.tasks.Input;
|
import org.gradle.api.tasks.Input;
|
||||||
import org.gradle.api.tasks.InputFile;
|
import org.gradle.api.tasks.InputFile;
|
||||||
import org.gradle.api.tasks.Internal;
|
import org.gradle.api.tasks.Internal;
|
||||||
import org.gradle.api.tasks.Optional;
|
import org.gradle.api.tasks.Optional;
|
||||||
import org.gradle.api.tasks.OutputFile;
|
import org.gradle.api.tasks.OutputFile;
|
||||||
|
import org.gradle.api.tasks.PathSensitive;
|
||||||
|
import org.gradle.api.tasks.PathSensitivity;
|
||||||
import org.gradle.api.tasks.TaskAction;
|
import org.gradle.api.tasks.TaskAction;
|
||||||
import org.gradle.api.tasks.options.Option;
|
import org.gradle.api.tasks.options.Option;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
import static net.woggioni.gradle.dependency.export.DependencyExportPlugin.DEPENDENCY_EXPORT_GROUP;
|
||||||
|
|
||||||
|
@CacheableTask
|
||||||
public class RenderDependencies extends DefaultTask {
|
public class RenderDependencies extends DefaultTask {
|
||||||
|
|
||||||
@Getter(onMethod_ = { @InputFile })
|
@Getter(onMethod_ = {@InputFile, @PathSensitive(PathSensitivity.NONE)})
|
||||||
private Provider<File> sourceFile;
|
private Provider<File> sourceFile;
|
||||||
|
|
||||||
@Getter(onMethod_ = { @Input})
|
@Getter(onMethod_ = {@Input})
|
||||||
private final Property<String> format;
|
private final Property<String> format;
|
||||||
|
|
||||||
@Getter(onMethod_ = { @Input })
|
@Getter(onMethod_ = {@Input})
|
||||||
private final Property<String> graphvizExecutable;
|
private final Property<String> graphvizExecutable;
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
@@ -45,6 +53,7 @@ public class RenderDependencies extends DefaultTask {
|
|||||||
return outputFile.map(RegularFile::getAsFile).map(File::getAbsolutePath).getOrNull();
|
return outputFile.map(RegularFile::getAsFile).map(File::getAbsolutePath).getOrNull();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Optional
|
||||||
@OutputFile
|
@OutputFile
|
||||||
public Provider<File> getResult() {
|
public Provider<File> getResult() {
|
||||||
return outputFile.map(RegularFile::getAsFile);
|
return outputFile.map(RegularFile::getAsFile);
|
||||||
@@ -64,33 +73,46 @@ public class RenderDependencies extends DefaultTask {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void setExportTask(Provider<ExportDependencies> taskProvider) {
|
public void setExportTask(Provider<ExportDependencies> taskProvider) {
|
||||||
|
dependsOn(taskProvider);
|
||||||
sourceFile = taskProvider.flatMap(ExportDependencies::getResult);
|
sourceFile = taskProvider.flatMap(ExportDependencies::getResult);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public RenderDependencies(ObjectFactory objects) {
|
public RenderDependencies(ObjectFactory objects) {
|
||||||
|
setGroup(DEPENDENCY_EXPORT_GROUP);
|
||||||
sourceFile = objects.property(File.class);
|
sourceFile = objects.property(File.class);
|
||||||
javaPluginConvention = getProject().getConvention().getPlugin(JavaPluginConvention.class);
|
javaPluginConvention = getProject().getConvention().getPlugin(JavaPluginConvention.class);
|
||||||
format = objects.property(String.class).convention("xlib");
|
format = objects.property(String.class).convention("xlib");
|
||||||
graphvizExecutable = objects.property(String.class).convention("dot");
|
graphvizExecutable = objects.property(String.class).convention("dot");
|
||||||
Provider<File> defaultOutputFileProvider =
|
Provider<File> defaultOutputFileProvider =
|
||||||
getProject().provider(() -> new File(javaPluginConvention.getDocsDir(), "renderedDependencies"));
|
getProject().provider(() -> new File(javaPluginConvention.getDocsDir(), "renderedDependencies"));
|
||||||
outputFile = objects.fileProperty().convention(getProject().getLayout().file(defaultOutputFileProvider));
|
outputFile = objects.fileProperty().convention(getProject().getLayout().file(defaultOutputFileProvider)
|
||||||
|
.zip(format, (file, type) -> Objects.equals("xlib", type) ? null : file));
|
||||||
|
getOutputs().upToDateWhen(t -> outputFile.isPresent());
|
||||||
}
|
}
|
||||||
|
|
||||||
@TaskAction
|
@TaskAction
|
||||||
@SneakyThrows
|
@SneakyThrows
|
||||||
void run() {
|
void run() {
|
||||||
Path destination = outputFile
|
java.util.Optional<Path> destination = java.util.Optional.of(
|
||||||
|
outputFile
|
||||||
.map(RegularFile::getAsFile)
|
.map(RegularFile::getAsFile)
|
||||||
.map(File::toPath)
|
.map(File::toPath)
|
||||||
.get();
|
)
|
||||||
List<String> cmd = Arrays.asList(
|
.filter(Provider::isPresent)
|
||||||
|
.map(Provider::get);
|
||||||
|
|
||||||
|
List<String> cmd = new ArrayList<>(Arrays.asList(
|
||||||
graphvizExecutable.get(),
|
graphvizExecutable.get(),
|
||||||
"-T" + format.get(),
|
"-T" + format.get()
|
||||||
"-o" + destination,
|
));
|
||||||
sourceFile.get().toString()
|
|
||||||
);
|
if (destination.isPresent()) {
|
||||||
|
cmd.add("-o");
|
||||||
|
cmd.add(destination.get().toString());
|
||||||
|
}
|
||||||
|
cmd.add(sourceFile.get().toString());
|
||||||
|
|
||||||
int returnCode = new ProcessBuilder(cmd).inheritIO().start().waitFor();
|
int returnCode = new ProcessBuilder(cmd).inheritIO().start().waitFor();
|
||||||
if (returnCode != 0) {
|
if (returnCode != 0) {
|
||||||
throw new GradleException("Error invoking graphviz");
|
throw new GradleException("Error invoking graphviz");
|
||||||
|
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
@@ -2,11 +2,8 @@ package net.woggioni.gradle.graalvm;
|
|||||||
|
|
||||||
import org.gradle.api.Plugin;
|
import org.gradle.api.Plugin;
|
||||||
import org.gradle.api.Project;
|
import org.gradle.api.Project;
|
||||||
import org.gradle.api.Task;
|
|
||||||
import org.gradle.api.artifacts.ConfigurationContainer;
|
import org.gradle.api.artifacts.ConfigurationContainer;
|
||||||
import org.gradle.api.file.FileCollection;
|
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.BasePluginExtension;
|
||||||
import org.gradle.api.plugins.ExtensionContainer;
|
import org.gradle.api.plugins.ExtensionContainer;
|
||||||
import org.gradle.api.plugins.JavaApplication;
|
import org.gradle.api.plugins.JavaApplication;
|
||||||
@@ -14,23 +11,22 @@ import org.gradle.api.plugins.JavaLibraryPlugin;
|
|||||||
import org.gradle.api.plugins.JavaPlugin;
|
import org.gradle.api.plugins.JavaPlugin;
|
||||||
import org.gradle.api.provider.Provider;
|
import org.gradle.api.provider.Provider;
|
||||||
import org.gradle.api.tasks.TaskContainer;
|
import org.gradle.api.tasks.TaskContainer;
|
||||||
|
import org.gradle.api.tasks.bundling.Tar;
|
||||||
import org.gradle.api.tasks.bundling.Zip;
|
import org.gradle.api.tasks.bundling.Zip;
|
||||||
import org.gradle.jvm.tasks.Jar;
|
|
||||||
|
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
public class JlinkPlugin implements Plugin<Project> {
|
public class JlinkPlugin implements Plugin<Project> {
|
||||||
|
|
||||||
public static final String JLINK_TASK_NAME = "jlink";
|
public static final String JLINK_TASK_NAME = "jlink";
|
||||||
public static final String JLINK_DIST_TASK_NAME = "jlinkDist";
|
public static final String JLINK_DIST_ZIP_TASK_NAME = "jlinkDistZip";
|
||||||
|
public static final String JLINK_DIST_TAR_TASK_NAME = "jlinkDistTar";
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void apply(Project project) {
|
public void apply(Project project) {
|
||||||
project.getPluginManager().apply(JavaLibraryPlugin.class);
|
project.getPluginManager().apply(JavaLibraryPlugin.class);
|
||||||
ExtensionContainer extensionContainer = project.getExtensions();
|
ExtensionContainer extensionContainer = project.getExtensions();
|
||||||
BasePluginExtension basePluginExtension = extensionContainer.getByType(BasePluginExtension.class);
|
BasePluginExtension basePluginExtension = extensionContainer.getByType(BasePluginExtension.class);
|
||||||
JavaApplication javaApplicationExtension =
|
|
||||||
Optional.ofNullable(extensionContainer.findByType(JavaApplication.class))
|
|
||||||
.orElseGet(() -> extensionContainer.create("application", JavaApplication.class));
|
|
||||||
|
|
||||||
TaskContainer tasks = project.getTasks();
|
TaskContainer tasks = project.getTasks();
|
||||||
Provider<JlinkTask> jlinTaskProvider = tasks.register(JLINK_TASK_NAME, JlinkTask.class, jlinkTask -> {
|
Provider<JlinkTask> jlinTaskProvider = tasks.register(JLINK_TASK_NAME, JlinkTask.class, jlinkTask -> {
|
||||||
@@ -40,7 +36,7 @@ public class JlinkPlugin implements Plugin<Project> {
|
|||||||
jlinkTask.getClasspath().set(classpath);
|
jlinkTask.getClasspath().set(classpath);
|
||||||
});
|
});
|
||||||
|
|
||||||
Provider<Zip> jlinkZipTaskProvider = tasks.register(JLINK_DIST_TASK_NAME, Zip.class, zip -> {
|
Provider<Zip> jlinkZipTaskProvider = tasks.register(JLINK_DIST_ZIP_TASK_NAME, Zip.class, zip -> {
|
||||||
zip.getArchiveBaseName().set(project.getName());
|
zip.getArchiveBaseName().set(project.getName());
|
||||||
if(project.getVersion() != null) {
|
if(project.getVersion() != null) {
|
||||||
zip.getArchiveVersion().set(project.getVersion().toString());
|
zip.getArchiveVersion().set(project.getVersion().toString());
|
||||||
@@ -49,5 +45,19 @@ public class JlinkPlugin implements Plugin<Project> {
|
|||||||
zip.from(jlinTaskProvider);
|
zip.from(jlinTaskProvider);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Provider<Tar> jlinkTarTaskProvider = tasks.register(JLINK_DIST_TAR_TASK_NAME, Tar.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(JLINK_TASK_NAME, JlinkTask.class, jlinkTask -> {
|
||||||
|
jlinkTask.finalizedBy(jlinkZipTaskProvider);
|
||||||
|
jlinkTask.finalizedBy(jlinkTarTaskProvider);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,13 +1,15 @@
|
|||||||
package net.woggioni.gradle.graalvm;
|
package net.woggioni.gradle.graalvm;
|
||||||
|
|
||||||
import lombok.SneakyThrows;
|
import lombok.SneakyThrows;
|
||||||
|
import org.gradle.api.Action;
|
||||||
import org.gradle.api.Project;
|
import org.gradle.api.Project;
|
||||||
import org.gradle.api.file.Directory;
|
import org.gradle.api.file.Directory;
|
||||||
import org.gradle.api.file.DirectoryProperty;
|
import org.gradle.api.file.DirectoryProperty;
|
||||||
import org.gradle.api.file.FileCollection;
|
import org.gradle.api.file.FileCollection;
|
||||||
import org.gradle.api.file.ProjectLayout;
|
import org.gradle.api.file.ProjectLayout;
|
||||||
import org.gradle.api.file.RegularFileProperty;
|
|
||||||
import org.gradle.api.logging.Logger;
|
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.BasePluginExtension;
|
||||||
import org.gradle.api.plugins.ExtensionContainer;
|
import org.gradle.api.plugins.ExtensionContainer;
|
||||||
import org.gradle.api.plugins.JavaApplication;
|
import org.gradle.api.plugins.JavaApplication;
|
||||||
@@ -21,11 +23,12 @@ import org.gradle.api.tasks.Input;
|
|||||||
import org.gradle.api.tasks.InputDirectory;
|
import org.gradle.api.tasks.InputDirectory;
|
||||||
import org.gradle.api.tasks.Optional;
|
import org.gradle.api.tasks.Optional;
|
||||||
import org.gradle.api.tasks.OutputDirectory;
|
import org.gradle.api.tasks.OutputDirectory;
|
||||||
import org.gradle.api.tasks.OutputFile;
|
|
||||||
import org.gradle.internal.jvm.JavaModuleDetector;
|
import org.gradle.internal.jvm.JavaModuleDetector;
|
||||||
import org.gradle.jvm.toolchain.JavaInstallationMetadata;
|
import org.gradle.jvm.toolchain.JavaInstallationMetadata;
|
||||||
import org.gradle.jvm.toolchain.JavaLauncher;
|
import org.gradle.jvm.toolchain.JavaLauncher;
|
||||||
import org.gradle.jvm.toolchain.JavaToolchainService;
|
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 org.gradle.process.CommandLineArgumentProvider;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
@@ -43,6 +46,13 @@ import static net.woggioni.gradle.graalvm.Constants.GRAALVM_TASK_GROUP;
|
|||||||
|
|
||||||
public abstract class JlinkTask extends Exec {
|
public abstract class JlinkTask extends Exec {
|
||||||
|
|
||||||
|
private final JavaToolchainSpec toolchain;
|
||||||
|
|
||||||
|
public JavaToolchainSpec toolchain(Action<? super JavaToolchainSpec> action) {
|
||||||
|
action.execute(toolchain);
|
||||||
|
return toolchain;
|
||||||
|
}
|
||||||
|
|
||||||
@Classpath
|
@Classpath
|
||||||
public abstract Property<FileCollection> getClasspath();
|
public abstract Property<FileCollection> getClasspath();
|
||||||
|
|
||||||
@@ -60,15 +70,39 @@ public abstract class JlinkTask extends Exec {
|
|||||||
@Input
|
@Input
|
||||||
public abstract ListProperty<String> getAdditionalModules();
|
public abstract ListProperty<String> getAdditionalModules();
|
||||||
|
|
||||||
|
@Input
|
||||||
|
public abstract ListProperty<String> getLimitModules();
|
||||||
|
|
||||||
|
@Input
|
||||||
|
public abstract Property<Boolean> getBindServices();
|
||||||
|
|
||||||
|
@Input
|
||||||
|
public abstract Property<Boolean> getIncludeHeaderFiles();
|
||||||
|
|
||||||
|
@Input
|
||||||
|
public abstract Property<Boolean> getIncludeManPages();
|
||||||
|
|
||||||
|
@Input
|
||||||
|
public abstract Property<Boolean> getStripDebug();
|
||||||
|
|
||||||
|
@Input
|
||||||
|
public abstract Property<Boolean> getGenerateCdsArchive();
|
||||||
|
|
||||||
|
@Input
|
||||||
|
@Optional
|
||||||
|
public abstract Property<Integer> getCompressionLevel();
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
protected abstract JavaModuleDetector getJavaModuleDetector();
|
protected abstract JavaModuleDetector getJavaModuleDetector();
|
||||||
|
|
||||||
@OutputDirectory
|
@OutputDirectory
|
||||||
public abstract DirectoryProperty getOutputDir();
|
public abstract DirectoryProperty getOutputDir();
|
||||||
private final Logger logger;
|
|
||||||
public JlinkTask() {
|
private static final Logger log = Logging.getLogger(JlinkTask.class);
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
public JlinkTask(ObjectFactory objects) {
|
||||||
Project project = getProject();
|
Project project = getProject();
|
||||||
logger = project.getLogger();
|
|
||||||
setGroup(GRAALVM_TASK_GROUP);
|
setGroup(GRAALVM_TASK_GROUP);
|
||||||
setDescription(
|
setDescription(
|
||||||
"Generates a custom Java runtime image that contains only the platform modules" +
|
"Generates a custom Java runtime image that contains only the platform modules" +
|
||||||
@@ -79,17 +113,27 @@ public abstract class JlinkTask extends Exec {
|
|||||||
getMainClass().convention(javaApplication.getMainClass());
|
getMainClass().convention(javaApplication.getMainClass());
|
||||||
getMainModule().convention(javaApplication.getMainModule());
|
getMainModule().convention(javaApplication.getMainModule());
|
||||||
}
|
}
|
||||||
|
getIncludeManPages().convention(false);
|
||||||
|
getIncludeHeaderFiles().convention(false);
|
||||||
|
getGenerateCdsArchive().convention(true);
|
||||||
|
getStripDebug().convention(true);
|
||||||
getClasspath().convention(project.files());
|
getClasspath().convention(project.files());
|
||||||
ProjectLayout layout = project.getLayout();
|
ProjectLayout layout = project.getLayout();
|
||||||
|
toolchain = getObjectFactory().newInstance(DefaultToolchainSpec.class);
|
||||||
JavaToolchainService javaToolchainService = ext.findByType(JavaToolchainService.class);
|
JavaToolchainService javaToolchainService = ext.findByType(JavaToolchainService.class);
|
||||||
JavaPluginExtension javaPluginExtension = ext.findByType(JavaPluginExtension.class);
|
Provider<Directory> graalHomeDirectoryProvider = javaToolchainService.launcherFor(it -> {
|
||||||
Provider<Directory> graalHomeDirectoryProvider = ofNullable(javaPluginExtension.getToolchain()).map(javaToolchainSpec ->
|
it.getLanguageVersion().set(toolchain.getLanguageVersion());
|
||||||
javaToolchainService.launcherFor(javaToolchainSpec)
|
it.getVendor().set(toolchain.getVendor());
|
||||||
).map(javaLauncher ->
|
it.getImplementation().set(toolchain.getImplementation());
|
||||||
javaLauncher.map(JavaLauncher::getMetadata).map(JavaInstallationMetadata::getInstallationPath)
|
}).map(javaLauncher ->
|
||||||
).orElseGet(() -> layout.dir(project.provider(() ->project.file(System.getProperty("java.home")))));
|
javaLauncher.getMetadata().getInstallationPath()
|
||||||
|
).orElse(layout.dir(project.provider(() -> project.file(System.getProperty("java.home")))));
|
||||||
|
getGraalVmHome().convention(graalHomeDirectoryProvider);
|
||||||
|
|
||||||
getGraalVmHome().convention(graalHomeDirectoryProvider);
|
getGraalVmHome().convention(graalHomeDirectoryProvider);
|
||||||
getAdditionalModules().convention(new ArrayList<>());
|
getAdditionalModules().convention(new ArrayList<>());
|
||||||
|
getLimitModules().convention(new ArrayList<>());
|
||||||
|
getBindServices().convention(false);
|
||||||
|
|
||||||
BasePluginExtension basePluginExtension =
|
BasePluginExtension basePluginExtension =
|
||||||
ext.getByType(BasePluginExtension.class);
|
ext.getByType(BasePluginExtension.class);
|
||||||
@@ -110,7 +154,13 @@ public abstract class JlinkTask extends Exec {
|
|||||||
@SneakyThrows
|
@SneakyThrows
|
||||||
public Iterable<String> asArguments() {
|
public Iterable<String> asArguments() {
|
||||||
List<String> result = new ArrayList<>();
|
List<String> result = new ArrayList<>();
|
||||||
result.add("--compress=2");
|
final Property<Integer> compressionLevelProperty = getCompressionLevel();
|
||||||
|
if(compressionLevelProperty.isPresent()) {
|
||||||
|
result.add(String.format("--compress=zip-%d", compressionLevelProperty.get()));
|
||||||
|
}
|
||||||
|
if(getBindServices().get()) {
|
||||||
|
result.add("--bind-services");
|
||||||
|
}
|
||||||
JavaModuleDetector javaModuleDetector = getJavaModuleDetector();
|
JavaModuleDetector javaModuleDetector = getJavaModuleDetector();
|
||||||
FileCollection classpath = getClasspath().get();
|
FileCollection classpath = getClasspath().get();
|
||||||
FileCollection mp = javaModuleDetector.inferModulePath(true, classpath);
|
FileCollection mp = javaModuleDetector.inferModulePath(true, classpath);
|
||||||
@@ -131,8 +181,34 @@ public abstract class JlinkTask extends Exec {
|
|||||||
List<String> additionalModules = getAdditionalModules().get();
|
List<String> additionalModules = getAdditionalModules().get();
|
||||||
if(getMainModule().isPresent() || !additionalModules.isEmpty()) {
|
if(getMainModule().isPresent() || !additionalModules.isEmpty()) {
|
||||||
result.add("--add-modules");
|
result.add("--add-modules");
|
||||||
ofNullable(getMainModule().getOrElse(null)).ifPresent(result::add);
|
final List<String> modules2BeAdded = new ArrayList<>();
|
||||||
additionalModules.forEach(result::add);
|
ofNullable(getMainModule().getOrElse(null)).ifPresent(modules2BeAdded::add);
|
||||||
|
modules2BeAdded.addAll(additionalModules);
|
||||||
|
if(!modules2BeAdded.isEmpty()) {
|
||||||
|
result.add(String.join(",", modules2BeAdded));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
List<String> limitModules = getLimitModules().get();
|
||||||
|
if(!limitModules.isEmpty()) {
|
||||||
|
result.add("--limit-modules");
|
||||||
|
final List<String> modules2BeAdded = new ArrayList<>();
|
||||||
|
modules2BeAdded.addAll(limitModules);
|
||||||
|
if(!modules2BeAdded.isEmpty()) {
|
||||||
|
result.add(String.join(",", modules2BeAdded));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(getStripDebug().getOrElse(false)) {
|
||||||
|
result.add("--strip-debug");
|
||||||
|
}
|
||||||
|
if(getGenerateCdsArchive().getOrElse(false)) {
|
||||||
|
result.add("--generate-cds-archive");
|
||||||
|
}
|
||||||
|
if(!getIncludeHeaderFiles().getOrElse(true)) {
|
||||||
|
result.add("--no-header-files");
|
||||||
|
}
|
||||||
|
if(!getIncludeManPages().getOrElse(true)) {
|
||||||
|
result.add("--no-man-pages");
|
||||||
}
|
}
|
||||||
return Collections.unmodifiableList(result);
|
return Collections.unmodifiableList(result);
|
||||||
}
|
}
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
package net.woggioni.gradle.graalvm;
|
package net.woggioni.gradle.graalvm;
|
||||||
|
|
||||||
|
import org.gradle.api.Action;
|
||||||
import org.gradle.api.artifacts.Configuration;
|
import org.gradle.api.artifacts.Configuration;
|
||||||
import org.gradle.api.artifacts.ConfigurationContainer;
|
import org.gradle.api.artifacts.ConfigurationContainer;
|
||||||
import org.gradle.api.file.DirectoryProperty;
|
import org.gradle.api.file.DirectoryProperty;
|
||||||
@@ -17,6 +18,8 @@ import org.gradle.api.tasks.TaskContainer;
|
|||||||
import org.gradle.api.tasks.bundling.Jar;
|
import org.gradle.api.tasks.bundling.Jar;
|
||||||
import org.gradle.jvm.toolchain.JavaLauncher;
|
import org.gradle.jvm.toolchain.JavaLauncher;
|
||||||
import org.gradle.jvm.toolchain.JavaToolchainService;
|
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 org.gradle.process.CommandLineArgumentProvider;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@@ -35,10 +38,18 @@ public abstract class NativeImageConfigurationTask extends JavaExec {
|
|||||||
@OutputDirectory
|
@OutputDirectory
|
||||||
public abstract DirectoryProperty getConfigurationDir();
|
public abstract DirectoryProperty getConfigurationDir();
|
||||||
|
|
||||||
|
private final JavaToolchainSpec toolchain;
|
||||||
|
|
||||||
|
public JavaToolchainSpec toolchain(Action<? super JavaToolchainSpec> action) {
|
||||||
|
action.execute(toolchain);
|
||||||
|
return toolchain;
|
||||||
|
}
|
||||||
|
|
||||||
public NativeImageConfigurationTask() {
|
public NativeImageConfigurationTask() {
|
||||||
setGroup(GRAALVM_TASK_GROUP);
|
setGroup(GRAALVM_TASK_GROUP);
|
||||||
setDescription("Run the application with the native-image-agent " +
|
setDescription("Run the application with the native-image-agent " +
|
||||||
"to create a configuration for native image creation");
|
"to create a configuration for native image creation");
|
||||||
|
toolchain = getProject().getObjects().newInstance(DefaultToolchainSpec.class);
|
||||||
ProjectLayout layout = getProject().getLayout();
|
ProjectLayout layout = getProject().getLayout();
|
||||||
TaskContainer taskContainer = getProject().getTasks();
|
TaskContainer taskContainer = getProject().getTasks();
|
||||||
JavaApplication javaApplication = getProject().getExtensions().findByType(JavaApplication.class);
|
JavaApplication javaApplication = getProject().getExtensions().findByType(JavaApplication.class);
|
||||||
@@ -46,8 +57,8 @@ public abstract class NativeImageConfigurationTask extends JavaExec {
|
|||||||
ExtensionContainer ext = getProject().getExtensions();
|
ExtensionContainer ext = getProject().getExtensions();
|
||||||
Property<JavaLauncher> javaLauncherProperty = getJavaLauncher();
|
Property<JavaLauncher> javaLauncherProperty = getJavaLauncher();
|
||||||
Optional.ofNullable(ext.findByType(JavaToolchainService.class))
|
Optional.ofNullable(ext.findByType(JavaToolchainService.class))
|
||||||
.flatMap(ts -> Optional.ofNullable(javaExtension.getToolchain()).map(ts::launcherFor))
|
.flatMap(ts -> Optional.of(toolchain).map(ts::launcherFor))
|
||||||
.ifPresent(javaLauncherProperty::set);
|
.ifPresent(javaLauncherProperty::convention);
|
||||||
if(!Objects.isNull(javaApplication)) {
|
if(!Objects.isNull(javaApplication)) {
|
||||||
getMainClass().convention(javaApplication.getMainClass());
|
getMainClass().convention(javaApplication.getMainClass());
|
||||||
getMainModule().convention(javaApplication.getMainModule());
|
getMainModule().convention(javaApplication.getMainModule());
|
||||||
@@ -74,7 +85,9 @@ public abstract class NativeImageConfigurationTask extends JavaExec {
|
|||||||
} else {
|
} else {
|
||||||
jvmArgs.add("-agentlib:native-image-agent=config-output-dir=" + getConfigurationDir().get());
|
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);
|
jvmArgs.add(jvmArg);
|
||||||
}
|
}
|
||||||
return jvmArgs;
|
return jvmArgs;
|
||||||
|
@@ -0,0 +1,32 @@
|
|||||||
|
package net.woggioni.gradle.graalvm;
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
|
||||||
|
public interface NativeImageExtension {
|
||||||
|
Property<FileCollection> getClasspath();
|
||||||
|
|
||||||
|
@Nested
|
||||||
|
JavaToolchainSpec getToolchain();
|
||||||
|
|
||||||
|
JavaToolchainSpec toolchain(Action<? super JavaToolchainSpec> action);
|
||||||
|
|
||||||
|
Property<Boolean> getUseMusl();
|
||||||
|
Property<Boolean> getBuildStaticImage();
|
||||||
|
Property<Boolean> getEnableFallback();
|
||||||
|
Property<Boolean> getLinkAtBuildTime();
|
||||||
|
|
||||||
|
Property<String> getMainClass();
|
||||||
|
|
||||||
|
Property<String> getMainModule();
|
||||||
|
|
||||||
|
Property<Boolean> getCompressExecutable();
|
||||||
|
|
||||||
|
Property<Boolean> getUseLZMA();
|
||||||
|
|
||||||
|
Property<Integer> getCompressionLevel();
|
||||||
|
}
|
@@ -2,36 +2,41 @@ package net.woggioni.gradle.graalvm;
|
|||||||
|
|
||||||
import org.gradle.api.Plugin;
|
import org.gradle.api.Plugin;
|
||||||
import org.gradle.api.Project;
|
import org.gradle.api.Project;
|
||||||
import org.gradle.api.Task;
|
|
||||||
import org.gradle.api.artifacts.ConfigurationContainer;
|
import org.gradle.api.artifacts.ConfigurationContainer;
|
||||||
import org.gradle.api.file.FileCollection;
|
import org.gradle.api.file.FileCollection;
|
||||||
import org.gradle.api.file.ProjectLayout;
|
import org.gradle.api.file.ProjectLayout;
|
||||||
import org.gradle.api.plugins.BasePlugin;
|
import org.gradle.api.model.ObjectFactory;
|
||||||
import org.gradle.api.plugins.ExtensionContainer;
|
import org.gradle.api.plugins.ExtensionContainer;
|
||||||
import org.gradle.api.plugins.JavaApplication;
|
|
||||||
import org.gradle.api.plugins.JavaLibraryPlugin;
|
import org.gradle.api.plugins.JavaLibraryPlugin;
|
||||||
import org.gradle.api.plugins.JavaPlugin;
|
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.provider.Provider;
|
||||||
|
import org.gradle.api.tasks.CacheableTask;
|
||||||
import org.gradle.api.tasks.TaskContainer;
|
import org.gradle.api.tasks.TaskContainer;
|
||||||
import org.gradle.jvm.tasks.Jar;
|
import org.gradle.jvm.tasks.Jar;
|
||||||
|
import org.gradle.jvm.toolchain.JavaToolchainSpec;
|
||||||
|
import org.gradle.jvm.toolchain.internal.DefaultToolchainSpec;
|
||||||
|
|
||||||
import java.util.Optional;
|
@CacheableTask
|
||||||
|
|
||||||
public class NativeImagePlugin implements Plugin<Project> {
|
public class NativeImagePlugin implements Plugin<Project> {
|
||||||
|
|
||||||
public static final String NATIVE_IMAGE_TASK_NAME = "nativeImage";
|
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 CONFIGURE_NATIVE_IMAGE_TASK_NAME = "configureNativeImage";
|
||||||
public static final String NATIVE_IMAGE_CONFIGURATION_FOLDER_NAME = "native-image";
|
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()) {
|
||||||
|
p1.set(provider);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void apply(Project project) {
|
public void apply(Project project) {
|
||||||
project.getPluginManager().apply(JavaLibraryPlugin.class);
|
project.getPluginManager().apply(JavaLibraryPlugin.class);
|
||||||
ProjectLayout layout = project.getLayout();
|
ProjectLayout layout = project.getLayout();
|
||||||
ExtensionContainer extensionContainer = project.getExtensions();
|
ExtensionContainer extensionContainer = project.getExtensions();
|
||||||
JavaApplication javaApplicationExtension =
|
|
||||||
Optional.ofNullable(extensionContainer.findByType(JavaApplication.class))
|
|
||||||
.orElseGet(() -> extensionContainer.create("application", JavaApplication.class));
|
|
||||||
|
|
||||||
TaskContainer tasks = project.getTasks();
|
TaskContainer tasks = project.getTasks();
|
||||||
|
|
||||||
Provider<Jar> jarTaskProvider = tasks.named(JavaPlugin.JAR_TASK_NAME, Jar.class, jar -> {
|
Provider<Jar> jarTaskProvider = tasks.named(JavaPlugin.JAR_TASK_NAME, Jar.class, jar -> {
|
||||||
@@ -44,16 +49,70 @@ public class NativeImagePlugin implements Plugin<Project> {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
ExtensionContainer ext = project.getExtensions();
|
||||||
|
JavaPluginExtension javaPluginExtension = ext.findByType(JavaPluginExtension.class);
|
||||||
|
ObjectFactory objects = project.getObjects();
|
||||||
|
NativeImageExtension nativeImageExtension = objects.newInstance(DefaultNativeImageExtension.class);
|
||||||
|
extensionContainer.add("nativeImage", nativeImageExtension);
|
||||||
|
|
||||||
Provider<NativeImageConfigurationTask> nativeImageConfigurationTaskProvider =
|
nativeImageExtension.toolchain(jts -> {
|
||||||
tasks.register(CONFIGURE_NATIVE_IMAGE_TASK_NAME, NativeImageConfigurationTask.class);
|
jts.getImplementation().convention(javaPluginExtension.getToolchain().getImplementation());
|
||||||
|
jts.getVendor().convention(javaPluginExtension.getToolchain().getVendor());
|
||||||
|
jts.getLanguageVersion().convention(javaPluginExtension.getToolchain().getLanguageVersion());
|
||||||
|
});
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
Provider<NativeImageTask> nativeImageTaskProvider = tasks.register(NATIVE_IMAGE_TASK_NAME, NativeImageTask.class, nativeImageTask -> {
|
|
||||||
nativeImageTask.getInputs().files(nativeImageConfigurationTaskProvider);
|
|
||||||
ConfigurationContainer configurations = project.getConfigurations();
|
ConfigurationContainer configurations = project.getConfigurations();
|
||||||
FileCollection classpath = project.files(jarTaskProvider,
|
FileCollection classpath = project.files(jarTaskProvider,
|
||||||
configurations.getByName(JavaPlugin.RUNTIME_CLASSPATH_CONFIGURATION_NAME));
|
configurations.getByName(JavaPlugin.RUNTIME_CLASSPATH_CONFIGURATION_NAME));
|
||||||
nativeImageTask.getClasspath().set(classpath);
|
nativeImageExtension.getClasspath().convention(classpath);
|
||||||
|
|
||||||
|
Provider<NativeImageConfigurationTask> nativeImageConfigurationTaskProvider = tasks.register(
|
||||||
|
CONFIGURE_NATIVE_IMAGE_TASK_NAME,
|
||||||
|
NativeImageConfigurationTask.class,
|
||||||
|
nativeImageConfigurationTask -> {
|
||||||
|
nativeImageConfigurationTask.toolchain(jts -> {
|
||||||
|
jts.getImplementation().convention(nativeImageExtension.getToolchain().getImplementation());
|
||||||
|
jts.getVendor().convention(nativeImageExtension.getToolchain().getVendor());
|
||||||
|
jts.getLanguageVersion().convention(nativeImageExtension.getToolchain().getLanguageVersion());
|
||||||
});
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
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());
|
||||||
|
nativeImageTask.getMainClass().set(nativeImageExtension.getMainClass());
|
||||||
|
nativeImageTask.getMainModule().set(nativeImageExtension.getMainModule());
|
||||||
|
nativeImageTask.getEnableFallback().set(nativeImageExtension.getEnableFallback());
|
||||||
|
});
|
||||||
|
|
||||||
|
Provider<UpxTask> 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);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
package net.woggioni.gradle.graalvm;
|
package net.woggioni.gradle.graalvm;
|
||||||
|
|
||||||
|
import org.gradle.api.Action;
|
||||||
import org.gradle.api.Project;
|
import org.gradle.api.Project;
|
||||||
import org.gradle.api.file.Directory;
|
import org.gradle.api.file.Directory;
|
||||||
import org.gradle.api.file.DirectoryProperty;
|
import org.gradle.api.file.DirectoryProperty;
|
||||||
@@ -7,49 +8,71 @@ import org.gradle.api.file.FileCollection;
|
|||||||
import org.gradle.api.file.ProjectLayout;
|
import org.gradle.api.file.ProjectLayout;
|
||||||
import org.gradle.api.file.RegularFileProperty;
|
import org.gradle.api.file.RegularFileProperty;
|
||||||
import org.gradle.api.logging.Logger;
|
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.BasePluginExtension;
|
||||||
import org.gradle.api.plugins.ExtensionContainer;
|
import org.gradle.api.plugins.ExtensionContainer;
|
||||||
import org.gradle.api.plugins.JavaApplication;
|
import org.gradle.api.plugins.JavaApplication;
|
||||||
import org.gradle.api.plugins.JavaPluginExtension;
|
|
||||||
import org.gradle.api.provider.Property;
|
import org.gradle.api.provider.Property;
|
||||||
import org.gradle.api.provider.Provider;
|
import org.gradle.api.provider.Provider;
|
||||||
|
import org.gradle.api.tasks.CacheableTask;
|
||||||
import org.gradle.api.tasks.Classpath;
|
import org.gradle.api.tasks.Classpath;
|
||||||
import org.gradle.api.tasks.Exec;
|
import org.gradle.api.tasks.Exec;
|
||||||
import org.gradle.api.tasks.Input;
|
import org.gradle.api.tasks.Input;
|
||||||
import org.gradle.api.tasks.InputDirectory;
|
import org.gradle.api.tasks.InputDirectory;
|
||||||
|
import org.gradle.api.tasks.InputFile;
|
||||||
import org.gradle.api.tasks.Optional;
|
import org.gradle.api.tasks.Optional;
|
||||||
import org.gradle.api.tasks.OutputFile;
|
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.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.JavaToolchainService;
|
||||||
|
import org.gradle.jvm.toolchain.JavaToolchainSpec;
|
||||||
|
import org.gradle.jvm.toolchain.internal.DefaultToolchainSpec;
|
||||||
import org.gradle.process.CommandLineArgumentProvider;
|
import org.gradle.process.CommandLineArgumentProvider;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
import java.io.File;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
import static java.util.Optional.ofNullable;
|
|
||||||
import static net.woggioni.gradle.graalvm.Constants.GRAALVM_TASK_GROUP;
|
import static net.woggioni.gradle.graalvm.Constants.GRAALVM_TASK_GROUP;
|
||||||
|
|
||||||
|
@CacheableTask
|
||||||
public abstract class NativeImageTask extends Exec {
|
public abstract class NativeImageTask extends Exec {
|
||||||
|
|
||||||
|
public static final String NATIVE_COMPILER_PATH_ENV_VARIABLE = "GRAAL_NATIVE_COMPILER_PATH";
|
||||||
|
public static final String NATIVE_COMPILER_PATH_PROPERTY_KEY = "graal.native.compiler.path";
|
||||||
|
|
||||||
@Classpath
|
@Classpath
|
||||||
public abstract Property<FileCollection> getClasspath();
|
public abstract Property<FileCollection> getClasspath();
|
||||||
|
|
||||||
@InputDirectory
|
@InputDirectory
|
||||||
|
@PathSensitive(PathSensitivity.RELATIVE)
|
||||||
public abstract DirectoryProperty getGraalVmHome();
|
public abstract DirectoryProperty getGraalVmHome();
|
||||||
|
|
||||||
@Input
|
private final JavaToolchainSpec toolchain;
|
||||||
public abstract Property<Boolean> getUseJpms();
|
|
||||||
|
public JavaToolchainSpec toolchain(Action<? super JavaToolchainSpec> action) {
|
||||||
|
action.execute(toolchain);
|
||||||
|
return toolchain;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Optional
|
||||||
|
@InputFile
|
||||||
|
@PathSensitive(PathSensitivity.ABSOLUTE)
|
||||||
|
public abstract RegularFileProperty getNativeCompilerPath();
|
||||||
|
|
||||||
@Input
|
@Input
|
||||||
public abstract Property<Boolean> getUseMusl();
|
public abstract Property<Boolean> getUseMusl();
|
||||||
@Input
|
@Input
|
||||||
public abstract Property<Boolean> getBuildStaticImage();
|
public abstract Property<Boolean> getBuildStaticImage();
|
||||||
@Input
|
@Input
|
||||||
public abstract Property<Boolean> getEnableFallback();
|
public abstract Property<Boolean> getEnableFallback();
|
||||||
|
@Input
|
||||||
|
public abstract Property<Boolean> getLinkAtBuildTime();
|
||||||
|
|
||||||
@Input
|
@Input
|
||||||
public abstract Property<String> getMainClass();
|
public abstract Property<String> getMainClass();
|
||||||
@@ -63,16 +86,30 @@ public abstract class NativeImageTask extends Exec {
|
|||||||
|
|
||||||
@OutputFile
|
@OutputFile
|
||||||
protected abstract RegularFileProperty getOutputFile();
|
protected abstract RegularFileProperty getOutputFile();
|
||||||
private final Logger logger;
|
|
||||||
public NativeImageTask() {
|
private static final Logger log = Logging.getLogger(NativeImageTask.class);
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
public NativeImageTask(ObjectFactory objects) {
|
||||||
Project project = getProject();
|
Project project = getProject();
|
||||||
logger = project.getLogger();
|
|
||||||
setGroup(GRAALVM_TASK_GROUP);
|
setGroup(GRAALVM_TASK_GROUP);
|
||||||
setDescription("Create a native image of the application using GraalVM");
|
setDescription("Create a native image of the application using GraalVM");
|
||||||
getUseJpms().convention(false);
|
toolchain = objects.newInstance(DefaultToolchainSpec.class);
|
||||||
getUseMusl().convention(false);
|
getUseMusl().convention(false);
|
||||||
getBuildStaticImage().convention(false);
|
getBuildStaticImage().convention(false);
|
||||||
getEnableFallback().convention(false);
|
getEnableFallback().convention(false);
|
||||||
|
getLinkAtBuildTime().convention(false);
|
||||||
|
Provider<File> nativeComnpilerProvider = project.provider(() -> {
|
||||||
|
String envVar;
|
||||||
|
File compilerPath = null;
|
||||||
|
if(project.hasProperty(NATIVE_COMPILER_PATH_PROPERTY_KEY)) {
|
||||||
|
compilerPath = new File(project.property(NATIVE_COMPILER_PATH_PROPERTY_KEY).toString());
|
||||||
|
} else if((envVar = System.getenv(NATIVE_COMPILER_PATH_ENV_VARIABLE)) != null) {
|
||||||
|
compilerPath = new File(envVar);
|
||||||
|
}
|
||||||
|
return compilerPath;
|
||||||
|
});
|
||||||
|
getNativeCompilerPath().convention(project.getLayout().file(nativeComnpilerProvider));
|
||||||
ExtensionContainer ext = project.getExtensions();
|
ExtensionContainer ext = project.getExtensions();
|
||||||
JavaApplication javaApplication = ext.findByType(JavaApplication.class);
|
JavaApplication javaApplication = ext.findByType(JavaApplication.class);
|
||||||
if(!Objects.isNull(javaApplication)) {
|
if(!Objects.isNull(javaApplication)) {
|
||||||
@@ -81,15 +118,16 @@ public abstract class NativeImageTask extends Exec {
|
|||||||
}
|
}
|
||||||
getClasspath().convention(project.files());
|
getClasspath().convention(project.files());
|
||||||
ProjectLayout layout = project.getLayout();
|
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 =
|
BasePluginExtension basePluginExtension =
|
||||||
ext.getByType(BasePluginExtension.class);
|
ext.getByType(BasePluginExtension.class);
|
||||||
getOutputFile().convention(basePluginExtension.getLibsDirectory().file(project.getName()));
|
getOutputFile().convention(basePluginExtension.getLibsDirectory().file(project.getName()));
|
||||||
@@ -114,8 +152,14 @@ public abstract class NativeImageTask extends Exec {
|
|||||||
if(getUseMusl().get()) {
|
if(getUseMusl().get()) {
|
||||||
result.add("--libc=musl");
|
result.add("--libc=musl");
|
||||||
}
|
}
|
||||||
|
if(getLinkAtBuildTime().get()) {
|
||||||
|
result.add("--link-at-build-time");
|
||||||
|
}
|
||||||
|
if(getNativeCompilerPath().isPresent()) {
|
||||||
|
result.add("--native-compiler-path=" + getNativeCompilerPath().getAsFile().get());
|
||||||
|
}
|
||||||
JavaModuleDetector javaModuleDetector = getJavaModuleDetector();
|
JavaModuleDetector javaModuleDetector = getJavaModuleDetector();
|
||||||
boolean useJpms = getUseJpms().get();
|
boolean useJpms = getMainModule().isPresent();
|
||||||
FileCollection classpath = getClasspath().get();
|
FileCollection classpath = getClasspath().get();
|
||||||
FileCollection cp = javaModuleDetector.inferClasspath(useJpms, classpath);
|
FileCollection cp = javaModuleDetector.inferClasspath(useJpms, classpath);
|
||||||
FileCollection mp = javaModuleDetector.inferModulePath(useJpms, classpath);
|
FileCollection mp = javaModuleDetector.inferModulePath(useJpms, classpath);
|
||||||
@@ -129,7 +173,15 @@ public abstract class NativeImageTask extends Exec {
|
|||||||
}
|
}
|
||||||
result.add("-o");
|
result.add("-o");
|
||||||
result.add(getOutputFile().get().getAsFile().toString());
|
result.add(getOutputFile().get().getAsFile().toString());
|
||||||
|
if(getMainModule().isPresent()) {
|
||||||
|
result.add("--module");
|
||||||
|
String mainModule = getMainModule().get();
|
||||||
|
result.add(getMainClass()
|
||||||
|
.map(mainClass -> String.format("%s/%s", mainModule, mainClass))
|
||||||
|
.getOrElse(mainModule));
|
||||||
|
} else {
|
||||||
result.add(getMainClass().get());
|
result.add(getMainClass().get());
|
||||||
|
}
|
||||||
return Collections.unmodifiableList(result);
|
return Collections.unmodifiableList(result);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
108
graalvm/src/main/java/net/woggioni/gradle/graalvm/UpxTask.java
Normal file
108
graalvm/src/main/java/net/woggioni/gradle/graalvm/UpxTask.java
Normal file
@@ -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<Boolean> getUseLZMA();
|
||||||
|
|
||||||
|
@Input
|
||||||
|
public abstract Property<Integer> 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<String> asArguments() {
|
||||||
|
List<String> result = new ArrayList<String>();
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
@@ -1,15 +1,5 @@
|
|||||||
woggioniMavenRepositoryUrl=https://mvn.woggioni.net/
|
lys.catalog.version=2025.02.05
|
||||||
|
version.myGradlePlugins=2025.04.16
|
||||||
|
version.gradle=8.12
|
||||||
|
|
||||||
lys.catalog.version=2024.02.12
|
gitea.maven.url = https://gitea.woggioni.net/api/packages/woggioni/maven
|
||||||
|
|
||||||
version.myGradlePlugins=2024.03.11
|
|
||||||
version.gradle=7.6
|
|
||||||
version.felix.config.admin=1.9.26
|
|
||||||
version.felix=7.0.5
|
|
||||||
version.felix.scr=2.2.4
|
|
||||||
version.felix.security=2.8.2
|
|
||||||
version.osgi=8.0.0
|
|
||||||
version.osgi.cm=1.6.0
|
|
||||||
version.osgi.service.component=1.5.1
|
|
||||||
version.osgi.function=1.2.0
|
|
||||||
version.osgi.promise=1.3.0
|
|
||||||
|
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
Binary file not shown.
4
gradle/wrapper/gradle-wrapper.properties
vendored
4
gradle/wrapper/gradle-wrapper.properties
vendored
@@ -1,5 +1,7 @@
|
|||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.6-all.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-8.12-all.zip
|
||||||
|
networkTimeout=10000
|
||||||
|
validateDistributionUrl=true
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
|
43
gradlew
vendored
43
gradlew
vendored
@@ -15,6 +15,8 @@
|
|||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
#
|
#
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
#
|
||||||
|
|
||||||
##############################################################################
|
##############################################################################
|
||||||
#
|
#
|
||||||
@@ -55,7 +57,7 @@
|
|||||||
# Darwin, MinGW, and NonStop.
|
# Darwin, MinGW, and NonStop.
|
||||||
#
|
#
|
||||||
# (3) This script is generated from the Groovy template
|
# (3) This script is generated from the Groovy template
|
||||||
# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
|
# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
|
||||||
# within the Gradle project.
|
# within the Gradle project.
|
||||||
#
|
#
|
||||||
# You can find Gradle at https://github.com/gradle/gradle/.
|
# You can find Gradle at https://github.com/gradle/gradle/.
|
||||||
@@ -80,13 +82,11 @@ do
|
|||||||
esac
|
esac
|
||||||
done
|
done
|
||||||
|
|
||||||
APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
|
# This is normally unused
|
||||||
|
# shellcheck disable=SC2034
|
||||||
APP_NAME="Gradle"
|
|
||||||
APP_BASE_NAME=${0##*/}
|
APP_BASE_NAME=${0##*/}
|
||||||
|
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
|
||||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit
|
||||||
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
|
||||||
|
|
||||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||||
MAX_FD=maximum
|
MAX_FD=maximum
|
||||||
@@ -133,22 +133,29 @@ location of your Java installation."
|
|||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
JAVACMD=java
|
JAVACMD=java
|
||||||
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
if ! command -v java >/dev/null 2>&1
|
||||||
|
then
|
||||||
|
die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||||
|
|
||||||
Please set the JAVA_HOME variable in your environment to match the
|
Please set the JAVA_HOME variable in your environment to match the
|
||||||
location of your Java installation."
|
location of your Java installation."
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Increase the maximum file descriptors if we can.
|
# Increase the maximum file descriptors if we can.
|
||||||
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
|
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
|
||||||
case $MAX_FD in #(
|
case $MAX_FD in #(
|
||||||
max*)
|
max*)
|
||||||
|
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
|
||||||
|
# shellcheck disable=SC2039,SC3045
|
||||||
MAX_FD=$( ulimit -H -n ) ||
|
MAX_FD=$( ulimit -H -n ) ||
|
||||||
warn "Could not query maximum file descriptor limit"
|
warn "Could not query maximum file descriptor limit"
|
||||||
esac
|
esac
|
||||||
case $MAX_FD in #(
|
case $MAX_FD in #(
|
||||||
'' | soft) :;; #(
|
'' | soft) :;; #(
|
||||||
*)
|
*)
|
||||||
|
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
|
||||||
|
# shellcheck disable=SC2039,SC3045
|
||||||
ulimit -n "$MAX_FD" ||
|
ulimit -n "$MAX_FD" ||
|
||||||
warn "Could not set maximum file descriptor limit to $MAX_FD"
|
warn "Could not set maximum file descriptor limit to $MAX_FD"
|
||||||
esac
|
esac
|
||||||
@@ -193,11 +200,15 @@ if "$cygwin" || "$msys" ; then
|
|||||||
done
|
done
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Collect all arguments for the java command;
|
|
||||||
# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
|
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||||
# shell script including quotes and variable substitutions, so put them in
|
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
||||||
# double quotes to make sure that they get re-expanded; and
|
|
||||||
# * put everything else in single quotes, so that it's not re-expanded.
|
# Collect all arguments for the java command:
|
||||||
|
# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
|
||||||
|
# and any embedded shellness will be escaped.
|
||||||
|
# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
|
||||||
|
# treated as '${Hostname}' itself on the command line.
|
||||||
|
|
||||||
set -- \
|
set -- \
|
||||||
"-Dorg.gradle.appname=$APP_BASE_NAME" \
|
"-Dorg.gradle.appname=$APP_BASE_NAME" \
|
||||||
@@ -205,6 +216,12 @@ set -- \
|
|||||||
org.gradle.wrapper.GradleWrapperMain \
|
org.gradle.wrapper.GradleWrapperMain \
|
||||||
"$@"
|
"$@"
|
||||||
|
|
||||||
|
# Stop when "xargs" is not available.
|
||||||
|
if ! command -v xargs >/dev/null 2>&1
|
||||||
|
then
|
||||||
|
die "xargs is not available"
|
||||||
|
fi
|
||||||
|
|
||||||
# Use "xargs" to parse quoted args.
|
# Use "xargs" to parse quoted args.
|
||||||
#
|
#
|
||||||
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
|
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
|
||||||
|
37
gradlew.bat
vendored
37
gradlew.bat
vendored
@@ -13,8 +13,10 @@
|
|||||||
@rem See the License for the specific language governing permissions and
|
@rem See the License for the specific language governing permissions and
|
||||||
@rem limitations under the License.
|
@rem limitations under the License.
|
||||||
@rem
|
@rem
|
||||||
|
@rem SPDX-License-Identifier: Apache-2.0
|
||||||
|
@rem
|
||||||
|
|
||||||
@if "%DEBUG%" == "" @echo off
|
@if "%DEBUG%"=="" @echo off
|
||||||
@rem ##########################################################################
|
@rem ##########################################################################
|
||||||
@rem
|
@rem
|
||||||
@rem Gradle startup script for Windows
|
@rem Gradle startup script for Windows
|
||||||
@@ -25,7 +27,8 @@
|
|||||||
if "%OS%"=="Windows_NT" setlocal
|
if "%OS%"=="Windows_NT" setlocal
|
||||||
|
|
||||||
set DIRNAME=%~dp0
|
set DIRNAME=%~dp0
|
||||||
if "%DIRNAME%" == "" set DIRNAME=.
|
if "%DIRNAME%"=="" set DIRNAME=.
|
||||||
|
@rem This is normally unused
|
||||||
set APP_BASE_NAME=%~n0
|
set APP_BASE_NAME=%~n0
|
||||||
set APP_HOME=%DIRNAME%
|
set APP_HOME=%DIRNAME%
|
||||||
|
|
||||||
@@ -40,13 +43,13 @@ if defined JAVA_HOME goto findJavaFromJavaHome
|
|||||||
|
|
||||||
set JAVA_EXE=java.exe
|
set JAVA_EXE=java.exe
|
||||||
%JAVA_EXE% -version >NUL 2>&1
|
%JAVA_EXE% -version >NUL 2>&1
|
||||||
if "%ERRORLEVEL%" == "0" goto execute
|
if %ERRORLEVEL% equ 0 goto execute
|
||||||
|
|
||||||
echo.
|
echo. 1>&2
|
||||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
|
||||||
echo.
|
echo. 1>&2
|
||||||
echo Please set the JAVA_HOME variable in your environment to match the
|
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
|
||||||
echo location of your Java installation.
|
echo location of your Java installation. 1>&2
|
||||||
|
|
||||||
goto fail
|
goto fail
|
||||||
|
|
||||||
@@ -56,11 +59,11 @@ set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
|||||||
|
|
||||||
if exist "%JAVA_EXE%" goto execute
|
if exist "%JAVA_EXE%" goto execute
|
||||||
|
|
||||||
echo.
|
echo. 1>&2
|
||||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
|
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
|
||||||
echo.
|
echo. 1>&2
|
||||||
echo Please set the JAVA_HOME variable in your environment to match the
|
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
|
||||||
echo location of your Java installation.
|
echo location of your Java installation. 1>&2
|
||||||
|
|
||||||
goto fail
|
goto fail
|
||||||
|
|
||||||
@@ -75,13 +78,15 @@ set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
|||||||
|
|
||||||
:end
|
:end
|
||||||
@rem End local scope for the variables with windows NT shell
|
@rem End local scope for the variables with windows NT shell
|
||||||
if "%ERRORLEVEL%"=="0" goto mainEnd
|
if %ERRORLEVEL% equ 0 goto mainEnd
|
||||||
|
|
||||||
:fail
|
:fail
|
||||||
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
||||||
rem the _cmd.exe /c_ return code!
|
rem the _cmd.exe /c_ return code!
|
||||||
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
|
set EXIT_CODE=%ERRORLEVEL%
|
||||||
exit /b 1
|
if %EXIT_CODE% equ 0 set EXIT_CODE=1
|
||||||
|
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
|
||||||
|
exit /b %EXIT_CODE%
|
||||||
|
|
||||||
:mainEnd
|
:mainEnd
|
||||||
if "%OS%"=="Windows_NT" endlocal
|
if "%OS%"=="Windows_NT" endlocal
|
||||||
|
13
jdeps/build.gradle
Normal file
13
jdeps/build.gradle
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
plugins {
|
||||||
|
id 'java-gradle-plugin'
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
gradlePlugin {
|
||||||
|
plugins {
|
||||||
|
create("JdepsPlugin") {
|
||||||
|
id = 'net.woggioni.gradle.jdeps'
|
||||||
|
implementationClass = "net.woggioni.gradle.jdeps.JdepsPlugin"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,5 @@
|
|||||||
|
package net.woggioni.gradle.jdeps;
|
||||||
|
|
||||||
|
public class Constants {
|
||||||
|
public static final String JDEPS_TASK_GROUP = "jdeps";
|
||||||
|
}
|
@@ -0,0 +1,26 @@
|
|||||||
|
package net.woggioni.gradle.jdeps;
|
||||||
|
|
||||||
|
import org.gradle.api.Plugin;
|
||||||
|
import org.gradle.api.Project;
|
||||||
|
import org.gradle.api.artifacts.ConfigurationContainer;
|
||||||
|
import org.gradle.api.file.FileCollection;
|
||||||
|
import org.gradle.api.plugins.JavaLibraryPlugin;
|
||||||
|
import org.gradle.api.plugins.JavaPlugin;
|
||||||
|
import org.gradle.api.provider.Provider;
|
||||||
|
import org.gradle.api.tasks.TaskContainer;
|
||||||
|
|
||||||
|
public class JdepsPlugin implements Plugin<Project> {
|
||||||
|
public static final String JDEPS_TASK_NAME = "jdeps";
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void apply(Project project) {
|
||||||
|
project.getPluginManager().apply(JavaLibraryPlugin.class);
|
||||||
|
TaskContainer tasks = project.getTasks();
|
||||||
|
Provider<JdepsTask> jdepsTaskProvider = tasks.register(JDEPS_TASK_NAME, JdepsTask.class, jdepsTask -> {
|
||||||
|
ConfigurationContainer configurations = project.getConfigurations();
|
||||||
|
FileCollection classpath = project.files(configurations.getByName(JavaPlugin.RUNTIME_CLASSPATH_CONFIGURATION_NAME));
|
||||||
|
jdepsTask.getClasspath().set(classpath);
|
||||||
|
jdepsTask.getArchives().set(project.files(tasks.named(JavaPlugin.JAR_TASK_NAME)));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
209
jdeps/src/main/java/net/woggioni/gradle/jdeps/JdepsTask.java
Normal file
209
jdeps/src/main/java/net/woggioni/gradle/jdeps/JdepsTask.java
Normal file
@@ -0,0 +1,209 @@
|
|||||||
|
package net.woggioni.gradle.jdeps;
|
||||||
|
|
||||||
|
import lombok.SneakyThrows;
|
||||||
|
import org.gradle.api.Action;
|
||||||
|
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.logging.Logger;
|
||||||
|
import org.gradle.api.logging.Logging;
|
||||||
|
import org.gradle.api.plugins.BasePluginExtension;
|
||||||
|
import org.gradle.api.plugins.ExtensionContainer;
|
||||||
|
import org.gradle.api.plugins.JavaApplication;
|
||||||
|
import org.gradle.api.provider.ListProperty;
|
||||||
|
import org.gradle.api.provider.Property;
|
||||||
|
import org.gradle.api.provider.Provider;
|
||||||
|
import org.gradle.api.reporting.ReportingExtension;
|
||||||
|
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.internal.jvm.JavaModuleDetector;
|
||||||
|
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;
|
||||||
|
import java.io.File;
|
||||||
|
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.jdeps.Constants.JDEPS_TASK_GROUP;
|
||||||
|
|
||||||
|
public abstract class JdepsTask extends Exec {
|
||||||
|
|
||||||
|
private final JavaToolchainSpec toolchain;
|
||||||
|
|
||||||
|
public JavaToolchainSpec toolchain(Action<? super JavaToolchainSpec> action) {
|
||||||
|
action.execute(toolchain);
|
||||||
|
return toolchain;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Classpath
|
||||||
|
public abstract Property<FileCollection> getClasspath();
|
||||||
|
|
||||||
|
@Classpath
|
||||||
|
public abstract Property<FileCollection> getArchives();
|
||||||
|
|
||||||
|
@InputDirectory
|
||||||
|
public abstract DirectoryProperty getJavaHome();
|
||||||
|
|
||||||
|
@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();
|
||||||
|
|
||||||
|
@Optional
|
||||||
|
@OutputDirectory
|
||||||
|
public abstract DirectoryProperty getDotOutput();
|
||||||
|
|
||||||
|
@Input
|
||||||
|
@Optional
|
||||||
|
public abstract Property<Integer> getJavaRelease();
|
||||||
|
|
||||||
|
@Input
|
||||||
|
public abstract Property<Boolean> getRecursive();
|
||||||
|
|
||||||
|
private static final Logger log = Logging.getLogger(JdepsTask.class);
|
||||||
|
|
||||||
|
public JdepsTask() {
|
||||||
|
Project project = getProject();
|
||||||
|
setGroup(JDEPS_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());
|
||||||
|
getRecursive().convention(true);
|
||||||
|
ProjectLayout layout = project.getLayout();
|
||||||
|
toolchain = getObjectFactory().newInstance(DefaultToolchainSpec.class);
|
||||||
|
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")))));
|
||||||
|
getJavaHome().convention(graalHomeDirectoryProvider);
|
||||||
|
|
||||||
|
getJavaHome().convention(graalHomeDirectoryProvider);
|
||||||
|
getAdditionalModules().convention(new ArrayList<>());
|
||||||
|
|
||||||
|
ReportingExtension reporting = ext.getByType(ReportingExtension.class);
|
||||||
|
|
||||||
|
getOutputDir().convention(
|
||||||
|
reporting.getBaseDirectory()
|
||||||
|
.dir(project.getName() +
|
||||||
|
ofNullable(project.getVersion()).map(it -> "-" + it).orElse(""))
|
||||||
|
);
|
||||||
|
getDotOutput().convention(getOutputDir().dir("graphviz"));
|
||||||
|
Object executableProvider = new Object() {
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return getJavaHome().get() + "/bin/jdeps";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
executable(executableProvider);
|
||||||
|
CommandLineArgumentProvider argumentProvider = new CommandLineArgumentProvider() {
|
||||||
|
@Override
|
||||||
|
@SneakyThrows
|
||||||
|
public Iterable<String> asArguments() {
|
||||||
|
List<String> result = new ArrayList<>();
|
||||||
|
JavaModuleDetector javaModuleDetector = getJavaModuleDetector();
|
||||||
|
FileCollection classpath = getClasspath().get();
|
||||||
|
FileCollection mp = javaModuleDetector.inferModulePath(true, classpath);
|
||||||
|
if (!mp.isEmpty()) {
|
||||||
|
result.add("--module-path");
|
||||||
|
result.add(mp.getAsPath());
|
||||||
|
}
|
||||||
|
|
||||||
|
FileCollection cp = classpath.minus(mp);
|
||||||
|
if(!cp.isEmpty()) {
|
||||||
|
result.add("-cp");
|
||||||
|
result.add(cp.getAsPath());
|
||||||
|
}
|
||||||
|
|
||||||
|
List<String> additionalModules = getAdditionalModules().get();
|
||||||
|
if (!additionalModules.isEmpty()) {
|
||||||
|
result.add("--add-modules");
|
||||||
|
final List<String> modules2BeAdded = new ArrayList<>();
|
||||||
|
modules2BeAdded.addAll(additionalModules);
|
||||||
|
if (!modules2BeAdded.isEmpty()) {
|
||||||
|
result.add(String.join(",", modules2BeAdded));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (getDotOutput().isPresent()) {
|
||||||
|
result.add("-dotoutput");
|
||||||
|
result.add(getDotOutput().get().getAsFile().toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
if(getRecursive().get()) {
|
||||||
|
result.add("--recursive");
|
||||||
|
} else {
|
||||||
|
result.add("--no-recursive");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (getMainModule().isPresent()) {
|
||||||
|
result.add("-m");
|
||||||
|
result.add(getMainModule().get());
|
||||||
|
}
|
||||||
|
if (getJavaRelease().isPresent()) {
|
||||||
|
result.add("--multi-release");
|
||||||
|
result.add(getJavaRelease().get().toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
for (File archive : getArchives().get()) {
|
||||||
|
result.add(archive.toString());
|
||||||
|
}
|
||||||
|
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,216 +1,43 @@
|
|||||||
package net.woggioni.gradle.jpms.check
|
package net.woggioni.gradle.jpms.check
|
||||||
|
|
||||||
import groovy.json.JsonBuilder
|
|
||||||
import groovy.transform.Canonical
|
|
||||||
import groovy.transform.CompileStatic
|
import groovy.transform.CompileStatic
|
||||||
import groovy.xml.MarkupBuilder
|
|
||||||
import org.gradle.api.GradleException
|
|
||||||
import org.gradle.api.Plugin
|
import org.gradle.api.Plugin
|
||||||
import org.gradle.api.Project
|
import org.gradle.api.Project
|
||||||
import org.gradle.api.artifacts.Configuration
|
import org.gradle.api.file.RegularFile
|
||||||
import org.gradle.api.artifacts.result.ResolvedArtifactResult
|
import org.gradle.api.plugins.JavaPlugin
|
||||||
|
import org.gradle.api.plugins.ReportingBasePlugin
|
||||||
import java.nio.file.Files
|
import org.gradle.api.reporting.ReportingExtension
|
||||||
import java.nio.file.Path
|
|
||||||
import java.nio.file.Paths
|
|
||||||
import java.util.jar.JarFile
|
|
||||||
import java.util.stream.Collectors
|
|
||||||
import java.util.stream.Stream
|
|
||||||
import java.util.zip.ZipFile
|
|
||||||
|
|
||||||
class JPMSCheckPlugin implements Plugin<Project> {
|
class JPMSCheckPlugin implements Plugin<Project> {
|
||||||
|
|
||||||
@Canonical
|
|
||||||
@CompileStatic
|
|
||||||
private class CheckResult {
|
|
||||||
ResolvedArtifactResult dep
|
|
||||||
String automaticModuleName
|
|
||||||
boolean multiReleaseJar
|
|
||||||
boolean moduleInfo
|
|
||||||
|
|
||||||
boolean getJpmsFriendly() {
|
|
||||||
return automaticModuleName != null || moduleInfo
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
boolean equals(Object other) {
|
|
||||||
if(other == null) {
|
|
||||||
return false
|
|
||||||
} else if(other.class == CheckResult.class) {
|
|
||||||
return dep?.id?.componentIdentifier == ((CheckResult) other).dep?.id?.componentIdentifier
|
|
||||||
} else {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
int hashCode() {
|
|
||||||
return dep.id.componentIdentifier.hashCode()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@CompileStatic
|
|
||||||
private Stream<CheckResult> computeResults(Stream<ResolvedArtifactResult> artifacts) {
|
|
||||||
return artifacts.filter { ResolvedArtifactResult res ->
|
|
||||||
res.file.exists() && res.file.name.endsWith(".jar")
|
|
||||||
}.<CheckResult>map { resolvedArtifact ->
|
|
||||||
JarFile jarFile = new JarFile(resolvedArtifact.file).with {
|
|
||||||
if (it.isMultiRelease()) {
|
|
||||||
new JarFile(
|
|
||||||
resolvedArtifact.file,
|
|
||||||
false,
|
|
||||||
ZipFile.OPEN_READ,
|
|
||||||
Runtime.version()
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
it
|
|
||||||
}
|
|
||||||
}
|
|
||||||
String automaticModuleName = jarFile.manifest?.with {it.mainAttributes.getValue("Automatic-Module-Name") }
|
|
||||||
def moduleInfoEntry = jarFile.getJarEntry("module-info.class")
|
|
||||||
new CheckResult(
|
|
||||||
resolvedArtifact,
|
|
||||||
automaticModuleName,
|
|
||||||
jarFile.isMultiRelease(),
|
|
||||||
moduleInfoEntry != null
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void createHtmlReport(Project project, Stream<CheckResult> checkResults, Writer writer) {
|
|
||||||
def builder = new MarkupBuilder(writer)
|
|
||||||
int friendly = 0
|
|
||||||
int total = 0
|
|
||||||
def results = checkResults.peek { CheckResult res ->
|
|
||||||
total += 1
|
|
||||||
if(res.jpmsFriendly) friendly += 1
|
|
||||||
}.collect(Collectors.toList())
|
|
||||||
builder.html {
|
|
||||||
head {
|
|
||||||
meta name: "viewport", content: "width=device-width, initial-scale=1"
|
|
||||||
InputStream resourceStream = getClass().classLoader.getResourceAsStream('net/woggioni/plugins/jpms/check/github-markdown.css')
|
|
||||||
resourceStream.withReader { Reader reader ->
|
|
||||||
style reader.text
|
|
||||||
}
|
|
||||||
body {
|
|
||||||
article(class: 'markdown-body') {
|
|
||||||
h1 "Project ${project.group}:${project.name}:${project.version}", style: "text-align: center;"
|
|
||||||
div {
|
|
||||||
table {
|
|
||||||
thead {
|
|
||||||
tr {
|
|
||||||
th "JPMS friendly"
|
|
||||||
th "Not JPMS friendly", colspan: 2
|
|
||||||
th "Total", colspan: 2
|
|
||||||
}
|
|
||||||
}
|
|
||||||
tbody {
|
|
||||||
tr {
|
|
||||||
td friendly, style: "text-align: center;"
|
|
||||||
td total - friendly, style: "text-align: center;", colspan: 2
|
|
||||||
td total, style: "text-align: center;", colspan: 2
|
|
||||||
}
|
|
||||||
}
|
|
||||||
thead {
|
|
||||||
th "Name"
|
|
||||||
th "Multi-release jar"
|
|
||||||
th "Automatic-Module-Name"
|
|
||||||
th "Module descriptor"
|
|
||||||
th "JPMS friendly"
|
|
||||||
}
|
|
||||||
tbody {
|
|
||||||
results.forEach {res ->
|
|
||||||
String color = res.jpmsFriendly ? "#dfd" : "fdd"
|
|
||||||
tr(style: "background-color:$color;") {
|
|
||||||
td res.dep.id.displayName
|
|
||||||
td style: "text-align: center;", res.multiReleaseJar ? "✓" : "✕"
|
|
||||||
td style: "text-align: center;", res.automaticModuleName ?: "n/a"
|
|
||||||
td style: "text-align: center;", res.moduleInfo ? "✓" : "✕"
|
|
||||||
td style: "text-align: center;", res.jpmsFriendly ? "✓" : "✕"
|
|
||||||
}
|
|
||||||
total += 1
|
|
||||||
if(res.jpmsFriendly) friendly += 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@CompileStatic
|
|
||||||
private createJsonReport(Stream<CheckResult> checkResults, Writer writer) {
|
|
||||||
def builder = new JsonBuilder()
|
|
||||||
builder (checkResults.map {
|
|
||||||
[
|
|
||||||
name: it.dep.id.componentIdentifier.displayName,
|
|
||||||
automaticModuleName: it.automaticModuleName,
|
|
||||||
isMultiReleaseJar: it.multiReleaseJar,
|
|
||||||
hasModuleInfo: it.moduleInfo,
|
|
||||||
jpmsFriendly: it.jpmsFriendly
|
|
||||||
]
|
|
||||||
}.collect(Collectors.toList()))
|
|
||||||
builder.writeTo(writer)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@CompileStatic
|
@CompileStatic
|
||||||
void apply(Project project) {
|
void apply(Project project) {
|
||||||
project.tasks.register("jpms-check") {task ->
|
project.pluginManager.apply(ReportingBasePlugin.class)
|
||||||
boolean recursive = project.properties["jpms-check.recursive"]?.with(Boolean.&parseBoolean) ?: false
|
project.tasks.register("jpms-check", JPMSCheckTask) {task ->
|
||||||
String cfgName = project.properties["jpms-check.configurationName"] ?: "default"
|
ReportingExtension reporting = project.extensions.getByType(ReportingExtension.class)
|
||||||
String outputFormat = project.properties["jpms-check.outputFormat"] ?: "html"
|
boolean recursive = project.properties["jpms-check.recursive"]?.with(Object.&toString)?.with(Boolean.&parseBoolean) ?: false
|
||||||
Path outputFile = project.properties["jpms-check.outputFile"]?.with {
|
String cfgName = project.properties["jpms-check.configurationName"] ?: JavaPlugin.RUNTIME_CLASSPATH_CONFIGURATION_NAME
|
||||||
Paths.get(it as String)
|
OutputFormat defaultOutputFormat = (project.properties["jpms-check.outputFormat"]
|
||||||
} ?: with {
|
?.with(Object.&toString)
|
||||||
|
?.with(OutputFormat.&valueOf)
|
||||||
|
?: OutputFormat.html)
|
||||||
|
task.getConfigurationName().convention(cfgName)
|
||||||
|
task.getRecursive().convention(recursive)
|
||||||
|
task.outputFormat.convention(defaultOutputFormat)
|
||||||
|
task.getOutputFile().convention(reporting.baseDirectory.zip(task.getOutputFormat(), { dir, outputFormat ->
|
||||||
|
RegularFile result = null
|
||||||
switch(outputFormat) {
|
switch(outputFormat) {
|
||||||
case "html":
|
case OutputFormat.html:
|
||||||
Paths.get(project.buildDir.path, "jpms-report.html")
|
result = dir.file( "jpms-report.html")
|
||||||
break
|
break
|
||||||
case "json":
|
case OutputFormat.json:
|
||||||
Paths.get(project.buildDir.path, "jpms-report.json")
|
result = dir.file( "jpms-report.json")
|
||||||
break
|
break
|
||||||
default:
|
|
||||||
throw new IllegalArgumentException("Unsupported output format: $outputFormat")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
task.doLast {
|
|
||||||
Stream<Project> projects = Stream.of(project)
|
|
||||||
if(recursive) {
|
|
||||||
projects = Stream.concat(projects, project.subprojects.stream())
|
|
||||||
}
|
|
||||||
Set<CheckResult> results = projects.flatMap {
|
|
||||||
Configuration requestedConfiguration = (project.configurations.<Configuration>find { Configuration cfg ->
|
|
||||||
cfg.canBeResolved && cfg.name == cfgName
|
|
||||||
} ?: {
|
|
||||||
def resolvableConfigurations = "[" + project.configurations
|
|
||||||
.grep { Configuration cfg -> cfg.canBeResolved }
|
|
||||||
.collect { "'${it.name}'" }
|
|
||||||
.join(",") + "]"
|
|
||||||
throw new GradleException("Configuration '$cfgName' doesn't exist or cannot be resolved, " +
|
|
||||||
"resolvable configurations in this project are " + resolvableConfigurations)
|
|
||||||
}) as Configuration
|
|
||||||
computeResults(requestedConfiguration.incoming.artifacts.artifacts.stream())
|
|
||||||
}.collect(Collectors.toSet())
|
|
||||||
Files.createDirectories(outputFile.parent)
|
|
||||||
Files.newBufferedWriter(outputFile).withWriter {
|
|
||||||
Stream<CheckResult> resultStream = results.stream().sorted(Comparator.<CheckResult, String>comparing { CheckResult res ->
|
|
||||||
res.dep.id.componentIdentifier.displayName
|
|
||||||
})
|
|
||||||
switch(outputFormat) {
|
|
||||||
case "html":
|
|
||||||
createHtmlReport(project, resultStream, it)
|
|
||||||
break
|
|
||||||
case "json":
|
|
||||||
createJsonReport(resultStream, it)
|
|
||||||
break
|
|
||||||
default:
|
|
||||||
throw new IllegalArgumentException("Unsupported output format: $outputFormat")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
result
|
||||||
|
}))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -0,0 +1,213 @@
|
|||||||
|
package net.woggioni.gradle.jpms.check
|
||||||
|
|
||||||
|
import groovy.json.JsonBuilder
|
||||||
|
import groovy.transform.Canonical
|
||||||
|
import groovy.transform.CompileStatic
|
||||||
|
import groovy.xml.MarkupBuilder
|
||||||
|
import org.gradle.api.DefaultTask
|
||||||
|
import org.gradle.api.GradleException
|
||||||
|
import org.gradle.api.Project
|
||||||
|
import org.gradle.api.artifacts.Configuration
|
||||||
|
import org.gradle.api.artifacts.result.ResolvedArtifactResult
|
||||||
|
import org.gradle.api.file.RegularFileProperty
|
||||||
|
import org.gradle.api.provider.Property
|
||||||
|
import org.gradle.api.tasks.Input
|
||||||
|
import org.gradle.api.tasks.OutputFile
|
||||||
|
import org.gradle.api.tasks.TaskAction
|
||||||
|
|
||||||
|
import java.nio.file.Files
|
||||||
|
import java.nio.file.Path
|
||||||
|
import java.util.jar.JarFile
|
||||||
|
import java.util.stream.Collectors
|
||||||
|
import java.util.stream.Stream
|
||||||
|
import java.util.zip.ZipFile
|
||||||
|
|
||||||
|
abstract class JPMSCheckTask extends DefaultTask {
|
||||||
|
|
||||||
|
@Input
|
||||||
|
abstract Property<String> getConfigurationName()
|
||||||
|
|
||||||
|
@Input
|
||||||
|
abstract Property<Boolean> getRecursive()
|
||||||
|
|
||||||
|
@Input
|
||||||
|
abstract Property<OutputFormat> getOutputFormat()
|
||||||
|
|
||||||
|
@OutputFile
|
||||||
|
abstract RegularFileProperty getOutputFile()
|
||||||
|
|
||||||
|
@Canonical
|
||||||
|
@CompileStatic
|
||||||
|
private class CheckResult {
|
||||||
|
ResolvedArtifactResult dep
|
||||||
|
String automaticModuleName
|
||||||
|
boolean multiReleaseJar
|
||||||
|
boolean moduleInfo
|
||||||
|
|
||||||
|
boolean getJpmsFriendly() {
|
||||||
|
return automaticModuleName != null || moduleInfo
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
boolean equals(Object other) {
|
||||||
|
if(other == null) {
|
||||||
|
return false
|
||||||
|
} else if(other.class == CheckResult.class) {
|
||||||
|
return dep?.id?.componentIdentifier == ((CheckResult) other).dep?.id?.componentIdentifier
|
||||||
|
} else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
int hashCode() {
|
||||||
|
return dep.id.componentIdentifier.hashCode()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@CompileStatic
|
||||||
|
private Stream<CheckResult> computeResults(Stream<ResolvedArtifactResult> artifacts) {
|
||||||
|
return artifacts.filter { ResolvedArtifactResult res ->
|
||||||
|
res.file.exists() && res.file.name.endsWith(".jar")
|
||||||
|
}.<CheckResult>map { resolvedArtifact ->
|
||||||
|
JarFile jarFile = new JarFile(resolvedArtifact.file).with {
|
||||||
|
if (it.isMultiRelease()) {
|
||||||
|
new JarFile(
|
||||||
|
resolvedArtifact.file,
|
||||||
|
false,
|
||||||
|
ZipFile.OPEN_READ,
|
||||||
|
Runtime.version()
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
it
|
||||||
|
}
|
||||||
|
}
|
||||||
|
String automaticModuleName = jarFile.manifest?.with {it.mainAttributes.getValue("Automatic-Module-Name") }
|
||||||
|
def moduleInfoEntry = jarFile.getJarEntry("module-info.class")
|
||||||
|
new CheckResult(
|
||||||
|
resolvedArtifact,
|
||||||
|
automaticModuleName,
|
||||||
|
jarFile.isMultiRelease(),
|
||||||
|
moduleInfoEntry != null
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void createHtmlReport(Project project, Stream<CheckResult> checkResults, Writer writer) {
|
||||||
|
def builder = new MarkupBuilder(writer)
|
||||||
|
int friendly = 0
|
||||||
|
int total = 0
|
||||||
|
def results = checkResults.peek { CheckResult res ->
|
||||||
|
total += 1
|
||||||
|
if(res.jpmsFriendly) friendly += 1
|
||||||
|
}.collect(Collectors.toList())
|
||||||
|
builder.html {
|
||||||
|
head {
|
||||||
|
meta name: "viewport", content: "width=device-width, initial-scale=1"
|
||||||
|
InputStream resourceStream = getClass().classLoader.getResourceAsStream('net/woggioni/plugins/jpms/check/github-markdown.css')
|
||||||
|
resourceStream.withReader { Reader reader ->
|
||||||
|
style reader.text
|
||||||
|
}
|
||||||
|
body {
|
||||||
|
article(class: 'markdown-body') {
|
||||||
|
h1 "Project ${project.group}:${project.name}:${project.version}", style: "text-align: center;"
|
||||||
|
div {
|
||||||
|
table {
|
||||||
|
thead {
|
||||||
|
tr {
|
||||||
|
th "JPMS friendly"
|
||||||
|
th "Not JPMS friendly", colspan: 2
|
||||||
|
th "Total", colspan: 2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tbody {
|
||||||
|
tr {
|
||||||
|
td friendly, style: "text-align: center;"
|
||||||
|
td total - friendly, style: "text-align: center;", colspan: 2
|
||||||
|
td total, style: "text-align: center;", colspan: 2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
thead {
|
||||||
|
th "Name"
|
||||||
|
th "Multi-release jar"
|
||||||
|
th "Automatic-Module-Name"
|
||||||
|
th "Module descriptor"
|
||||||
|
th "JPMS friendly"
|
||||||
|
}
|
||||||
|
tbody {
|
||||||
|
results.forEach {res ->
|
||||||
|
String color = res.jpmsFriendly ? "#dfd" : "fdd"
|
||||||
|
tr(style: "background-color:$color;") {
|
||||||
|
td res.dep.id.displayName
|
||||||
|
td style: "text-align: center;", res.multiReleaseJar ? "✓" : "✕"
|
||||||
|
td style: "text-align: center;", res.automaticModuleName ?: "n/a"
|
||||||
|
td style: "text-align: center;", res.moduleInfo ? "✓" : "✕"
|
||||||
|
td style: "text-align: center;", res.jpmsFriendly ? "✓" : "✕"
|
||||||
|
}
|
||||||
|
total += 1
|
||||||
|
if(res.jpmsFriendly) friendly += 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@CompileStatic
|
||||||
|
private createJsonReport(Stream<CheckResult> checkResults, Writer writer) {
|
||||||
|
def builder = new JsonBuilder()
|
||||||
|
builder (checkResults.map {
|
||||||
|
[
|
||||||
|
name: it.dep.id.componentIdentifier.displayName,
|
||||||
|
automaticModuleName: it.automaticModuleName,
|
||||||
|
isMultiReleaseJar: it.multiReleaseJar,
|
||||||
|
hasModuleInfo: it.moduleInfo,
|
||||||
|
jpmsFriendly: it.jpmsFriendly
|
||||||
|
]
|
||||||
|
}.collect(Collectors.toList()))
|
||||||
|
builder.writeTo(writer)
|
||||||
|
}
|
||||||
|
|
||||||
|
@TaskAction
|
||||||
|
@CompileStatic
|
||||||
|
def createReport() {
|
||||||
|
String cfgName = configurationName.get()
|
||||||
|
Path outputFile = outputFile.get().asFile.toPath()
|
||||||
|
Stream<Project> projects = Stream.of(project)
|
||||||
|
if(recursive.get()) {
|
||||||
|
projects = Stream.concat(projects, project.subprojects.stream())
|
||||||
|
}
|
||||||
|
Set<CheckResult> results = projects.flatMap {
|
||||||
|
Configuration requestedConfiguration = (project.configurations.<Configuration>find { Configuration cfg ->
|
||||||
|
cfg.canBeResolved && cfg.name == cfgName
|
||||||
|
} ?: {
|
||||||
|
def resolvableConfigurations = "[" + project.configurations
|
||||||
|
.grep { Configuration cfg -> cfg.canBeResolved }
|
||||||
|
.collect { "'${it.name}'" }
|
||||||
|
.join(",") + "]"
|
||||||
|
throw new GradleException("Configuration '$cfgName' doesn't exist or cannot be resolved, " +
|
||||||
|
"resolvable configurations in this project are " + resolvableConfigurations)
|
||||||
|
}) as Configuration
|
||||||
|
computeResults(requestedConfiguration.incoming.artifacts.artifacts.stream())
|
||||||
|
}.collect(Collectors.toSet())
|
||||||
|
Files.createDirectories(outputFile.parent)
|
||||||
|
Files.newBufferedWriter(outputFile).withWriter {
|
||||||
|
Stream<CheckResult> resultStream = results.stream().sorted(Comparator.<CheckResult, String>comparing { CheckResult res ->
|
||||||
|
res.dep.id.componentIdentifier.displayName
|
||||||
|
})
|
||||||
|
switch(outputFormat.get()) {
|
||||||
|
case OutputFormat.html:
|
||||||
|
createHtmlReport(project, resultStream, it)
|
||||||
|
break
|
||||||
|
case OutputFormat.json:
|
||||||
|
createJsonReport(resultStream, it)
|
||||||
|
break
|
||||||
|
default:
|
||||||
|
throw new IllegalArgumentException("Unsupported output format: $outputFormat")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,5 @@
|
|||||||
|
package net.woggioni.gradle.jpms.check
|
||||||
|
|
||||||
|
enum OutputFormat {
|
||||||
|
html, json
|
||||||
|
}
|
@@ -28,7 +28,6 @@ public class LombokPlugin implements Plugin<Project> {
|
|||||||
@Override
|
@Override
|
||||||
public void apply(Project project) {
|
public void apply(Project project) {
|
||||||
project.getPluginManager().apply(JavaPlugin.class);
|
project.getPluginManager().apply(JavaPlugin.class);
|
||||||
ObjectFactory objectFactory = project.getObjects();
|
|
||||||
LombokExtension ext = project.getExtensions().create("lombok", LombokExtension.class);
|
LombokExtension ext = project.getExtensions().create("lombok", LombokExtension.class);
|
||||||
ExtraPropertiesExtension epe = project.getExtensions().getExtraProperties();
|
ExtraPropertiesExtension epe = project.getExtensions().getExtraProperties();
|
||||||
if(epe.has("version.lombok")) {
|
if(epe.has("version.lombok")) {
|
||||||
@@ -75,7 +74,9 @@ public class LombokPlugin implements Plugin<Project> {
|
|||||||
delombok.getSourceSet().set(ss);
|
delombok.getSourceSet().set(ss);
|
||||||
delombok.getOutputDir().set(outputDir);
|
delombok.getOutputDir().set(outputDir);
|
||||||
delombok.getLombokJar().set(lombokConfiguration);
|
delombok.getLombokJar().set(lombokConfiguration);
|
||||||
delombok.getInferModulePath().set(javaPluginExtension.getModularity().getInferModulePath());
|
// Disabled for now due to https://github.com/projectlombok/lombok/issues/2829
|
||||||
|
//delombok.getInferModulePath().set(javaPluginExtension.getModularity().getInferModulePath());
|
||||||
|
delombok.getInferModulePath().set(false);
|
||||||
}));
|
}));
|
||||||
javadoc.setSource(outputDir);
|
javadoc.setSource(outputDir);
|
||||||
javadoc.getInputs().files(delombokTaskProvider);
|
javadoc.getInputs().files(delombokTaskProvider);
|
||||||
|
@@ -2,25 +2,6 @@ plugins {
|
|||||||
id "java-gradle-plugin"
|
id "java-gradle-plugin"
|
||||||
}
|
}
|
||||||
|
|
||||||
childProjects.forEach {name, child ->
|
|
||||||
child.with {
|
|
||||||
apply plugin: 'maven-publish'
|
|
||||||
|
|
||||||
publishing {
|
|
||||||
repositories {
|
|
||||||
maven {
|
|
||||||
url = woggioniMavenRepositoryUrl
|
|
||||||
}
|
|
||||||
}
|
|
||||||
publications {
|
|
||||||
maven(MavenPublication) {
|
|
||||||
from(components["java"])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
evaluationDependsOnChildren()
|
evaluationDependsOnChildren()
|
||||||
|
|
||||||
configurations {
|
configurations {
|
||||||
|
@@ -1,5 +1,7 @@
|
|||||||
package net.woggioni.gradle.sambal;
|
package net.woggioni.gradle.sambal;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
import lombok.SneakyThrows;
|
import lombok.SneakyThrows;
|
||||||
import org.codehaus.groovy.runtime.MethodClosure;
|
import org.codehaus.groovy.runtime.MethodClosure;
|
||||||
import org.eclipse.jgit.api.Git;
|
import org.eclipse.jgit.api.Git;
|
||||||
@@ -13,11 +15,13 @@ import org.gradle.api.artifacts.Configuration;
|
|||||||
import org.gradle.api.attributes.Attribute;
|
import org.gradle.api.attributes.Attribute;
|
||||||
import org.gradle.api.attributes.AttributeContainer;
|
import org.gradle.api.attributes.AttributeContainer;
|
||||||
import org.gradle.api.java.archives.Attributes;
|
import org.gradle.api.java.archives.Attributes;
|
||||||
import org.gradle.api.logging.Logger;
|
|
||||||
import org.gradle.api.plugins.AppliedPlugin;
|
import org.gradle.api.plugins.AppliedPlugin;
|
||||||
import org.gradle.api.plugins.ExtraPropertiesExtension;
|
import org.gradle.api.plugins.ExtraPropertiesExtension;
|
||||||
import org.gradle.api.plugins.JavaPlugin;
|
import org.gradle.api.plugins.JavaPlugin;
|
||||||
import org.gradle.api.plugins.PluginManager;
|
import org.gradle.api.plugins.PluginManager;
|
||||||
|
import org.gradle.api.provider.Provider;
|
||||||
|
import org.gradle.api.provider.ValueSource;
|
||||||
|
import org.gradle.api.provider.ValueSourceParameters;
|
||||||
import org.gradle.api.tasks.TaskContainer;
|
import org.gradle.api.tasks.TaskContainer;
|
||||||
import org.gradle.api.tasks.bundling.Jar;
|
import org.gradle.api.tasks.bundling.Jar;
|
||||||
|
|
||||||
@@ -27,6 +31,7 @@ import java.io.FileInputStream;
|
|||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.InputStreamReader;
|
import java.io.InputStreamReader;
|
||||||
import java.io.Reader;
|
import java.io.Reader;
|
||||||
|
import java.io.Serializable;
|
||||||
import java.io.StringWriter;
|
import java.io.StringWriter;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
@@ -45,9 +50,6 @@ public class SambalPlugin implements Plugin<Project> {
|
|||||||
private static Pattern tagPattern = Pattern.compile("^refs/tags/v?(\\d+\\.\\d+.*)");
|
private static Pattern tagPattern = Pattern.compile("^refs/tags/v?(\\d+\\.\\d+.*)");
|
||||||
final private static char[] hexArray = "0123456789ABCDEF".toCharArray();
|
final private static char[] hexArray = "0123456789ABCDEF".toCharArray();
|
||||||
|
|
||||||
private static final String currentTagCachedKey = "CURRENT_TAG_CACHED";
|
|
||||||
private static final String currentRevCachedKey = "CURRENT_REV_CACHED";
|
|
||||||
|
|
||||||
private static String bytesToHex(byte[] bytes) {
|
private static String bytesToHex(byte[] bytes) {
|
||||||
char[] hexChars = new char[bytes.length * 2];
|
char[] hexChars = new char[bytes.length * 2];
|
||||||
for (int j = 0; j < bytes.length; j++) {
|
for (int j = 0; j < bytes.length; j++) {
|
||||||
@@ -131,7 +133,7 @@ public class SambalPlugin implements Plugin<Project> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@SneakyThrows
|
@SneakyThrows
|
||||||
private static String getCurrentTag(Git git, Logger logger) {
|
private static List<String> getCurrentTag(Git git) {
|
||||||
List<Ref> tags = git.tagList().call();
|
List<Ref> tags = git.tagList().call();
|
||||||
Ref currentRef = git.getRepository().findRef("HEAD");
|
Ref currentRef = git.getRepository().findRef("HEAD");
|
||||||
List<String> currentTag = tags.stream()
|
List<String> currentTag = tags.stream()
|
||||||
@@ -141,41 +143,8 @@ public class SambalPlugin implements Plugin<Project> {
|
|||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
if (currentTag.isEmpty()) return null;
|
if (currentTag.isEmpty()) return null;
|
||||||
else {
|
else {
|
||||||
if (currentTag.size() > 1) {
|
return currentTag;
|
||||||
logger.warn("Found more than one tag in correct format for HEAD.");
|
|
||||||
}
|
}
|
||||||
return currentTag.get(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@SneakyThrows
|
|
||||||
private static String getCurrentTag(Project project) {
|
|
||||||
ExtraPropertiesExtension ext = project.getRootProject().getExtensions().getExtraProperties();
|
|
||||||
if (!ext.has(currentTagCachedKey)) {
|
|
||||||
Git git = Git.open(project.getRootDir());
|
|
||||||
Status status = git.status().call();
|
|
||||||
String currentTag;
|
|
||||||
if (status.isClean() && (currentTag = getCurrentTag(git, project.getLogger())) != null) {
|
|
||||||
ext.set(currentTagCachedKey, currentTag);
|
|
||||||
} else {
|
|
||||||
ext.set(currentTagCachedKey, null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return Optional.ofNullable(ext.get(currentTagCachedKey))
|
|
||||||
.map(Object::toString)
|
|
||||||
.orElse(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
@SneakyThrows
|
|
||||||
private static String getGitRevision(Project project) {
|
|
||||||
ExtraPropertiesExtension ext = project.getRootProject().getExtensions().getExtraProperties();
|
|
||||||
if (!ext.has(currentRevCachedKey)) {
|
|
||||||
Git git = Git.open(project.getRootDir());
|
|
||||||
ext.set(currentRevCachedKey, git.getRepository().findRef("HEAD").getObjectId().name());
|
|
||||||
}
|
|
||||||
return Optional.ofNullable(ext.get(currentRevCachedKey))
|
|
||||||
.map(Object::toString)
|
|
||||||
.orElse(null);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String resolveProperty(Project project, String key, String defaultValue) {
|
private static String resolveProperty(Project project, String key, String defaultValue) {
|
||||||
@@ -204,15 +173,58 @@ public class SambalPlugin implements Plugin<Project> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public static class ProjectParameters implements ValueSourceParameters, Serializable {
|
||||||
|
private File rootDirectory;
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract static class GitTagValueSource implements ValueSource<List<String>, ProjectParameters> {
|
||||||
|
@Override
|
||||||
|
@SneakyThrows
|
||||||
|
public List<String> obtain() {
|
||||||
|
File rootDirectory = getParameters().getRootDirectory();
|
||||||
|
try(Git git = Git.open(rootDirectory)) {
|
||||||
|
Status status = git.status().call();
|
||||||
|
if (status.isClean()) {
|
||||||
|
return getCurrentTag(git);
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract static class GitRevisionValueSource implements ValueSource<String, ProjectParameters> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@SneakyThrows
|
||||||
|
public String obtain() {
|
||||||
|
File rootDirectory = getParameters().getRootDirectory();
|
||||||
|
try (Git git = Git.open(rootDirectory)) {
|
||||||
|
return git.getRepository().findRef("HEAD").getObjectId().name();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void apply(Project project) {
|
public void apply(Project project) {
|
||||||
ExtraPropertiesExtension ext = project.getRootProject().getExtensions().getExtraProperties();
|
ExtraPropertiesExtension ext = project.getRootProject().getExtensions().getExtraProperties();
|
||||||
ext.set("getIntegerVersion", new MethodClosure(this, "getVersionInt").curry(project));
|
ext.set("getIntegerVersion", new MethodClosure(this, "getVersionInt").curry(project));
|
||||||
ext.set("currentTag", getCurrentTag(project));
|
|
||||||
|
|
||||||
|
final Provider<List<String>> gitTagProvider = project.getProviders().of(GitTagValueSource.class, it -> {
|
||||||
|
it.parameters( params -> params.setRootDirectory(project.getRootDir()));
|
||||||
|
});
|
||||||
|
ext.set("currentTag", gitTagProvider);
|
||||||
ext.set("resolveProperty", new MethodClosure(this, "resolveProperty").curry(project));
|
ext.set("resolveProperty", new MethodClosure(this, "resolveProperty").curry(project));
|
||||||
ext.set("copyConfigurationAttributes", new MethodClosure(this, "copyConfigurationAttributes"));
|
ext.set("copyConfigurationAttributes", new MethodClosure(this, "copyConfigurationAttributes"));
|
||||||
final String gitRevision = getGitRevision(project);
|
|
||||||
ext.set("gitRevision", gitRevision);
|
final Provider<String> gitRevisionProvider = project.getProviders().of(GitRevisionValueSource.class, it -> {
|
||||||
|
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 pluginManager = project.getPluginManager();
|
||||||
pluginManager.withPlugin("java-library", (AppliedPlugin plugin) -> {
|
pluginManager.withPlugin("java-library", (AppliedPlugin plugin) -> {
|
||||||
@@ -223,7 +235,7 @@ public class SambalPlugin implements Plugin<Project> {
|
|||||||
Attributes attrs = mf.getAttributes();
|
Attributes attrs = mf.getAttributes();
|
||||||
attrs.put(java.util.jar.Attributes.Name.SPECIFICATION_TITLE.toString(), project.getName());
|
attrs.put(java.util.jar.Attributes.Name.SPECIFICATION_TITLE.toString(), project.getName());
|
||||||
attrs.put(java.util.jar.Attributes.Name.SPECIFICATION_VERSION.toString(), project.getVersion());
|
attrs.put(java.util.jar.Attributes.Name.SPECIFICATION_VERSION.toString(), project.getVersion());
|
||||||
attrs.put(java.util.jar.Attributes.Name.IMPLEMENTATION_VERSION.toString(), gitRevision);
|
attrs.put(java.util.jar.Attributes.Name.IMPLEMENTATION_VERSION.toString(), gitRevisionProvider);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@@ -6,7 +6,6 @@ import org.gradle.api.attributes.AttributeCompatibilityRule;
|
|||||||
import org.gradle.api.attributes.AttributeDisambiguationRule;
|
import org.gradle.api.attributes.AttributeDisambiguationRule;
|
||||||
import org.gradle.api.attributes.CompatibilityCheckDetails;
|
import org.gradle.api.attributes.CompatibilityCheckDetails;
|
||||||
import org.gradle.api.attributes.MultipleCandidatesDetails;
|
import org.gradle.api.attributes.MultipleCandidatesDetails;
|
||||||
import org.gradle.api.internal.ReusableAction;
|
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
@@ -19,7 +18,7 @@ public interface Sealing extends Named {
|
|||||||
String sealed = "sealed";
|
String sealed = "sealed";
|
||||||
String open = "open";
|
String open = "open";
|
||||||
|
|
||||||
class CompatibilityRules implements AttributeCompatibilityRule<Sealing>, ReusableAction {
|
class CompatibilityRules implements AttributeCompatibilityRule<Sealing> {
|
||||||
public void execute(CompatibilityCheckDetails<Sealing> details) {
|
public void execute(CompatibilityCheckDetails<Sealing> details) {
|
||||||
Sealing consumerValue = details.getConsumerValue();
|
Sealing consumerValue = details.getConsumerValue();
|
||||||
Sealing producerValue = details.getProducerValue();
|
Sealing producerValue = details.getProducerValue();
|
||||||
@@ -35,7 +34,7 @@ public interface Sealing extends Named {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class DisambiguationRules implements AttributeDisambiguationRule<Sealing>, ReusableAction {
|
class DisambiguationRules implements AttributeDisambiguationRule<Sealing> {
|
||||||
private static final List<String> ORDER = Arrays.asList(open, sealed);
|
private static final List<String> ORDER = Arrays.asList(open, sealed);
|
||||||
private static final Comparator<Sealing> comparator =
|
private static final Comparator<Sealing> comparator =
|
||||||
Comparator.comparingInt(sealing -> ORDER.indexOf(sealing.getName()));
|
Comparator.comparingInt(sealing -> ORDER.indexOf(sealing.getName()));
|
||||||
|
@@ -6,7 +6,6 @@ import org.gradle.api.attributes.AttributeCompatibilityRule;
|
|||||||
import org.gradle.api.attributes.AttributeDisambiguationRule;
|
import org.gradle.api.attributes.AttributeDisambiguationRule;
|
||||||
import org.gradle.api.attributes.CompatibilityCheckDetails;
|
import org.gradle.api.attributes.CompatibilityCheckDetails;
|
||||||
import org.gradle.api.attributes.MultipleCandidatesDetails;
|
import org.gradle.api.attributes.MultipleCandidatesDetails;
|
||||||
import org.gradle.api.internal.ReusableAction;
|
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
@@ -19,7 +18,7 @@ public interface Signing extends Named {
|
|||||||
String signed = "signed";
|
String signed = "signed";
|
||||||
String unsigned = "unsigned";
|
String unsigned = "unsigned";
|
||||||
|
|
||||||
class CompatibilityRules implements AttributeCompatibilityRule<Signing>, ReusableAction {
|
class CompatibilityRules implements AttributeCompatibilityRule<Signing> {
|
||||||
public void execute(CompatibilityCheckDetails<Signing> details) {
|
public void execute(CompatibilityCheckDetails<Signing> details) {
|
||||||
Signing consumerValue = details.getConsumerValue();
|
Signing consumerValue = details.getConsumerValue();
|
||||||
Signing producerValue = details.getProducerValue();
|
Signing producerValue = details.getProducerValue();
|
||||||
@@ -35,7 +34,7 @@ public interface Signing extends Named {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class DisambiguationRules implements AttributeDisambiguationRule<Signing>, ReusableAction {
|
class DisambiguationRules implements AttributeDisambiguationRule<Signing> {
|
||||||
private static final List<String> ORDER = Arrays.asList(unsigned, signed);
|
private static final List<String> ORDER = Arrays.asList(unsigned, signed);
|
||||||
private static final Comparator<Signing> comparator =
|
private static final Comparator<Signing> comparator =
|
||||||
Comparator.comparingInt(signing -> ORDER.indexOf(signing.getName()));
|
Comparator.comparingInt(signing -> ORDER.indexOf(signing.getName()));
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
dependencyResolutionManagement {
|
dependencyResolutionManagement {
|
||||||
repositories {
|
repositories {
|
||||||
maven {
|
maven {
|
||||||
url = 'https://woggioni.net/mvn/'
|
url = getProperty('gitea.maven.url')
|
||||||
content {
|
content {
|
||||||
includeGroup 'com.lys'
|
includeGroup 'com.lys'
|
||||||
}
|
}
|
||||||
@@ -27,3 +27,4 @@ include 'osgi-app:osgi-simple-bootstrapper-application'
|
|||||||
include 'wildfly'
|
include 'wildfly'
|
||||||
include 'sambal'
|
include 'sambal'
|
||||||
include 'graalvm'
|
include 'graalvm'
|
||||||
|
include 'jdeps'
|
||||||
|
Reference in New Issue
Block a user