mirror of
https://github.com/architectury/architectury-loom.git
synced 2026-04-01 21:17:46 -05:00
Move access widener jar processor for new processor API. (#787)
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* This file is part of fabric-loom, licensed under the MIT License (MIT).
|
||||
*
|
||||
* Copyright (c) 2021-2022 FabricMC
|
||||
* Copyright (c) 2021-2023 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
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* This file is part of fabric-loom, licensed under the MIT License (MIT).
|
||||
*
|
||||
* Copyright (c) 2022 FabricMC
|
||||
* Copyright (c) 2022-2023 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
|
||||
@@ -24,5 +24,10 @@
|
||||
|
||||
package net.fabricmc.loom.api.processor;
|
||||
|
||||
import net.fabricmc.loom.api.mappings.layered.MappingsNamespace;
|
||||
import net.fabricmc.loom.util.LazyCloseable;
|
||||
import net.fabricmc.tinyremapper.TinyRemapper;
|
||||
|
||||
public interface MappingProcessorContext {
|
||||
LazyCloseable<TinyRemapper> createRemapper(MappingsNamespace from, MappingsNamespace to);
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* This file is part of fabric-loom, licensed under the MIT License (MIT).
|
||||
*
|
||||
* Copyright (c) 2022 FabricMC
|
||||
* Copyright (c) 2022-2023 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
|
||||
@@ -26,6 +26,7 @@ package net.fabricmc.loom.api.processor;
|
||||
|
||||
import net.fabricmc.loom.api.mappings.layered.MappingsNamespace;
|
||||
import net.fabricmc.loom.configuration.providers.minecraft.MinecraftJarConfiguration;
|
||||
import net.fabricmc.loom.util.LazyCloseable;
|
||||
import net.fabricmc.tinyremapper.TinyRemapper;
|
||||
|
||||
public interface ProcessorContext {
|
||||
@@ -37,5 +38,5 @@ public interface ProcessorContext {
|
||||
|
||||
boolean includesServer();
|
||||
|
||||
TinyRemapper createRemapper(MappingsNamespace from, MappingsNamespace to);
|
||||
LazyCloseable<TinyRemapper> createRemapper(MappingsNamespace from, MappingsNamespace to);
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* This file is part of fabric-loom, licensed under the MIT License (MIT).
|
||||
*
|
||||
* Copyright (c) 2016-2022 FabricMC
|
||||
* Copyright (c) 2016-2023 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
|
||||
@@ -49,7 +49,6 @@ import net.fabricmc.loom.build.mixin.JavaApInvoker;
|
||||
import net.fabricmc.loom.build.mixin.KaptApInvoker;
|
||||
import net.fabricmc.loom.build.mixin.ScalaApInvoker;
|
||||
import net.fabricmc.loom.configuration.accesswidener.AccessWidenerJarProcessor;
|
||||
import net.fabricmc.loom.configuration.accesswidener.TransitiveAccessWidenerJarProcessor;
|
||||
import net.fabricmc.loom.configuration.ifaceinject.InterfaceInjectionProcessor;
|
||||
import net.fabricmc.loom.configuration.processors.MinecraftJarProcessorManager;
|
||||
import net.fabricmc.loom.configuration.processors.ModJavadocProcessor;
|
||||
@@ -221,17 +220,8 @@ public final class CompileConfiguration {
|
||||
private static void registerGameProcessors(ConfigContext configContext) {
|
||||
final LoomGradleExtension extension = configContext.extension();
|
||||
|
||||
if (extension.getAccessWidenerPath().isPresent()) {
|
||||
extension.getGameJarProcessors().add(new AccessWidenerJarProcessor(configContext));
|
||||
}
|
||||
|
||||
if (extension.getEnableTransitiveAccessWideners().get()) {
|
||||
TransitiveAccessWidenerJarProcessor transitiveAccessWidenerJarProcessor = new TransitiveAccessWidenerJarProcessor(configContext);
|
||||
|
||||
if (!transitiveAccessWidenerJarProcessor.isEmpty()) {
|
||||
extension.getGameJarProcessors().add(transitiveAccessWidenerJarProcessor);
|
||||
}
|
||||
}
|
||||
final boolean enableTransitiveAccessWideners = extension.getEnableTransitiveAccessWideners().get();
|
||||
extension.addMinecraftJarProcessor(AccessWidenerJarProcessor.class, "fabric-loom:access-widener", enableTransitiveAccessWideners, extension.getAccessWidenerPath());
|
||||
|
||||
if (extension.getEnableModProvidedJavadoc().get()) {
|
||||
extension.addMinecraftJarProcessor(ModJavadocProcessor.class, "fabric-loom:mod-javadoc");
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* This file is part of fabric-loom, licensed under the MIT License (MIT).
|
||||
*
|
||||
* Copyright (c) 2023 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.configuration.accesswidener;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import net.fabricmc.accesswidener.AccessWidenerVisitor;
|
||||
import net.fabricmc.loom.util.LazyCloseable;
|
||||
import net.fabricmc.loom.util.fmj.ModEnvironment;
|
||||
import net.fabricmc.tinyremapper.TinyRemapper;
|
||||
|
||||
public interface AccessWidenerEntry {
|
||||
ModEnvironment environment();
|
||||
|
||||
/**
|
||||
* @return The mod id to be used in {@link TransitiveAccessWidenerMappingsProcessor} or null when this entry does not contain transitive entries.
|
||||
*/
|
||||
@Nullable
|
||||
String mappingId();
|
||||
|
||||
void read(AccessWidenerVisitor visitor, LazyCloseable<TinyRemapper> remapper) throws IOException;
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* This file is part of fabric-loom, licensed under the MIT License (MIT).
|
||||
*
|
||||
* Copyright (c) 2020-2021 FabricMC
|
||||
* Copyright (c) 2023 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
|
||||
@@ -24,73 +24,118 @@
|
||||
|
||||
package net.fabricmc.loom.configuration.accesswidener;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.UncheckedIOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.NoSuchFileException;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import com.google.common.hash.Hashing;
|
||||
import org.gradle.api.Project;
|
||||
import javax.inject.Inject;
|
||||
|
||||
import org.gradle.api.file.RegularFileProperty;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import net.fabricmc.accesswidener.AccessWidener;
|
||||
import net.fabricmc.accesswidener.AccessWidenerReader;
|
||||
import net.fabricmc.loom.LoomGradleExtension;
|
||||
import net.fabricmc.loom.configuration.ConfigContext;
|
||||
import net.fabricmc.loom.configuration.processors.JarProcessor;
|
||||
import net.fabricmc.loom.util.Checksum;
|
||||
import net.fabricmc.loom.util.ZipUtils;
|
||||
import net.fabricmc.loom.api.mappings.layered.MappingsNamespace;
|
||||
import net.fabricmc.loom.api.processor.MinecraftJarProcessor;
|
||||
import net.fabricmc.loom.api.processor.ProcessorContext;
|
||||
import net.fabricmc.loom.api.processor.SpecContext;
|
||||
import net.fabricmc.loom.util.LazyCloseable;
|
||||
import net.fabricmc.loom.util.fmj.FabricModJson;
|
||||
import net.fabricmc.loom.util.fmj.ModEnvironment;
|
||||
import net.fabricmc.tinyremapper.TinyRemapper;
|
||||
|
||||
public class AccessWidenerJarProcessor implements JarProcessor {
|
||||
// Filename used to store hash of input access widener in processed jar file
|
||||
private static final String HASH_FILENAME = "aw.sha256";
|
||||
private final AccessWidener accessWidener = new AccessWidener();
|
||||
private final Project project;
|
||||
// This is a SHA256 hash across the mod's and all transitive AWs
|
||||
private byte[] inputHash;
|
||||
public class AccessWidenerJarProcessor implements MinecraftJarProcessor<AccessWidenerJarProcessor.Spec> {
|
||||
private final String name;
|
||||
private final boolean includeTransitive;
|
||||
private final RegularFileProperty localAccessWidenerProperty;
|
||||
|
||||
public AccessWidenerJarProcessor(ConfigContext configContext) {
|
||||
this.project = configContext.project();
|
||||
@Inject
|
||||
public AccessWidenerJarProcessor(String name, boolean includeTransitive, RegularFileProperty localAccessWidenerProperty) {
|
||||
this.name = name;
|
||||
this.includeTransitive = includeTransitive;
|
||||
this.localAccessWidenerProperty = localAccessWidenerProperty;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return "loom:access_widener:" + Checksum.toHex(inputHash);
|
||||
}
|
||||
public @Nullable AccessWidenerJarProcessor.Spec buildSpec(SpecContext context) {
|
||||
List<AccessWidenerEntry> accessWideners = new ArrayList<>();
|
||||
|
||||
@Override
|
||||
public void setup() {
|
||||
LoomGradleExtension extension = LoomGradleExtension.get(project);
|
||||
Path awPath = extension.getAccessWidenerPath().get().getAsFile().toPath();
|
||||
|
||||
// Read our own mod's access widener, used later for producing a version remapped to intermediary
|
||||
// The mod's own access widener file
|
||||
byte[] modAccessWidener;
|
||||
|
||||
try {
|
||||
modAccessWidener = Files.readAllBytes(awPath);
|
||||
} catch (NoSuchFileException e) {
|
||||
throw new RuntimeException("Could not find access widener file @ " + awPath.toAbsolutePath());
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException("Failed to read access widener: " + awPath);
|
||||
if (localAccessWidenerProperty.isPresent()) {
|
||||
// Add the access widener specified in the extension
|
||||
accessWideners.add(new LocalAccessWidenerEntry(localAccessWidenerProperty.get().getAsFile().toPath()));
|
||||
}
|
||||
|
||||
AccessWidenerReader reader = new AccessWidenerReader(accessWidener);
|
||||
reader.read(modAccessWidener);
|
||||
/* Uncomment to read all access wideners from local mods.
|
||||
|
||||
inputHash = Hashing.sha256().hashBytes(modAccessWidener).asBytes();
|
||||
for (FabricModJson fabricModJson : context.localMods()) {
|
||||
accessWideners.addAll(ModAccessWidenerEntry.readAll(fabricModJson, false));
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
if (includeTransitive) {
|
||||
for (FabricModJson fabricModJson : context.modDependencies()) {
|
||||
accessWideners.addAll(ModAccessWidenerEntry.readAll(fabricModJson, true));
|
||||
}
|
||||
}
|
||||
|
||||
if (accessWideners.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return new Spec(Collections.unmodifiableList(accessWideners));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void process(File file) {
|
||||
AccessWidenerTransformer applier = new AccessWidenerTransformer(project.getLogger(), accessWidener);
|
||||
applier.apply(file);
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
try {
|
||||
ZipUtils.add(file.toPath(), HASH_FILENAME, inputHash);
|
||||
} catch (IOException e) {
|
||||
throw new UncheckedIOException("Failed to write aw jar hash", e);
|
||||
public record Spec(List<AccessWidenerEntry> accessWideners) implements MinecraftJarProcessor.Spec {
|
||||
List<AccessWidenerEntry> accessWidenersForContext(ProcessorContext context) {
|
||||
return accessWideners.stream()
|
||||
.filter(entry -> isSupported(entry.environment(), context))
|
||||
.toList();
|
||||
}
|
||||
|
||||
private static boolean isSupported(ModEnvironment modEnvironment, ProcessorContext context) {
|
||||
if (context.isMerged()) {
|
||||
// All envs are supported wth a merged jar
|
||||
return true;
|
||||
}
|
||||
|
||||
if (context.includesClient() && modEnvironment.isClient()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (context.includesServer() && modEnvironment.isServer()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Universal supports all jars
|
||||
return modEnvironment == ModEnvironment.UNIVERSAL;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processJar(Path jar, AccessWidenerJarProcessor.Spec spec, ProcessorContext context) throws IOException {
|
||||
final List<AccessWidenerEntry> accessWideners = spec.accessWidenersForContext(context);
|
||||
|
||||
final var accessWidener = new AccessWidener();
|
||||
|
||||
try (LazyCloseable<TinyRemapper> remapper = context.createRemapper(MappingsNamespace.INTERMEDIARY, MappingsNamespace.NAMED)) {
|
||||
for (AccessWidenerEntry widener : accessWideners) {
|
||||
widener.read(accessWidener, remapper);
|
||||
}
|
||||
}
|
||||
|
||||
AccessWidenerTransformer transformer = new AccessWidenerTransformer(accessWidener);
|
||||
transformer.apply(jar);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable MappingsProcessor<Spec> processMappings() {
|
||||
return TransitiveAccessWidenerMappingsProcessor.INSTANCE;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,17 +24,18 @@
|
||||
|
||||
package net.fabricmc.loom.configuration.accesswidener;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.UncheckedIOException;
|
||||
import java.nio.file.Path;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.gradle.api.logging.Logger;
|
||||
import org.objectweb.asm.ClassReader;
|
||||
import org.objectweb.asm.ClassVisitor;
|
||||
import org.objectweb.asm.ClassWriter;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import net.fabricmc.accesswidener.AccessWidener;
|
||||
import net.fabricmc.accesswidener.AccessWidenerClassVisitor;
|
||||
@@ -43,20 +44,20 @@ import net.fabricmc.loom.util.Pair;
|
||||
import net.fabricmc.loom.util.ZipUtils;
|
||||
|
||||
final class AccessWidenerTransformer {
|
||||
private final Logger logger;
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(AccessWidenerTransformer.class);
|
||||
|
||||
private final AccessWidener accessWidener;
|
||||
|
||||
AccessWidenerTransformer(Logger logger, AccessWidener accessWidener) {
|
||||
this.logger = logger;
|
||||
AccessWidenerTransformer(AccessWidener accessWidener) {
|
||||
this.accessWidener = accessWidener;
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply the rules from an access-widener to the given jar or zip file.
|
||||
*/
|
||||
void apply(File jarFile) {
|
||||
void apply(Path jarFile) {
|
||||
try {
|
||||
ZipUtils.transform(jarFile.toPath(), getTransformers(accessWidener.getTargets()));
|
||||
ZipUtils.transform(jarFile, getTransformers(accessWidener.getTargets()));
|
||||
} catch (IOException e) {
|
||||
throw new UncheckedIOException("Failed to apply access wideners to %s".formatted(jarFile), e);
|
||||
}
|
||||
@@ -74,7 +75,7 @@ final class AccessWidenerTransformer {
|
||||
ClassWriter writer = new ClassWriter(0);
|
||||
ClassVisitor classVisitor = AccessWidenerClassVisitor.createClassVisitor(Constants.ASM_VERSION, writer, accessWidener);
|
||||
|
||||
logger.info("Applying access widener to " + className);
|
||||
LOGGER.debug("Applying access widener to " + className);
|
||||
|
||||
reader.accept(classVisitor, 0);
|
||||
return writer.toByteArray();
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* This file is part of fabric-loom, licensed under the MIT License (MIT).
|
||||
*
|
||||
* Copyright (c) 2023 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.configuration.accesswidener;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import net.fabricmc.accesswidener.AccessWidenerReader;
|
||||
import net.fabricmc.accesswidener.AccessWidenerVisitor;
|
||||
import net.fabricmc.loom.util.LazyCloseable;
|
||||
import net.fabricmc.loom.util.fmj.ModEnvironment;
|
||||
import net.fabricmc.tinyremapper.TinyRemapper;
|
||||
|
||||
public record LocalAccessWidenerEntry(Path path) implements AccessWidenerEntry {
|
||||
@Override
|
||||
public void read(AccessWidenerVisitor visitor, LazyCloseable<TinyRemapper> remapper) throws IOException {
|
||||
var reader = new AccessWidenerReader(visitor);
|
||||
reader.read(Files.readAllBytes(path));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ModEnvironment environment() {
|
||||
return ModEnvironment.UNIVERSAL;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable String mappingId() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
* This file is part of fabric-loom, licensed under the MIT License (MIT).
|
||||
*
|
||||
* Copyright (c) 2023 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.configuration.accesswidener;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import net.fabricmc.accesswidener.AccessWidenerReader;
|
||||
import net.fabricmc.accesswidener.AccessWidenerRemapper;
|
||||
import net.fabricmc.accesswidener.AccessWidenerVisitor;
|
||||
import net.fabricmc.accesswidener.TransitiveOnlyFilter;
|
||||
import net.fabricmc.loom.api.mappings.layered.MappingsNamespace;
|
||||
import net.fabricmc.loom.util.LazyCloseable;
|
||||
import net.fabricmc.loom.util.fmj.FabricModJson;
|
||||
import net.fabricmc.loom.util.fmj.ModEnvironment;
|
||||
import net.fabricmc.tinyremapper.TinyRemapper;
|
||||
|
||||
/**
|
||||
* {@link AccessWidenerEntry} implementation for a {@link FabricModJson}.
|
||||
*/
|
||||
public record ModAccessWidenerEntry(FabricModJson mod, String path, ModEnvironment environment, boolean transitiveOnly) implements AccessWidenerEntry {
|
||||
public static List<ModAccessWidenerEntry> readAll(FabricModJson modJson, boolean transitiveOnly) {
|
||||
var entries = new ArrayList<ModAccessWidenerEntry>();
|
||||
|
||||
for (Map.Entry<String, ModEnvironment> entry : modJson.getClassTweakers().entrySet()) {
|
||||
entries.add(new ModAccessWidenerEntry(modJson, entry.getKey(), entry.getValue(), transitiveOnly));
|
||||
}
|
||||
|
||||
return Collections.unmodifiableList(entries);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable String mappingId() {
|
||||
return transitiveOnly ? mod.getId() : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void read(AccessWidenerVisitor visitor, LazyCloseable<TinyRemapper> remapper) throws IOException {
|
||||
if (transitiveOnly) {
|
||||
// Filter for only transitive rules
|
||||
visitor = new TransitiveOnlyFilter(visitor);
|
||||
}
|
||||
|
||||
final byte[] data = readRaw();
|
||||
final AccessWidenerReader.Header header = AccessWidenerReader.readHeader(data);
|
||||
|
||||
if (!header.getNamespace().equals(MappingsNamespace.NAMED.toString())) {
|
||||
// Remap the AW if needed
|
||||
visitor = getRemapper(visitor, remapper.get());
|
||||
}
|
||||
|
||||
var reader = new AccessWidenerReader(visitor);
|
||||
reader.read(data);
|
||||
}
|
||||
|
||||
private static AccessWidenerRemapper getRemapper(AccessWidenerVisitor visitor, TinyRemapper tinyRemapper) {
|
||||
return new AccessWidenerRemapper(
|
||||
visitor,
|
||||
tinyRemapper.getEnvironment().getRemapper(),
|
||||
MappingsNamespace.INTERMEDIARY.toString(),
|
||||
MappingsNamespace.NAMED.toString()
|
||||
);
|
||||
}
|
||||
|
||||
private byte[] readRaw() throws IOException {
|
||||
return mod.getSource().read(path);
|
||||
}
|
||||
}
|
||||
@@ -1,221 +0,0 @@
|
||||
/*
|
||||
* This file is part of fabric-loom, licensed under the MIT License (MIT).
|
||||
*
|
||||
* Copyright (c) 2020-2021 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.configuration.accesswidener;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import org.gradle.api.Project;
|
||||
import org.gradle.api.artifacts.Configuration;
|
||||
import org.gradle.api.artifacts.FileCollectionDependency;
|
||||
import org.gradle.api.artifacts.ResolvedArtifact;
|
||||
import org.gradle.api.file.FileCollection;
|
||||
|
||||
import net.fabricmc.accesswidener.AccessWidener;
|
||||
import net.fabricmc.accesswidener.AccessWidenerReader;
|
||||
import net.fabricmc.accesswidener.AccessWidenerRemapper;
|
||||
import net.fabricmc.accesswidener.AccessWidenerVisitor;
|
||||
import net.fabricmc.accesswidener.TransitiveOnlyFilter;
|
||||
import net.fabricmc.loom.LoomGradleExtension;
|
||||
import net.fabricmc.loom.api.RemapConfigurationSettings;
|
||||
import net.fabricmc.loom.api.mappings.layered.MappingsNamespace;
|
||||
import net.fabricmc.loom.configuration.ConfigContext;
|
||||
import net.fabricmc.loom.configuration.processors.JarProcessor;
|
||||
import net.fabricmc.loom.util.TinyRemapperHelper;
|
||||
import net.fabricmc.tinyremapper.TinyRemapper;
|
||||
|
||||
/**
|
||||
* Applies transitive access wideners that are inherited from mod and api dependencies.
|
||||
*/
|
||||
public class TransitiveAccessWidenerJarProcessor implements JarProcessor {
|
||||
private final ConfigContext configContext;
|
||||
private final Project project;
|
||||
private final LoomGradleExtension extension;
|
||||
|
||||
private final List<AccessWidenerFile> transitiveAccessWideners;
|
||||
|
||||
public TransitiveAccessWidenerJarProcessor(ConfigContext configContext) {
|
||||
this.configContext = configContext;
|
||||
this.project = configContext.project();
|
||||
this.extension = configContext.extension();
|
||||
|
||||
transitiveAccessWideners = getTransitiveAccessWideners();
|
||||
|
||||
extension.addTransitiveAccessWideners(transitiveAccessWideners);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setup() {
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
return transitiveAccessWideners.isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
Preconditions.checkArgument(!isEmpty());
|
||||
|
||||
return "loom:transitive_access_wideners:" + transitiveAccessWideners.hashCode();
|
||||
}
|
||||
|
||||
private List<AccessWidenerFile> getTransitiveAccessWideners() {
|
||||
final List<AccessWidenerFile> accessWideners = new ArrayList<>();
|
||||
final Set<Path> possibleModJars = new HashSet<>();
|
||||
|
||||
// Only apply global AWs from mods that are part of the compile classpath
|
||||
for (RemapConfigurationSettings entry : extension.getCompileRemapConfigurations()) {
|
||||
final Configuration configuration = entry.getSourceConfiguration().get();
|
||||
|
||||
// Based off the logic in ModCompileRemapper.
|
||||
for (ResolvedArtifact artifact : configuration.getResolvedConfiguration().getResolvedArtifacts()) {
|
||||
possibleModJars.add(artifact.getFile().toPath());
|
||||
}
|
||||
|
||||
for (FileCollectionDependency dependency : configuration.getAllDependencies().withType(FileCollectionDependency.class)) {
|
||||
FileCollection files = dependency.getFiles();
|
||||
|
||||
for (File artifact : files) {
|
||||
possibleModJars.add(artifact.toPath());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (Path path : possibleModJars) {
|
||||
if (!Files.exists(path)) {
|
||||
project.getLogger().debug("Could not find transitive access widener in {} as it does not exist", path.toAbsolutePath());
|
||||
continue;
|
||||
}
|
||||
|
||||
AccessWidenerFile accessWidener = AccessWidenerFile.fromModJar(path);
|
||||
|
||||
if (accessWidener == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!TransitiveDetectorVisitor.isTransitive(accessWidener.content())) {
|
||||
// AW does not contain anything transitive, skip over it
|
||||
continue;
|
||||
}
|
||||
|
||||
accessWideners.add(accessWidener);
|
||||
}
|
||||
|
||||
return accessWideners;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void process(File file) {
|
||||
Preconditions.checkArgument(!isEmpty());
|
||||
|
||||
AccessWidener accessWidener = createAccessWidener();
|
||||
AccessWidenerTransformer transformer = new AccessWidenerTransformer(project.getLogger(), accessWidener);
|
||||
transformer.apply(file);
|
||||
}
|
||||
|
||||
private AccessWidener createAccessWidener() {
|
||||
AccessWidener accessWidener = new AccessWidener();
|
||||
// For other mods, only consider transitive AWs and remap from intermediary->named
|
||||
TinyRemapper tinyRemapper = createTinyRemapper();
|
||||
|
||||
try {
|
||||
AccessWidenerRemapper remappingVisitor = new AccessWidenerRemapper(
|
||||
accessWidener,
|
||||
tinyRemapper.getEnvironment().getRemapper(),
|
||||
MappingsNamespace.INTERMEDIARY.toString(),
|
||||
MappingsNamespace.NAMED.toString()
|
||||
);
|
||||
AccessWidenerReader transitiveReader = new AccessWidenerReader(new TransitiveOnlyFilter(remappingVisitor));
|
||||
|
||||
for (AccessWidenerFile accessWidenerFile : transitiveAccessWideners) {
|
||||
project.getLogger().info("Reading transitive access widener from {}", accessWidenerFile.modId());
|
||||
transitiveReader.read(accessWidenerFile.content());
|
||||
}
|
||||
} finally {
|
||||
tinyRemapper.finish();
|
||||
}
|
||||
|
||||
return accessWidener;
|
||||
}
|
||||
|
||||
private TinyRemapper createTinyRemapper() {
|
||||
try {
|
||||
TinyRemapper tinyRemapper = TinyRemapperHelper.getTinyRemapper(project, configContext.serviceManager(), "intermediary", "named");
|
||||
|
||||
tinyRemapper.readClassPath(TinyRemapperHelper.getMinecraftDependencies(project));
|
||||
|
||||
for (Path minecraftJar : extension.getMinecraftJars(MappingsNamespace.INTERMEDIARY)) {
|
||||
tinyRemapper.readClassPath(minecraftJar);
|
||||
}
|
||||
|
||||
return tinyRemapper;
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException("Failed to create tiny remapper for intermediary->named", e);
|
||||
}
|
||||
}
|
||||
|
||||
private static class TransitiveDetectorVisitor implements AccessWidenerVisitor {
|
||||
private boolean transitive = false;
|
||||
|
||||
@Override
|
||||
public void visitClass(String name, AccessWidenerReader.AccessType access, boolean transitive) {
|
||||
if (transitive) {
|
||||
this.transitive = true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitMethod(String owner, String name, String descriptor, AccessWidenerReader.AccessType access, boolean transitive) {
|
||||
if (transitive) {
|
||||
this.transitive = true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitField(String owner, String name, String descriptor, AccessWidenerReader.AccessType access, boolean transitive) {
|
||||
if (transitive) {
|
||||
this.transitive = true;
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isTransitive(byte[] content) {
|
||||
if (AccessWidenerReader.readVersion(content) < 2) {
|
||||
// Transitive AWs are only in v2 or higher, so we can save parsing the file to find out...
|
||||
return false;
|
||||
}
|
||||
|
||||
TransitiveDetectorVisitor transitiveDetector = new TransitiveDetectorVisitor();
|
||||
new AccessWidenerReader(transitiveDetector).read(content);
|
||||
return transitiveDetector.transitive;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* This file is part of fabric-loom, licensed under the MIT License (MIT).
|
||||
*
|
||||
* Copyright (c) 2021-2022 FabricMC
|
||||
* Copyright (c) 2021-2023 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
|
||||
@@ -24,25 +24,34 @@
|
||||
|
||||
package net.fabricmc.loom.configuration.accesswidener;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.UncheckedIOException;
|
||||
import java.util.List;
|
||||
|
||||
import org.gradle.api.Project;
|
||||
import org.gradle.api.logging.Logger;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import net.fabricmc.accesswidener.AccessWidenerReader;
|
||||
import net.fabricmc.accesswidener.AccessWidenerVisitor;
|
||||
import net.fabricmc.accesswidener.TransitiveOnlyFilter;
|
||||
import net.fabricmc.loom.LoomGradleExtension;
|
||||
import net.fabricmc.loom.api.mappings.layered.MappingsNamespace;
|
||||
import net.fabricmc.loom.task.GenerateSourcesTask;
|
||||
import net.fabricmc.loom.api.processor.MappingProcessorContext;
|
||||
import net.fabricmc.loom.api.processor.MinecraftJarProcessor;
|
||||
import net.fabricmc.loom.util.LazyCloseable;
|
||||
import net.fabricmc.mappingio.tree.MappingTree;
|
||||
import net.fabricmc.mappingio.tree.MemoryMappingTree;
|
||||
import net.fabricmc.tinyremapper.TinyRemapper;
|
||||
|
||||
public final class TransitiveAccessWidenerMappingsProcessor implements MinecraftJarProcessor.MappingsProcessor<AccessWidenerJarProcessor.Spec> {
|
||||
public static final TransitiveAccessWidenerMappingsProcessor INSTANCE = new TransitiveAccessWidenerMappingsProcessor();
|
||||
|
||||
private TransitiveAccessWidenerMappingsProcessor() {
|
||||
}
|
||||
|
||||
public record TransitiveAccessWidenerMappingsProcessor(Project project) implements GenerateSourcesTask.MappingsProcessor {
|
||||
@Override
|
||||
public boolean transform(MemoryMappingTree mappings) {
|
||||
final LoomGradleExtension extension = LoomGradleExtension.get(project);
|
||||
List<AccessWidenerFile> accessWideners = extension.getTransitiveAccessWideners();
|
||||
public boolean transform(MemoryMappingTree mappings, AccessWidenerJarProcessor.Spec spec, MappingProcessorContext context) {
|
||||
final List<AccessWidenerEntry> accessWideners = spec.accessWideners().stream()
|
||||
.filter(entry -> entry.mappingId() != null)
|
||||
.toList();
|
||||
|
||||
if (accessWideners.isEmpty()) {
|
||||
return false;
|
||||
@@ -52,22 +61,27 @@ public record TransitiveAccessWidenerMappingsProcessor(Project project) implemen
|
||||
throw new IllegalStateException("Mapping tree must have intermediary src mappings not " + mappings.getSrcNamespace());
|
||||
}
|
||||
|
||||
for (AccessWidenerFile accessWidener : accessWideners) {
|
||||
MappingCommentVisitor mappingCommentVisitor = new MappingCommentVisitor(accessWidener.modId(), mappings, project.getLogger());
|
||||
AccessWidenerReader accessWidenerReader = new AccessWidenerReader(new TransitiveOnlyFilter(mappingCommentVisitor));
|
||||
accessWidenerReader.read(accessWidener.content());
|
||||
try (LazyCloseable<TinyRemapper> remapper = context.createRemapper(MappingsNamespace.INTERMEDIARY, MappingsNamespace.NAMED)) {
|
||||
for (AccessWidenerEntry accessWidener : accessWideners) {
|
||||
var visitor = new MappingCommentVisitor(accessWidener.mappingId(), mappings);
|
||||
accessWidener.read(visitor, remapper);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new UncheckedIOException("Failed to transform access widener mappings", e);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private record MappingCommentVisitor(String modId, MemoryMappingTree mappingTree, Logger logger) implements AccessWidenerVisitor {
|
||||
private record MappingCommentVisitor(String modId, MemoryMappingTree mappingTree) implements AccessWidenerVisitor {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(MappingCommentVisitor.class);
|
||||
|
||||
@Override
|
||||
public void visitClass(String name, AccessWidenerReader.AccessType access, boolean transitive) {
|
||||
MappingTree.ClassMapping classMapping = mappingTree.getClass(name);
|
||||
|
||||
if (classMapping == null) {
|
||||
logger.info("Failed to find class ({}) to mark access widened by mod ({})", name, modId());
|
||||
LOGGER.info("Failed to find class ({}) to mark access widened by mod ({})", name, modId());
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -82,14 +96,14 @@ public record TransitiveAccessWidenerMappingsProcessor(Project project) implemen
|
||||
MappingTree.ClassMapping classMapping = mappingTree.getClass(owner);
|
||||
|
||||
if (classMapping == null) {
|
||||
logger.info("Failed to find class ({}) to mark access widened by mod ({})", owner, modId());
|
||||
LOGGER.info("Failed to find class ({}) to mark access widened by mod ({})", owner, modId());
|
||||
return;
|
||||
}
|
||||
|
||||
MappingTree.MethodMapping methodMapping = classMapping.getMethod(name, descriptor);
|
||||
|
||||
if (methodMapping == null) {
|
||||
logger.info("Failed to find method ({}) in ({}) to mark access widened by mod ({})", name, owner, modId());
|
||||
LOGGER.info("Failed to find method ({}) in ({}) to mark access widened by mod ({})", name, owner, modId());
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -104,14 +118,14 @@ public record TransitiveAccessWidenerMappingsProcessor(Project project) implemen
|
||||
MappingTree.ClassMapping classMapping = mappingTree.getClass(owner);
|
||||
|
||||
if (classMapping == null) {
|
||||
logger.info("Failed to find class ({}) to mark access widened by mod ({})", name, modId());
|
||||
LOGGER.info("Failed to find class ({}) to mark access widened by mod ({})", name, modId());
|
||||
return;
|
||||
}
|
||||
|
||||
MappingTree.FieldMapping fieldMapping = classMapping.getField(name, descriptor);
|
||||
|
||||
if (fieldMapping == null) {
|
||||
logger.info("Failed to find field ({}) in ({}) to mark access widened by mod ({})", name, owner, modId());
|
||||
LOGGER.info("Failed to find field ({}) in ({}) to mark access widened by mod ({})", name, owner, modId());
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -56,7 +56,6 @@ import net.fabricmc.loom.util.Pair;
|
||||
import net.fabricmc.loom.util.ZipUtils;
|
||||
import net.fabricmc.loom.util.fmj.FabricModJson;
|
||||
import net.fabricmc.mappingio.tree.MappingTree;
|
||||
import net.fabricmc.tinyremapper.TinyRemapper;
|
||||
|
||||
public abstract class InterfaceInjectionProcessor implements MinecraftJarProcessor<InterfaceInjectionProcessor.Spec> {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(InterfaceInjectionProcessor.class);
|
||||
@@ -99,17 +98,15 @@ public abstract class InterfaceInjectionProcessor implements MinecraftJarProcess
|
||||
|
||||
@Override
|
||||
public void processJar(Path jar, Spec spec, ProcessorContext context) throws IOException {
|
||||
// Remap from intermediary->named
|
||||
final TinyRemapper tinyRemapper = context.createRemapper(MappingsNamespace.INTERMEDIARY, MappingsNamespace.NAMED);
|
||||
final Remapper remapper = tinyRemapper.getEnvironment().getRemapper();
|
||||
final List<InjectedInterface> remappedInjectedInterfaces;
|
||||
|
||||
try {
|
||||
// Remap from intermediary->named
|
||||
try (var tinyRemapper = context.createRemapper(MappingsNamespace.INTERMEDIARY, MappingsNamespace.NAMED)) {
|
||||
final Remapper remapper = tinyRemapper.get().getEnvironment().getRemapper();
|
||||
|
||||
remappedInjectedInterfaces = spec.injectedInterfaces().stream()
|
||||
.map(injectedInterface -> remap(injectedInterface, remapper))
|
||||
.toList();
|
||||
} finally {
|
||||
tinyRemapper.finish();
|
||||
}
|
||||
|
||||
try {
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* This file is part of fabric-loom, licensed under the MIT License (MIT).
|
||||
*
|
||||
* Copyright (c) 2022-2023 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.configuration.processors;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.UncheckedIOException;
|
||||
import java.nio.file.Path;
|
||||
|
||||
import net.fabricmc.loom.api.mappings.layered.MappingsNamespace;
|
||||
import net.fabricmc.loom.configuration.ConfigContext;
|
||||
import net.fabricmc.loom.util.LazyCloseable;
|
||||
import net.fabricmc.loom.util.TinyRemapperHelper;
|
||||
import net.fabricmc.tinyremapper.TinyRemapper;
|
||||
|
||||
public final class ContextImplHelper {
|
||||
private ContextImplHelper() {
|
||||
}
|
||||
|
||||
public static LazyCloseable<TinyRemapper> createRemapper(ConfigContext configContext, MappingsNamespace from, MappingsNamespace to) {
|
||||
return new LazyCloseable<>(() -> {
|
||||
try {
|
||||
TinyRemapper tinyRemapper = TinyRemapperHelper.getTinyRemapper(configContext.project(), configContext.serviceManager(), from.toString(), to.toString());
|
||||
tinyRemapper.readClassPath(TinyRemapperHelper.getMinecraftDependencies(configContext.project()));
|
||||
|
||||
for (Path minecraftJar : configContext.extension().getMinecraftJars(MappingsNamespace.INTERMEDIARY)) {
|
||||
tinyRemapper.readClassPath(minecraftJar);
|
||||
}
|
||||
|
||||
return tinyRemapper;
|
||||
} catch (IOException e) {
|
||||
throw new UncheckedIOException("Failed to create tiny remapper", e);
|
||||
}
|
||||
}, TinyRemapper::finish);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* This file is part of fabric-loom, licensed under the MIT License (MIT).
|
||||
*
|
||||
* Copyright (c) 2022-2023 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.configuration.processors;
|
||||
|
||||
import net.fabricmc.loom.api.mappings.layered.MappingsNamespace;
|
||||
import net.fabricmc.loom.api.processor.MappingProcessorContext;
|
||||
import net.fabricmc.loom.configuration.ConfigContext;
|
||||
import net.fabricmc.loom.util.LazyCloseable;
|
||||
import net.fabricmc.tinyremapper.TinyRemapper;
|
||||
|
||||
public record MappingProcessorContextImpl(ConfigContext configContext) implements MappingProcessorContext {
|
||||
@Override
|
||||
public LazyCloseable<TinyRemapper> createRemapper(MappingsNamespace from, MappingsNamespace to) {
|
||||
return ContextImplHelper.createRemapper(configContext, from, to);
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* This file is part of fabric-loom, licensed under the MIT License (MIT).
|
||||
*
|
||||
* Copyright (c) 2022 FabricMC
|
||||
* Copyright (c) 2022-2023 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
|
||||
@@ -24,16 +24,12 @@
|
||||
|
||||
package net.fabricmc.loom.configuration.processors;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.UncheckedIOException;
|
||||
import java.nio.file.Path;
|
||||
|
||||
import net.fabricmc.loom.api.mappings.layered.MappingsNamespace;
|
||||
import net.fabricmc.loom.api.processor.ProcessorContext;
|
||||
import net.fabricmc.loom.configuration.ConfigContext;
|
||||
import net.fabricmc.loom.configuration.providers.minecraft.MinecraftJar;
|
||||
import net.fabricmc.loom.configuration.providers.minecraft.MinecraftJarConfiguration;
|
||||
import net.fabricmc.loom.util.TinyRemapperHelper;
|
||||
import net.fabricmc.loom.util.LazyCloseable;
|
||||
import net.fabricmc.tinyremapper.TinyRemapper;
|
||||
|
||||
public record ProcessorContextImpl(ConfigContext configContext, MinecraftJar minecraftJar) implements ProcessorContext {
|
||||
@@ -58,18 +54,7 @@ public record ProcessorContextImpl(ConfigContext configContext, MinecraftJar min
|
||||
}
|
||||
|
||||
@Override
|
||||
public TinyRemapper createRemapper(MappingsNamespace from, MappingsNamespace to) {
|
||||
try {
|
||||
TinyRemapper tinyRemapper = TinyRemapperHelper.getTinyRemapper(configContext().project(), configContext().serviceManager(), from.toString(), to.toString());
|
||||
tinyRemapper.readClassPath(TinyRemapperHelper.getMinecraftDependencies(configContext.project()));
|
||||
|
||||
for (Path minecraftJar : configContext.extension().getMinecraftJars(MappingsNamespace.INTERMEDIARY)) {
|
||||
tinyRemapper.readClassPath(minecraftJar);
|
||||
}
|
||||
|
||||
return tinyRemapper;
|
||||
} catch (IOException e) {
|
||||
throw new UncheckedIOException("Failed to create tiny remapper", e);
|
||||
}
|
||||
public LazyCloseable<TinyRemapper> createRemapper(MappingsNamespace from, MappingsNamespace to) {
|
||||
return ContextImplHelper.createRemapper(configContext, from, to);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* This file is part of fabric-loom, licensed under the MIT License (MIT).
|
||||
*
|
||||
* Copyright (c) 2022 FabricMC
|
||||
* Copyright (c) 2022-2023 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
|
||||
@@ -25,8 +25,6 @@
|
||||
package net.fabricmc.loom.configuration.processors;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.UncheckedIOException;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
@@ -41,7 +39,6 @@ import org.gradle.api.Project;
|
||||
import org.gradle.api.artifacts.Configuration;
|
||||
import org.gradle.api.artifacts.ProjectDependency;
|
||||
import org.gradle.api.plugins.JavaPlugin;
|
||||
import org.gradle.api.tasks.SourceSet;
|
||||
|
||||
import net.fabricmc.loom.LoomGradleExtension;
|
||||
import net.fabricmc.loom.api.RemapConfigurationSettings;
|
||||
@@ -49,8 +46,8 @@ import net.fabricmc.loom.api.processor.SpecContext;
|
||||
import net.fabricmc.loom.util.Constants;
|
||||
import net.fabricmc.loom.util.fmj.FabricModJson;
|
||||
import net.fabricmc.loom.util.fmj.FabricModJsonFactory;
|
||||
import net.fabricmc.loom.util.fmj.FabricModJsonHelpers;
|
||||
import net.fabricmc.loom.util.gradle.GradleUtils;
|
||||
import net.fabricmc.loom.util.gradle.SourceSetHelper;
|
||||
|
||||
/**
|
||||
* @param modDependencies External mods that are depended on
|
||||
@@ -59,7 +56,7 @@ import net.fabricmc.loom.util.gradle.SourceSetHelper;
|
||||
*/
|
||||
public record SpecContextImpl(List<FabricModJson> modDependencies, List<FabricModJson> localMods, List<FabricModJson> compileRuntimeMods) implements SpecContext {
|
||||
public static SpecContextImpl create(Project project) {
|
||||
return new SpecContextImpl(getDependentMods(project), getModsInProject(project), getCompileRuntimeMods(project));
|
||||
return new SpecContextImpl(getDependentMods(project), FabricModJsonHelpers.getModsInProject(project), getCompileRuntimeMods(project));
|
||||
}
|
||||
|
||||
// Reruns a list of mods found on both the compile and/or runtime classpaths
|
||||
@@ -82,7 +79,7 @@ public record SpecContextImpl(List<FabricModJson> modDependencies, List<FabricMo
|
||||
if (!GradleUtils.getBooleanProperty(project, Constants.Properties.DISABLE_PROJECT_DEPENDENT_MODS)) {
|
||||
// Add all the dependent projects
|
||||
for (Project dependentProject : getDependentProjects(project).toList()) {
|
||||
mods.addAll(getModsInProject(dependentProject));
|
||||
mods.addAll(FabricModJsonHelpers.getModsInProject(dependentProject));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -97,35 +94,12 @@ public record SpecContextImpl(List<FabricModJson> modDependencies, List<FabricMo
|
||||
.distinct();
|
||||
}
|
||||
|
||||
// Returns a list of Mods found in the provided project
|
||||
private static List<FabricModJson> getModsInProject(Project project) {
|
||||
final LoomGradleExtension extension = LoomGradleExtension.get(project);
|
||||
var sourceSets = new ArrayList<SourceSet>();
|
||||
sourceSets.add(SourceSetHelper.getMainSourceSet(project));
|
||||
|
||||
if (extension.areEnvironmentSourceSetsSplit()) {
|
||||
sourceSets.add(SourceSetHelper.getSourceSetByName("client", project));
|
||||
}
|
||||
|
||||
try {
|
||||
final FabricModJson fabricModJson = FabricModJsonFactory.createFromSourceSetsNullable(sourceSets.toArray(SourceSet[]::new));
|
||||
|
||||
if (fabricModJson != null) {
|
||||
return List.of(fabricModJson);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new UncheckedIOException(e);
|
||||
}
|
||||
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
// Returns a list of mods that are on both to compile and runtime classpath
|
||||
private static List<FabricModJson> getCompileRuntimeMods(Project project) {
|
||||
var mods = new ArrayList<>(getCompileRuntimeModsFromRemapConfigs(project).toList());
|
||||
|
||||
for (Project dependentProject : getCompileRuntimeProjectDependencies(project).toList()) {
|
||||
mods.addAll(getModsInProject(dependentProject));
|
||||
mods.addAll(FabricModJsonHelpers.getModsInProject(dependentProject));
|
||||
}
|
||||
|
||||
return Collections.unmodifiableList(mods);
|
||||
|
||||
@@ -143,10 +143,6 @@ public abstract class LoomGradleExtensionApiImpl implements LoomGradleExtensionA
|
||||
|
||||
// Add main source set by default
|
||||
interfaceInjection(interfaceInjection -> {
|
||||
final SourceSet main = SourceSetHelper.getMainSourceSet(project);
|
||||
interfaceInjection.getInterfaceInjectionSourceSets().add(main);
|
||||
|
||||
interfaceInjection.getInterfaceInjectionSourceSets().finalizeValueOnRead();
|
||||
interfaceInjection.getEnableDependencyInterfaceInjection().convention(true).finalizeValueOnRead();
|
||||
});
|
||||
}
|
||||
|
||||
@@ -64,8 +64,8 @@ import net.fabricmc.loom.api.decompilers.DecompilationMetadata;
|
||||
import net.fabricmc.loom.api.decompilers.DecompilerOptions;
|
||||
import net.fabricmc.loom.api.decompilers.LoomDecompiler;
|
||||
import net.fabricmc.loom.api.mappings.layered.MappingsNamespace;
|
||||
import net.fabricmc.loom.api.processor.MappingProcessorContext;
|
||||
import net.fabricmc.loom.configuration.accesswidener.TransitiveAccessWidenerMappingsProcessor;
|
||||
import net.fabricmc.loom.configuration.ConfigContextImpl;
|
||||
import net.fabricmc.loom.configuration.processors.MappingProcessorContextImpl;
|
||||
import net.fabricmc.loom.configuration.processors.MinecraftJarProcessorManager;
|
||||
import net.fabricmc.loom.decompilers.LineNumberRemapper;
|
||||
import net.fabricmc.loom.util.Constants;
|
||||
@@ -77,6 +77,7 @@ import net.fabricmc.loom.util.gradle.ThreadedSimpleProgressLogger;
|
||||
import net.fabricmc.loom.util.gradle.WorkerDaemonClientsManagerHelper;
|
||||
import net.fabricmc.loom.util.ipc.IPCClient;
|
||||
import net.fabricmc.loom.util.ipc.IPCServer;
|
||||
import net.fabricmc.loom.util.service.ScopedSharedServiceManager;
|
||||
import net.fabricmc.mappingio.MappingReader;
|
||||
import net.fabricmc.mappingio.adapter.MappingSourceNsSwitch;
|
||||
import net.fabricmc.mappingio.format.Tiny2Writer;
|
||||
@@ -330,14 +331,15 @@ public abstract class GenerateSourcesTask extends AbstractLoomTask {
|
||||
|
||||
final List<MappingsProcessor> mappingsProcessors = new ArrayList<>();
|
||||
|
||||
if (getExtension().getEnableTransitiveAccessWideners().get()) {
|
||||
mappingsProcessors.add(new TransitiveAccessWidenerMappingsProcessor(getProject()));
|
||||
}
|
||||
|
||||
MinecraftJarProcessorManager minecraftJarProcessorManager = MinecraftJarProcessorManager.create(getProject());
|
||||
|
||||
if (minecraftJarProcessorManager != null) {
|
||||
mappingsProcessors.add(mappings -> minecraftJarProcessorManager.processMappings(mappings, new MappingProcessorContextImpl()));
|
||||
mappingsProcessors.add(mappings -> {
|
||||
try (var serviceManager = new ScopedSharedServiceManager()) {
|
||||
final var configContext = new ConfigContextImpl(getProject(), serviceManager, getExtension());
|
||||
return minecraftJarProcessorManager.processMappings(mappings, new MappingProcessorContextImpl(configContext));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (mappingsProcessors.isEmpty()) {
|
||||
@@ -388,7 +390,4 @@ public abstract class GenerateSourcesTask extends AbstractLoomTask {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private static class MappingProcessorContextImpl implements MappingProcessorContext {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* This file is part of fabric-loom, licensed under the MIT License (MIT).
|
||||
*
|
||||
* Copyright (c) 2021 FabricMC
|
||||
* Copyright (c) 2021-2023 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
|
||||
@@ -35,10 +35,18 @@ public interface DeprecationHelper {
|
||||
toBeRemovedIn(currentName, newName, "Loom 2.0");
|
||||
}
|
||||
|
||||
default void removedInLoom2_0(String currentName) {
|
||||
toBeRemovedIn(currentName, "Loom 2.0");
|
||||
}
|
||||
|
||||
default void toBeRemovedIn(String currentName, String newName, String removalVersion) {
|
||||
warn("The '%s' property has been deprecated, and has been replaced with '%s'. This is scheduled to be removed in %s.".formatted(currentName, newName, removalVersion));
|
||||
}
|
||||
|
||||
default void toBeRemovedIn(String currentName, String removalVersion) {
|
||||
warn("The '%s' property has been deprecated, and can be removed. This is scheduled to be removed in %s.".formatted(currentName, removalVersion));
|
||||
}
|
||||
|
||||
Project getProject();
|
||||
|
||||
void warn(String warning);
|
||||
|
||||
58
src/main/java/net/fabricmc/loom/util/LazyCloseable.java
Normal file
58
src/main/java/net/fabricmc/loom/util/LazyCloseable.java
Normal file
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* This file is part of fabric-loom, licensed under the MIT License (MIT).
|
||||
*
|
||||
* Copyright (c) 2023 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 java.io.Closeable;
|
||||
import java.io.IOException;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
// Not thread safe
|
||||
public class LazyCloseable<T> implements Closeable {
|
||||
private final Supplier<T> valueSupplier;
|
||||
private final Consumer<T> closeConsumer;
|
||||
private T value;
|
||||
|
||||
public LazyCloseable(Supplier<T> valueSupplier, Consumer<T> closeConsumer) {
|
||||
this.valueSupplier = valueSupplier;
|
||||
this.closeConsumer = closeConsumer;
|
||||
}
|
||||
|
||||
public T get() {
|
||||
if (value == null) {
|
||||
value = valueSupplier.get();
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
if (value != null) {
|
||||
closeConsumer.accept(value);
|
||||
value = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* This file is part of fabric-loom, licensed under the MIT License (MIT).
|
||||
*
|
||||
* Copyright (c) 2023 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.fmj;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.UncheckedIOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.gradle.api.Project;
|
||||
import org.gradle.api.tasks.SourceSet;
|
||||
|
||||
import net.fabricmc.loom.LoomGradleExtension;
|
||||
import net.fabricmc.loom.util.gradle.SourceSetHelper;
|
||||
|
||||
public class FabricModJsonHelpers {
|
||||
// Returns a list of Mods found in the provided project's main or client sourcesets
|
||||
public static List<FabricModJson> getModsInProject(Project project) {
|
||||
final LoomGradleExtension extension = LoomGradleExtension.get(project);
|
||||
var sourceSets = new ArrayList<SourceSet>();
|
||||
sourceSets.add(SourceSetHelper.getMainSourceSet(project));
|
||||
|
||||
if (extension.areEnvironmentSourceSetsSplit()) {
|
||||
sourceSets.add(SourceSetHelper.getSourceSetByName("client", project));
|
||||
}
|
||||
|
||||
try {
|
||||
final FabricModJson fabricModJson = FabricModJsonFactory.createFromSourceSetsNullable(sourceSets.toArray(SourceSet[]::new));
|
||||
|
||||
if (fabricModJson != null) {
|
||||
return List.of(fabricModJson);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new UncheckedIOException(e);
|
||||
}
|
||||
|
||||
return Collections.emptyList();
|
||||
}
|
||||
}
|
||||
@@ -59,13 +59,17 @@ public interface FabricModJsonSource {
|
||||
record SourceSetSource(SourceSet... sourceSets) implements FabricModJsonSource {
|
||||
@Override
|
||||
public byte[] read(String path) throws IOException {
|
||||
return Files.readAllBytes(findFile(path).toPath());
|
||||
}
|
||||
|
||||
private File findFile(String path) throws IOException {
|
||||
final File file = SourceSetHelper.findFirstFileInResource(path, sourceSets);
|
||||
|
||||
if (file == null) {
|
||||
throw new FileNotFoundException("Could not find: " + path);
|
||||
}
|
||||
|
||||
return Files.readAllBytes(file.toPath());
|
||||
return file;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user