Skip to content

Commit

Permalink
Make Forge tools compatible with config cache
Browse files Browse the repository at this point in the history
  • Loading branch information
Juuxel committed Dec 6, 2024
1 parent 1837cd7 commit 598ef19
Show file tree
Hide file tree
Showing 11 changed files with 234 additions and 137 deletions.
141 changes: 141 additions & 0 deletions src/main/java/dev/architectury/loom/forge/tool/ForgeToolExecutor.java
Original file line number Diff line number Diff line change
@@ -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.
*
* <p>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<String> getExecutable();

@Input
ListProperty<String> getProgramArgs();

@Input
ListProperty<String> getJvmArgs();

@Input
Property<String> getMainClass();

@Classpath
ConfigurableFileCollection getExecClasspath();

@Input
Property<Boolean> getShowVerboseStdout();

@Input
Property<Boolean> 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<String> args) {
getProgramArgs().addAll(args);
}

default void setArgs(List<String> args) {
getProgramArgs().set(args);
}

default void jvmArgs(String... args) {
getJvmArgs().addAll(args);
}

default void jvmArgs(Collection<String> args) {
getJvmArgs().addAll(args);
}
}
}
Original file line number Diff line number Diff line change
@@ -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<ExecResult, ForgeToolValueSource.Parameters> {
@Inject
protected abstract ExecOperations getExecOperations();

public static Provider<ExecResult> 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<ForgeToolExecutor.Settings> getSettings();
}
}
Original file line number Diff line number Diff line change
@@ -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";
Expand Down
Original file line number Diff line number Diff line change
@@ -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<String> 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();
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;

Expand Down Expand Up @@ -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) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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<File> getMinecraftLibraries();

default List<String> resolve(List<ConfigValue> configValues) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -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",
Expand Down
Loading

0 comments on commit 598ef19

Please sign in to comment.