Skip to content

Commit

Permalink
Promote native dependencies to compile-time dependencies if they're i…
Browse files Browse the repository at this point in the history
…n all platforms
  • Loading branch information
shartte committed Dec 9, 2024
1 parent 999449c commit ad19379
Show file tree
Hide file tree
Showing 3 changed files with 177 additions and 2 deletions.
1 change: 1 addition & 0 deletions buildSrc/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@ repositories {

dependencies {
implementation 'de.undercouch.download:de.undercouch.download.gradle.plugin:5.5.0'
implementation 'org.apache.maven:maven-artifact:3.9.9'
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,16 @@ package net.neoforged.minecraftdependencies
import groovy.json.JsonOutput
import groovy.json.JsonSlurper
import groovy.transform.CompileStatic
import org.apache.maven.artifact.versioning.ComparableVersion
import org.gradle.api.DefaultTask
import org.gradle.api.file.RegularFileProperty
import org.gradle.api.provider.Property
import org.gradle.api.tasks.*
import org.gradle.api.tasks.Input
import org.gradle.api.tasks.InputFile
import org.gradle.api.tasks.OutputFile
import org.gradle.api.tasks.PathSensitive
import org.gradle.api.tasks.PathSensitivity
import org.gradle.api.tasks.TaskAction

import javax.inject.Inject
import java.util.zip.ZipFile
Expand Down Expand Up @@ -48,9 +54,10 @@ abstract class GenerateModuleMetadata extends DefaultTask implements HasMinecraf
metadata.variants = variants

List<String> clientDeps = []
List<String> clientCompileOnlyDeps = []
List<String> serverDeps = []
Map<String, List<String>> clientNatives = [:]
getMcDeps(serverDeps, clientDeps, clientNatives)
getMcDeps(serverDeps, clientDeps, clientCompileOnlyDeps, clientNatives)

Map metaJson = new JsonSlurper().parse(meta.get().asFile) as Map
int javaVersion = (metaJson.javaVersion as Map).majorVersion as int
Expand Down Expand Up @@ -79,6 +86,7 @@ abstract class GenerateModuleMetadata extends DefaultTask implements HasMinecraf
if (objcBridge) {
clientDepEntries.add(depOf(objcBridge))
}
clientDepEntries.addAll(depsOf(clientCompileOnlyDeps))

variants.add([
name : 'clientCompileDependencies',
Expand Down Expand Up @@ -187,6 +195,50 @@ abstract class GenerateModuleMetadata extends DefaultTask implements HasMinecraf
}
}
}

// Remove duplicates in natives
for (var libs in clientNatives.values()) {
var dedupedLibs = new LinkedHashSet(libs)
libs.clear()
libs.addAll(dedupedLibs)
}

// Promote natives to compile time dependencies if the same G+A+Classifier is present for all platforms
// Use the lowest version. This happens on some versions (i.e. 1.18.2) where lwjgl and all such dependencies
// are used in a lower version on OSX
for (String windowNativeArtifact in clientNatives.getOrDefault(platforms[0], [])) {
var coordinate = MavenCoordinate.parse(windowNativeArtifact)
var version = new ComparableVersion(coordinate.version())

var inAllPlatforms = true
for (var otherPlatform in platforms.drop(1)) {
var found = false
for (var otherPlatformArtifact in clientNatives.getOrDefault(otherPlatform, [])) {
var otherPlatformCoordinate = MavenCoordinate.parse(otherPlatformArtifact)
if (coordinate.equalsIgnoringVersion(otherPlatformCoordinate)) {
found = true
var otherVersion = new ComparableVersion(otherPlatformCoordinate.version())
if (otherVersion < version) {
version = otherVersion // use lowest
}
break
}
}
if (!found) {
inAllPlatforms = false
break
}
}

if (inAllPlatforms) {
println("Promoting " + coordinate + " (" + version + ") from natives to compile time dependency")
coordinate = coordinate.withVersion(version.toString())
if (client.stream().map(MavenCoordinate::parse).noneMatch { c -> c.equalsIgnoringVersion(coordinate) }) {
clientCompileOnly.add(coordinate.toString())
}
}
}

try (def zf = new ZipFile(serverJar.get().getAsFile())) {
def entry = zf.getEntry('META-INF/libraries.list')
if (entry != null) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
package net.neoforged.minecraftdependencies;

import java.net.URI;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Objects;

/**
* Models the Maven coordinates for an artifact.
*/
public record MavenCoordinate(String groupId, String artifactId, String extension, String classifier, String version) {
public MavenCoordinate {
Objects.requireNonNull(groupId);
Objects.requireNonNull(artifactId);
Objects.requireNonNull(version);
if (extension == null) {
extension = "";
}
if (classifier == null) {
classifier = "";
}
}

/**
* Valid forms:
* <ul>
* <li>{@code groupId:artifactId:version}</li>
* <li>{@code groupId:artifactId:version:classifier}</li>
* <li>{@code groupId:artifactId:version:classifier@extension}</li>
* <li>{@code groupId:artifactId:version@extension}</li>
* </ul>
*/
public static MavenCoordinate parse(String coordinate) {
var coordinateAndExt = coordinate.split("@");
String extension = "";
if (coordinateAndExt.length > 2) {
throw new IllegalArgumentException("Malformed Maven coordinate: " + coordinate);
} else if (coordinateAndExt.length == 2) {
extension = coordinateAndExt[1];
coordinate = coordinateAndExt[0];
}

var parts = coordinate.split(":");
if (parts.length != 3 && parts.length != 4) {
throw new IllegalArgumentException("Malformed Maven coordinate: " + coordinate);
}

var groupId = parts[0];
var artifactId = parts[1];
var version = parts[2];
var classifier = parts.length == 4 ? parts[3] : "";
return new MavenCoordinate(groupId, artifactId, extension, classifier, version);
}

/**
* Constructs a path relative to the root of a Maven repository pointing to the artifact expressed through
* these coordinates.
*/
public Path toRelativeRepositoryPath() {
final String fileName = artifactId + "-" + version +
(!classifier.isEmpty() ? "-" + classifier : "") +
(!extension.isEmpty() ? "." + extension : ".jar");

String[] groups = groupId.split("\\.");
Path result = Paths.get(groups[0]);
for (int i = 1; i < groups.length; i++) {
result = result.resolve(groups[i]);
}

return result.resolve(artifactId).resolve(version).resolve(fileName);
}

@Override
public String toString() {
var result = new StringBuilder();
result.append(groupId).append(":").append(artifactId).append(":").append(version);
if (!classifier.isEmpty()) {
result.append(":").append(classifier);
}
if (!extension.isEmpty()) {
result.append("@").append(extension);
}
return result.toString();
}

public URI toRepositoryUri(URI baseUri) {
var originalBaseUri = baseUri.toString();
var relativePath = toRelativeRepositoryPath().toString().replace('\\', '/');
if (originalBaseUri.endsWith("/")) {
return URI.create(originalBaseUri + relativePath);
} else {
return URI.create(originalBaseUri + "/" + relativePath);
}
}

public boolean equalsIgnoringVersion(MavenCoordinate other) {
return groupId.equals(other.groupId)
&& artifactId.equals(other.artifactId)
&& extension.equals(other.extension)
&& classifier.equals(other.classifier);
}

public MavenCoordinate withClassifier(String classifier) {
return new MavenCoordinate(
groupId,
artifactId,
extension,
classifier,
version
);
}

public MavenCoordinate withVersion(String version) {
return new MavenCoordinate(
groupId,
artifactId,
extension,
classifier,
version
);
}
}

0 comments on commit ad19379

Please sign in to comment.