Version 0.7.1, Merge pull request #15 from architectury/feature/perf

Performance Optimisations on Project Setup
This commit is contained in:
shedaniel
2021-05-05 02:27:29 +08:00
committed by GitHub
23 changed files with 323 additions and 118 deletions

View File

@@ -17,9 +17,9 @@ plugins {
sourceCompatibility = 1.8
targetCompatibility = 1.8
group = 'me.shedaniel'
group = "dev.architectury"
archivesBaseName = project.name
def baseVersion = '0.7.0'
def baseVersion = '0.7.1'
def runNumber = System.getenv("GITHUB_RUN_NUMBER") ?: "9999"
def isSnapshot = System.getenv("PR_NUM") != null
@@ -35,7 +35,6 @@ if (!isSnapshot) {
logger.lifecycle(":building plugin v${version}")
configurations {
shadowArchitectury
forgeInjectShadow
forgeInjectCompileClasspath.extendsFrom(forgeInjectShadow)
forgeInjectRuntimeClasspath.extendsFrom(forgeInjectShadow)
@@ -77,10 +76,7 @@ dependencies {
}
// tinyfile management
compileOnly ('net.fabricmc:tiny-remapper:0.3.2-architectury.7')
shadowArchitectury ('net.fabricmc:tiny-remapper:0.3.2-architectury.7') {
transitive = false
}
implementation ('dev.architectury:tiny-remapper:1.0.0')
implementation ('net.fabricmc:tiny-mappings-parser:0.3.0+build.17')
implementation 'net.fabricmc:access-widener:1.0.0'
@@ -89,17 +85,14 @@ dependencies {
transitive = false
}
implementation ('org.cadixdev:lorenz-io-proguard:0.5.6')
compileOnly "me.shedaniel.architectury:refmap-remapper:1.0.4"
shadowArchitectury ("me.shedaniel.architectury:refmap-remapper:1.0.4") {
transitive = false
}
implementation "dev.architectury:refmap-remapper:1.0.5"
// decompilers
implementation ('net.fabricmc:fabric-fernflower:1.3.0')
implementation ('org.benf:cfr:0.150')
// source code remapping
implementation ('org.cadixdev:mercury:0.2.8')
implementation ('org.cadixdev:mercury:0.2.9-architectury')
// Kapt integration
compileOnly('org.jetbrains.kotlin:kotlin-gradle-plugin:1.4.21')
@@ -110,7 +103,7 @@ dependencies {
implementation ('org.cadixdev:lorenz-asm:0.5.3')
implementation ('net.minecraftforge:accesstransformers:2.2.0')
implementation ('de.oceanlabs.mcp:mcinjector:3.8.0')
implementation ('net.md-5:SpecialSource:1.8.3')
implementation ('com.opencsv:opencsv:5.4')
// Forge injection
forgeInjectShadow ('net.fabricmc:tiny-mappings-parser:0.2.2.14')
@@ -141,17 +134,10 @@ jar {
classifier 'jar'
}
shadowJar {
relocate "net.fabricmc.tinyremapper", "me.shedaniel.architectury.loom.shadowed.impl.net.fabricmc.tinyremapper"
relocate "me.shedaniel.architectury.refmapremapper", "me.shedaniel.architectury.loom.shadowed.impl.me.shedaniel.architectury.refmapremapper"
configurations = [project.configurations.shadowArchitectury]
classifier "shadow"
}
task mainJar(type: Jar, dependsOn: shadowJar) {
task mainJar(type: Jar, dependsOn: jar) {
dependsOn forgeInjectJar
from zipTree(shadowJar.archivePath)
from zipTree(jar.archivePath)
from(forgeInjectJar.outputs) {
into "inject"
rename { "injection.jar" }
@@ -195,7 +181,7 @@ codenarc {
gradlePlugin {
plugins {
fabricLoom {
id = 'forgified-fabric-loom'
id = 'dev.architectury.loom'
implementationClass = 'net.fabricmc.loom.LoomGradlePlugin'
}
}
@@ -228,8 +214,8 @@ import org.w3c.dom.Node
publishing {
publications {
plugin(MavenPublication) {
groupId 'forgified-fabric-loom'
artifactId 'forgified-fabric-loom.gradle.plugin'
groupId 'dev.architectury.loom'
artifactId 'dev.architectury.loom.gradle.plugin'
from components.java
artifact mainJar
@@ -260,8 +246,8 @@ publishing {
}
pluginSnapshot(MavenPublication) {
groupId 'forgified-fabric-loom'
artifactId 'forgified-fabric-loom.gradle.plugin'
groupId 'dev.architectury.loom'
artifactId 'dev.architectury.loom.gradle.plugin'
version baseVersion + '-SNAPSHOT'
pom.withXml {

View File

@@ -1 +1 @@
rootProject.name = "forgified-fabric-loom"
rootProject.name = "architectury-loom"

View File

@@ -35,16 +35,16 @@ import java.util.Set;
import java.util.function.BiConsumer;
import java.util.function.BiFunction;
import dev.architectury.tinyremapper.IMappingProvider;
import dev.architectury.tinyremapper.InputTag;
import dev.architectury.tinyremapper.OutputConsumerPath;
import dev.architectury.tinyremapper.TinyRemapper;
import org.gradle.api.Action;
import org.gradle.api.Project;
import org.objectweb.asm.commons.Remapper;
import net.fabricmc.loom.util.LoggerFilter;
import net.fabricmc.stitch.util.Pair;
import net.fabricmc.tinyremapper.IMappingProvider;
import net.fabricmc.tinyremapper.InputTag;
import net.fabricmc.tinyremapper.OutputConsumerPath;
import net.fabricmc.tinyremapper.TinyRemapper;
public class JarRemapper {
private final List<IMappingProvider> mappingProviders = new ArrayList<>();

View File

@@ -38,6 +38,7 @@ import java.util.zip.ZipEntry;
import com.google.gson.Gson;
import com.google.gson.JsonObject;
import dev.architectury.tinyremapper.TinyRemapper;
import org.gradle.api.Project;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
@@ -58,7 +59,6 @@ import net.fabricmc.loom.configuration.processors.JarProcessor;
import net.fabricmc.loom.configuration.providers.minecraft.MinecraftMappedProvider;
import net.fabricmc.loom.util.Checksum;
import net.fabricmc.loom.util.Constants;
import net.fabricmc.tinyremapper.TinyRemapper;
public class AccessWidenerJarProcessor implements JarProcessor {
private AccessWidener accessWidener = new AccessWidener();

View File

@@ -45,7 +45,11 @@ import java.util.jar.Manifest;
import java.util.stream.Collectors;
import java.util.zip.ZipEntry;
import com.google.common.base.Stopwatch;
import com.google.gson.JsonObject;
import dev.architectury.tinyremapper.InputTag;
import dev.architectury.tinyremapper.OutputConsumerPath;
import dev.architectury.tinyremapper.TinyRemapper;
import org.apache.commons.io.IOUtils;
import org.gradle.api.Project;
import org.objectweb.asm.commons.Remapper;
@@ -69,9 +73,6 @@ import net.fabricmc.loom.util.TinyRemapperMappingsHelper;
import net.fabricmc.loom.util.srg.AtRemapper;
import net.fabricmc.loom.util.srg.CoreModClassRemapper;
import net.fabricmc.mapping.tree.TinyTree;
import net.fabricmc.tinyremapper.InputTag;
import net.fabricmc.tinyremapper.OutputConsumerPath;
import net.fabricmc.tinyremapper.TinyRemapper;
public class ModProcessor {
public static void processMods(Project project, List<ModDependencyInfo> processList) throws IOException {
@@ -150,6 +151,7 @@ public class ModProcessor {
List<ModDependencyInfo> remapList = processList.stream().filter(ModDependencyInfo::requiresRemapping).collect(Collectors.toList());
Stopwatch stopwatch = Stopwatch.createStarted();
project.getLogger().lifecycle(":remapping " + remapList.size() + " mods (TinyRemapper, " + fromM + " -> " + toM + ")");
TinyTree mappings = extension.isForge() ? mappingsProvider.getMappingsWithSrg() : mappingsProvider.getMappings();
@@ -201,6 +203,7 @@ public class ModProcessor {
}
remapper.finish();
project.getLogger().lifecycle(":remapped " + remapList.size() + " mods (TinyRemapper, " + fromM + " -> " + toM + ") in " + stopwatch.stop());
for (ModDependencyInfo info : remapList) {
outputConsumerMap.get(info).close();

View File

@@ -33,6 +33,7 @@ import java.util.Optional;
import java.util.function.Consumer;
import java.util.zip.ZipError;
import com.google.common.base.Stopwatch;
import com.google.common.io.Files;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
@@ -112,6 +113,7 @@ public class MinecraftProvider extends DependencyProvider {
} catch (ZipError e) {
HashedDownloadUtil.delete(minecraftClientJar);
HashedDownloadUtil.delete(minecraftServerJar);
HashedDownloadUtil.delete(minecraftMergedJar);
getProject().getLogger().error("Could not merge JARs! Deleting source JARs - please re-run the command and move on.", e);
throw new RuntimeException();
@@ -232,11 +234,14 @@ public class MinecraftProvider extends DependencyProvider {
private void mergeJars(Logger logger) throws IOException {
logger.info(":merging jars");
Stopwatch stopwatch = Stopwatch.createStarted();
try (JarMerger jarMerger = new JarMerger(minecraftClientJar, minecraftServerJar, minecraftMergedJar)) {
jarMerger.enableSyntheticParamsOffset();
jarMerger.merge();
}
logger.info(":merged jars in " + stopwatch);
}
public File getMergedJar() {

View File

@@ -51,9 +51,12 @@ import java.util.function.Predicate;
import java.util.stream.Stream;
import com.google.common.base.Predicates;
import com.google.common.base.Stopwatch;
import com.google.common.collect.ImmutableMap;
import com.google.gson.JsonParser;
import de.oceanlabs.mcp.mcinjector.adaptors.ParameterAnnotationFixer;
import dev.architectury.tinyremapper.OutputConsumerPath;
import dev.architectury.tinyremapper.TinyRemapper;
import net.minecraftforge.accesstransformer.AccessTransformerEngine;
import net.minecraftforge.accesstransformer.TransformerProcessor;
import net.minecraftforge.accesstransformer.parser.AccessTransformerList;
@@ -87,8 +90,6 @@ import net.fabricmc.loom.util.function.FsPathConsumer;
import net.fabricmc.loom.util.srg.InnerClassRemapper;
import net.fabricmc.loom.util.srg.SpecialSourceExecutor;
import net.fabricmc.mapping.tree.TinyTree;
import net.fabricmc.tinyremapper.OutputConsumerPath;
import net.fabricmc.tinyremapper.TinyRemapper;
public class MinecraftPatchedProvider extends DependencyProvider {
private final MappingsProvider mappingsProvider;
@@ -291,12 +292,16 @@ public class MinecraftPatchedProvider extends DependencyProvider {
}
private void fixParameterAnnotation(File jarFile) throws Exception {
getProject().getLogger().info(":fixing parameter annotations for " + jarFile.toString());
getProject().getLogger().info(":fixing parameter annotations for " + jarFile.getAbsolutePath());
Stopwatch stopwatch = Stopwatch.createStarted();
try (FileSystem fs = FileSystems.newFileSystem(new URI("jar:" + jarFile.toURI()), ImmutableMap.of("create", false))) {
for (Path rootDir : fs.getRootDirectories()) {
for (Path file : (Iterable<? extends Path>) Files.walk(rootDir)::iterator) {
if (!file.toString().endsWith(".class")) continue;
ThreadingUtils.TaskCompleter completer = ThreadingUtils.taskCompleter();
for (Path file : (Iterable<? extends Path>) Files.walk(fs.getPath("/"))::iterator) {
if (!file.toString().endsWith(".class")) continue;
completer.add(() -> {
byte[] bytes = Files.readAllBytes(file);
ClassReader reader = new ClassReader(bytes);
ClassNode node = new ClassNode();
@@ -311,9 +316,13 @@ public class MinecraftPatchedProvider extends DependencyProvider {
Files.delete(file);
Files.write(file, out);
}
}
});
}
completer.complete();
}
getProject().getLogger().info(":fixing parameter annotations for " + jarFile.getAbsolutePath() + " in " + stopwatch);
}
private void injectForgeClasses(Logger logger) throws IOException {

View File

@@ -37,6 +37,7 @@ import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.function.Consumer;
@@ -67,6 +68,7 @@ import net.fabricmc.loom.util.DownloadUtil;
import net.fabricmc.loom.util.srg.MCPReader;
import net.fabricmc.loom.util.srg.SrgMerger;
import net.fabricmc.loom.util.srg.SrgNamedWriter;
import net.fabricmc.mapping.reader.v2.TinyMetadata;
import net.fabricmc.mapping.reader.v2.TinyV2Factory;
import net.fabricmc.mapping.tree.TinyTree;
import net.fabricmc.stitch.Command;
@@ -274,7 +276,12 @@ public class MappingsProvider extends DependencyProvider {
extractUnpickDefinitions(fileSystem, unpickDefinitionsFile.toPath());
}
if (baseMappingsAreV2()) {
if (baseMappingsAreMergedV2()) {
// Architectury Loom Patch
// If a merged tiny v2 mappings file is provided
// Skip merging, should save a lot of time
Files.copy(baseTinyMappings, tinyMappings.toPath(), StandardCopyOption.REPLACE_EXISTING);
} else if (baseMappingsAreV2()) {
// These are unmerged v2 mappings
mergeAndSaveMappings(project, yarnJar);
} else {
@@ -337,6 +344,15 @@ public class MappingsProvider extends DependencyProvider {
}
}
private boolean baseMappingsAreMergedV2() throws IOException {
try (BufferedReader reader = Files.newBufferedReader(baseTinyMappings)) {
TinyMetadata metadata = TinyV2Factory.readMetadata(reader);
return metadata.getNamespaces().containsAll(Arrays.asList("named", "intermediary", "official"));
} catch (IllegalArgumentException e) {
return false;
}
}
public static void extractMappings(FileSystem jar, Path extractTo) throws IOException {
Files.copy(jar.getPath("mappings/mappings.tiny"), extractTo, StandardCopyOption.REPLACE_EXISTING);
}

View File

@@ -34,32 +34,36 @@ import java.nio.file.FileSystem;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Consumer;
import java.util.jar.Attributes;
import java.util.jar.Manifest;
import com.google.common.base.Stopwatch;
import com.google.common.collect.ImmutableMap;
import dev.architectury.tinyremapper.IMappingProvider;
import dev.architectury.tinyremapper.TinyRemapper;
import org.gradle.api.Project;
import org.jetbrains.annotations.Nullable;
import net.fabricmc.loom.configuration.DependencyProvider;
import net.fabricmc.loom.configuration.providers.MinecraftProvider;
import net.fabricmc.loom.configuration.providers.mappings.MappingsProvider;
import net.fabricmc.loom.configuration.providers.minecraft.tr.OutputRemappingHandler;
import net.fabricmc.loom.util.Constants;
import net.fabricmc.loom.util.DownloadUtil;
import net.fabricmc.loom.util.FileSystemUtil;
import net.fabricmc.loom.util.ThreadingUtils;
import net.fabricmc.loom.util.TinyRemapperMappingsHelper;
import net.fabricmc.loom.util.srg.AtRemapper;
import net.fabricmc.loom.util.srg.CoreModClassRemapper;
import net.fabricmc.loom.util.srg.InnerClassRemapper;
import net.fabricmc.mapping.tree.TinyTree;
import net.fabricmc.tinyremapper.IMappingProvider;
import net.fabricmc.tinyremapper.NonClassCopyMode;
import net.fabricmc.tinyremapper.OutputConsumerPath;
import net.fabricmc.tinyremapper.TinyRemapper;
public class MinecraftMappedProvider extends DependencyProvider {
private static final Map<String, String> JSR_TO_JETBRAINS = new ImmutableMap.Builder<String, String>()
@@ -145,29 +149,57 @@ public class MinecraftMappedProvider extends DependencyProvider {
remapper.readClassPath(libraries);
remapper.prepareClasses();
for (String toM : getExtension().isForge() ? Arrays.asList("named", "intermediary", "srg") : Arrays.asList("named", "intermediary")) {
Path output = "named".equals(toM) ? outputMapped : "srg".equals(toM) ? outputSrg : outputIntermediary;
Path tmpAssets = Files.createTempFile("tmpAssets", null);
Files.deleteIfExists(tmpAssets);
tmpAssets.toFile().deleteOnExit();
getProject().getLogger().lifecycle(":remapping minecraft (TinyRemapper, " + fromM + " -> " + toM + ")");
List<byte[]> inputByteList = new ArrayList<>();
Files.deleteIfExists(output);
try (FileSystemUtil.FileSystemDelegate inputFs = FileSystemUtil.getJarFileSystem(input, false)) {
ThreadingUtils.TaskCompleter taskCompleter = ThreadingUtils.taskCompleter();
try (OutputConsumerPath outputConsumer = new OutputConsumerPath.Builder(output).build()) {
if (getExtension().isForge()) {
outputConsumer.addNonClassFiles(input, NonClassCopyMode.FIX_META_INF, remapper);
} else {
outputConsumer.addNonClassFiles(input);
try (FileSystemUtil.FileSystemDelegate assetsFs = FileSystemUtil.getJarFileSystem(tmpAssets, true)) {
for (Path path : (Iterable<? extends Path>) Files.walk(inputFs.get().getPath("/"))::iterator) {
if (Files.isRegularFile(path)) {
if (path.getFileName().toString().endsWith(".class")) {
taskCompleter.add(() -> {
byte[] bytes = Files.readAllBytes(path);
synchronized (inputByteList) {
inputByteList.add(bytes);
}
});
} else {
Path p = assetsFs.get().getPath(path.toString());
if (p.getParent() != null) {
Files.createDirectories(p.getParent());
}
taskCompleter.add(() -> {
Files.copy(path, p);
});
}
}
}
remapper.replaceMappings(getMappings(input, fromM, toM));
remapper.readInputs(input);
remapper.apply(outputConsumer);
} catch (Exception e) {
Files.deleteIfExists(output);
throw new RuntimeException("Failed to remap JAR " + input + " with mappings from " + mappingsProvider.tinyMappings, e);
} finally {
remapper.removeInput();
taskCompleter.complete();
}
}
byte[][] inputBytes = inputByteList.toArray(new byte[0][0]);
for (String toM : getExtension().isForge() ? Arrays.asList("intermediary", "srg", "named") : Arrays.asList("intermediary", "named")) {
Path output = "named".equals(toM) ? outputMapped : "srg".equals(toM) ? outputSrg : outputIntermediary;
Stopwatch stopwatch = Stopwatch.createStarted();
getProject().getLogger().lifecycle(":remapping minecraft (TinyRemapper, " + fromM + " -> " + toM + ")");
remapper.readInputs(inputBytes);
remapper.replaceMappings(getMappings(input, fromM, toM));
OutputRemappingHandler.remap(remapper, tmpAssets, output);
getProject().getLogger().lifecycle(":remapped minecraft (TinyRemapper, " + fromM + " -> " + toM + ") in " + stopwatch);
remapper.removeInput();
if (getExtension().isForge() && !"srg".equals(toM)) {
getProject().getLogger().info(":running forge finalising tasks");

View File

@@ -0,0 +1,18 @@
package net.fabricmc.loom.configuration.providers.minecraft.tr;
import org.cadixdev.mercury.Mercury;
public class MercuryUtils {
public static Mercury copyMercury(Mercury mercury) {
Mercury copy = new Mercury();
copy.getClassPath().addAll(mercury.getClassPath());
copy.getContext().putAll(mercury.getContext());
copy.getProcessors().addAll(mercury.getProcessors());
copy.setEncoding(mercury.getEncoding());
copy.setFlexibleAnonymousClassMemberLookups(mercury.isFlexibleAnonymousClassMemberLookups());
copy.setGracefulClasspathChecks(mercury.isGracefulClasspathChecks());
copy.setGracefulJavadocClasspathChecks(mercury.isGracefulJavadocClasspathChecks());
copy.setSourceCompatibility(mercury.getSourceCompatibility());
return copy;
}
}

View File

@@ -0,0 +1,58 @@
package net.fabricmc.loom.configuration.providers.minecraft.tr;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
import java.nio.file.StandardOpenOption;
import java.util.function.BiConsumer;
import dev.architectury.tinyremapper.InputTag;
import dev.architectury.tinyremapper.TinyRemapper;
import net.fabricmc.loom.util.FileSystemUtil;
import net.fabricmc.loom.util.FileSystemUtil.FileSystemDelegate;
import net.fabricmc.loom.util.ThreadingUtils;
public class OutputRemappingHandler {
public static void remap(TinyRemapper remapper, Path assets, Path output) throws IOException {
remap(remapper, assets, output, null);
}
public static void remap(TinyRemapper remapper, Path assets, Path output, BiConsumer<String, byte[]> then) throws IOException {
remap(remapper, assets, output, then, (InputTag[]) null);
}
public static void remap(TinyRemapper remapper, Path assets, Path output, BiConsumer<String, byte[]> then, InputTag... inputTags) throws IOException {
Files.copy(assets, output, StandardCopyOption.REPLACE_EXISTING);
try (FileSystemDelegate system = FileSystemUtil.getJarFileSystem(output, true)) {
ThreadingUtils.TaskCompleter taskCompleter = ThreadingUtils.taskCompleter();
remapper.apply((path, bytes) -> {
if (path.startsWith("/")) path = path.substring(1);
try {
Path fsPath = system.get().getPath(path + ".class");
if (fsPath.getParent() != null) {
Files.createDirectories(fsPath.getParent());
}
taskCompleter.add(() -> {
Files.write(fsPath, bytes, StandardOpenOption.CREATE);
});
if (then != null) {
then.accept(path, bytes);
}
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}, inputTags);
taskCompleter.complete();
}
}
}

View File

@@ -28,10 +28,11 @@ import org.gradle.api.DefaultTask;
import org.gradle.api.tasks.Internal;
import net.fabricmc.loom.LoomGradleExtension;
import net.fabricmc.loom.util.Constants;
public abstract class AbstractLoomTask extends DefaultTask {
public AbstractLoomTask() {
setGroup("fabric");
setGroup(Constants.TASK_CATEGORY);
}
@Internal

View File

@@ -35,13 +35,14 @@ import org.gradle.api.Project;
import org.gradle.api.tasks.JavaExec;
import net.fabricmc.loom.configuration.ide.RunConfig;
import net.fabricmc.loom.util.Constants;
public abstract class AbstractRunTask extends JavaExec {
private final RunConfig config;
public AbstractRunTask(Function<Project, RunConfig> configProvider) {
super();
setGroup("fabric");
setGroup(Constants.TASK_CATEGORY);
this.config = configProvider.apply(getProject());
setClasspath(config.sourceSet.getRuntimeClasspath());

View File

@@ -56,7 +56,6 @@ public class GenerateSourcesTask extends AbstractLoomTask {
public GenerateSourcesTask(LoomDecompiler decompiler) {
this.decompiler = decompiler;
setGroup("fabric");
getOutputs().upToDateWhen((o) -> false);
}

View File

@@ -35,6 +35,7 @@ import net.fabricmc.loom.api.decompilers.LoomDecompiler;
import net.fabricmc.loom.configuration.ide.RunConfigSettings;
import net.fabricmc.loom.configuration.providers.mappings.MappingsProvider;
import net.fabricmc.loom.decompilers.fernflower.FabricFernFlowerDecompiler;
import net.fabricmc.loom.util.Constants;
public final class LoomTasks {
private LoomTasks() {
@@ -50,7 +51,7 @@ public final class LoomTasks {
tasks.register("remapJar", RemapJarTask.class, t -> {
t.setDescription("Remaps the built project jar to intermediary mappings.");
t.setGroup("fabric");
t.setGroup(Constants.TASK_CATEGORY);
});
tasks.register("downloadAssets", DownloadAssetsTask.class, t -> t.setDescription("Downloads required assets for Fabric."));
@@ -97,7 +98,6 @@ public final class LoomTasks {
tasks.register(taskName, RunGameTask.class, config).configure(t -> {
t.setDescription("Starts the '" + config.getConfigName() + "' run configuration");
t.setGroup("fabric");
if (config.getEnvironment().equals("client")) {
t.dependsOn("downloadAssets");

View File

@@ -39,21 +39,24 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableMap;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonObject;
import me.shedaniel.architectury.refmapremapper.RefmapRemapper;
import me.shedaniel.architectury.refmapremapper.remapper.MappingsRemapper;
import me.shedaniel.architectury.refmapremapper.remapper.ReferenceRemapper;
import me.shedaniel.architectury.refmapremapper.remapper.Remapper;
import me.shedaniel.architectury.refmapremapper.remapper.SimpleReferenceRemapper;
import dev.architectury.refmapremapper.RefmapRemapper;
import dev.architectury.refmapremapper.remapper.MappingsRemapper;
import dev.architectury.refmapremapper.remapper.ReferenceRemapper;
import dev.architectury.refmapremapper.remapper.Remapper;
import dev.architectury.refmapremapper.remapper.SimpleReferenceRemapper;
import dev.architectury.tinyremapper.IMappingProvider;
import dev.architectury.tinyremapper.TinyRemapper;
import dev.architectury.tinyremapper.TinyUtils;
import org.gradle.api.Action;
import org.gradle.api.Project;
import org.gradle.api.artifacts.Configuration;
@@ -72,27 +75,23 @@ import net.fabricmc.loom.LoomGradleExtension;
import net.fabricmc.loom.build.JarRemapper;
import net.fabricmc.loom.build.MixinRefmapHelper;
import net.fabricmc.loom.build.nesting.EmptyNestedJarProvider;
import net.fabricmc.loom.build.nesting.NestedJarPathProvider;
import net.fabricmc.loom.build.nesting.JarNester;
import net.fabricmc.loom.build.nesting.MergedNestedJarProvider;
import net.fabricmc.loom.build.nesting.NestedDependencyProvider;
import net.fabricmc.loom.build.nesting.NestedJarPathProvider;
import net.fabricmc.loom.build.nesting.NestedJarProvider;
import net.fabricmc.loom.configuration.accesswidener.AccessWidenerJarProcessor;
import net.fabricmc.loom.configuration.providers.mappings.MappingsProvider;
import net.fabricmc.loom.util.Constants;
import net.fabricmc.loom.util.SourceRemapper;
import net.fabricmc.loom.util.TinyRemapperMappingsHelper;
import net.fabricmc.loom.util.gradle.GradleSupport;
import net.fabricmc.loom.util.ZipReprocessorUtil;
import net.fabricmc.loom.util.gradle.GradleSupport;
import net.fabricmc.mapping.tree.ClassDef;
import net.fabricmc.mapping.tree.FieldDef;
import net.fabricmc.mapping.tree.MethodDef;
import net.fabricmc.mapping.tree.TinyTree;
import net.fabricmc.stitch.util.Pair;
import net.fabricmc.tinyremapper.IMappingProvider;
import net.fabricmc.tinyremapper.OutputConsumerPath;
import net.fabricmc.tinyremapper.TinyRemapper;
import net.fabricmc.tinyremapper.TinyUtils;
public class RemapJarTask extends Jar {
private final RegularFileProperty input;

View File

@@ -34,12 +34,13 @@ import net.fabricmc.loom.configuration.RemappedConfigurationEntry;
import net.fabricmc.loom.util.gradle.GradleSupport;
public class Constants {
public static final String PLUGIN_ID = "forgified-fabric-loom";
public static final String PLUGIN_ID = "dev.architectury.loom";
public static final String LIBRARIES_BASE = "https://libraries.minecraft.net/";
public static final String RESOURCES_BASE = "http://resources.download.minecraft.net/";
public static final String VERSION_MANIFESTS = "https://launchermeta.mojang.com/mc/game/version_manifest_v2.json";
public static final String SYSTEM_ARCH = System.getProperty("os.arch").equals("64") ? "64" : "32";
public static final String TASK_CATEGORY = "loom";
public static final int ASM_VERSION = Opcodes.ASM9;

View File

@@ -33,6 +33,7 @@ import java.util.List;
import java.util.Set;
import java.util.function.Consumer;
import com.google.common.base.Stopwatch;
import org.cadixdev.lorenz.MappingSet;
import org.cadixdev.mercury.Mercury;
import org.cadixdev.mercury.remapper.MercuryRemapper;
@@ -45,7 +46,7 @@ import net.fabricmc.loom.LoomGradleExtension;
import net.fabricmc.loom.configuration.RemappedConfigurationEntry;
import net.fabricmc.loom.configuration.providers.LaunchProvider;
import net.fabricmc.loom.configuration.providers.mappings.MappingsProvider;
import net.fabricmc.loom.util.gradle.ProgressLogger;
import net.fabricmc.loom.configuration.providers.minecraft.tr.MercuryUtils;
import net.fabricmc.lorenztiny.TinyMappingsReader;
import net.fabricmc.mapping.tree.TinyTree;
import net.fabricmc.stitch.util.StitchUtil;
@@ -54,7 +55,7 @@ public class SourceRemapper {
private final Project project;
private String from;
private String to;
private final List<Consumer<ProgressLogger>> remapTasks = new ArrayList<>();
private final List<Consumer<Mercury>> remapTasks = new ArrayList<>();
private Mercury mercury;
@@ -80,10 +81,9 @@ public class SourceRemapper {
}
public void scheduleRemapSources(File source, File destination, boolean reproducibleFileOrder, boolean preserveFileTimestamps) {
remapTasks.add((logger) -> {
remapTasks.add((mercury) -> {
try {
logger.progress("remapping sources - " + source.getName());
remapSourcesInner(source, destination);
remapSourcesInner(mercury, source, destination);
ZipReprocessorUtil.reprocessZip(destination, reproducibleFileOrder, preserveFileTimestamps);
// Set the remapped sources creation date to match the sources if we're likely succeeded in making it
@@ -101,22 +101,21 @@ public class SourceRemapper {
return;
}
project.getLogger().lifecycle(":remapping sources");
Stopwatch stopwatch = Stopwatch.createStarted();
project.getLogger().lifecycle(":remapping " + remapTasks.size() + " sources");
ProgressLogger progressLogger = ProgressLogger.getProgressFactory(project, SourceRemapper.class.getName());
progressLogger.start("Remapping dependency sources", "sources");
Mercury mercury = getMercuryInstance();
ThreadingUtils.run(remapTasks, consumer -> consumer.accept(MercuryUtils.copyMercury(mercury)));
remapTasks.forEach(consumer -> consumer.accept(progressLogger));
progressLogger.completed();
project.getLogger().lifecycle(":remapped " + remapTasks.size() + " sources in " + stopwatch.stop());
// TODO: FIXME - WORKAROUND https://github.com/FabricMC/fabric-loom/issues/45
System.gc();
}
private void remapSourcesInner(File source, File destination) throws Exception {
private void remapSourcesInner(Mercury mercury, File source, File destination) throws Exception {
Stopwatch stopwatch = Stopwatch.createStarted();
project.getLogger().info(":remapping source jar " + source.getName() + " from " + from + " to " + to);
Mercury mercury = getMercuryInstance();
if (source.equals(destination)) {
if (source.isDirectory()) {
@@ -166,6 +165,8 @@ public class SourceRemapper {
if (isSrcTmp) {
Files.walkFileTree(srcPath, new DeletingFileVisitor());
}
project.getLogger().info(":remapped source jar " + source.getName() + " from " + from + " to " + to + " in " + stopwatch.stop());
}
private Mercury getMercuryInstance() {

View File

@@ -29,13 +29,17 @@ import java.util.Arrays;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.stream.Collectors;
import com.google.common.base.Stopwatch;
public class ThreadingUtils {
public static <T> void run(Collection<T> values, UnsafeConsumer<T> action) {
run(values.stream()
@@ -121,4 +125,56 @@ public class ThreadingUtils {
public interface UnsafeConsumer<T> {
void accept(T value) throws Throwable;
}
public static TaskCompleter taskCompleter() {
return new TaskCompleter();
}
public static class TaskCompleter implements Function<Throwable, Void> {
Stopwatch stopwatch = Stopwatch.createUnstarted();
List<CompletableFuture<?>> tasks = new ArrayList<>();
ExecutorService service = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
List<Consumer<Stopwatch>> completionListener = new ArrayList<>();
public TaskCompleter add(UnsafeRunnable job) {
if (!stopwatch.isRunning()) {
stopwatch.start();
}
tasks.add(CompletableFuture.runAsync(() -> {
try {
job.run();
} catch (Throwable throwable) {
throw new RuntimeException(throwable);
}
}, service).exceptionally(this));
return this;
}
public TaskCompleter onComplete(Consumer<Stopwatch> consumer) {
completionListener.add(consumer);
return this;
}
public void complete() {
try {
CompletableFuture.allOf(tasks.toArray(new CompletableFuture[0])).exceptionally(this).get();
service.shutdownNow();
stopwatch.stop();
for (Consumer<Stopwatch> consumer : completionListener) {
consumer.accept(stopwatch);
}
} catch (InterruptedException | ExecutionException e) {
throw new RuntimeException(e);
}
}
@Override
public Void apply(Throwable throwable) {
throwable.printStackTrace();
return null;
}
}
}

View File

@@ -24,13 +24,14 @@
package net.fabricmc.loom.util;
import dev.architectury.tinyremapper.IMappingProvider;
import net.fabricmc.mapping.tree.ClassDef;
import net.fabricmc.mapping.tree.FieldDef;
import net.fabricmc.mapping.tree.LocalVariableDef;
import net.fabricmc.mapping.tree.MethodDef;
import net.fabricmc.mapping.tree.ParameterDef;
import net.fabricmc.mapping.tree.TinyTree;
import net.fabricmc.tinyremapper.IMappingProvider;
public class TinyRemapperMappingsHelper {
private TinyRemapperMappingsHelper() { }

View File

@@ -26,17 +26,20 @@ package net.fabricmc.loom.util.srg;
import java.io.IOException;
import java.io.StringReader;
import java.net.URI;
import java.nio.charset.StandardCharsets;
import java.nio.file.FileSystem;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardOpenOption;
import java.util.ArrayList;
import java.util.List;
import java.util.function.UnaryOperator;
import java.util.zip.ZipEntry;
import com.google.common.collect.ImmutableMap;
import org.apache.logging.log4j.util.Strings;
import org.gradle.api.logging.Logger;
import org.zeroturnaround.zip.ZipUtil;
import org.zeroturnaround.zip.transform.StringZipEntryTransformer;
import org.zeroturnaround.zip.transform.ZipEntryTransformerEntry;
import net.fabricmc.loom.util.function.CollectionUtil;
import net.fabricmc.mapping.tree.TinyTree;
@@ -48,10 +51,13 @@ import net.fabricmc.mapping.tree.TinyTree;
*/
public final class AtRemapper {
public static void remap(Logger logger, Path jar, TinyTree mappings) throws IOException {
ZipUtil.transformEntries(jar.toFile(), new ZipEntryTransformerEntry[] {(new ZipEntryTransformerEntry("META-INF/accesstransformer.cfg", new StringZipEntryTransformer() {
@Override
protected String transform(ZipEntry zipEntry, String input) {
String[] lines = input.split("\n");
try (FileSystem fs = FileSystems.newFileSystem(URI.create("jar:" + jar.toUri()), ImmutableMap.of("create", false))) {
Path atPath = fs.getPath("META-INF/accesstransformer.cfg");
if (Files.exists(atPath)) {
String atContent = new String(Files.readAllBytes(atPath), StandardCharsets.UTF_8);
String[] lines = atContent.split("\n");
List<String> output = new ArrayList<>(lines.length);
for (int i = 0; i < lines.length; i++) {
@@ -90,9 +96,9 @@ public final class AtRemapper {
output.add(i, String.join(" ", parts));
}
return String.join("\n", output);
Files.write(atPath, String.join("\n", output).getBytes(StandardCharsets.UTF_8), StandardOpenOption.CREATE);
}
}))});
}
}
private static String remapDescriptor(String original, UnaryOperator<String> classMappings) {

View File

@@ -25,18 +25,19 @@
package net.fabricmc.loom.util.srg;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Iterator;
import java.util.Map;
import java.util.function.BiConsumer;
import java.util.stream.Collectors;
import org.zeroturnaround.zip.ZipUtil;
import dev.architectury.tinyremapper.IMappingProvider;
import net.fabricmc.loom.util.FileSystemUtil;
import net.fabricmc.loom.util.FileSystemUtil.FileSystemDelegate;
import net.fabricmc.mapping.tree.ClassDef;
import net.fabricmc.mapping.tree.TinyTree;
import net.fabricmc.tinyremapper.IMappingProvider;
public class InnerClassRemapper {
public static IMappingProvider of(Path fromJar, TinyTree mappingsWithSrg, String from, String to) throws IOException {
@@ -46,7 +47,7 @@ public class InnerClassRemapper {
}
private static void remapInnerClass(Path fromJar, TinyTree mappingsWithSrg, String from, String to, BiConsumer<String, String> action) {
try (InputStream inputStream = Files.newInputStream(fromJar)) {
try (FileSystemDelegate system = FileSystemUtil.getJarFileSystem(fromJar, false)) {
Map<String, String> availableClasses = mappingsWithSrg.getClasses().stream()
.collect(Collectors.groupingBy(classDef -> classDef.getName(from),
Collectors.<ClassDef, String>reducing(
@@ -55,9 +56,15 @@ public class InnerClassRemapper {
(first, last) -> last
))
);
ZipUtil.iterate(inputStream, (in, zipEntry) -> {
if (!zipEntry.isDirectory() && zipEntry.getName().contains("$") && zipEntry.getName().endsWith(".class")) {
String className = zipEntry.getName().substring(0, zipEntry.getName().length() - 6);
Iterator<Path> iterator = Files.walk(system.get().getPath("/")).iterator();
while (iterator.hasNext()) {
Path path = iterator.next();
String name = path.toString();
if (name.startsWith("/")) name = name.substring(1);
if (!Files.isDirectory(path) && name.contains("$") && name.endsWith(".class")) {
String className = name.substring(0, name.length() - 6);
if (!availableClasses.containsKey(className)) {
String parentName = className.substring(0, className.indexOf('$'));
@@ -70,7 +77,7 @@ public class InnerClassRemapper {
}
}
}
});
}
} catch (IOException e) {
throw new RuntimeException(e);
}

View File

@@ -39,7 +39,8 @@ import java.util.Objects;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import au.com.bytecode.opencsv.CSVReader;
import com.opencsv.CSVReader;
import com.opencsv.exceptions.CsvValidationException;
import org.cadixdev.lorenz.MappingSet;
import org.cadixdev.lorenz.io.srg.tsrg.TSrgReader;
import org.cadixdev.lorenz.model.ClassMapping;
@@ -71,7 +72,12 @@ public class MCPReader {
Map<String, String> intermediaryToMCPMap = createIntermediaryToMCPMap(intermediaryTiny, srgTokens);
Map<String, String[]> intermediaryToDocsMap = new HashMap<>();
Map<String, Map<Integer, String>> intermediaryToParamsMap = new HashMap<>();
injectMcp(mcpJar, intermediaryToMCPMap, intermediaryToDocsMap, intermediaryToParamsMap);
try {
injectMcp(mcpJar, intermediaryToMCPMap, intermediaryToDocsMap, intermediaryToParamsMap);
} catch (CsvValidationException e) {
throw new RuntimeException(e);
}
mergeTokensIntoIntermediary(intermediaryTiny, intermediaryToMCPMap, intermediaryToDocsMap, intermediaryToParamsMap);
return intermediaryTiny;
@@ -186,7 +192,7 @@ public class MCPReader {
}
private void injectMcp(Path mcpJar, Map<String, String> intermediaryToSrgMap, Map<String, String[]> intermediaryToDocsMap, Map<String, Map<Integer, String>> intermediaryToParamsMap)
throws IOException {
throws IOException, CsvValidationException {
Map<String, List<String>> srgToIntermediary = inverseMap(intermediaryToSrgMap);
Map<String, List<String>> simpleSrgToIntermediary = new HashMap<>();
Pattern methodPattern = Pattern.compile("(func_\\d*)_.*");