Add versions used to compile/build against to jar manifest (#428)

* Add versions used to compile/build against to jar manifest

* checkstyle

* Move to post remap

* Fix build

* Add mc version and mixin group

* Typo

* Make test run across versions better.
dev/0.11
modmuss50 2021-07-13 23:10:07 +01:00 committed by GitHub
parent e3b2f8610e
commit 2259a4efc8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 186 additions and 27 deletions

View File

@ -2,3 +2,4 @@
indent_style = tab
ij_continuation_indent_size = 8
ij_java_imports_layout = $*,|,java.**,|,javax.**,|,*,|,net.fabricmc.**
ij_java_class_count_to_use_import_on_demand = 999

View File

@ -35,7 +35,6 @@ import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import com.google.gson.JsonObject;
import org.cadixdev.lorenz.MappingSet;
import org.cadixdev.mercury.Mercury;
import org.gradle.api.Action;
@ -47,6 +46,7 @@ import org.gradle.api.plugins.BasePluginConvention;
import org.jetbrains.annotations.ApiStatus;
import net.fabricmc.loom.api.decompilers.LoomDecompiler;
import net.fabricmc.loom.configuration.InstallerData;
import net.fabricmc.loom.configuration.LoomDependencyManager;
import net.fabricmc.loom.configuration.LoomProjectData;
import net.fabricmc.loom.configuration.ide.RunConfigSettings;
@ -79,7 +79,7 @@ public class LoomGradleExtension {
private final Project project;
private LoomDependencyManager dependencyManager;
private JarProcessorManager jarProcessorManager;
private JsonObject installerJson;
private InstallerData installerData;
private MappingSet[] srcMappingCache = new MappingSet[2];
private Mercury[] srcMercuryCache = new Mercury[2];
private Set<File> mixinMappings = Collections.synchronizedSet(new HashSet<>());
@ -159,12 +159,12 @@ public class LoomGradleExtension {
return unmappedMods;
}
public void setInstallerJson(JsonObject object) {
this.installerJson = object;
public void setInstallerData(InstallerData data) {
this.installerData = data;
}
public JsonObject getInstallerJson() {
return installerJson;
public InstallerData getInstallerData() {
return installerData;
}
public void accessWidener(Object file) {

View File

@ -24,6 +24,8 @@
package net.fabricmc.loom;
import java.util.Objects;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.collect.ImmutableMap;
@ -45,6 +47,7 @@ public class LoomGradlePlugin implements BootstrappedPlugin {
public static boolean refreshDeps;
public static final Gson GSON = new GsonBuilder().setPrettyPrinting().create();
public static final ObjectMapper OBJECT_MAPPER = new ObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
public static final String LOOM_VERSION = Objects.requireNonNullElse(LoomGradlePlugin.class.getPackage().getImplementationVersion(), "0.0.0+unknown");
@Override
public void apply(PluginAware target) {
@ -56,7 +59,7 @@ public class LoomGradlePlugin implements BootstrappedPlugin {
}
public void apply(Project project) {
project.getLogger().lifecycle("Fabric Loom: " + LoomGradlePlugin.class.getPackage().getImplementationVersion());
project.getLogger().lifecycle("Fabric Loom: " + LOOM_VERSION);
refreshDeps = project.getGradle().getStartParameter().isRefreshDependencies();

View File

@ -29,9 +29,9 @@ import org.gradle.api.artifacts.ConfigurationContainer;
import org.gradle.api.plugins.JavaPlugin;
import org.gradle.api.plugins.JavaPluginConvention;
import org.gradle.api.tasks.SourceSet;
import org.gradle.api.tasks.bundling.AbstractArchiveTask;
import org.gradle.api.tasks.compile.JavaCompile;
import org.gradle.api.tasks.javadoc.Javadoc;
import org.gradle.jvm.tasks.Jar;
import net.fabricmc.loom.LoomGradleExtension;
import net.fabricmc.loom.build.mixin.JavaApInvoker;
@ -132,7 +132,7 @@ public final class CompileConfiguration {
if (extension.remapMod) {
RemapConfiguration.setupDefaultRemap(project);
} else {
AbstractArchiveTask jarTask = (AbstractArchiveTask) project.getTasks().getByName("jar");
Jar jarTask = (Jar) project.getTasks().getByName("jar");
extension.getUnmappedModCollection().from(jarTask);
}

View File

@ -0,0 +1,30 @@
/*
* This file is part of fabric-loom, licensed under the MIT License (MIT).
*
* Copyright (c) 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;
import com.google.gson.JsonObject;
public record InstallerData(String version, JsonObject installerJson) {
}

View File

@ -0,0 +1,91 @@
/*
* This file is part of fabric-loom, licensed under the MIT License (MIT).
*
* Copyright (c) 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;
import java.util.Optional;
import java.util.jar.Attributes;
import java.util.jar.Manifest;
import org.gradle.api.Project;
import org.gradle.util.GradleVersion;
import net.fabricmc.loom.LoomGradleExtension;
import net.fabricmc.loom.LoomGradlePlugin;
import net.fabricmc.loom.util.Constants;
import net.fabricmc.tinyremapper.TinyRemapper;
public final record JarManifestConfiguration(Project project) {
public void configure(Manifest manifest) {
// Dont set when running the reproducible build tests as it will break them when anything updates
if (Boolean.getBoolean("loom.test.reproducible")) {
return;
}
LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class);
Attributes attributes = manifest.getMainAttributes();
var tinyRemapperVersion = Optional.ofNullable(TinyRemapper.class.getPackage().getImplementationVersion());
attributes.putValue("Fabric-Gradle-Version", GradleVersion.current().getVersion());
attributes.putValue("Fabric-Loom-Version", LoomGradlePlugin.LOOM_VERSION);
attributes.putValue("Fabric-Mixin-Compile-Extensions-Version", Constants.Dependencies.Versions.MIXIN_COMPILE_EXTENSIONS);
attributes.putValue("Fabric-Minecraft-Version", extension.getMinecraftProvider().minecraftVersion());
tinyRemapperVersion.ifPresent(s -> attributes.putValue("Fabric-Tiny-Remapper-Version", s));
getLoaderVersion().ifPresent(s -> attributes.putValue("Fabric-Loader-Version", s));
// This can be overridden by mods if required
if (!attributes.containsKey("Fabric-Mixin-Version")) {
addMixinVersion(attributes);
}
}
private void addMixinVersion(Attributes attributes) {
// Not super ideal that this uses the mod compile classpath, should prob look into making this not a thing at somepoint
var dependency = project.getConfigurations().getByName(Constants.Configurations.LOADER_DEPENDENCIES)
.getDependencies()
.stream()
.filter(dep -> "sponge-mixin".equals(dep.getName()))
.findFirst();
if (dependency.isEmpty()) {
project.getLogger().warn("Could not determine Mixin version for jar manifest");
return;
}
attributes.putValue("Fabric-Mixin-Version", dependency.get().getVersion());
attributes.putValue("Fabric-Mixin-Group", dependency.get().getGroup());
}
private Optional<String> getLoaderVersion() {
LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class);
if (extension.getInstallerData() == null) {
project.getLogger().warn("Could not determine fabric loader version for jar manifest");
return Optional.empty();
}
return Optional.of(extension.getInstallerData().version());
}
}

View File

@ -140,28 +140,30 @@ public class LoomDependencyManager {
SourceRemapper sourceRemapper = new SourceRemapper(project, true);
String mappingsKey = mappingsProvider.getMappingsKey();
if (extension.getInstallerJson() == null) {
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 (File input : configuration.resolve()) {
for (Dependency dependency : configuration.getAllDependencies()) {
for (File input : configuration.files(dependency)) {
JsonObject jsonObject = ModProcessor.readInstallerJson(input, project);
if (jsonObject != null) {
if (extension.getInstallerJson() != 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.setInstallerJson(jsonObject);
handleInstallerJson(extension.getInstallerJson(), project);
extension.setInstallerData(new InstallerData(dependency.getVersion(), jsonObject));
handleInstallerJson(jsonObject, project);
}
}
}
}
if (extension.getInstallerJson() == null) {
if (extension.getInstallerData() == null) {
project.getLogger().warn("fabric-installer.json not found in classpath!");
}

View File

@ -120,7 +120,7 @@ public class RunConfig {
if (extension.getLoaderLaunchMethod().equals("launchwrapper")) {
// if installer.json found...
JsonObject installerJson = extension.getInstallerJson();
JsonObject installerJson = extension.getInstallerData().installerJson();
if (installerJson != null) {
List<String> sideKeys = ImmutableList.of(environment, "common");
@ -244,7 +244,7 @@ public class RunConfig {
}
private static String getMainClass(String side, LoomGradleExtension extension, String defaultMainClass) {
JsonObject installerJson = extension.getInstallerJson();
JsonObject installerJson = extension.getInstallerData().installerJson();
if (installerJson != null && installerJson.has("mainClass")) {
JsonElement mainClassJson = installerJson.get("mainClass");

View File

@ -27,6 +27,8 @@ package net.fabricmc.loom.task;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
@ -34,6 +36,8 @@ import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import java.util.jar.Manifest;
import java.util.zip.ZipEntry;
import com.google.common.base.Preconditions;
import org.gradle.api.Action;
@ -48,15 +52,18 @@ import org.gradle.api.tasks.TaskAction;
import org.gradle.jvm.tasks.Jar;
import org.jetbrains.annotations.ApiStatus;
import org.zeroturnaround.zip.ZipUtil;
import org.zeroturnaround.zip.transform.StreamZipEntryTransformer;
import org.zeroturnaround.zip.transform.ZipEntryTransformerEntry;
import net.fabricmc.loom.LoomGradleExtension;
import net.fabricmc.loom.build.JarRemapper;
import net.fabricmc.loom.build.MixinRefmapHelper;
import net.fabricmc.loom.build.nesting.NestedJarPathProvider;
import net.fabricmc.loom.build.nesting.JarNester;
import net.fabricmc.loom.build.nesting.MergedNestedJarProvider;
import net.fabricmc.loom.build.nesting.NestedDependencyProvider;
import net.fabricmc.loom.build.nesting.NestedJarPathProvider;
import net.fabricmc.loom.build.nesting.NestedJarProvider;
import net.fabricmc.loom.configuration.JarManifestConfiguration;
import net.fabricmc.loom.configuration.accesswidener.AccessWidenerJarProcessor;
import net.fabricmc.loom.configuration.providers.mappings.MappingsProviderImpl;
import net.fabricmc.loom.util.Constants;
@ -67,6 +74,8 @@ import net.fabricmc.tinyremapper.TinyRemapper;
import net.fabricmc.tinyremapper.TinyUtils;
public class RemapJarTask extends Jar {
private static final String MANIFEST_PATH = "META-INF/MANIFEST.MF";
private final RegularFileProperty input;
private final Property<Boolean> addNestedDependencies;
private final Property<Boolean> addDefaultNestedDependencies;
@ -174,6 +183,23 @@ public class RemapJarTask extends Jar {
Preconditions.checkArgument(replaced, "Failed to remap access widener");
}
// Add data to the manifest
boolean transformed = ZipUtil.transformEntries(data.output.toFile(), new ZipEntryTransformerEntry[]{
new ZipEntryTransformerEntry(MANIFEST_PATH, new StreamZipEntryTransformer() {
@Override
protected void transform(ZipEntry zipEntry, InputStream in, OutputStream out) throws IOException {
var manifest = new Manifest(in);
var manifestConfiguration = new JarManifestConfiguration(project);
manifestConfiguration.configure(manifest);
manifest.getMainAttributes().putValue("Fabric-Mapping-Namespace", toM);
manifest.write(out);
}
})
});
Preconditions.checkArgument(transformed, "Failed to transform jar manifest");
if (isReproducibleFileOrder() || !isPreserveFileTimestamps()) {
try {
ZipReprocessorUtil.reprocessZip(output.toFile(), isReproducibleFileOrder(), isPreserveFileTimestamps());

View File

@ -30,7 +30,9 @@ import com.google.common.io.Files
import net.fabricmc.loom.test.util.ProjectTestTrait
import spock.lang.Specification
import spock.lang.Unroll
import spock.util.environment.RestoreSystemProperties
import static java.lang.System.setProperty
import static org.gradle.testkit.runner.TaskOutcome.SUCCESS
class ReproducibleBuildTest extends Specification implements ProjectTestTrait {
@ -39,9 +41,11 @@ class ReproducibleBuildTest extends Specification implements ProjectTestTrait {
"reproducible"
}
@RestoreSystemProperties
@Unroll
def "build (gradle #gradle)"() {
when:
setProperty('loom.test.reproducible', 'true')
def result = create("build", gradle)
then:
result.task(":build").outcome == SUCCESS
@ -49,8 +53,8 @@ class ReproducibleBuildTest extends Specification implements ProjectTestTrait {
getOutputHash("fabric-example-mod-1.0.0-sources.jar") in sourceHash // Done for different line endings.
where:
gradle | modHash | sourceHash
DEFAULT_GRADLE | "0f954aa060fd8fc005e834c7cd271303" | ["be31766e6cafbe4ae3bca9e35ba63169", "7348b0bd87d36d7ec6f3bca9c2b66062"]
PRE_RELEASE_GRADLE | "0f954aa060fd8fc005e834c7cd271303" | ["be31766e6cafbe4ae3bca9e35ba63169", "7348b0bd87d36d7ec6f3bca9c2b66062"]
DEFAULT_GRADLE | "ed3306ef60f434c55048cba8de5dab95" | ["be31766e6cafbe4ae3bca9e35ba63169", "7348b0bd87d36d7ec6f3bca9c2b66062"]
PRE_RELEASE_GRADLE | "ed3306ef60f434c55048cba8de5dab95" | ["be31766e6cafbe4ae3bca9e35ba63169", "7348b0bd87d36d7ec6f3bca9c2b66062"]
}
String getOutputHash(String name) {

View File

@ -24,13 +24,14 @@
package net.fabricmc.loom.test.integration
import net.fabricmc.loom.test.util.ArchiveAssertionsTrait
import net.fabricmc.loom.test.util.ProjectTestTrait
import spock.lang.Specification
import spock.lang.Unroll
import static org.gradle.testkit.runner.TaskOutcome.SUCCESS
class SimpleProjectTest extends Specification implements ProjectTestTrait {
class SimpleProjectTest extends Specification implements ProjectTestTrait, ArchiveAssertionsTrait {
@Override
String name() {
"simple"
@ -42,6 +43,7 @@ class SimpleProjectTest extends Specification implements ProjectTestTrait {
def result = create("build", gradle)
then:
result.task(":build").outcome == SUCCESS
getArchiveEntry("fabric-example-mod-1.0.0.jar", "META-INF/MANIFEST.MF").contains("Fabric-Loom-Version: 0.0.0+unknown")
where:
gradle | _
DEFAULT_GRADLE | _