Intermediate mapping handling improvements. (#593)

* Add API for intermediate mappings. Add hacky option to run with no intermediate mappings.

* Add setter, and some getters that I need :)

* Remove unused inject.

* Don't add asm-all to the libraries.

* Fix unit tests.
This commit is contained in:
modmuss50
2022-02-09 13:49:15 +00:00
committed by GitHub
parent cbcdf66c6d
commit de31f1e083
17 changed files with 359 additions and 44 deletions

View File

@@ -112,10 +112,6 @@ public interface LoomGradleExtension extends LoomGradleExtensionAPI {
boolean isRootProject();
default String getIntermediaryUrl(String minecraftVersion) {
return String.format(this.getIntermediaryUrl().get(), minecraftVersion);
}
@Override
MixinExtension getMixin();

View File

@@ -35,9 +35,11 @@ import org.gradle.api.publish.maven.MavenPublication;
import org.jetbrains.annotations.ApiStatus;
import net.fabricmc.loom.api.decompilers.DecompilerOptions;
import net.fabricmc.loom.api.mappings.intermediate.IntermediateMappingsProvider;
import net.fabricmc.loom.api.mappings.layered.spec.LayeredMappingSpecBuilder;
import net.fabricmc.loom.configuration.ide.RunConfigSettings;
import net.fabricmc.loom.configuration.processors.JarProcessor;
import net.fabricmc.loom.configuration.providers.mappings.NoOpIntermediateMappingsProvider;
import net.fabricmc.loom.configuration.providers.minecraft.MinecraftJarConfiguration;
import net.fabricmc.loom.util.DeprecationHelper;
@@ -130,6 +132,23 @@ public interface LoomGradleExtensionAPI {
*/
Property<Boolean> getEnableTransitiveAccessWideners();
@ApiStatus.Experimental
IntermediateMappingsProvider getIntermediateMappingsProvider();
@ApiStatus.Experimental
void setIntermediateMappingsProvider(IntermediateMappingsProvider intermediateMappingsProvider);
@ApiStatus.Experimental
<T extends IntermediateMappingsProvider> void setIntermediateMappingsProvider(Class<T> clazz, Action<T> action);
/**
* An Experimental option to provide empty intermediate mappings, to be used for game versions without any intermediate mappings.
*/
@ApiStatus.Experimental
default void noIntermediateMappings() {
setIntermediateMappingsProvider(NoOpIntermediateMappingsProvider.class, p -> { });
}
/**
* Use "%1$s" as a placeholder for the minecraft version.
*

View File

@@ -0,0 +1,47 @@
/*
* This file is part of fabric-loom, licensed under the MIT License (MIT).
*
* Copyright (c) 2022 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.api.mappings.intermediate;
import java.io.IOException;
import java.nio.file.Path;
import org.gradle.api.Named;
import org.gradle.api.provider.Property;
import org.jetbrains.annotations.ApiStatus;
/**
* A simple API to allow 3rd party plugins.
* Implement by creating an abstract class overriding provide and getName
*/
@ApiStatus.Experimental
public abstract class IntermediateMappingsProvider implements Named {
public abstract Property<String> getMinecraftVersion();
/**
* Generate or download a tinyv2 mapping file with intermediary and named namespaces.
* @throws IOException
*/
public abstract void provide(Path tinyMappings) throws IOException;
}

View File

@@ -65,7 +65,7 @@ public class GradleMappingContext implements MappingContext {
@Override
public Supplier<MemoryMappingTree> intermediaryTree() {
return () -> IntermediaryService.getInstance(project, minecraftProvider()).getMemoryMappingTree();
return () -> IntermediateMappingsService.getInstance(project, minecraftProvider()).getMemoryMappingTree();
}
@Override
@@ -82,4 +82,12 @@ public class GradleMappingContext implements MappingContext {
public Logger getLogger() {
return project.getLogger();
}
public Project getProject() {
return project;
}
public LoomGradleExtension getExtension() {
return extension;
}
}

View File

@@ -0,0 +1,71 @@
/*
* This file is part of fabric-loom, licensed under the MIT License (MIT).
*
* Copyright (c) 2022 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.providers.mappings;
import java.io.IOException;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
import com.google.common.net.UrlEscapers;
import org.gradle.api.provider.Property;
import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import net.fabricmc.loom.LoomGradlePlugin;
import net.fabricmc.loom.api.mappings.intermediate.IntermediateMappingsProvider;
import net.fabricmc.loom.util.DownloadUtil;
public abstract class IntermediaryMappingsProvider extends IntermediateMappingsProvider {
private static final Logger LOGGER = LoggerFactory.getLogger(IntermediateMappingsProvider.class);
public abstract Property<String> getIntermediaryUrl();
@Override
public void provide(Path tinyMappings) throws IOException {
if (Files.exists(tinyMappings) && !LoomGradlePlugin.refreshDeps) {
return;
}
// Download and extract intermediary
final Path intermediaryJarPath = Files.createTempFile(getName(), ".jar");
final String encodedMcVersion = UrlEscapers.urlFragmentEscaper().escape(getMinecraftVersion().get());
final URL url = new URL(getIntermediaryUrl().get().formatted(encodedMcVersion));
LOGGER.info("Downloading intermediary from {}", url);
Files.deleteIfExists(tinyMappings);
Files.deleteIfExists(intermediaryJarPath);
DownloadUtil.downloadIfChanged(url, intermediaryJarPath.toFile(), LOGGER);
MappingsProviderImpl.extractMappings(intermediaryJarPath, tinyMappings);
}
@Override
public @NotNull String getName() {
return "intermediary-v2";
}
}

View File

@@ -25,10 +25,8 @@
package net.fabricmc.loom.configuration.providers.mappings;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
@@ -37,59 +35,52 @@ import java.util.Objects;
import java.util.function.Supplier;
import com.google.common.base.Suppliers;
import com.google.common.net.UrlEscapers;
import org.gradle.api.Project;
import org.jetbrains.annotations.VisibleForTesting;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import net.fabricmc.loom.LoomGradleExtension;
import net.fabricmc.loom.LoomGradlePlugin;
import net.fabricmc.loom.api.mappings.intermediate.IntermediateMappingsProvider;
import net.fabricmc.loom.api.mappings.layered.MappingsNamespace;
import net.fabricmc.loom.configuration.providers.minecraft.MinecraftProvider;
import net.fabricmc.loom.util.DownloadUtil;
import net.fabricmc.loom.util.service.SharedService;
import net.fabricmc.loom.util.service.SharedServiceManager;
import net.fabricmc.mappingio.adapter.MappingNsCompleter;
import net.fabricmc.mappingio.format.Tiny2Reader;
import net.fabricmc.mappingio.tree.MemoryMappingTree;
public final class IntermediaryService implements SharedService {
private static final Logger LOGGER = LoggerFactory.getLogger(IntermediaryService.class);
public final class IntermediateMappingsService implements SharedService {
private final Path intermediaryTiny;
private final Supplier<MemoryMappingTree> memoryMappingTree = Suppliers.memoize(this::createMemoryMappingTree);
private IntermediaryService(Path intermediaryTiny) {
private IntermediateMappingsService(Path intermediaryTiny) {
this.intermediaryTiny = intermediaryTiny;
}
public static synchronized IntermediaryService getInstance(Project project, MinecraftProvider minecraftProvider) {
public static synchronized IntermediateMappingsService getInstance(Project project, MinecraftProvider minecraftProvider) {
final LoomGradleExtension extension = LoomGradleExtension.get(project);
final String encodedMinecraftVersion = UrlEscapers.urlFragmentEscaper().escape(minecraftProvider.minecraftVersion());
final String intermediaryArtifactUrl = extension.getIntermediaryUrl(encodedMinecraftVersion);
final IntermediateMappingsProvider intermediateProvider = extension.getIntermediateMappingsProvider();
final String id = "IntermediateMappingsService:%s:%s".formatted(intermediateProvider.getName(), intermediateProvider.getMinecraftVersion().get());
return SharedServiceManager.get(project).getOrCreateService("IntermediaryService:" + intermediaryArtifactUrl,
() -> create(intermediaryArtifactUrl, minecraftProvider));
return SharedServiceManager.get(project).getOrCreateService(id, () -> create(intermediateProvider, minecraftProvider));
}
@VisibleForTesting
public static IntermediaryService create(String intermediaryUrl, MinecraftProvider minecraftProvider) {
final Path intermediaryTiny = minecraftProvider.file("intermediary-v2.tiny").toPath();
if (!Files.exists(intermediaryTiny) || LoomGradlePlugin.refreshDeps) {
// Download and extract intermediary
File intermediaryJar = minecraftProvider.file("intermediary-v2.jar");
public static IntermediateMappingsService create(IntermediateMappingsProvider intermediateMappingsProvider, MinecraftProvider minecraftProvider) {
final Path intermediaryTiny = minecraftProvider.file(intermediateMappingsProvider.getName() + ".tiny").toPath();
try {
intermediateMappingsProvider.provide(intermediaryTiny);
} catch (IOException e) {
try {
DownloadUtil.downloadIfChanged(new URL(intermediaryUrl), intermediaryJar, LOGGER);
MappingsProviderImpl.extractMappings(intermediaryJar.toPath(), intermediaryTiny);
} catch (IOException e) {
throw new UncheckedIOException("Failed to download and extract intermediary", e);
Files.deleteIfExists(intermediaryTiny);
} catch (IOException ex) {
ex.printStackTrace();
}
throw new UncheckedIOException("Failed to provide intermediate mappings", e);
}
return new IntermediaryService(intermediaryTiny);
return new IntermediateMappingsService(intermediaryTiny);
}
private MemoryMappingTree createMemoryMappingTree() {

View File

@@ -83,9 +83,9 @@ public class MappingsProviderImpl implements MappingsProvider, SharedService {
private UnpickMetadata unpickMetadata;
private Map<String, String> signatureFixes;
private final Supplier<IntermediaryService> intermediaryService;
private final Supplier<IntermediateMappingsService> intermediaryService;
private MappingsProviderImpl(String mappingsIdentifier, Path mappingsWorkingDir, Supplier<IntermediaryService> intermediaryService) {
private MappingsProviderImpl(String mappingsIdentifier, Path mappingsWorkingDir, Supplier<IntermediateMappingsService> intermediaryService) {
this.mappingsIdentifier = mappingsIdentifier;
this.mappingsWorkingDir = mappingsWorkingDir;
@@ -99,7 +99,7 @@ public class MappingsProviderImpl implements MappingsProvider, SharedService {
public static synchronized MappingsProviderImpl getInstance(Project project, DependencyInfo dependency, MinecraftProvider minecraftProvider) {
return SharedServiceManager.get(project).getOrCreateService("MappingsProvider:%s:%s".formatted(dependency.getDepString(), minecraftProvider.minecraftVersion()), () -> {
Supplier<IntermediaryService> intermediaryService = Suppliers.memoize(() -> IntermediaryService.getInstance(project, minecraftProvider));
Supplier<IntermediateMappingsService> intermediaryService = Suppliers.memoize(() -> IntermediateMappingsService.getInstance(project, minecraftProvider));
return create(dependency, minecraftProvider, intermediaryService);
});
}
@@ -108,7 +108,7 @@ public class MappingsProviderImpl implements MappingsProvider, SharedService {
return Objects.requireNonNull(mappingTree, "Cannot get mappings before they have been read").get();
}
private static MappingsProviderImpl create(DependencyInfo dependency, MinecraftProvider minecraftProvider, Supplier<IntermediaryService> intermediaryService) {
private static MappingsProviderImpl create(DependencyInfo dependency, MinecraftProvider minecraftProvider, Supplier<IntermediateMappingsService> intermediaryService) {
final String version = dependency.getResolvedVersion();
final Path inputJar = dependency.resolveFile().orElseThrow(() -> new RuntimeException("Could not resolve mappings: " + dependency)).toPath();
final String mappingsName = StringUtils.removeSuffix(dependency.getDependency().getGroup() + "." + dependency.getDependency().getName(), "-unmerged");

View File

@@ -0,0 +1,51 @@
/*
* This file is part of fabric-loom, licensed under the MIT License (MIT).
*
* Copyright (c) 2022 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.providers.mappings;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import org.jetbrains.annotations.NotNull;
import net.fabricmc.loom.api.mappings.intermediate.IntermediateMappingsProvider;
/**
* A bit of a hack, creates an empty intermediary mapping file to be used for mc versions without any intermediate mappings.
*/
public abstract class NoOpIntermediateMappingsProvider extends IntermediateMappingsProvider {
private static final String HEADER = "tiny\t2\t0\tofficial\tintermediary";
@Override
public void provide(Path tinyMappings) throws IOException {
Files.writeString(tinyMappings, HEADER, StandardCharsets.UTF_8);
}
@Override
public @NotNull String getName() {
return "empty-intermediate";
}
}

View File

@@ -38,7 +38,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import net.fabricmc.loom.api.mappings.layered.MappingsNamespace;
import net.fabricmc.loom.configuration.providers.mappings.IntermediaryService;
import net.fabricmc.loom.configuration.providers.mappings.IntermediateMappingsService;
import net.fabricmc.mappingio.adapter.MappingNsCompleter;
import net.fabricmc.mappingio.adapter.MappingSourceNsSwitch;
import net.fabricmc.mappingio.format.Tiny2Reader;
@@ -49,12 +49,12 @@ import net.fabricmc.mappingio.tree.MemoryMappingTree;
public final class MappingsMerger {
private static final Logger LOGGER = LoggerFactory.getLogger(MappingsMerger.class);
public static void mergeAndSaveMappings(Path from, Path out, IntermediaryService intermediaryService) throws IOException {
public static void mergeAndSaveMappings(Path from, Path out, IntermediateMappingsService intermediateMappingsService) throws IOException {
Stopwatch stopwatch = Stopwatch.createStarted();
LOGGER.info(":merging mappings");
MemoryMappingTree intermediaryTree = new MemoryMappingTree();
intermediaryService.getMemoryMappingTree().accept(new MappingSourceNsSwitch(intermediaryTree, MappingsNamespace.INTERMEDIARY.toString()));
intermediateMappingsService.getMemoryMappingTree().accept(new MappingSourceNsSwitch(intermediaryTree, MappingsNamespace.INTERMEDIARY.toString()));
try (BufferedReader reader = Files.newBufferedReader(from, StandardCharsets.UTF_8)) {
Tiny2Reader.read(reader, intermediaryTree);

View File

@@ -62,6 +62,9 @@ public class MinecraftLibraryProvider {
// 1.4.7 contains an LWJGL version with an invalid maven pom, set the metadata sources to not use the pom for this version.
if ("org.lwjgl.lwjgl:lwjgl:2.9.1-nightly-20130708-debug3".equals(library.name())) {
LoomRepositoryPlugin.setupForLegacyVersions(project);
} else if (library.name().startsWith("org.ow2.asm:asm-all")) {
// Don't want asm-all, use the modern split version.
continue;
}
if (runtimeOnlyLog4j && library.name().startsWith("org.apache.logging.log4j")) {

View File

@@ -40,6 +40,7 @@ import net.fabricmc.loom.api.InterfaceInjectionExtensionAPI;
import net.fabricmc.loom.api.LoomGradleExtensionAPI;
import net.fabricmc.loom.api.MixinExtensionAPI;
import net.fabricmc.loom.api.decompilers.DecompilerOptions;
import net.fabricmc.loom.api.mappings.intermediate.IntermediateMappingsProvider;
import net.fabricmc.loom.api.mappings.layered.spec.LayeredMappingSpecBuilder;
import net.fabricmc.loom.configuration.ide.RunConfigSettings;
import net.fabricmc.loom.configuration.mods.ModVersionParser;
@@ -65,6 +66,7 @@ public abstract class LoomGradleExtensionApiImpl implements LoomGradleExtensionA
protected final Property<Boolean> setupRemappedVariants;
protected final Property<Boolean> transitiveAccessWideners;
protected final Property<String> intermediary;
protected final Property<IntermediateMappingsProvider> intermediateMappingsProvider;
private final Property<Boolean> runtimeOnlyLog4j;
private final Property<MinecraftJarConfiguration> minecraftJarConfiguration;
private final InterfaceInjectionExtensionAPI interfaceInjectionExtension;
@@ -92,6 +94,9 @@ public abstract class LoomGradleExtensionApiImpl implements LoomGradleExtensionA
this.intermediary = project.getObjects().property(String.class)
.convention("https://maven.fabricmc.net/net/fabricmc/intermediary/%1$s/intermediary-%1$s-v2.jar");
this.intermediateMappingsProvider = project.getObjects().property(IntermediateMappingsProvider.class);
this.intermediateMappingsProvider.finalizeValueOnRead();
this.versionParser = new ModVersionParser(project);
this.deprecationHelper = new DeprecationHelper.ProjectBased(project);
@@ -214,6 +219,26 @@ public abstract class LoomGradleExtensionApiImpl implements LoomGradleExtensionA
return intermediary;
}
@Override
public IntermediateMappingsProvider getIntermediateMappingsProvider() {
return intermediateMappingsProvider.get();
}
@Override
public void setIntermediateMappingsProvider(IntermediateMappingsProvider intermediateMappingsProvider) {
this.intermediateMappingsProvider.set(intermediateMappingsProvider);
}
@Override
public <T extends IntermediateMappingsProvider> void setIntermediateMappingsProvider(Class<T> clazz, Action<T> action) {
T provider = getProject().getObjects().newInstance(clazz);
configureIntermediateMappingsProviderInternal(provider);
action.execute(provider);
intermediateMappingsProvider.set(provider);
}
protected abstract <T extends IntermediateMappingsProvider> void configureIntermediateMappingsProviderInternal(T provider);
@Override
public void disableDeprecatedPomGeneration(MavenPublication publication) {
net.fabricmc.loom.configuration.MavenPublication.excludePublication(publication);
@@ -256,6 +281,11 @@ public abstract class LoomGradleExtensionApiImpl implements LoomGradleExtensionA
throw new RuntimeException("Yeah... something is really wrong");
}
@Override
protected <T extends IntermediateMappingsProvider> void configureIntermediateMappingsProviderInternal(T provider) {
throw new RuntimeException("Yeah... something is really wrong");
}
@Override
public MixinExtension getMixin() {
throw new RuntimeException("Yeah... something is really wrong");

View File

@@ -42,11 +42,13 @@ import org.gradle.api.file.ConfigurableFileCollection;
import org.gradle.api.file.FileCollection;
import net.fabricmc.loom.LoomGradleExtension;
import net.fabricmc.loom.api.mappings.intermediate.IntermediateMappingsProvider;
import net.fabricmc.loom.api.mappings.layered.MappingsNamespace;
import net.fabricmc.loom.configuration.InstallerData;
import net.fabricmc.loom.configuration.LoomDependencyManager;
import net.fabricmc.loom.configuration.accesswidener.AccessWidenerFile;
import net.fabricmc.loom.configuration.processors.JarProcessorManager;
import net.fabricmc.loom.configuration.providers.mappings.IntermediaryMappingsProvider;
import net.fabricmc.loom.configuration.providers.mappings.MappingsProviderImpl;
import net.fabricmc.loom.configuration.providers.minecraft.MinecraftProvider;
import net.fabricmc.loom.configuration.providers.minecraft.mapped.IntermediaryMinecraftProvider;
@@ -78,6 +80,13 @@ public class LoomGradleExtensionImpl extends LoomGradleExtensionApiImpl implemen
this.mixinApExtension = project.getObjects().newInstance(MixinExtensionImpl.class, project);
this.loomFiles = files;
this.unmappedMods = project.files();
// Setup the default intermediate mappings provider.
setIntermediateMappingsProvider(IntermediaryMappingsProvider.class, provider -> {
provider.getIntermediaryUrl()
.convention(getIntermediaryUrl())
.finalizeValueOnRead();
});
}
@Override
@@ -226,4 +235,10 @@ public class LoomGradleExtensionImpl extends LoomGradleExtensionApiImpl implemen
public void addTransitiveAccessWideners(List<AccessWidenerFile> accessWidenerFiles) {
transitiveAccessWideners.addAll(accessWidenerFiles);
}
@Override
protected <T extends IntermediateMappingsProvider> void configureIntermediateMappingsProviderInternal(T provider) {
provider.getMinecraftVersion().set(getProject().provider(() -> getMinecraftProvider().minecraftVersion()));
provider.getMinecraftVersion().disallowChanges();
}
}