From 598ef19370d6655ea98402f6910ad0646c6e87f4 Mon Sep 17 00:00:00 2001
From: Juuz <6596629+Juuxel@users.noreply.github.com>
Date: Fri, 6 Dec 2024 23:20:04 +0200
Subject: [PATCH] Make Forge tools compatible with config cache
---
.../loom/forge/tool/ForgeToolExecutor.java | 141 ++++++++++++++++++
.../loom/forge/tool/ForgeToolValueSource.java | 46 ++++++
.../loom/forge/{ => tool}/ForgeTools.java | 2 +-
.../forge/tool/JavaExecutableFetcher.java | 31 ++++
.../AccessTransformerJarProcessor.java | 6 +-
.../forge/MinecraftPatchedProvider.java | 4 +-
.../forge/mcpconfig/McpExecutor.java | 8 +-
.../forge/mcpconfig/steplogic/StepLogic.java | 4 +-
.../sources/ForgeSourcesRemapper.java | 2 +-
.../task/GenerateForgePatchedSourcesTask.java | 6 +-
.../fabricmc/loom/util/ForgeToolExecutor.java | 121 ---------------
11 files changed, 234 insertions(+), 137 deletions(-)
create mode 100644 src/main/java/dev/architectury/loom/forge/tool/ForgeToolExecutor.java
create mode 100644 src/main/java/dev/architectury/loom/forge/tool/ForgeToolValueSource.java
rename src/main/java/dev/architectury/loom/forge/{ => tool}/ForgeTools.java (74%)
create mode 100644 src/main/java/dev/architectury/loom/forge/tool/JavaExecutableFetcher.java
delete mode 100644 src/main/java/net/fabricmc/loom/util/ForgeToolExecutor.java
diff --git a/src/main/java/dev/architectury/loom/forge/tool/ForgeToolExecutor.java b/src/main/java/dev/architectury/loom/forge/tool/ForgeToolExecutor.java
new file mode 100644
index 000000000..ce3a58c0a
--- /dev/null
+++ b/src/main/java/dev/architectury/loom/forge/tool/ForgeToolExecutor.java
@@ -0,0 +1,141 @@
+package dev.architectury.loom.forge.tool;
+
+import java.util.Collection;
+import java.util.List;
+
+import javax.inject.Inject;
+
+import org.apache.commons.io.output.NullOutputStream;
+import org.gradle.api.Action;
+import org.gradle.api.Project;
+import org.gradle.api.file.ConfigurableFileCollection;
+import org.gradle.api.logging.LogLevel;
+import org.gradle.api.logging.configuration.ShowStacktrace;
+import org.gradle.api.provider.ListProperty;
+import org.gradle.api.provider.Property;
+import org.gradle.api.tasks.Classpath;
+import org.gradle.api.tasks.Input;
+import org.gradle.process.ExecOperations;
+import org.gradle.process.ExecResult;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * Contains helpers for executing Forge's command line tools
+ * with suppressed output streams to prevent annoying log spam.
+ */
+public abstract class ForgeToolExecutor {
+ @Inject
+ protected abstract ExecOperations getExecOperations();
+
+ public static boolean shouldShowVerboseStdout(Project project) {
+ // if running with INFO or DEBUG logging
+ return project.getGradle().getStartParameter().getLogLevel().compareTo(LogLevel.LIFECYCLE) < 0;
+ }
+
+ public static boolean shouldShowVerboseStderr(Project project) {
+ // if stdout is shown or stacktraces are visible so that errors printed to stderr show up
+ return shouldShowVerboseStdout(project) || project.getGradle().getStartParameter().getShowStacktrace() != ShowStacktrace.INTERNAL_EXCEPTIONS;
+ }
+
+ public static Settings getDefaultSettings(Project project) {
+ final Settings settings = project.getObjects().newInstance(Settings.class);
+ settings.getExecutable().set(JavaExecutableFetcher.getJavaToolchainExecutable(project));
+ settings.getShowVerboseStdout().set(shouldShowVerboseStdout(project));
+ settings.getShowVerboseStderr().set(shouldShowVerboseStderr(project));
+ return settings;
+ }
+
+ /**
+ * Executes an external Java process.
+ *
+ *
This method cannot be used during configuration.
+ * Use {@link ForgeToolValueSource#exec(Project, Action)} for those cases.
+ *
+ * @param project the project
+ * @param configurator the {@code javaexec} configuration action
+ * @return the execution result
+ */
+ public static ExecResult exec(Project project, Action super Settings> configurator) {
+ final Settings settings = getDefaultSettings(project);
+ configurator.execute(settings);
+ return project.getObjects().newInstance(ForgeToolExecutor.class).exec(settings);
+ }
+
+ private ExecResult exec(Settings settings) {
+ return exec(getExecOperations(), settings);
+ }
+
+ public static ExecResult exec(ExecOperations execOperations, Settings settings) {
+ return execOperations.javaexec(spec -> {
+ final @Nullable String executable = settings.getExecutable().getOrNull();
+ if (executable != null) spec.setExecutable(executable);
+ spec.getMainClass().set(settings.getMainClass());
+ spec.setArgs(settings.getProgramArgs().get());
+ spec.setJvmArgs(settings.getJvmArgs().get());
+ spec.setClasspath(settings.getExecClasspath());
+
+ if (settings.getShowVerboseStdout().get()) {
+ spec.setStandardOutput(System.out);
+ } else {
+ spec.setStandardOutput(NullOutputStream.INSTANCE);
+ }
+
+ if (settings.getShowVerboseStderr().get()) {
+ spec.setErrorOutput(System.err);
+ } else {
+ spec.setErrorOutput(NullOutputStream.INSTANCE);
+ }
+ });
+ }
+
+ public interface Settings {
+ @Input
+ Property getExecutable();
+
+ @Input
+ ListProperty getProgramArgs();
+
+ @Input
+ ListProperty getJvmArgs();
+
+ @Input
+ Property getMainClass();
+
+ @Classpath
+ ConfigurableFileCollection getExecClasspath();
+
+ @Input
+ Property getShowVerboseStdout();
+
+ @Input
+ Property getShowVerboseStderr();
+
+ default void classpath(Object... paths) {
+ getExecClasspath().from(paths);
+ }
+
+ default void setClasspath(Object... paths) {
+ getExecClasspath().setFrom(paths);
+ }
+
+ default void args(String... args) {
+ getProgramArgs().addAll(args);
+ }
+
+ default void args(Collection args) {
+ getProgramArgs().addAll(args);
+ }
+
+ default void setArgs(List args) {
+ getProgramArgs().set(args);
+ }
+
+ default void jvmArgs(String... args) {
+ getJvmArgs().addAll(args);
+ }
+
+ default void jvmArgs(Collection args) {
+ getJvmArgs().addAll(args);
+ }
+ }
+}
diff --git a/src/main/java/dev/architectury/loom/forge/tool/ForgeToolValueSource.java b/src/main/java/dev/architectury/loom/forge/tool/ForgeToolValueSource.java
new file mode 100644
index 000000000..15c715f05
--- /dev/null
+++ b/src/main/java/dev/architectury/loom/forge/tool/ForgeToolValueSource.java
@@ -0,0 +1,46 @@
+package dev.architectury.loom.forge.tool;
+
+import javax.inject.Inject;
+
+import org.gradle.api.Action;
+import org.gradle.api.Project;
+import org.gradle.api.provider.Property;
+import org.gradle.api.provider.Provider;
+import org.gradle.api.provider.ValueSource;
+import org.gradle.api.provider.ValueSourceParameters;
+import org.gradle.api.tasks.Nested;
+import org.gradle.process.ExecOperations;
+import org.gradle.process.ExecResult;
+
+public abstract class ForgeToolValueSource implements ValueSource {
+ @Inject
+ protected abstract ExecOperations getExecOperations();
+
+ public static Provider create(Project project, Action super ForgeToolExecutor.Settings> configurator) {
+ return project.getProviders().of(ForgeToolValueSource.class, spec -> {
+ ForgeToolExecutor.Settings settings = ForgeToolExecutor.getDefaultSettings(project);
+ configurator.execute(settings);
+ spec.getParameters().getSettings().set(settings);
+ });
+ }
+
+ /**
+ * Executes an external Java process during project configuration.
+ *
+ * @param project the project
+ * @param configurator an action that configures the exec settings
+ */
+ public static void exec(Project project, Action super ForgeToolExecutor.Settings> configurator) {
+ create(project, configurator).get().rethrowFailure().assertNormalExitValue();
+ }
+
+ @Override
+ public ExecResult obtain() {
+ return ForgeToolExecutor.exec(getExecOperations(), getParameters().getSettings().get());
+ }
+
+ public interface Parameters extends ValueSourceParameters {
+ @Nested
+ Property getSettings();
+ }
+}
diff --git a/src/main/java/dev/architectury/loom/forge/ForgeTools.java b/src/main/java/dev/architectury/loom/forge/tool/ForgeTools.java
similarity index 74%
rename from src/main/java/dev/architectury/loom/forge/ForgeTools.java
rename to src/main/java/dev/architectury/loom/forge/tool/ForgeTools.java
index 5a9430295..07b1a4d0c 100644
--- a/src/main/java/dev/architectury/loom/forge/ForgeTools.java
+++ b/src/main/java/dev/architectury/loom/forge/tool/ForgeTools.java
@@ -1,4 +1,4 @@
-package dev.architectury.loom.forge;
+package dev.architectury.loom.forge.tool;
public final class ForgeTools {
public static final String SIDE_STRIPPER = "net.minecraftforge:mergetool:1.1.6:fatjar";
diff --git a/src/main/java/dev/architectury/loom/forge/tool/JavaExecutableFetcher.java b/src/main/java/dev/architectury/loom/forge/tool/JavaExecutableFetcher.java
new file mode 100644
index 000000000..1c7d5a723
--- /dev/null
+++ b/src/main/java/dev/architectury/loom/forge/tool/JavaExecutableFetcher.java
@@ -0,0 +1,31 @@
+package dev.architectury.loom.forge.tool;
+
+import javax.inject.Inject;
+
+import org.gradle.api.Project;
+import org.gradle.api.plugins.JavaPluginExtension;
+import org.gradle.api.provider.Provider;
+import org.gradle.jvm.toolchain.JavaLauncher;
+import org.gradle.jvm.toolchain.JavaToolchainService;
+import org.gradle.jvm.toolchain.JavaToolchainSpec;
+
+public abstract class JavaExecutableFetcher {
+ @Inject
+ protected abstract JavaToolchainService getToolchainService();
+
+ public static Provider getJavaToolchainExecutable(Project project) {
+ return project.provider(() -> {
+ final JavaExecutableFetcher fetcher = project.getObjects().newInstance(JavaExecutableFetcher.class);
+ final JavaPluginExtension java = project.getExtensions().getByType(JavaPluginExtension.class);
+ final JavaToolchainSpec toolchain = java.getToolchain();
+
+ if (!toolchain.getLanguageVersion().isPresent()) {
+ // Toolchain not configured, we'll use the runtime Java version.
+ return null;
+ }
+
+ final JavaLauncher launcher = fetcher.getToolchainService().launcherFor(toolchain).get();
+ return launcher.getExecutablePath().getAsFile().getAbsolutePath();
+ });
+ }
+}
diff --git a/src/main/java/net/fabricmc/loom/configuration/accesstransformer/AccessTransformerJarProcessor.java b/src/main/java/net/fabricmc/loom/configuration/accesstransformer/AccessTransformerJarProcessor.java
index 1f8f99929..223210340 100644
--- a/src/main/java/net/fabricmc/loom/configuration/accesstransformer/AccessTransformerJarProcessor.java
+++ b/src/main/java/net/fabricmc/loom/configuration/accesstransformer/AccessTransformerJarProcessor.java
@@ -42,6 +42,7 @@
import com.google.common.io.MoreFiles;
import dev.architectury.at.AccessTransformSet;
import dev.architectury.at.io.AccessTransformFormats;
+import dev.architectury.loom.forge.tool.ForgeToolValueSource;
import dev.architectury.loom.util.TempFiles;
import org.gradle.api.Project;
import org.gradle.api.file.FileCollection;
@@ -59,7 +60,6 @@
import net.fabricmc.loom.util.Constants;
import net.fabricmc.loom.util.DependencyDownloader;
import net.fabricmc.loom.util.ExceptionUtil;
-import net.fabricmc.loom.util.ForgeToolExecutor;
import net.fabricmc.loom.util.LoomVersions;
import net.fabricmc.loom.util.fmj.FabricModJson;
@@ -174,11 +174,11 @@ public static void executeAt(Project project, Path input, Path output, AccessTra
configuration.apply(args);
- ForgeToolExecutor.exec(project, spec -> {
+ ForgeToolValueSource.exec(project, spec -> {
spec.getMainClass().set(mainClass);
spec.setArgs(args);
spec.setClasspath(classpath);
- }).rethrowFailure().assertNormalExitValue();
+ });
}
private static LoomVersions chooseAccessTransformer(Project project) {
diff --git a/src/main/java/net/fabricmc/loom/configuration/providers/forge/MinecraftPatchedProvider.java b/src/main/java/net/fabricmc/loom/configuration/providers/forge/MinecraftPatchedProvider.java
index b4c347683..db2ea3abd 100644
--- a/src/main/java/net/fabricmc/loom/configuration/providers/forge/MinecraftPatchedProvider.java
+++ b/src/main/java/net/fabricmc/loom/configuration/providers/forge/MinecraftPatchedProvider.java
@@ -53,6 +53,7 @@
import com.google.common.base.Stopwatch;
import de.oceanlabs.mcp.mcinjector.adaptors.ParameterAnnotationFixer;
import dev.architectury.loom.forge.UserdevConfig;
+import dev.architectury.loom.forge.tool.ForgeToolValueSource;
import dev.architectury.loom.util.MappingOption;
import dev.architectury.loom.util.TempFiles;
import org.gradle.api.Project;
@@ -78,7 +79,6 @@
import net.fabricmc.loom.util.Constants;
import net.fabricmc.loom.util.DependencyDownloader;
import net.fabricmc.loom.util.FileSystemUtil;
-import net.fabricmc.loom.util.ForgeToolExecutor;
import net.fabricmc.loom.util.MappingsProviderVerbose;
import net.fabricmc.loom.util.ThreadingUtils;
import net.fabricmc.loom.util.TinyRemapperHelper;
@@ -459,7 +459,7 @@ private void patchJars() throws Exception {
}
private void patchJars(Path clean, Path output, Path patches) {
- ForgeToolExecutor.exec(project, spec -> {
+ ForgeToolValueSource.exec(project, spec -> {
UserdevConfig.BinaryPatcherConfig config = getExtension().getForgeUserdevProvider().getConfig().binpatcher();
final FileCollection download = DependencyDownloader.download(project, config.dependency());
spec.classpath(download);
diff --git a/src/main/java/net/fabricmc/loom/configuration/providers/forge/mcpconfig/McpExecutor.java b/src/main/java/net/fabricmc/loom/configuration/providers/forge/mcpconfig/McpExecutor.java
index ca50f3a83..6e0ffa4d6 100644
--- a/src/main/java/net/fabricmc/loom/configuration/providers/forge/mcpconfig/McpExecutor.java
+++ b/src/main/java/net/fabricmc/loom/configuration/providers/forge/mcpconfig/McpExecutor.java
@@ -44,13 +44,14 @@
import com.google.common.hash.Hashing;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
+import dev.architectury.loom.forge.tool.ForgeToolExecutor;
+import dev.architectury.loom.forge.tool.ForgeToolValueSource;
import org.gradle.api.Action;
import org.gradle.api.Project;
import org.gradle.api.artifacts.Configuration;
import org.gradle.api.artifacts.Dependency;
import org.gradle.api.logging.LogLevel;
import org.gradle.api.logging.Logger;
-import org.gradle.process.JavaExecSpec;
import org.jetbrains.annotations.Nullable;
import net.fabricmc.loom.LoomGradleExtension;
@@ -67,7 +68,6 @@
import net.fabricmc.loom.configuration.providers.forge.mcpconfig.steplogic.StripLogic;
import net.fabricmc.loom.configuration.providers.minecraft.MinecraftProvider;
import net.fabricmc.loom.util.Constants;
-import net.fabricmc.loom.util.ForgeToolExecutor;
import net.fabricmc.loom.util.download.DownloadBuilder;
import net.fabricmc.loom.util.function.CollectionUtil;
import net.fabricmc.loom.util.gradle.GradleUtils;
@@ -368,8 +368,8 @@ private static void redirectAwareDownload(String urlString, Path path) throws IO
}
@Override
- public void javaexec(Action super JavaExecSpec> configurator) {
- ForgeToolExecutor.exec(project, configurator).rethrowFailure().assertNormalExitValue();
+ public void javaexec(Action super ForgeToolExecutor.Settings> configurator) {
+ ForgeToolValueSource.exec(project, configurator);
}
@Override
diff --git a/src/main/java/net/fabricmc/loom/configuration/providers/forge/mcpconfig/steplogic/StepLogic.java b/src/main/java/net/fabricmc/loom/configuration/providers/forge/mcpconfig/steplogic/StepLogic.java
index 590b81cc0..0b7908ca2 100644
--- a/src/main/java/net/fabricmc/loom/configuration/providers/forge/mcpconfig/steplogic/StepLogic.java
+++ b/src/main/java/net/fabricmc/loom/configuration/providers/forge/mcpconfig/steplogic/StepLogic.java
@@ -31,9 +31,9 @@
import java.util.Optional;
import java.util.Set;
+import dev.architectury.loom.forge.tool.ForgeToolExecutor;
import org.gradle.api.Action;
import org.gradle.api.logging.Logger;
-import org.gradle.process.JavaExecSpec;
import net.fabricmc.loom.configuration.providers.forge.ConfigValue;
import net.fabricmc.loom.util.download.DownloadBuilder;
@@ -64,7 +64,7 @@ interface ExecutionContext {
Path downloadFile(String url) throws IOException;
Path downloadDependency(String notation);
DownloadBuilder downloadBuilder(String url);
- void javaexec(Action super JavaExecSpec> configurator);
+ void javaexec(Action super ForgeToolExecutor.Settings> configurator);
Set getMinecraftLibraries();
default List resolve(List configValues) {
diff --git a/src/main/java/net/fabricmc/loom/configuration/sources/ForgeSourcesRemapper.java b/src/main/java/net/fabricmc/loom/configuration/sources/ForgeSourcesRemapper.java
index bae894730..7d53c02e8 100644
--- a/src/main/java/net/fabricmc/loom/configuration/sources/ForgeSourcesRemapper.java
+++ b/src/main/java/net/fabricmc/loom/configuration/sources/ForgeSourcesRemapper.java
@@ -41,6 +41,7 @@
import java.util.function.Predicate;
import java.util.stream.Collectors;
+import dev.architectury.loom.forge.tool.ForgeToolExecutor;
import dev.architectury.loom.util.MappingOption;
import org.apache.commons.io.output.NullOutputStream;
import org.cadixdev.lorenz.MappingSet;
@@ -57,7 +58,6 @@
import net.fabricmc.loom.util.DeletingFileVisitor;
import net.fabricmc.loom.util.DependencyDownloader;
import net.fabricmc.loom.util.FileSystemUtil;
-import net.fabricmc.loom.util.ForgeToolExecutor;
import net.fabricmc.loom.util.LoomVersions;
import net.fabricmc.loom.util.SourceRemapper;
import net.fabricmc.loom.util.ThreadingUtils;
diff --git a/src/main/java/net/fabricmc/loom/task/GenerateForgePatchedSourcesTask.java b/src/main/java/net/fabricmc/loom/task/GenerateForgePatchedSourcesTask.java
index 94de74c0a..38c9fbad0 100644
--- a/src/main/java/net/fabricmc/loom/task/GenerateForgePatchedSourcesTask.java
+++ b/src/main/java/net/fabricmc/loom/task/GenerateForgePatchedSourcesTask.java
@@ -37,7 +37,8 @@
import codechicken.diffpatch.util.LoggingOutputStream;
import codechicken.diffpatch.util.PatchMode;
import com.google.common.base.Stopwatch;
-import dev.architectury.loom.forge.ForgeTools;
+import dev.architectury.loom.forge.tool.ForgeToolValueSource;
+import dev.architectury.loom.forge.tool.ForgeTools;
import dev.architectury.loom.util.TempFiles;
import org.gradle.api.file.FileCollection;
import org.gradle.api.file.RegularFileProperty;
@@ -55,7 +56,6 @@
import net.fabricmc.loom.configuration.sources.ForgeSourcesRemapper;
import net.fabricmc.loom.util.DependencyDownloader;
import net.fabricmc.loom.util.FileSystemUtil;
-import net.fabricmc.loom.util.ForgeToolExecutor;
import net.fabricmc.loom.util.SourceRemapper;
import net.fabricmc.loom.util.service.ScopedServiceFactory;
import net.fabricmc.loom.util.service.ServiceFactory;
@@ -191,7 +191,7 @@ private void stripSideAnnotations(Path input, Path output) throws IOException {
final FileCollection classpath = DependencyDownloader.download(getProject(), ForgeTools.SIDE_STRIPPER, false, true);
- ForgeToolExecutor.exec(getProject(), spec -> {
+ ForgeToolValueSource.exec(getProject(), spec -> {
spec.setClasspath(classpath);
spec.args(
"--strip",
diff --git a/src/main/java/net/fabricmc/loom/util/ForgeToolExecutor.java b/src/main/java/net/fabricmc/loom/util/ForgeToolExecutor.java
deleted file mode 100644
index 3e7ad6ea0..000000000
--- a/src/main/java/net/fabricmc/loom/util/ForgeToolExecutor.java
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- * This file is part of fabric-loom, licensed under the MIT License (MIT).
- *
- * Copyright (c) 2022-2024 FabricMC
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-package net.fabricmc.loom.util;
-
-import javax.inject.Inject;
-
-import org.apache.commons.io.output.NullOutputStream;
-import org.gradle.api.Action;
-import org.gradle.api.Project;
-import org.gradle.api.logging.LogLevel;
-import org.gradle.api.logging.configuration.ShowStacktrace;
-import org.gradle.api.plugins.JavaPluginExtension;
-import org.gradle.jvm.toolchain.JavaLauncher;
-import org.gradle.jvm.toolchain.JavaToolchainService;
-import org.gradle.jvm.toolchain.JavaToolchainSpec;
-import org.gradle.process.ExecOperations;
-import org.gradle.process.ExecResult;
-import org.gradle.process.JavaExecSpec;
-import org.jetbrains.annotations.Nullable;
-
-/**
- * Contains helpers for executing Forge's command line tools
- * with suppressed output streams to prevent annoying log spam.
- */
-public abstract class ForgeToolExecutor {
- @Inject
- protected abstract JavaToolchainService getToolchainService();
-
- @Inject
- protected abstract ExecOperations getExecOperations();
-
- @Inject
- protected abstract Project getProject();
-
- public static boolean shouldShowVerboseStdout(Project project) {
- // if running with INFO or DEBUG logging
- return project.getGradle().getStartParameter().getLogLevel().compareTo(LogLevel.LIFECYCLE) < 0;
- }
-
- public static boolean shouldShowVerboseStderr(Project project) {
- // if stdout is shown or stacktraces are visible so that errors printed to stderr show up
- return shouldShowVerboseStdout(project) || project.getGradle().getStartParameter().getShowStacktrace() != ShowStacktrace.INTERNAL_EXCEPTIONS;
- }
-
- /**
- * Executes a {@link ExecOperations#javaexec(Action) javaexec} action with suppressed output.
- *
- * @param project the project
- * @param configurator the {@code javaexec} configuration action
- * @return the execution result
- */
- public static ExecResult exec(Project project, Action super JavaExecSpec> configurator) {
- return project.getObjects().newInstance(ForgeToolExecutor.class)
- .exec(configurator);
- }
-
- private ExecResult exec(Action super JavaExecSpec> configurator) {
- final Project project = getProject();
- return getExecOperations().javaexec(spec -> {
- configurator.execute(spec);
-
- if (shouldShowVerboseStdout(project)) {
- spec.setStandardOutput(System.out);
- } else {
- spec.setStandardOutput(NullOutputStream.INSTANCE);
- }
-
- if (shouldShowVerboseStderr(project)) {
- spec.setErrorOutput(System.err);
- } else {
- spec.setErrorOutput(NullOutputStream.INSTANCE);
- }
-
- // Use project toolchain for executing if possible.
- // Note: This feature cannot be tested using the test kit since
- // - Gradle disables native services in test kit environments.
- // - The only resolver plugin I could find, foojay-resolver,
- // requires the services for finding the OS architecture.
- final @Nullable String executable = findJavaToolchainExecutable(project);
-
- if (executable != null) {
- spec.setExecutable(executable);
- }
- });
- }
-
- private @Nullable String findJavaToolchainExecutable(Project project) {
- final JavaPluginExtension java = project.getExtensions().getByType(JavaPluginExtension.class);
- final JavaToolchainSpec toolchain = java.getToolchain();
-
- if (!toolchain.getLanguageVersion().isPresent()) {
- // Toolchain not configured, we'll use the runtime Java version.
- return null;
- }
-
- final JavaLauncher launcher = getToolchainService().launcherFor(toolchain).get();
- return launcher.getExecutablePath().getAsFile().getAbsolutePath();
- }
-}