mirror of
https://github.com/architectury/architectury-loom.git
synced 2026-03-28 04:07:01 -05:00
Merge 1.11
This commit is contained in:
@@ -28,7 +28,6 @@ import java.io.BufferedReader;
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.UncheckedIOException;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
@@ -37,9 +36,7 @@ import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.StandardCopyOption;
|
||||
import java.time.Duration;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
@@ -59,7 +56,6 @@ import org.gradle.api.file.RegularFileProperty;
|
||||
import org.gradle.api.provider.Property;
|
||||
import org.gradle.api.services.ServiceReference;
|
||||
import org.gradle.api.tasks.Input;
|
||||
import org.gradle.api.tasks.InputFile;
|
||||
import org.gradle.api.tasks.InputFiles;
|
||||
import org.gradle.api.tasks.Internal;
|
||||
import org.gradle.api.tasks.Nested;
|
||||
@@ -70,7 +66,6 @@ import org.gradle.api.tasks.UntrackedTask;
|
||||
import org.gradle.api.tasks.options.Option;
|
||||
import org.gradle.internal.logging.progress.ProgressLoggerFactory;
|
||||
import org.gradle.process.ExecOperations;
|
||||
import org.gradle.process.ExecResult;
|
||||
import org.gradle.workers.WorkAction;
|
||||
import org.gradle.workers.WorkParameters;
|
||||
import org.gradle.workers.WorkQueue;
|
||||
@@ -91,6 +86,7 @@ import net.fabricmc.loom.decompilers.cache.CachedData;
|
||||
import net.fabricmc.loom.decompilers.cache.CachedFileStoreImpl;
|
||||
import net.fabricmc.loom.decompilers.cache.CachedJarProcessor;
|
||||
import net.fabricmc.loom.task.service.SourceMappingsService;
|
||||
import net.fabricmc.loom.task.service.UnpickService;
|
||||
import net.fabricmc.loom.util.Checksum;
|
||||
import net.fabricmc.loom.util.Constants;
|
||||
import net.fabricmc.loom.util.ExceptionUtil;
|
||||
@@ -106,6 +102,7 @@ import net.fabricmc.loom.util.gradle.daemon.DaemonUtils;
|
||||
import net.fabricmc.loom.util.ipc.IPCClient;
|
||||
import net.fabricmc.loom.util.ipc.IPCServer;
|
||||
import net.fabricmc.loom.util.service.ScopedServiceFactory;
|
||||
import net.fabricmc.loom.util.service.ServiceFactory;
|
||||
import net.fabricmc.mappingio.tree.MemoryMappingTree;
|
||||
|
||||
@UntrackedTask(because = "Manually invoked, has internal caching")
|
||||
@@ -135,31 +132,6 @@ public abstract class GenerateSourcesTask extends AbstractLoomTask {
|
||||
@OutputFile
|
||||
protected abstract ConfigurableFileCollection getClassesOutputJar(); // Single jar
|
||||
|
||||
// Unpick
|
||||
@InputFile
|
||||
@Optional
|
||||
public abstract RegularFileProperty getUnpickDefinitions();
|
||||
|
||||
@InputFiles
|
||||
@Optional
|
||||
public abstract ConfigurableFileCollection getUnpickConstantJar();
|
||||
|
||||
@InputFiles
|
||||
@Optional
|
||||
public abstract ConfigurableFileCollection getUnpickClasspath();
|
||||
|
||||
@InputFiles
|
||||
@Optional
|
||||
@ApiStatus.Internal
|
||||
public abstract ConfigurableFileCollection getUnpickRuntimeClasspath();
|
||||
|
||||
@OutputFile
|
||||
@Optional
|
||||
public abstract RegularFileProperty getUnpickOutputJar();
|
||||
|
||||
@OutputFile
|
||||
protected abstract RegularFileProperty getUnpickLogConfig();
|
||||
|
||||
@Input
|
||||
@Option(option = "use-cache", description = "Use the decompile cache")
|
||||
@ApiStatus.Experimental
|
||||
@@ -204,6 +176,10 @@ public abstract class GenerateSourcesTask extends AbstractLoomTask {
|
||||
@Nested
|
||||
protected abstract Property<DaemonUtils.Context> getDaemonUtilsContext();
|
||||
|
||||
@Nested
|
||||
@Optional
|
||||
protected abstract Property<UnpickService.Options> getUnpickOptions();
|
||||
|
||||
// Prevent Gradle from running two gen sources tasks in parallel
|
||||
@ServiceReference(SyncTaskBuildService.NAME)
|
||||
abstract Property<SyncTaskBuildService> getSyncTask();
|
||||
@@ -246,8 +222,6 @@ public abstract class GenerateSourcesTask extends AbstractLoomTask {
|
||||
|
||||
getMinecraftCompileLibraries().from(getProject().getConfigurations().getByName(Constants.Configurations.MINECRAFT_COMPILE_LIBRARIES));
|
||||
getDecompileCacheFile().set(getExtension().getFiles().getDecompileCache(CACHE_VERSION));
|
||||
getUnpickRuntimeClasspath().from(getProject().getConfigurations().getByName(Constants.Configurations.UNPICK_CLASSPATH));
|
||||
getUnpickLogConfig().set(getExtension().getFiles().getUnpickLoggingConfigFile());
|
||||
|
||||
getUseCache().convention(true);
|
||||
getResetCache().convention(getExtension().refreshDeps());
|
||||
@@ -259,6 +233,8 @@ public abstract class GenerateSourcesTask extends AbstractLoomTask {
|
||||
|
||||
getDaemonUtilsContext().set(getProject().getObjects().newInstance(DaemonUtils.Context.class, getProject()));
|
||||
|
||||
getUnpickOptions().set(UnpickService.createOptions(this));
|
||||
|
||||
mustRunAfter(getProject().getTasks().withType(AbstractRemapJarTask.class));
|
||||
}
|
||||
|
||||
@@ -270,57 +246,59 @@ public abstract class GenerateSourcesTask extends AbstractLoomTask {
|
||||
throw new UnsupportedOperationException("GenSources task requires a 64bit JVM to run due to the memory requirements.");
|
||||
}
|
||||
|
||||
if (!getUseCache().get()) {
|
||||
getLogger().info("Not using decompile cache.");
|
||||
try (ScopedServiceFactory serviceFactory = new ScopedServiceFactory()) {
|
||||
if (!getUseCache().get()) {
|
||||
getLogger().info("Not using decompile cache.");
|
||||
|
||||
try (var timer = new Timer("Decompiled sources")) {
|
||||
runWithoutCache();
|
||||
try (var timer = new Timer("Decompiled sources")) {
|
||||
runWithoutCache(serviceFactory);
|
||||
} catch (Exception e) {
|
||||
ExceptionUtil.processException(e, getDaemonUtilsContext().get());
|
||||
throw ExceptionUtil.createDescriptiveWrapper(RuntimeException::new, "Failed to decompile", e);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
getLogger().info("Using decompile cache.");
|
||||
|
||||
try (var timer = new Timer("Decompiled sources with cache")) {
|
||||
final Path cacheFile = getDecompileCacheFile().getAsFile().get().toPath();
|
||||
|
||||
if (getResetCache().get()) {
|
||||
getLogger().warn("Resetting decompile cache");
|
||||
Files.deleteIfExists(cacheFile);
|
||||
}
|
||||
|
||||
// TODO ensure we have a lock on this file to prevent multiple tasks from running at the same time
|
||||
Files.createDirectories(cacheFile.getParent());
|
||||
|
||||
if (Files.exists(cacheFile)) {
|
||||
try (FileSystemUtil.Delegate fs = FileSystemUtil.getJarFileSystem(cacheFile, true)) {
|
||||
// Success, cache exists and can be read
|
||||
} catch (IOException e) {
|
||||
getLogger().warn("Discarding invalid decompile cache file: {}", cacheFile, e);
|
||||
Files.delete(cacheFile);
|
||||
}
|
||||
}
|
||||
|
||||
try (FileSystemUtil.Delegate fs = FileSystemUtil.getJarFileSystem(cacheFile, true)) {
|
||||
runWithCache(serviceFactory, fs.getRoot());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
ExceptionUtil.processException(e, getDaemonUtilsContext().get());
|
||||
throw ExceptionUtil.createDescriptiveWrapper(RuntimeException::new, "Failed to decompile", e);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
getLogger().info("Using decompile cache.");
|
||||
|
||||
try (var timer = new Timer("Decompiled sources with cache")) {
|
||||
final Path cacheFile = getDecompileCacheFile().getAsFile().get().toPath();
|
||||
|
||||
if (getResetCache().get()) {
|
||||
getLogger().warn("Resetting decompile cache");
|
||||
Files.deleteIfExists(cacheFile);
|
||||
}
|
||||
|
||||
// TODO ensure we have a lock on this file to prevent multiple tasks from running at the same time
|
||||
Files.createDirectories(cacheFile.getParent());
|
||||
|
||||
if (Files.exists(cacheFile)) {
|
||||
try (FileSystemUtil.Delegate fs = FileSystemUtil.getJarFileSystem(cacheFile, true)) {
|
||||
// Success, cache exists and can be read
|
||||
} catch (IOException e) {
|
||||
getLogger().warn("Discarding invalid decompile cache file: {}", cacheFile, e);
|
||||
Files.delete(cacheFile);
|
||||
}
|
||||
}
|
||||
|
||||
try (FileSystemUtil.Delegate fs = FileSystemUtil.getJarFileSystem(cacheFile, true)) {
|
||||
runWithCache(fs.getRoot());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
ExceptionUtil.processException(e, getDaemonUtilsContext().get());
|
||||
throw ExceptionUtil.createDescriptiveWrapper(RuntimeException::new, "Failed to decompile", e);
|
||||
}
|
||||
}
|
||||
|
||||
private void runWithCache(Path cacheRoot) throws IOException {
|
||||
private void runWithCache(ServiceFactory serviceFactory, Path cacheRoot) throws IOException {
|
||||
final Path classesInputJar = getClassesInputJar().getSingleFile().toPath();
|
||||
final Path sourcesOutputJar = getSourcesOutputJar().get().getAsFile().toPath();
|
||||
final Path classesOutputJar = getClassesOutputJar().getSingleFile().toPath();
|
||||
final var cacheRules = new CachedFileStoreImpl.CacheRules(getMaxCachedFiles().get(), Duration.ofDays(getMaxCacheFileAge().get()));
|
||||
final var decompileCache = new CachedFileStoreImpl<>(cacheRoot, CachedData.SERIALIZER, cacheRules);
|
||||
final String cacheKey = getCacheKey();
|
||||
final String cacheKey = getCacheKey(serviceFactory);
|
||||
final CachedJarProcessor cachedJarProcessor = new CachedJarProcessor(decompileCache, cacheKey);
|
||||
final CachedJarProcessor.WorkRequest workRequest;
|
||||
|
||||
@@ -342,9 +320,10 @@ public abstract class GenerateSourcesTask extends AbstractLoomTask {
|
||||
Path workInputJar = workToDoJob.incomplete();
|
||||
@Nullable Path existingClasses = (job instanceof CachedJarProcessor.PartialWorkJob partialWorkJob) ? partialWorkJob.existingClasses() : null;
|
||||
|
||||
if (getUnpickDefinitions().isPresent()) {
|
||||
if (usingUnpick()) {
|
||||
try (var timer = new Timer("Unpick")) {
|
||||
workInputJar = unpickJar(workInputJar, existingClasses);
|
||||
UnpickService unpick = serviceFactory.get(getUnpickOptions());
|
||||
workInputJar = unpick.unpickJar(workInputJar, existingClasses);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -381,16 +360,17 @@ public abstract class GenerateSourcesTask extends AbstractLoomTask {
|
||||
}
|
||||
}
|
||||
|
||||
private void runWithoutCache() throws IOException {
|
||||
private void runWithoutCache(ServiceFactory serviceFactory) throws IOException {
|
||||
final Path classesInputJar = getClassesInputJar().getSingleFile().toPath();
|
||||
final Path sourcesOutputJar = getSourcesOutputJar().get().getAsFile().toPath();
|
||||
final Path classesOutputJar = getClassesOutputJar().getSingleFile().toPath();
|
||||
|
||||
Path workClassesJar = classesInputJar;
|
||||
|
||||
if (getUnpickDefinitions().isPresent()) {
|
||||
if (usingUnpick()) {
|
||||
try (var timer = new Timer("Unpick")) {
|
||||
workClassesJar = unpickJar(workClassesJar, null);
|
||||
UnpickService unpick = serviceFactory.get(getUnpickOptions());
|
||||
workClassesJar = unpick.unpickJar(workClassesJar, null);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -427,24 +407,24 @@ public abstract class GenerateSourcesTask extends AbstractLoomTask {
|
||||
Files.move(tempJar, classesOutputJar, StandardCopyOption.REPLACE_EXISTING);
|
||||
}
|
||||
|
||||
private String getCacheKey() {
|
||||
private String getCacheKey(ServiceFactory serviceFactory) {
|
||||
var sj = new StringJoiner(",");
|
||||
sj.add(getDecompilerCheckKey());
|
||||
sj.add(getUnpickCacheKey());
|
||||
|
||||
if (usingUnpick()) {
|
||||
UnpickService unpick = serviceFactory.get(getUnpickOptions());
|
||||
sj.add(unpick.getUnpickCacheKey());
|
||||
}
|
||||
|
||||
getLogger().info("Decompile cache data: {}", sj);
|
||||
|
||||
try {
|
||||
return Checksum.sha256Hex(sj.toString().getBytes(StandardCharsets.UTF_8));
|
||||
} catch (IOException e) {
|
||||
throw new UncheckedIOException(e);
|
||||
}
|
||||
return Checksum.of(sj.toString()).sha256().hex();
|
||||
}
|
||||
|
||||
private String getDecompilerCheckKey() {
|
||||
var sj = new StringJoiner(",");
|
||||
sj.add(decompilerOptions.getDecompilerClassName().get());
|
||||
sj.add(fileCollectionHash(decompilerOptions.getClasspath()));
|
||||
sj.add(Checksum.of(decompilerOptions.getClasspath()).sha256().hex());
|
||||
|
||||
for (Map.Entry<String, String> entry : decompilerOptions.getOptions().get().entrySet()) {
|
||||
sj.add(entry.getKey() + "=" + entry.getValue());
|
||||
@@ -453,19 +433,6 @@ public abstract class GenerateSourcesTask extends AbstractLoomTask {
|
||||
return sj.toString();
|
||||
}
|
||||
|
||||
private String getUnpickCacheKey() {
|
||||
if (!getUnpickDefinitions().isPresent()) {
|
||||
return "";
|
||||
}
|
||||
|
||||
var sj = new StringJoiner(",");
|
||||
sj.add(fileHash(getUnpickDefinitions().getAsFile().get()));
|
||||
sj.add(fileCollectionHash(getUnpickConstantJar()));
|
||||
sj.add(fileCollectionHash(getUnpickRuntimeClasspath()));
|
||||
|
||||
return sj.toString();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private ClassLineNumbers runDecompileJob(Path inputJar, Path outputJar, @Nullable Path existingJar) throws IOException {
|
||||
final Platform platform = Platform.CURRENT;
|
||||
@@ -565,55 +532,6 @@ public abstract class GenerateSourcesTask extends AbstractLoomTask {
|
||||
}
|
||||
}
|
||||
|
||||
private Path unpickJar(Path inputJar, @Nullable Path existingClasses) {
|
||||
final Path outputJar = getUnpickOutputJar().get().getAsFile().toPath();
|
||||
final List<String> args = getUnpickArgs(inputJar, outputJar, existingClasses);
|
||||
|
||||
ExecResult result = getExecOperations().javaexec(spec -> {
|
||||
spec.getMainClass().set("daomephsta.unpick.cli.Main");
|
||||
spec.classpath(getUnpickRuntimeClasspath());
|
||||
spec.args(args);
|
||||
spec.systemProperty("java.util.logging.config.file", writeUnpickLogConfig().getAbsolutePath());
|
||||
});
|
||||
|
||||
result.rethrowFailure();
|
||||
|
||||
return outputJar;
|
||||
}
|
||||
|
||||
private List<String> getUnpickArgs(Path inputJar, Path outputJar, @Nullable Path existingClasses) {
|
||||
var fileArgs = new ArrayList<File>();
|
||||
|
||||
fileArgs.add(inputJar.toFile());
|
||||
fileArgs.add(outputJar.toFile());
|
||||
fileArgs.add(getUnpickDefinitions().get().getAsFile());
|
||||
fileArgs.add(getUnpickConstantJar().getSingleFile());
|
||||
|
||||
for (File file : getUnpickClasspath()) {
|
||||
fileArgs.add(file);
|
||||
}
|
||||
|
||||
if (existingClasses != null) {
|
||||
fileArgs.add(existingClasses.toFile());
|
||||
}
|
||||
|
||||
return fileArgs.stream()
|
||||
.map(File::getAbsolutePath)
|
||||
.toList();
|
||||
}
|
||||
|
||||
private File writeUnpickLogConfig() {
|
||||
final File unpickLoggingConfigFile = getUnpickLogConfig().getAsFile().get();
|
||||
|
||||
try (InputStream is = GenerateSourcesTask.class.getClassLoader().getResourceAsStream("unpick-logging.properties")) {
|
||||
Files.copy(Objects.requireNonNull(is), unpickLoggingConfigFile.toPath(), StandardCopyOption.REPLACE_EXISTING);
|
||||
} catch (IOException e) {
|
||||
throw new UncheckedIOException("Failed to copy unpick logging config", e);
|
||||
}
|
||||
|
||||
return unpickLoggingConfigFile;
|
||||
}
|
||||
|
||||
private void remapLineNumbers(ClassLineNumbers lineNumbers, Path inputJar, Path outputJar) throws IOException {
|
||||
Objects.requireNonNull(lineNumbers, "lineNumbers");
|
||||
final var remapper = new LineNumberRemapper(lineNumbers);
|
||||
@@ -689,6 +607,10 @@ public abstract class GenerateSourcesTask extends AbstractLoomTask {
|
||||
return !Boolean.getBoolean("fabric.loom.genSources.debug");
|
||||
}
|
||||
|
||||
private boolean usingUnpick() {
|
||||
return getUnpickOptions().isPresent();
|
||||
}
|
||||
|
||||
public interface DecompileParams extends WorkParameters {
|
||||
Property<DecompilerOptions.Dto> getDecompilerOptions();
|
||||
|
||||
@@ -816,26 +738,6 @@ public abstract class GenerateSourcesTask extends AbstractLoomTask {
|
||||
}
|
||||
}
|
||||
|
||||
private static String fileHash(File file) {
|
||||
try {
|
||||
return Checksum.sha256Hex(Files.readAllBytes(file.toPath()));
|
||||
} catch (IOException e) {
|
||||
throw new UncheckedIOException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private static String fileCollectionHash(FileCollection files) {
|
||||
var sj = new StringJoiner(",");
|
||||
|
||||
files.getFiles()
|
||||
.stream()
|
||||
.sorted(Comparator.comparing(File::getAbsolutePath))
|
||||
.map(GenerateSourcesTask::fileHash)
|
||||
.forEach(sj::add);
|
||||
|
||||
return sj.toString();
|
||||
}
|
||||
|
||||
public interface MappingsProcessor {
|
||||
boolean transform(MemoryMappingTree mappings);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user