Resolve libraries for all platforms when generating verification metadata. (#1286)

* Resolve libraries for all platforms when generating verification metadata.

* Fix build
This commit is contained in:
modmuss
2025-04-07 21:01:45 +01:00
committed by GitHub
parent 0012682ec7
commit 4165168558
6 changed files with 138 additions and 0 deletions

View File

@@ -123,4 +123,9 @@ public interface LoomGradleExtension extends LoomGradleExtensionAPI {
boolean isConfigurationCacheActive();
boolean isProjectIsolationActive();
/**
* @return true when '--write-verification-metadata` is set
*/
boolean isCollectingDependencyVerificationMetadata();
}

View File

@@ -31,6 +31,7 @@ import java.util.List;
import org.gradle.api.JavaVersion;
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.ModuleDependency;
@@ -94,6 +95,10 @@ public class MinecraftLibraryProvider {
if (provideServer) {
provideServerLibraries();
}
if (extension.isCollectingDependencyVerificationMetadata()) {
resolveAllLibraries();
}
}
private void provideClientLibraries() {
@@ -114,6 +119,22 @@ public class MinecraftLibraryProvider {
processLibraries.forEach(this::applyServerLibrary);
}
/**
* When Gradle is writing dependency verification metadata, we need to resolve all libraries across all platforms,
* to ensure that they are captured.
*/
private void resolveAllLibraries() {
project.getLogger().info("Resolving all libraries for dependency verification metadata generation");
final List<Library> libraries = MinecraftLibraryHelper.getAllLibraries(minecraftProvider.getVersionInfo());
Configuration detachedConfiguration = project.getConfigurations().detachedConfiguration(
libraries.stream()
.map(library -> project.getDependencies().create(library.mavenNotation()))
.toArray(Dependency[]::new)
);
detachedConfiguration.getFiles();
}
private List<Library> processLibraries(List<Library> libraries) {
final LibraryContext libraryContext = new LibraryContext(minecraftProvider.getVersionInfo(), getTargetRuntimeJavaVersion());
return processorManager.processLibraries(libraries, libraryContext);

View File

@@ -27,6 +27,7 @@ package net.fabricmc.loom.configuration.providers.minecraft.library;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -72,6 +73,35 @@ public class MinecraftLibraryHelper {
return Collections.unmodifiableList(libraries);
}
public static List<Library> getAllLibraries(MinecraftVersionMeta versionMeta) {
var libraries = new ArrayList<Library>();
for (MinecraftVersionMeta.Library library : versionMeta.libraries()) {
if (library.artifact() != null) {
Library mavenLib = Library.fromMaven(library.name(), Library.Target.COMPILE);
// Versions that have the natives on the classpath, attempt to target them as natives.
if (mavenLib.classifier() != null && mavenLib.classifier().startsWith("natives-")) {
mavenLib = mavenLib.withTarget(Library.Target.NATIVES);
}
libraries.add(mavenLib);
}
Map<String, MinecraftVersionMeta.Download> classifiers = library.downloads().classifiers();
if (classifiers == null) {
continue;
}
for (MinecraftVersionMeta.Download download : classifiers.values()) {
libraries.add(downloadToLibrary(download));
}
}
return Collections.unmodifiableList(libraries);
}
private static Library downloadToLibrary(MinecraftVersionMeta.Download download) {
final String path = download.path();
final Matcher matcher = NATIVES_PATTERN.matcher(path);

View File

@@ -77,6 +77,7 @@ public abstract class LoomGradleExtensionImpl extends LoomGradleExtensionApiImpl
private final ListProperty<LibraryProcessorManager.LibraryProcessorFactory> libraryProcessorFactories;
private final boolean configurationCacheActive;
private final boolean isolatedProjectsActive;
private final boolean isCollectingDependencyVerificationMetadata;
@Inject
protected abstract BuildFeatures getBuildFeatures();
@@ -106,6 +107,7 @@ public abstract class LoomGradleExtensionImpl extends LoomGradleExtensionApiImpl
configurationCacheActive = getBuildFeatures().getConfigurationCache().getActive().get();
isolatedProjectsActive = getBuildFeatures().getIsolatedProjects().getActive().get();
isCollectingDependencyVerificationMetadata = !project.getGradle().getStartParameter().getWriteDependencyVerifications().isEmpty();
if (refreshDeps) {
project.getLogger().lifecycle("Refresh dependencies is in use, loom will be significantly slower.");
@@ -306,4 +308,9 @@ public abstract class LoomGradleExtensionImpl extends LoomGradleExtensionApiImpl
public boolean isProjectIsolationActive() {
return isolatedProjectsActive;
}
@Override
public boolean isCollectingDependencyVerificationMetadata() {
return isCollectingDependencyVerificationMetadata;
}
}

View File

@@ -24,6 +24,7 @@
package net.fabricmc.loom.test.integration
import org.intellij.lang.annotations.Language
import spock.lang.Specification
import spock.lang.Stepwise
import spock.lang.Unroll
@@ -58,6 +59,71 @@ class SignedProjectTest extends Specification implements MockMavenServerTrait, G
version << STANDARD_TEST_VERSIONS
}
@Unroll
def "dependency verification #version"() {
setup:
def gradle = gradleProject(project: "minimalBase", version: version)
gradle.buildGradle << """
dependencies {
minecraft 'com.mojang:minecraft:1.21.5'
mappings 'net.fabricmc:yarn:1.21.5+build.1:v2'
modImplementation 'net.fabricmc:fabric-loader:0.16.12'
modImplementation 'net.fabricmc.fabric-api:fabric-api:0.119.9+1.21.5'
}
"""
def gradleDir = new File(gradle.projectDir, "gradle")
def verificationMetadata = new File(gradleDir, "verification-metadata.xml")
gradleDir.mkdirs()
verificationMetadata.text = METADATA_TEMPLATE
when:
def setupResult = gradle.run(tasks: [
"--write-verification-metadata",
"pgp,sha256",
"dependencies",
"--refresh-keys"
])
def checkResult = gradle.run(tasks: ["dependencies"])
def result = verificationMetadata.text
println(result)
then:
setupResult.task(":dependencies").outcome == SUCCESS
checkResult.task(":dependencies").outcome == SUCCESS
// A quick test to make sure that natives for all platforms are included in the verification metadata
result.contains("jtracy-1.0.29-natives-linux")
result.contains("jtracy-1.0.29-natives-macos")
result.contains("jtracy-1.0.29-natives-windows")
// Test that the Fabric PGP key is included in the verification metadata
result.contains("9E2B2198D20DC6E4B02C703111B891CFE51C003E")
where:
version << STANDARD_TEST_VERSIONS
}
@Language("xml")
static final String METADATA_TEMPLATE = """
<?xml version="1.0" encoding="UTF-8"?>
<verification-metadata xmlns="https://schema.gradle.org/dependency-verification" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="https://schema.gradle.org/dependency-verification https://schema.gradle.org/dependency-verification/dependency-verification-1.3.xsd">
<configuration>
<verify-metadata>true</verify-metadata>
<verify-signatures>true</verify-signatures>
<key-servers>
<key-server uri="https://keyserver.ubuntu.com"/>
<key-server uri="https://keys.openpgp.org"/>
</key-servers>
<trusted-artifacts>
<trust group="net.minecraft" regex="true" reason="Generated via loom"/>
<trust group="remapped.*" regex="true" reason="Generated via loom"/>
</trusted-artifacts>
</configuration>
</verification-metadata>
""".trim()
static final String PRIVATE_KEY = """
-----BEGIN PGP PRIVATE KEY BLOCK-----

View File

@@ -76,4 +76,13 @@ class MinecraftLibraryHelperTest extends Specification {
then:
libraries.find { it.is("ca.weblite:java-objc-bridge") && it.target() == Library.Target.NATIVES } == null
}
def "get all libraries"() {
when:
def meta = MinecraftTestUtils.getVersionMeta("1.21.5")
def libraries = MinecraftLibraryHelper.getAllLibraries(meta)
then:
libraries.size() > 0
}
}