mirror of
https://github.com/architectury/architectury-loom.git
synced 2026-03-30 21:05:58 -05:00
Read "Fabric-Loom-Remap" manifest entry to allow an artifact to control if its remapped or not. (#749)
This allows for none mod jars to opt-into remapping, as well as mods or mod loaders to opt-out. Setting "Fabric-Loom-Remap" to true/false in the jar's manifest.
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 FabricMC
|
||||
* Copyright (c) 2021-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
|
||||
@@ -25,6 +25,55 @@
|
||||
package net.fabricmc.loom.configuration;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
import org.gradle.api.Project;
|
||||
import org.gradle.api.artifacts.Configuration;
|
||||
import org.gradle.api.artifacts.ExternalModuleDependency;
|
||||
import org.gradle.api.artifacts.repositories.MavenArtifactRepository;
|
||||
|
||||
import net.fabricmc.loom.LoomGradleExtension;
|
||||
import net.fabricmc.loom.LoomRepositoryPlugin;
|
||||
import net.fabricmc.loom.configuration.ide.idea.IdeaUtils;
|
||||
import net.fabricmc.loom.util.Constants;
|
||||
|
||||
public record InstallerData(String version, JsonObject installerJson) {
|
||||
public void applyToProject(Project project) {
|
||||
LoomGradleExtension extension = LoomGradleExtension.get(project);
|
||||
|
||||
if (extension.getInstallerData() != null) {
|
||||
throw new IllegalStateException("Already applied installer data");
|
||||
}
|
||||
|
||||
extension.setInstallerData(this);
|
||||
|
||||
JsonObject libraries = installerJson.get("libraries").getAsJsonObject();
|
||||
Configuration loaderDepsConfig = project.getConfigurations().getByName(Constants.Configurations.LOADER_DEPENDENCIES);
|
||||
Configuration apDepsConfig = project.getConfigurations().getByName("annotationProcessor");
|
||||
|
||||
libraries.get("common").getAsJsonArray().forEach(jsonElement -> {
|
||||
String name = jsonElement.getAsJsonObject().get("name").getAsString();
|
||||
project.getLogger().debug("Adding dependency ({}) from installer JSON", name);
|
||||
|
||||
ExternalModuleDependency modDep = (ExternalModuleDependency) project.getDependencies().create(name);
|
||||
modDep.setTransitive(false);
|
||||
loaderDepsConfig.getDependencies().add(modDep);
|
||||
|
||||
// TODO: work around until https://github.com/FabricMC/Mixin/pull/60 and https://github.com/FabricMC/fabric-mixin-compile-extensions/issues/14 is fixed.
|
||||
if (!IdeaUtils.isIdeaSync() && extension.getMixin().getUseLegacyMixinAp().get()) {
|
||||
apDepsConfig.getDependencies().add(modDep);
|
||||
}
|
||||
|
||||
// If user choose to use dependencyResolutionManagement, then they should declare
|
||||
// these repositories manually in the settings file.
|
||||
if (jsonElement.getAsJsonObject().has("url") && !project.getGradle().getPlugins().hasPlugin(LoomRepositoryPlugin.class)) {
|
||||
String url = jsonElement.getAsJsonObject().get("url").getAsString();
|
||||
long count = project.getRepositories().stream().filter(artifactRepository -> artifactRepository instanceof MavenArtifactRepository)
|
||||
.map(artifactRepository -> (MavenArtifactRepository) artifactRepository)
|
||||
.filter(mavenArtifactRepository -> mavenArtifactRepository.getUrl().toString().equalsIgnoreCase(url)).count();
|
||||
|
||||
if (count == 0) {
|
||||
project.getRepositories().maven(mavenArtifactRepository -> mavenArtifactRepository.setUrl(jsonElement.getAsJsonObject().get("url").getAsString()));
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,58 +24,18 @@
|
||||
|
||||
package net.fabricmc.loom.configuration;
|
||||
|
||||
import java.io.File;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
import org.gradle.api.Project;
|
||||
import org.gradle.api.artifacts.Configuration;
|
||||
import org.gradle.api.artifacts.Dependency;
|
||||
import org.gradle.api.artifacts.ExternalModuleDependency;
|
||||
import org.gradle.api.artifacts.repositories.MavenArtifactRepository;
|
||||
|
||||
import net.fabricmc.loom.LoomGradleExtension;
|
||||
import net.fabricmc.loom.LoomGradlePlugin;
|
||||
import net.fabricmc.loom.LoomRepositoryPlugin;
|
||||
import net.fabricmc.loom.configuration.ide.idea.IdeaUtils;
|
||||
import net.fabricmc.loom.configuration.mods.ModConfigurationRemapper;
|
||||
import net.fabricmc.loom.util.Constants;
|
||||
import net.fabricmc.loom.util.SourceRemapper;
|
||||
import net.fabricmc.loom.util.ZipUtils;
|
||||
import net.fabricmc.loom.util.service.SharedServiceManager;
|
||||
|
||||
public class LoomDependencyManager {
|
||||
public void handleDependencies(Project project, SharedServiceManager serviceManager) {
|
||||
List<Runnable> afterTasks = new ArrayList<>();
|
||||
|
||||
project.getLogger().info(":setting up loom dependencies");
|
||||
LoomGradleExtension extension = LoomGradleExtension.get(project);
|
||||
|
||||
if (extension.getInstallerData() == null) {
|
||||
//If we've not found the installer JSON we've probably skipped remapping Fabric loader, let's go looking
|
||||
project.getLogger().info("Searching through modCompileClasspath for installer JSON");
|
||||
final Configuration configuration = project.getConfigurations().getByName(Constants.Configurations.MOD_COMPILE_CLASSPATH);
|
||||
|
||||
for (Dependency dependency : configuration.getAllDependencies()) {
|
||||
for (File input : configuration.files(dependency)) {
|
||||
JsonObject jsonObject = readInstallerJson(input);
|
||||
|
||||
if (jsonObject != null) {
|
||||
if (extension.getInstallerData() != null) {
|
||||
project.getLogger().info("Found another installer JSON in, ignoring it! " + input);
|
||||
continue;
|
||||
}
|
||||
|
||||
project.getLogger().info("Found installer JSON in " + input);
|
||||
extension.setInstallerData(new InstallerData(dependency.getVersion(), jsonObject));
|
||||
handleInstallerJson(jsonObject, project);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SourceRemapper sourceRemapper = new SourceRemapper(project, serviceManager, true);
|
||||
String mappingsIdentifier = extension.getMappingConfiguration().mappingsIdentifier();
|
||||
|
||||
@@ -84,61 +44,7 @@ public class LoomDependencyManager {
|
||||
sourceRemapper.remapAll();
|
||||
|
||||
if (extension.getInstallerData() == null) {
|
||||
project.getLogger().warn("fabric-installer.json not found in classpath!");
|
||||
project.getLogger().warn("fabric-installer.json not found in dependencies!");
|
||||
}
|
||||
|
||||
for (Runnable runnable : afterTasks) {
|
||||
runnable.run();
|
||||
}
|
||||
}
|
||||
|
||||
public static JsonObject readInstallerJson(File file) {
|
||||
try {
|
||||
byte[] bytes = ZipUtils.unpackNullable(file.toPath(), "fabric-installer.json");
|
||||
|
||||
if (bytes == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return LoomGradlePlugin.GSON.fromJson(new String(bytes, StandardCharsets.UTF_8), JsonObject.class);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("Failed to try and read installer json from " + file, e);
|
||||
}
|
||||
}
|
||||
|
||||
private static void handleInstallerJson(JsonObject jsonObject, Project project) {
|
||||
LoomGradleExtension extension = LoomGradleExtension.get(project);
|
||||
|
||||
JsonObject libraries = jsonObject.get("libraries").getAsJsonObject();
|
||||
Configuration loaderDepsConfig = project.getConfigurations().getByName(Constants.Configurations.LOADER_DEPENDENCIES);
|
||||
Configuration apDepsConfig = project.getConfigurations().getByName("annotationProcessor");
|
||||
|
||||
libraries.get("common").getAsJsonArray().forEach(jsonElement -> {
|
||||
String name = jsonElement.getAsJsonObject().get("name").getAsString();
|
||||
|
||||
ExternalModuleDependency modDep = (ExternalModuleDependency) project.getDependencies().create(name);
|
||||
modDep.setTransitive(false);
|
||||
loaderDepsConfig.getDependencies().add(modDep);
|
||||
|
||||
// TODO: work around until https://github.com/FabricMC/Mixin/pull/60 and https://github.com/FabricMC/fabric-mixin-compile-extensions/issues/14 is fixed.
|
||||
if (!IdeaUtils.isIdeaSync() && extension.getMixin().getUseLegacyMixinAp().get()) {
|
||||
apDepsConfig.getDependencies().add(modDep);
|
||||
}
|
||||
|
||||
project.getLogger().debug("Loom adding " + name + " from installer JSON");
|
||||
|
||||
// If user choose to use dependencyResolutionManagement, then they should declare
|
||||
// these repositories manually in the settings file.
|
||||
if (jsonElement.getAsJsonObject().has("url") && !project.getGradle().getPlugins().hasPlugin(LoomRepositoryPlugin.class)) {
|
||||
String url = jsonElement.getAsJsonObject().get("url").getAsString();
|
||||
long count = project.getRepositories().stream().filter(artifactRepository -> artifactRepository instanceof MavenArtifactRepository)
|
||||
.map(artifactRepository -> (MavenArtifactRepository) artifactRepository)
|
||||
.filter(mavenArtifactRepository -> mavenArtifactRepository.getUrl().toString().equalsIgnoreCase(url)).count();
|
||||
|
||||
if (count == 0) {
|
||||
project.getRepositories().maven(mavenArtifactRepository -> mavenArtifactRepository.setUrl(jsonElement.getAsJsonObject().get("url").getAsString()));
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
* 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.mods;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.jar.Attributes;
|
||||
import java.util.jar.Manifest;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import net.fabricmc.loom.LoomGradlePlugin;
|
||||
import net.fabricmc.loom.configuration.InstallerData;
|
||||
import net.fabricmc.loom.util.FileSystemUtil;
|
||||
import net.fabricmc.loom.util.fmj.FabricModJsonFactory;
|
||||
|
||||
public record ArtifactMetadata(boolean isFabricMod, RemapRequirements remapRequirements, @Nullable InstallerData installerData) {
|
||||
private static final String INSTALLER_PATH = "fabric-installer.json";
|
||||
private static final String MANIFEST_PATH = "META-INF/MANIFEST.MF";
|
||||
private static final String MANIFEST_REMAP_KEY = "Fabric-Loom-Remap";
|
||||
|
||||
public static ArtifactMetadata create(ArtifactRef artifact) throws IOException {
|
||||
boolean isFabricMod;
|
||||
RemapRequirements remapRequirements = RemapRequirements.DEFAULT;
|
||||
InstallerData installerData = null;
|
||||
|
||||
try (FileSystemUtil.Delegate fs = FileSystemUtil.getJarFileSystem(artifact.path())) {
|
||||
isFabricMod = FabricModJsonFactory.containsMod(fs);
|
||||
final Path manifestPath = fs.getPath(MANIFEST_PATH);
|
||||
|
||||
if (Files.exists(manifestPath)) {
|
||||
final var manifest = new Manifest(new ByteArrayInputStream(Files.readAllBytes(manifestPath)));
|
||||
final Attributes mainAttributes = manifest.getMainAttributes();
|
||||
final String value = mainAttributes.getValue(MANIFEST_REMAP_KEY);
|
||||
|
||||
if (value != null) {
|
||||
// Support opting into and out of remapping with "Fabric-Loom-Remap" manifest entry
|
||||
remapRequirements = Boolean.parseBoolean(value) ? RemapRequirements.OPT_IN : RemapRequirements.OPT_OUT;
|
||||
}
|
||||
}
|
||||
|
||||
final Path installerPath = fs.getPath(INSTALLER_PATH);
|
||||
|
||||
if (isFabricMod && Files.exists(installerPath)) {
|
||||
final JsonObject jsonObject = LoomGradlePlugin.GSON.fromJson(Files.readString(installerPath, StandardCharsets.UTF_8), JsonObject.class);
|
||||
installerData = new InstallerData(artifact.version(), jsonObject);
|
||||
}
|
||||
}
|
||||
|
||||
return new ArtifactMetadata(isFabricMod, remapRequirements, installerData);
|
||||
}
|
||||
|
||||
public boolean shouldRemap() {
|
||||
return remapRequirements().getShouldRemap().test(this);
|
||||
}
|
||||
|
||||
public enum RemapRequirements {
|
||||
DEFAULT(ArtifactMetadata::isFabricMod),
|
||||
OPT_IN(true),
|
||||
OPT_OUT(false);
|
||||
|
||||
private final Predicate<ArtifactMetadata> shouldRemap;
|
||||
|
||||
RemapRequirements(Predicate<ArtifactMetadata> shouldRemap) {
|
||||
this.shouldRemap = shouldRemap;
|
||||
}
|
||||
|
||||
RemapRequirements(final boolean shouldRemap) {
|
||||
this.shouldRemap = artifactMetadata -> shouldRemap;
|
||||
}
|
||||
|
||||
private Predicate<ArtifactMetadata> getShouldRemap() {
|
||||
return shouldRemap;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -57,7 +57,6 @@ import net.fabricmc.loom.util.Checksum;
|
||||
import net.fabricmc.loom.util.Constants;
|
||||
import net.fabricmc.loom.util.OperatingSystem;
|
||||
import net.fabricmc.loom.util.SourceRemapper;
|
||||
import net.fabricmc.loom.util.fmj.FabricModJsonFactory;
|
||||
import net.fabricmc.loom.util.service.SharedServiceManager;
|
||||
|
||||
@SuppressWarnings("UnstableApiUsage")
|
||||
@@ -89,7 +88,24 @@ public class ModConfigurationRemapper {
|
||||
final List<ModDependency> modDependencies = new ArrayList<>();
|
||||
|
||||
for (ArtifactRef artifact : resolveArtifacts(project, sourceConfig)) {
|
||||
if (!FabricModJsonFactory.isModJar(artifact.path())) {
|
||||
final ArtifactMetadata artifactMetadata;
|
||||
|
||||
try {
|
||||
artifactMetadata = ArtifactMetadata.create(artifact);
|
||||
} catch (IOException e) {
|
||||
throw new UncheckedIOException("Failed to read metadata from" + artifact.path(), e);
|
||||
}
|
||||
|
||||
if (artifactMetadata.installerData() != null) {
|
||||
if (extension.getInstallerData() != null) {
|
||||
project.getLogger().info("Found another installer JSON in ({}), ignoring", artifact.path());
|
||||
} else {
|
||||
project.getLogger().info("Applying installer data from {}", artifact.path());
|
||||
artifactMetadata.installerData().applyToProject(project);
|
||||
}
|
||||
}
|
||||
|
||||
if (!artifactMetadata.shouldRemap()) {
|
||||
artifact.applyToConfiguration(project, targetConfig);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -41,6 +41,7 @@ import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.annotations.VisibleForTesting;
|
||||
|
||||
import net.fabricmc.loom.LoomGradlePlugin;
|
||||
import net.fabricmc.loom.util.FileSystemUtil;
|
||||
import net.fabricmc.loom.util.ZipUtils;
|
||||
import net.fabricmc.loom.util.gradle.SourceSetHelper;
|
||||
|
||||
@@ -124,4 +125,8 @@ public final class FabricModJsonFactory {
|
||||
public static boolean isModJar(Path input) {
|
||||
return ZipUtils.contains(input, FABRIC_MOD_JSON);
|
||||
}
|
||||
|
||||
public static boolean containsMod(FileSystemUtil.Delegate fs) {
|
||||
return Files.exists(fs.getPath(FABRIC_MOD_JSON));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user