Merge 1.2, part 2

This commit is contained in:
Juuz
2023-04-23 10:35:54 +03:00
68 changed files with 3241 additions and 1025 deletions

View File

@@ -14,7 +14,7 @@ jobs:
strategy:
fail-fast: false
matrix:
version: [7.5.1-jdk17]
version: [8.1.0-jdk17]
runs-on: ubuntu-22.04
container:
image: gradle:${{ matrix.version }}
@@ -36,7 +36,7 @@ jobs:
runs-on: ubuntu-22.04
container:
image: gradle:7.5.1-jdk17
image: gradle:8.1.0-jdk17
options: --user root
steps:
@@ -55,7 +55,7 @@ jobs:
strategy:
fail-fast: false
matrix:
version: [7.5.1-jdk17]
version: [8.1.0-jdk17]
test: ${{ fromJson(needs.prepare_test_matrix.outputs.matrix) }}
runs-on: ubuntu-22.04
@@ -136,7 +136,7 @@ jobs:
strategy:
fail-fast: false
matrix:
java: [ 17, 18 ]
java: [ 17, 20 ]
os: [ windows-2022, ubuntu-22.04, macos-12 ]
runs-on: ${{ matrix.os }}

View File

@@ -14,7 +14,7 @@ import org.gradle.util.GradleVersion;
*/
@SuppressWarnings("unused")
public class LoomGradlePluginBootstrap implements Plugin<PluginAware> {
private static final int MIN_SUPPORTED_MAJOR_GRADLE_VERSION = 7;
private static final String MIN_SUPPORTED_GRADLE_VERSION = "8.1";
private static final int MIN_SUPPORTED_MAJOR_JAVA_VERSION = 17;
private static final int MIN_SUPPORTED_MAJOR_IDEA_VERSION = 2021;
@@ -40,7 +40,7 @@ public class LoomGradlePluginBootstrap implements Plugin<PluginAware> {
List<String> errors = new ArrayList<>();
if (!isValidGradleRuntime()) {
errors.add(String.format("You are using an outdated version of Gradle (%s). Gradle %d or higher is required.", GradleVersion.current().getVersion(), MIN_SUPPORTED_MAJOR_GRADLE_VERSION));
errors.add(String.format("You are using an outdated version of Gradle (%s). Gradle %s or higher is required.", GradleVersion.current().getVersion(), MIN_SUPPORTED_GRADLE_VERSION));
}
if (!isValidJavaRuntime()) {
@@ -73,7 +73,7 @@ public class LoomGradlePluginBootstrap implements Plugin<PluginAware> {
}
private static boolean isValidGradleRuntime() {
return getMajorGradleVersion() >= MIN_SUPPORTED_MAJOR_GRADLE_VERSION;
return GradleVersion.current().compareTo(GradleVersion.version(MIN_SUPPORTED_GRADLE_VERSION)) >= 0;
}
private static boolean isValidIdeaRuntime() {
@@ -87,11 +87,6 @@ public class LoomGradlePluginBootstrap implements Plugin<PluginAware> {
return ideaYear >= MIN_SUPPORTED_MAJOR_IDEA_VERSION;
}
private static int getMajorGradleVersion() {
String version = GradleVersion.current().getVersion();
return Integer.parseInt(version.substring(0, version.indexOf(".")));
}
BootstrappedPlugin getActivePlugin() {
try {
return (BootstrappedPlugin) Class.forName(PLUGIN_CLASS_NAME).getConstructor().newInstance();

View File

@@ -8,9 +8,9 @@ plugins {
id 'checkstyle'
id 'jacoco'
id 'codenarc'
id "org.jetbrains.kotlin.jvm" version "1.6.10" // Must match the version included with gradle.
id "com.diffplug.spotless" version "6.13.0"
id "org.gradle.test-retry" version "1.5.1"
id "org.jetbrains.kotlin.jvm" version "1.8.0" // Must match the version included with gradle.
id "com.diffplug.spotless" version "6.18.0"
id "org.gradle.test-retry" version "1.5.2"
}
tasks.withType(JavaCompile).configureEach {
@@ -76,13 +76,13 @@ dependencies {
// libraries
implementation ('commons-io:commons-io:2.11.0')
implementation ('com.google.code.gson:gson:2.10.1')
implementation ('com.fasterxml.jackson.core:jackson-databind:2.14.1')
implementation ('com.fasterxml.jackson.core:jackson-databind:2.14.2')
implementation ('com.google.guava:guava:31.1-jre')
implementation ('org.ow2.asm:asm:9.4')
implementation ('org.ow2.asm:asm-analysis:9.4')
implementation ('org.ow2.asm:asm-commons:9.4')
implementation ('org.ow2.asm:asm-tree:9.4')
implementation ('org.ow2.asm:asm-util:9.4')
implementation ('org.ow2.asm:asm:9.5')
implementation ('org.ow2.asm:asm-analysis:9.5')
implementation ('org.ow2.asm:asm-commons:9.5')
implementation ('org.ow2.asm:asm-tree:9.5')
implementation ('org.ow2.asm:asm-util:9.5')
implementation ('me.tongfei:progressbar:0.9.0')
// game handling utils
@@ -109,12 +109,12 @@ dependencies {
implementation ('dev.architectury:mercury:0.1.2.15')
// Kotlin
implementation('org.jetbrains.kotlinx:kotlinx-metadata-jvm:0.5.0') {
implementation('org.jetbrains.kotlinx:kotlinx-metadata-jvm:0.6.0') {
transitive = false
}
// Kapt integration
compileOnly('org.jetbrains.kotlin:kotlin-gradle-plugin:1.6.10') // Must match the version included with gradle.
compileOnly('org.jetbrains.kotlin:kotlin-gradle-plugin:1.8.0') // Must match the version included with gradle.
// Forge patches
implementation ('net.minecraftforge:installertools:1.2.0')
@@ -133,13 +133,13 @@ dependencies {
exclude module: 'groovy-all'
}
testImplementation 'org.junit.jupiter:junit-jupiter-engine:5.9.2'
testImplementation ('io.javalin:javalin:5.3.1') {
testImplementation ('io.javalin:javalin:5.4.2') {
exclude group: 'org.jetbrains.kotlin'
}
testImplementation 'org.mockito:mockito-core:5.0.0'
testImplementation 'org.mockito:mockito-core:5.2.0'
compileOnly 'org.jetbrains:annotations:24.0.0'
testCompileOnly 'org.jetbrains:annotations:24.0.0'
compileOnly 'org.jetbrains:annotations:24.0.1'
testCompileOnly 'org.jetbrains:annotations:24.0.1'
testCompileOnly ('net.fabricmc:sponge-mixin:0.11.4+mixin.0.8.5') {
transitive = false
@@ -223,7 +223,7 @@ jacocoTestReport {
reports {
xml.required = false
csv.required = false
html.destination file("${buildDir}/jacocoHtml")
html.outputLocation = file("${buildDir}/jacocoHtml")
}
}
@@ -354,9 +354,9 @@ task downloadGradleSources() {
doLast {
// Awful hack to find the gradle api location
def gradleApiFile = project.configurations.detachedConfiguration(dependencies.gradleApi()).files.stream()
.filter {
.find {
it.name.startsWith("gradle-api")
}.findFirst().orElseThrow()
}
def gradleApiSources = new File(gradleApiFile.absolutePath.replace(".jar", "-sources.jar"))
def url = "https://services.gradle.org/distributions/gradle-${GradleVersion.current().getVersion()}-src.zip"

Binary file not shown.

View File

@@ -1,5 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.5.1-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.1-all.zip
networkTimeout=10000
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

19
gradlew vendored
View File

@@ -55,7 +55,7 @@
# Darwin, MinGW, and NonStop.
#
# (3) This script is generated from the Groovy template
# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# within the Gradle project.
#
# You can find Gradle at https://github.com/gradle/gradle/.
@@ -80,13 +80,10 @@ do
esac
done
APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
APP_NAME="Gradle"
# This is normally unused
# shellcheck disable=SC2034
APP_BASE_NAME=${0##*/}
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD=maximum
@@ -143,12 +140,16 @@ fi
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
case $MAX_FD in #(
max*)
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC3045
MAX_FD=$( ulimit -H -n ) ||
warn "Could not query maximum file descriptor limit"
esac
case $MAX_FD in #(
'' | soft) :;; #(
*)
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC3045
ulimit -n "$MAX_FD" ||
warn "Could not set maximum file descriptor limit to $MAX_FD"
esac
@@ -193,6 +194,10 @@ if "$cygwin" || "$msys" ; then
done
fi
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Collect all arguments for the java command;
# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
# shell script including quotes and variable substitutions, so put them in

1
gradlew.bat vendored
View File

@@ -26,6 +26,7 @@ if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%"=="" set DIRNAME=.
@rem This is normally unused
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%

View File

@@ -1,7 +1,7 @@
/*
* This file is part of fabric-loom, licensed under the MIT License (MIT).
*
* Copyright (c) 2016-2022 FabricMC
* Copyright (c) 2016-2023 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
@@ -84,9 +84,11 @@ public class LoomGradlePlugin implements BootstrappedPlugin {
project.getExtensions().create(LoomGradleExtensionAPI.class, "loom", LoomGradleExtensionImpl.class, project, LoomFiles.create(project));
project.getExtensions().create("fabricApi", FabricApiExtension.class, project);
CompileConfiguration.setupConfigurations(project);
final CompileConfiguration compileConfiguration = new CompileConfiguration(project);
compileConfiguration.setupConfigurations();
IdeConfiguration.setup(project);
CompileConfiguration.configureCompile(project);
compileConfiguration.configureCompile();
MavenPublication.configure(project);
LoomTasks.registerTasks(project);
DecompilerConfiguration.setup(project);

View File

@@ -135,9 +135,9 @@ public class LoomRepositoryPlugin implements Plugin<PluginAware> {
});
}
public static void setupForLegacyVersions(Project project) {
public static void setupForLegacyVersions(RepositoryHandler repositories) {
// 1.4.7 contains an LWJGL version with an invalid maven pom, set the metadata sources to not use the pom for this version.
project.getRepositories().named("Mojang", MavenArtifactRepository.class, repo -> {
repositories.named("Mojang", MavenArtifactRepository.class, repo -> {
repo.metadataSources(sources -> {
// Only use the maven artifact and not the pom or gradle metadata.
sources.artifact();
@@ -146,9 +146,14 @@ public class LoomRepositoryPlugin implements Plugin<PluginAware> {
});
}
public static void forceLWJGLFromMavenCentral(Project project) {
public static void forceLWJGLFromMavenCentral(RepositoryHandler repositories) {
if (repositories.findByName("MavenCentralLWJGL") != null) {
// Already applied.
return;
}
// Force LWJGL from central, as it contains all the platform natives.
MavenArtifactRepository central = project.getRepositories().maven(repo -> {
MavenArtifactRepository central = repositories.maven(repo -> {
repo.setName("MavenCentralLWJGL");
repo.setUrl(ArtifactRepositoryContainer.MAVEN_CENTRAL_URL);
repo.content(content -> {
@@ -156,7 +161,7 @@ public class LoomRepositoryPlugin implements Plugin<PluginAware> {
});
});
project.getRepositories().exclusiveContent(repository -> {
repositories.exclusiveContent(repository -> {
repository.forRepositories(central);
repository.filter(filter -> {
filter.includeGroup("org.lwjgl");

View File

@@ -24,12 +24,13 @@
package net.fabricmc.loom.configuration;
import static net.fabricmc.loom.util.Constants.Configurations;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
import java.util.function.Consumer;
import org.gradle.api.NamedDomainObjectProvider;
@@ -84,11 +85,15 @@ import net.fabricmc.loom.util.service.ScopedSharedServiceManager;
import net.fabricmc.loom.util.service.SharedServiceManager;
public final class CompileConfiguration {
private CompileConfiguration() {
private final Project project;
private final ConfigurationContainer configurations;
public CompileConfiguration(Project project) {
this.project = project;
this.configurations = project.getConfigurations();
}
public static void setupConfigurations(Project project) {
final ConfigurationContainer configurations = project.getConfigurations();
public void setupConfigurations() {
final LoomGradleExtension extension = LoomGradleExtension.get(project);
project.afterEvaluate(project1 -> {
@@ -103,84 +108,98 @@ public final class CompileConfiguration {
}
});
configurations.register(Constants.Configurations.MOD_COMPILE_CLASSPATH, configuration -> configuration.setTransitive(true));
configurations.register(Constants.Configurations.MOD_COMPILE_CLASSPATH_MAPPED, configuration -> configuration.setTransitive(false));
NamedDomainObjectProvider<Configuration> serverDeps = configurations.register(Constants.Configurations.MINECRAFT_SERVER_DEPENDENCIES, configuration -> configuration.setTransitive(false));
configurations.register(Constants.Configurations.MINECRAFT_RUNTIME_DEPENDENCIES, configuration -> configuration.setTransitive(false));
configurations.register(Constants.Configurations.MINECRAFT_DEPENDENCIES, configuration -> {
configuration.extendsFrom(serverDeps.get());
configuration.setTransitive(false);
configurations.register(Configurations.MOD_COMPILE_CLASSPATH);
createNonTransitive(Configurations.MOD_COMPILE_CLASSPATH_MAPPED);
// Set up the Minecraft compile configurations.
var minecraftClientCompile = createNonTransitive(Configurations.MINECRAFT_CLIENT_COMPILE_LIBRARIES);
var minecraftServerCompile = createNonTransitive(Configurations.MINECRAFT_SERVER_COMPILE_LIBRARIES);
var minecraftCompile = createNonTransitive(Configurations.MINECRAFT_COMPILE_LIBRARIES);
minecraftCompile.configure(configuration -> {
configuration.extendsFrom(minecraftClientCompile.get());
configuration.extendsFrom(minecraftServerCompile.get());
});
configurations.register(Constants.Configurations.LOADER_DEPENDENCIES, configuration -> configuration.setTransitive(false));
configurations.register(Constants.Configurations.MINECRAFT, configuration -> configuration.setTransitive(false));
// Set up the minecraft runtime configurations, this extends from the compile configurations.
var minecraftClientRuntime = createNonTransitive(Configurations.MINECRAFT_CLIENT_RUNTIME_LIBRARIES);
var minecraftServerRuntime = createNonTransitive(Configurations.MINECRAFT_SERVER_RUNTIME_LIBRARIES);
// Runtime extends from compile
minecraftClientRuntime.configure(configuration -> configuration.extendsFrom(minecraftClientCompile.get()));
minecraftServerRuntime.configure(configuration -> configuration.extendsFrom(minecraftServerCompile.get()));
createNonTransitive(Configurations.MINECRAFT_RUNTIME_LIBRARIES).configure(minecraftRuntime -> {
minecraftRuntime.extendsFrom(minecraftClientRuntime.get());
minecraftRuntime.extendsFrom(minecraftServerRuntime.get());
});
createNonTransitive(Configurations.MINECRAFT_NATIVES);
createNonTransitive(Configurations.LOADER_DEPENDENCIES);
createNonTransitive(Configurations.MINECRAFT);
createNonTransitive(Configurations.INCLUDE);
createNonTransitive(Configurations.MAPPING_CONSTANTS);
configurations.register(Configurations.NAMED_ELEMENTS, configuration -> {
configuration.setCanBeConsumed(true);
configuration.setCanBeResolved(false);
configuration.extendsFrom(configurations.getByName(JavaPlugin.API_CONFIGURATION_NAME));
});
extendsFrom(JavaPlugin.COMPILE_ONLY_CONFIGURATION_NAME, Configurations.MAPPING_CONSTANTS);
if (extension.isForge()) {
configurations.register(Constants.Configurations.FORGE).configure(configuration -> configuration.setTransitive(false));
configurations.register(Constants.Configurations.FORGE_USERDEV).configure(configuration -> configuration.setTransitive(false));
configurations.register(Constants.Configurations.FORGE_INSTALLER).configure(configuration -> configuration.setTransitive(false));
configurations.register(Constants.Configurations.FORGE_UNIVERSAL).configure(configuration -> configuration.setTransitive(false));
createNonTransitive(Constants.Configurations.FORGE);
createNonTransitive(Constants.Configurations.FORGE_USERDEV);
createNonTransitive(Constants.Configurations.FORGE_INSTALLER);
createNonTransitive(Constants.Configurations.FORGE_UNIVERSAL);
configurations.register(Constants.Configurations.FORGE_DEPENDENCIES);
configurations.register(Constants.Configurations.FORGE_NAMED).configure(configuration -> configuration.setTransitive(false));
configurations.register(Constants.Configurations.FORGE_EXTRA).configure(configuration -> configuration.setTransitive(false));
configurations.register(Constants.Configurations.MCP_CONFIG).configure(configuration -> configuration.setTransitive(false));
createNonTransitive(Constants.Configurations.FORGE_NAMED);
createNonTransitive(Constants.Configurations.FORGE_EXTRA);
createNonTransitive(Constants.Configurations.MCP_CONFIG);
configurations.register(Constants.Configurations.FORGE_RUNTIME_LIBRARY).configure(configuration -> {
// Resolve for runtime usage
Usage javaRuntime = project.getObjects().named(Usage.class, Usage.JAVA_RUNTIME);
configuration.attributes(attributes -> attributes.attribute(Usage.USAGE_ATTRIBUTE, javaRuntime));
});
extendsFrom(Constants.Configurations.MINECRAFT_SERVER_DEPENDENCIES, Constants.Configurations.FORGE_DEPENDENCIES, project);
extendsFrom(Constants.Configurations.MINECRAFT_SERVER_DEPENDENCIES, Constants.Configurations.FORGE_DEPENDENCIES);
extendsFrom(Constants.Configurations.FORGE_RUNTIME_LIBRARY, Constants.Configurations.FORGE_DEPENDENCIES, project);
extendsFrom(Constants.Configurations.FORGE_RUNTIME_LIBRARY, Constants.Configurations.MINECRAFT_DEPENDENCIES, project);
extendsFrom(Constants.Configurations.FORGE_RUNTIME_LIBRARY, Constants.Configurations.FORGE_EXTRA, project);
extendsFrom(Constants.Configurations.FORGE_RUNTIME_LIBRARY, Constants.Configurations.FORGE_NAMED, project);
extendsFrom(Constants.Configurations.FORGE_RUNTIME_LIBRARY, Constants.Configurations.FORGE_DEPENDENCIES);
extendsFrom(Constants.Configurations.FORGE_RUNTIME_LIBRARY, Constants.Configurations.MINECRAFT_DEPENDENCIES);
extendsFrom(Constants.Configurations.FORGE_RUNTIME_LIBRARY, Constants.Configurations.FORGE_EXTRA);
extendsFrom(Constants.Configurations.FORGE_RUNTIME_LIBRARY, Constants.Configurations.FORGE_NAMED);
// Include any user-defined libraries on the runtime CP.
// (All the other superconfigurations are already on there.)
extendsFrom(JavaPlugin.RUNTIME_CLASSPATH_CONFIGURATION_NAME, Constants.Configurations.FORGE_RUNTIME_LIBRARY, project);
extendsFrom(JavaPlugin.RUNTIME_CLASSPATH_CONFIGURATION_NAME, Constants.Configurations.FORGE_RUNTIME_LIBRARY);
extendsFrom(JavaPlugin.COMPILE_CLASSPATH_CONFIGURATION_NAME, Constants.Configurations.FORGE_NAMED, project);
extendsFrom(JavaPlugin.RUNTIME_CLASSPATH_CONFIGURATION_NAME, Constants.Configurations.FORGE_NAMED, project);
extendsFrom(JavaPlugin.TEST_COMPILE_CLASSPATH_CONFIGURATION_NAME, Constants.Configurations.FORGE_NAMED, project);
extendsFrom(JavaPlugin.TEST_RUNTIME_CLASSPATH_CONFIGURATION_NAME, Constants.Configurations.FORGE_NAMED, project);
extendsFrom(JavaPlugin.COMPILE_CLASSPATH_CONFIGURATION_NAME, Constants.Configurations.FORGE_EXTRA, project);
extendsFrom(JavaPlugin.RUNTIME_CLASSPATH_CONFIGURATION_NAME, Constants.Configurations.FORGE_EXTRA, project);
extendsFrom(JavaPlugin.TEST_COMPILE_CLASSPATH_CONFIGURATION_NAME, Constants.Configurations.FORGE_EXTRA, project);
extendsFrom(JavaPlugin.TEST_RUNTIME_CLASSPATH_CONFIGURATION_NAME, Constants.Configurations.FORGE_EXTRA, project);
extendsFrom(JavaPlugin.COMPILE_CLASSPATH_CONFIGURATION_NAME, Constants.Configurations.FORGE_NAMED);
extendsFrom(JavaPlugin.RUNTIME_CLASSPATH_CONFIGURATION_NAME, Constants.Configurations.FORGE_NAMED);
extendsFrom(JavaPlugin.TEST_COMPILE_CLASSPATH_CONFIGURATION_NAME, Constants.Configurations.FORGE_NAMED);
extendsFrom(JavaPlugin.TEST_RUNTIME_CLASSPATH_CONFIGURATION_NAME, Constants.Configurations.FORGE_NAMED);
extendsFrom(JavaPlugin.COMPILE_CLASSPATH_CONFIGURATION_NAME, Constants.Configurations.FORGE_EXTRA);
extendsFrom(JavaPlugin.RUNTIME_CLASSPATH_CONFIGURATION_NAME, Constants.Configurations.FORGE_EXTRA);
extendsFrom(JavaPlugin.TEST_COMPILE_CLASSPATH_CONFIGURATION_NAME, Constants.Configurations.FORGE_EXTRA);
extendsFrom(JavaPlugin.TEST_RUNTIME_CLASSPATH_CONFIGURATION_NAME, Constants.Configurations.FORGE_EXTRA);
}
configurations.register(Constants.Configurations.INCLUDE, configuration -> configuration.setTransitive(false)); // Dont get transitive deps
configurations.register(Constants.Configurations.MAPPING_CONSTANTS);
configurations.register(Constants.Configurations.NAMED_ELEMENTS, configuration -> {
configuration.setCanBeConsumed(true);
configuration.setCanBeResolved(false);
configuration.extendsFrom(configurations.getByName(JavaPlugin.API_CONFIGURATION_NAME));
});
extendsFrom(JavaPlugin.COMPILE_ONLY_CONFIGURATION_NAME, Constants.Configurations.MAPPING_CONSTANTS, project);
configurations.register(Constants.Configurations.MAPPINGS);
configurations.register(Constants.Configurations.MAPPINGS_FINAL);
configurations.register(Constants.Configurations.LOOM_DEVELOPMENT_DEPENDENCIES);
configurations.register(Constants.Configurations.UNPICK_CLASSPATH);
configurations.register(Constants.Configurations.LOCAL_RUNTIME);
extendsFrom(JavaPlugin.RUNTIME_CLASSPATH_CONFIGURATION_NAME, Constants.Configurations.LOCAL_RUNTIME, project);
configurations.register(Configurations.MAPPINGS);
configurations.register(Configurations.MAPPINGS_FINAL);
configurations.register(Configurations.LOOM_DEVELOPMENT_DEPENDENCIES);
configurations.register(Configurations.UNPICK_CLASSPATH);
configurations.register(Configurations.LOCAL_RUNTIME);
extendsFrom(JavaPlugin.RUNTIME_CLASSPATH_CONFIGURATION_NAME, Configurations.LOCAL_RUNTIME);
extension.createRemapConfigurations(SourceSetHelper.getMainSourceSet(project));
extendsFrom(Constants.Configurations.LOADER_DEPENDENCIES, Constants.Configurations.MINECRAFT_DEPENDENCIES, project);
extendsFrom(JavaPlugin.RUNTIME_CLASSPATH_CONFIGURATION_NAME, Configurations.MAPPINGS_FINAL);
extendsFrom(JavaPlugin.TEST_RUNTIME_CLASSPATH_CONFIGURATION_NAME, Configurations.MAPPINGS_FINAL);
extendsFrom(JavaPlugin.RUNTIME_CLASSPATH_CONFIGURATION_NAME, Constants.Configurations.MAPPINGS_FINAL, project);
extendsFrom(JavaPlugin.TEST_RUNTIME_CLASSPATH_CONFIGURATION_NAME, Constants.Configurations.MAPPINGS_FINAL, project);
extendsFrom(JavaPlugin.RUNTIME_CLASSPATH_CONFIGURATION_NAME, Constants.Configurations.LOOM_DEVELOPMENT_DEPENDENCIES, project);
extendsFrom(JavaPlugin.TEST_RUNTIME_CLASSPATH_CONFIGURATION_NAME, Constants.Configurations.LOOM_DEVELOPMENT_DEPENDENCIES, project);
extendsFrom(JavaPlugin.RUNTIME_CLASSPATH_CONFIGURATION_NAME, Constants.Configurations.MINECRAFT_RUNTIME_DEPENDENCIES, project);
extendsFrom(JavaPlugin.RUNTIME_CLASSPATH_CONFIGURATION_NAME, Configurations.MINECRAFT_RUNTIME_LIBRARIES);
// Add the dev time dependencies
project.getDependencies().add(Constants.Configurations.LOOM_DEVELOPMENT_DEPENDENCIES, Constants.Dependencies.DEV_LAUNCH_INJECTOR + Constants.Dependencies.Versions.DEV_LAUNCH_INJECTOR);
project.getDependencies().add(Constants.Configurations.LOOM_DEVELOPMENT_DEPENDENCIES, Constants.Dependencies.TERMINAL_CONSOLE_APPENDER + Constants.Dependencies.Versions.TERMINAL_CONSOLE_APPENDER);
project.getDependencies().add(Configurations.LOOM_DEVELOPMENT_DEPENDENCIES, Constants.Dependencies.DEV_LAUNCH_INJECTOR + Constants.Dependencies.Versions.DEV_LAUNCH_INJECTOR);
project.getDependencies().add(Configurations.LOOM_DEVELOPMENT_DEPENDENCIES, Constants.Dependencies.TERMINAL_CONSOLE_APPENDER + Constants.Dependencies.Versions.TERMINAL_CONSOLE_APPENDER);
project.getDependencies().add(JavaPlugin.COMPILE_ONLY_CONFIGURATION_NAME, Constants.Dependencies.JETBRAINS_ANNOTATIONS + Constants.Dependencies.Versions.JETBRAINS_ANNOTATIONS);
project.getDependencies().add(JavaPlugin.TEST_COMPILE_ONLY_CONFIGURATION_NAME, Constants.Dependencies.JETBRAINS_ANNOTATIONS + Constants.Dependencies.Versions.JETBRAINS_ANNOTATIONS);
@@ -191,7 +210,11 @@ public final class CompileConfiguration {
}
}
public static void configureCompile(Project project) {
private NamedDomainObjectProvider<Configuration> createNonTransitive(String name) {
return configurations.register(name, configuration -> configuration.setTransitive(false));
}
public void configureCompile() {
LoomGradleExtension extension = LoomGradleExtension.get(project);
project.getTasks().named(JavaPlugin.JAVADOC_TASK_NAME, Javadoc.class).configure(javadoc -> {
@@ -206,7 +229,7 @@ public final class CompileConfiguration {
final boolean previousRefreshDeps = extension.refreshDeps();
if (getAndLock(project)) {
if (getAndLock()) {
project.getLogger().lifecycle("Found existing cache lock file, rebuilding loom cache. This may have been caused by a failed or canceled build.");
extension.setRefreshDeps(true);
}
@@ -221,13 +244,13 @@ public final class CompileConfiguration {
extension.setDependencyManager(dependencyManager);
dependencyManager.handleDependencies(project, serviceManager);
releaseLock(project);
releaseLock();
extension.setRefreshDeps(previousRefreshDeps);
MixinExtension mixin = LoomGradleExtension.get(project).getMixin();
if (mixin.getUseLegacyMixinAp().get()) {
setupMixinAp(project, mixin);
setupMixinAp(mixin);
}
configureDecompileTasks(configContext);
@@ -249,12 +272,12 @@ public final class CompileConfiguration {
}
});
finalizedBy(project, "idea", "genIdeaWorkspace");
finalizedBy(project, "eclipse", "genEclipseRuns");
finalizedBy(project, "cleanEclipse", "cleanEclipseRuns");
finalizedBy("idea", "genIdeaWorkspace");
finalizedBy("eclipse", "genEclipseRuns");
finalizedBy("cleanEclipse", "cleanEclipseRuns");
// Add the "dev" jar to the "namedElements" configuration
project.artifacts(artifactHandler -> artifactHandler.add(Constants.Configurations.NAMED_ELEMENTS, project.getTasks().named("jar")));
project.artifacts(artifactHandler -> artifactHandler.add(Configurations.NAMED_ELEMENTS, project.getTasks().named("jar")));
// Ensure that the encoding is set to UTF-8, no matter what the system default is
// this fixes some edge cases with special characters not displaying correctly
@@ -277,7 +300,7 @@ public final class CompileConfiguration {
}
// This is not thread safe across projects synchronize it here just to be sure, might be possible to move this further down, but for now this will do.
private static synchronized void setupMinecraft(ConfigContext configContext) throws Exception {
private synchronized void setupMinecraft(ConfigContext configContext) throws Exception {
final Project project = configContext.project();
final LoomGradleExtension extension = configContext.extension();
final MinecraftJarConfiguration jarConfiguration = extension.getMinecraftJarConfiguration().get();
@@ -300,7 +323,7 @@ public final class CompileConfiguration {
minecraftProvider.provide();
}
final DependencyInfo mappingsDep = DependencyInfo.create(project, Constants.Configurations.MAPPINGS);
final DependencyInfo mappingsDep = DependencyInfo.create(project, Configurations.MAPPINGS);
final MappingConfiguration mappingConfiguration = MappingConfiguration.create(project, configContext.serviceManager(), mappingsDep, minecraftProvider);
extension.setMappingConfiguration(mappingConfiguration);
@@ -345,7 +368,7 @@ public final class CompileConfiguration {
}
}
private static void registerGameProcessors(ConfigContext configContext) {
private void registerGameProcessors(ConfigContext configContext) {
final LoomGradleExtension extension = configContext.extension();
final boolean enableTransitiveAccessWideners = extension.getEnableTransitiveAccessWideners().get();
@@ -366,7 +389,7 @@ public final class CompileConfiguration {
}
}
private static void setupMixinAp(Project project, MixinExtension mixin) {
private void setupMixinAp(MixinExtension mixin) {
mixin.init();
// Disable some things used by log4j via the mixin AP that prevent it from being garbage collected
@@ -394,22 +417,22 @@ public final class CompileConfiguration {
}
}
private static void configureDecompileTasks(ConfigContext configContext) {
private void configureDecompileTasks(ConfigContext configContext) {
final LoomGradleExtension extension = configContext.extension();
extension.getMinecraftJarConfiguration().get().getDecompileConfigurationBiFunction()
.apply(configContext, extension.getNamedMinecraftProvider()).afterEvaluation();
}
private static Path getLockFile(Project project) {
private Path getLockFile() {
final LoomGradleExtension extension = LoomGradleExtension.get(project);
final Path cacheDirectory = extension.getFiles().getUserCache().toPath();
final String pathHash = Checksum.projectHash(project);
return cacheDirectory.resolve("." + pathHash + ".lock");
}
private static boolean getAndLock(Project project) {
final Path lock = getLockFile(project);
private boolean getAndLock() {
final Path lock = getLockFile();
if (Files.exists(lock)) {
return true;
@@ -424,8 +447,8 @@ public final class CompileConfiguration {
return false;
}
private static void releaseLock(Project project) {
final Path lock = getLockFile(project);
private void releaseLock() {
final Path lock = getLockFile();
if (!Files.exists(lock)) {
return;
@@ -447,17 +470,11 @@ public final class CompileConfiguration {
}
}
public static void extendsFrom(List<String> parents, String b, Project project) {
for (String parent : parents) {
extendsFrom(parent, b, project);
}
}
public static void extendsFrom(String a, String b, Project project) {
public void extendsFrom(String a, String b) {
project.getConfigurations().getByName(a, configuration -> configuration.extendsFrom(project.getConfigurations().getByName(b)));
}
private static void finalizedBy(Project project, String a, String b) {
private void finalizedBy(String a, String b) {
project.getTasks().named(a).configure(task -> task.finalizedBy(project.getTasks().named(b)));
}

View File

@@ -29,6 +29,7 @@ import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedList;
@@ -293,11 +294,11 @@ public class RunConfig {
return Collections.emptyList();
}
final Set<ResolvedArtifact> allLibraries = getArtifacts(project, Constants.Configurations.MINECRAFT_DEPENDENCIES);
final Set<ResolvedArtifact> serverLibraries = getArtifacts(project, Constants.Configurations.MINECRAFT_SERVER_DEPENDENCIES);
final Set<ResolvedArtifact> clientLibraries = getArtifacts(project, Constants.Configurations.MINECRAFT_CLIENT_RUNTIME_LIBRARIES);
final Set<ResolvedArtifact> serverLibraries = getArtifacts(project, Constants.Configurations.MINECRAFT_SERVER_RUNTIME_LIBRARIES);
final List<String> clientOnlyLibraries = new LinkedList<>();
for (ResolvedArtifact library : allLibraries) {
for (ResolvedArtifact library : clientLibraries) {
if (!containsLibrary(serverLibraries, library.getModuleVersion().getId())) {
clientOnlyLibraries.add(library.getFile().getAbsolutePath());
}
@@ -307,9 +308,11 @@ public class RunConfig {
}
private static Set<ResolvedArtifact> getArtifacts(Project project, String configuration) {
return project.getConfigurations().getByName(configuration)
.getResolvedConfiguration()
.getResolvedArtifacts();
return project.getConfigurations().getByName(configuration).getHierarchy()
.stream()
.map(c -> c.getResolvedConfiguration().getResolvedArtifacts())
.flatMap(Collection::stream)
.collect(Collectors.toSet());
}
private static boolean containsLibrary(Set<ResolvedArtifact> artifacts, ModuleVersionIdentifier identifier) {

View File

@@ -44,7 +44,7 @@ import net.fabricmc.loom.configuration.providers.forge.ForgeRunsProvider;
import net.fabricmc.loom.configuration.providers.minecraft.MinecraftSourceSets;
import net.fabricmc.loom.util.Constants;
import net.fabricmc.loom.util.ModPlatform;
import net.fabricmc.loom.util.OperatingSystem;
import net.fabricmc.loom.util.Platform;
import net.fabricmc.loom.util.gradle.SourceSetHelper;
public final class RunConfigSettings implements Named {
@@ -285,7 +285,7 @@ public final class RunConfigSettings implements Named {
* Add the {@code -XstartOnFirstThread} JVM argument when on OSX.
*/
public void startFirstThread() {
if (OperatingSystem.CURRENT_OS.equals(OperatingSystem.MAC_OS)) {
if (Platform.CURRENT.getOperatingSystem().isMacOS()) {
vmArg("-XstartOnFirstThread");
}
}

View File

@@ -101,12 +101,10 @@ public abstract class IdeaSyncTask extends AbstractLoomTask {
final List<String> excludedLibraryPaths = config.getExcludedLibraryPaths(getProject());
if (!excludedLibraryPaths.isEmpty()) {
try {
setClasspathModifications(runConfigs.toPath(), excludedLibraryPaths);
} catch (Exception e) {
getProject().getLogger().error("Failed to modify run configuration xml", e);
}
try {
setClasspathModifications(runConfigs.toPath(), excludedLibraryPaths);
} catch (Exception e) {
getProject().getLogger().error("Failed to modify run configuration xml", e);
}
}
}

View File

@@ -63,7 +63,6 @@ import net.fabricmc.loom.configuration.mods.dependency.ModDependencyFactory;
import net.fabricmc.loom.configuration.providers.minecraft.MinecraftSourceSets;
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.gradle.SourceSetHelper;
import net.fabricmc.loom.util.service.SharedServiceManager;
@@ -275,7 +274,7 @@ public class ModConfigurationRemapper {
}
private static void scheduleSourcesRemapping(Project project, SourceRemapper sourceRemapper, ModDependency dependency) {
if (OperatingSystem.isCIBuild()) {
if (isCIBuild()) {
return;
}
@@ -301,4 +300,15 @@ public class ModConfigurationRemapper {
public static String replaceIfNullOrEmpty(@Nullable String s, Supplier<String> fallback) {
return s == null || s.isEmpty() ? fallback.get() : s;
}
private static boolean isCIBuild() {
final String loomProperty = System.getProperty("fabric.loom.ci");
if (loomProperty != null) {
return loomProperty.equalsIgnoreCase("true");
}
// CI seems to be set by most popular CI services
return System.getenv("CI") != null;
}
}

View File

@@ -155,7 +155,7 @@ public class ModProcessor {
final LoomGradleExtension extension = LoomGradleExtension.get(project);
final MappingConfiguration mappingConfiguration = extension.getMappingConfiguration();
String fromM = IntermediaryNamespaces.intermediary(project);
Path[] mcDeps = project.getConfigurations().getByName(Constants.Configurations.LOADER_DEPENDENCIES).getFiles()
Path[] mcDeps = project.getConfigurations().getByName(Constants.Configurations.MINECRAFT_COMPILE_LIBRARIES).getFiles()
.stream().map(File::toPath).toArray(Path[]::new);
Stopwatch stopwatch = Stopwatch.createStarted();

View File

@@ -43,7 +43,7 @@ public final class ContextImplHelper {
return new LazyCloseable<>(() -> {
try {
TinyRemapper tinyRemapper = TinyRemapperHelper.getTinyRemapper(configContext.project(), configContext.serviceManager(), from.toString(), to.toString());
tinyRemapper.readClassPath(TinyRemapperHelper.getMinecraftDependencies(configContext.project()));
tinyRemapper.readClassPath(TinyRemapperHelper.getMinecraftCompileLibraries(configContext.project()));
for (Path minecraftJar : configContext.extension().getMinecraftJars(MappingsNamespace.INTERMEDIARY)) {
tinyRemapper.readClassPath(minecraftJar);

View File

@@ -1,143 +0,0 @@
/*
* This file is part of fabric-loom, licensed under the MIT License (MIT).
*
* 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
* 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.minecraft;
import static net.fabricmc.loom.util.OperatingSystem.LINUX;
import static net.fabricmc.loom.util.OperatingSystem.MAC_OS;
import static net.fabricmc.loom.util.OperatingSystem.WINDOWS;
import java.util.List;
import org.gradle.api.Project;
import org.gradle.api.artifacts.ExternalModuleDependency;
import org.jetbrains.annotations.Nullable;
import net.fabricmc.loom.util.Architecture;
import net.fabricmc.loom.util.Constants;
import net.fabricmc.loom.util.OperatingSystem;
public class LWJGLVersionOverride {
public static final String LWJGL_VERSION = "3.3.1";
@Nullable
public static final String NATIVE_CLASSIFIER = getNativesClassifier();
public static final List<String> DEPENDENCIES = List.of(
"org.lwjgl:lwjgl:" + LWJGL_VERSION,
"org.lwjgl:lwjgl-glfw:" + LWJGL_VERSION,
"org.lwjgl:lwjgl-jemalloc:" + LWJGL_VERSION,
"org.lwjgl:lwjgl-openal:" + LWJGL_VERSION,
"org.lwjgl:lwjgl-opengl:" + LWJGL_VERSION,
"org.lwjgl:lwjgl-stb:" + LWJGL_VERSION,
"org.lwjgl:lwjgl-tinyfd:" + LWJGL_VERSION
);
public static final List<String> NATIVES = DEPENDENCIES.stream().map(s -> s + ":" + NATIVE_CLASSIFIER).toList();
public static final List<String> MACOS_DEPENDENCIES = List.of(
"ca.weblite:java-objc-bridge:1.1"
);
// Same for now, as java-objc-bridge includes the natives in the main jar.
public static final List<String> MACOS_NATIVES = MACOS_DEPENDENCIES;
/**
* Update lwjgl by default when running on arm and a supported configuration.
*/
public static boolean overrideByDefault(MinecraftVersionMeta versionMeta) {
if (NATIVE_CLASSIFIER == null || !Architecture.CURRENT.isArm()) {
return false;
}
boolean supportedLwjglVersion = versionMeta.libraries().stream()
.anyMatch(library -> library.name().startsWith("org.lwjgl:lwjgl:3"));
boolean hasExistingNatives = versionMeta.libraries().stream()
.filter(library -> library.name().startsWith("org.lwjgl:lwjgl"))
.anyMatch(MinecraftVersionMeta.Library::hasNativesForOS);
// Is LWJGL 3, and doesn't have any existing compatible LWGL natives.
return supportedLwjglVersion && !hasExistingNatives;
}
public static boolean forceOverride(Project project) {
return project.getProperties().get("fabric.loom.override-lwjgl") != null;
}
public static void applyOverrides(Project project, boolean isMacOS) {
DEPENDENCIES.forEach(s -> project.getDependencies().add(Constants.Configurations.MINECRAFT_DEPENDENCIES, s));
NATIVES.forEach(s -> project.getDependencies().add(Constants.Configurations.MINECRAFT_NATIVES, s));
if (isMacOS) {
MACOS_DEPENDENCIES.forEach(s -> project.getDependencies().add(Constants.Configurations.MINECRAFT_DEPENDENCIES, s));
MACOS_NATIVES.forEach(s -> project.getDependencies().add(Constants.Configurations.MINECRAFT_NATIVES, s));
}
// Add the native support mod that fixes a handful of issues related to the LWJGL update at runtime.
ExternalModuleDependency dependency = (ExternalModuleDependency) project.getDependencies().create(Constants.Dependencies.NATIVE_SUPPORT + Constants.Dependencies.Versions.NATIVE_SUPPORT_VERSION);
dependency.setTransitive(false);
project.getDependencies().add("modLocalRuntime", dependency);
}
@Nullable
private static String getNativesClassifier() {
return switch (OperatingSystem.CURRENT_OS) {
case WINDOWS -> getWindowsClassifier();
case MAC_OS -> getMacOSClassifier();
case LINUX -> getLinuxClassifier();
default -> null;
};
}
private static String getWindowsClassifier() {
if (Architecture.CURRENT.is64Bit()) {
if (Architecture.CURRENT.isArm()) {
// Arm 64 bit
return "natives-windows-arm64";
}
// None arm 64bit
return "natives-windows";
}
// All 32bit, including arm
return "natives-windows-x86";
}
private static String getMacOSClassifier() {
if (Architecture.CURRENT.isArm()) {
// Apple silicone arm
return "natives-macos-arm64";
}
// Intel 64bit.
return "natives-macos";
}
private static String getLinuxClassifier() {
if (Architecture.CURRENT.isArm()) {
return Architecture.CURRENT.is64Bit() ? "natives-linux-arm64" : "natives-linux-arm32";
}
return "natives-linux";
}
}

View File

@@ -1,7 +1,7 @@
/*
* This file is part of fabric-loom, licensed under the MIT License (MIT).
*
* Copyright (c) 2018-2022 FabricMC
* Copyright (c) 2018-2023 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
@@ -24,74 +24,70 @@
package net.fabricmc.loom.configuration.providers.minecraft;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import org.gradle.api.JavaVersion;
import org.gradle.api.Project;
import org.gradle.api.artifacts.Dependency;
import org.gradle.api.artifacts.ExternalModuleDependency;
import org.gradle.api.artifacts.ModuleDependency;
import org.gradle.api.provider.Provider;
import net.fabricmc.loom.LoomGradleExtension;
import net.fabricmc.loom.LoomRepositoryPlugin;
import net.fabricmc.loom.configuration.providers.BundleMetadata;
import net.fabricmc.loom.util.Architecture;
import net.fabricmc.loom.configuration.providers.minecraft.library.Library;
import net.fabricmc.loom.configuration.providers.minecraft.library.LibraryContext;
import net.fabricmc.loom.configuration.providers.minecraft.library.LibraryProcessorManager;
import net.fabricmc.loom.configuration.providers.minecraft.library.MinecraftLibraryHelper;
import net.fabricmc.loom.configuration.providers.minecraft.library.processors.RuntimeLog4jLibraryProcessor;
import net.fabricmc.loom.util.Constants;
import net.fabricmc.loom.util.OperatingSystem;
import net.fabricmc.loom.util.Platform;
public class MinecraftLibraryProvider {
private static final Pattern NATIVES_PATTERN = Pattern.compile("^(?<group>.*)/(.*?)/(?<version>.*)/((?<name>.*?)-(\\k<version>)-)(?<classifier>.*).jar$");
private static final boolean IS_MACOS = OperatingSystem.CURRENT_OS.equals(OperatingSystem.MAC_OS);
private static final Platform platform = Platform.CURRENT;
private final Project project;
private final MinecraftVersionMeta versionInfo;
private final BundleMetadata serverBundleMetadata;
private final boolean runtimeOnlyLog4j;
private final boolean provideClient;
private final boolean provideServer;
private final MinecraftProvider minecraftProvider;
private final LibraryProcessorManager processorManager;
public MinecraftLibraryProvider(MinecraftProvider minecraftProvider, Project project) {
final LoomGradleExtension extension = LoomGradleExtension.get(project);
final MinecraftJarConfiguration jarConfiguration = extension.getMinecraftJarConfiguration().get();
this.project = project;
this.versionInfo = minecraftProvider.getVersionInfo();
this.serverBundleMetadata = minecraftProvider.getServerBundleMetadata();
this.runtimeOnlyLog4j = extension.getRuntimeOnlyLog4j().get();
this.provideClient = jarConfiguration.getSupportedEnvironments().contains("client");
this.provideServer = jarConfiguration.getSupportedEnvironments().contains("server");
assert provideClient || provideServer;
this.minecraftProvider = minecraftProvider;
this.processorManager = new LibraryProcessorManager(platform, project.getRepositories(), getEnabledProcessors());
}
private void addDependency(String configuration, Object dependency) {
Dependency created = project.getDependencies().add(configuration, dependency);
private List<String> getEnabledProcessors() {
final LoomGradleExtension extension = LoomGradleExtension.get(project);
// The launcher doesn't download transitive deps, so neither will we.
// This will also prevent a LaunchWrapper library dependency from pulling in outdated ASM jars.
if (created instanceof ModuleDependency md) {
md.setTransitive(false);
var enabledProcessors = new ArrayList<String>();
if (extension.getRuntimeOnlyLog4j().get()) {
enabledProcessors.add(RuntimeLog4jLibraryProcessor.class.getSimpleName());
}
final Provider<String> libraryProcessorsProperty = project.getProviders().gradleProperty(Constants.Properties.LIBRARY_PROCESSORS);
if (libraryProcessorsProperty.isPresent()) {
String[] split = libraryProcessorsProperty.get().split(":");
enabledProcessors.addAll(Arrays.asList(split));
}
return Collections.unmodifiableList(enabledProcessors);
}
public void provide() {
final LoomGradleExtension extension = LoomGradleExtension.get(project);
final MinecraftJarConfiguration jarConfiguration = extension.getMinecraftJarConfiguration().get();
final boolean provideClient = jarConfiguration.getSupportedEnvironments().contains("client");
final boolean provideServer = jarConfiguration.getSupportedEnvironments().contains("server");
assert provideClient || provideServer;
if (provideClient) {
// Modern 1.19 version put the natives on the classpath.
final boolean hasNativesToExtract = versionInfo.hasNativesToExtract();
final boolean overrideLWJGL = hasNativesToExtract && (LWJGLVersionOverride.overrideByDefault(versionInfo) || LWJGLVersionOverride.forceOverride(project) || Boolean.getBoolean("loom.test.lwjgloverride"));
if (overrideLWJGL) {
project.getLogger().warn("Loom is upgrading Minecraft's LWJGL version to {}", LWJGLVersionOverride.LWJGL_VERSION);
}
if (hasNativesToExtract) {
// Create a configuration for
project.getConfigurations().register(Constants.Configurations.MINECRAFT_NATIVES, configuration -> configuration.setTransitive(false));
}
provideClientLibraries(overrideLWJGL, hasNativesToExtract);
if (overrideLWJGL) {
LWJGLVersionOverride.applyOverrides(project, IS_MACOS);
}
provideClientLibraries();
}
if (provideServer) {
@@ -99,96 +95,69 @@ public class MinecraftLibraryProvider {
}
}
private void provideClientLibraries(boolean overrideLWJGL, boolean hasNativesToExtract) {
final boolean isArm = Architecture.CURRENT.isArm();
final boolean classpathArmNatives = !hasNativesToExtract && isArm && !IS_MACOS;
private void provideClientLibraries() {
final List<Library> libraries = MinecraftLibraryHelper.getLibrariesForPlatform(minecraftProvider.getVersionInfo(), platform);
final List<Library> processLibraries = processLibraries(libraries);
processLibraries.forEach(this::applyClientLibrary);
if (classpathArmNatives) {
LoomRepositoryPlugin.forceLWJGLFromMavenCentral(project);
}
for (MinecraftVersionMeta.Library library : versionInfo.libraries()) {
if (overrideLWJGL && library.name().startsWith("org.lwjgl")) {
// Skip over Minecraft's LWJGL version, will will replace this with a newer version later.
continue;
}
if (library.isValidForOS() && !library.hasNatives() && library.artifact() != null) {
final String name = library.name();
if ("org.lwjgl.lwjgl:lwjgl:2.9.1-nightly-20130708-debug3".equals(name) || "org.lwjgl.lwjgl:lwjgl:2.9.1-nightly-20131017".equals(name)) {
// 1.4.7 contains an LWJGL version with an invalid maven pom, set the metadata sources to not use the pom for this version.
LoomRepositoryPlugin.setupForLegacyVersions(project);
}
if (name.startsWith("org.ow2.asm:asm-all")) {
// Don't want asm-all, use the modern split version.
continue;
}
if (runtimeOnlyLog4j && name.startsWith("org.apache.logging.log4j")) {
// Make log4j a runtime only dep to force slf4j.
addDependency(Constants.Configurations.MINECRAFT_RUNTIME_DEPENDENCIES, name);
continue;
}
if (classpathArmNatives && name.startsWith("org.lwjgl:")
&& (name.endsWith("natives-windows") || name.endsWith("natives-linux"))) {
// Add windows and Linux arm64 natives for modern classpath native MC versions.
addDependency(Constants.Configurations.MINECRAFT_DEPENDENCIES, name + "-arm64");
}
addDependency(Constants.Configurations.MINECRAFT_DEPENDENCIES, name);
}
if (library.hasNativesForOS()) {
provideNativesForLibrary(library, overrideLWJGL, IS_MACOS);
}
// After Minecraft 1.19-pre1 the natives should be on the runtime classpath.
if (!minecraftProvider.getVersionInfo().hasNativesToExtract()) {
project.getConfigurations().named(Constants.Configurations.MINECRAFT_RUNTIME_LIBRARIES, configuration -> configuration.extendsFrom(project.getConfigurations().getByName(Constants.Configurations.MINECRAFT_NATIVES)));
}
}
private void provideServerLibraries() {
if (serverBundleMetadata != null) {
for (BundleMetadata.Entry library : serverBundleMetadata.libraries()) {
if (runtimeOnlyLog4j && library.name().startsWith("org.apache.logging.log4j")) {
// Make log4j a runtime only dep to force slf4j.
addDependency(Constants.Configurations.MINECRAFT_RUNTIME_DEPENDENCIES, library.name());
continue;
}
final BundleMetadata serverBundleMetadata = minecraftProvider.getServerBundleMetadata();
addDependency(Constants.Configurations.MINECRAFT_SERVER_DEPENDENCIES, library.name());
}
if (serverBundleMetadata == null) {
return;
}
final List<Library> libraries = MinecraftLibraryHelper.getServerLibraries(serverBundleMetadata);
final List<Library> processLibraries = processLibraries(libraries);
processLibraries.forEach(this::applyServerLibrary);
}
private List<Library> processLibraries(List<Library> libraries) {
final LibraryContext libraryContext = new LibraryContext(minecraftProvider.getVersionInfo(), JavaVersion.current());
return processorManager.processLibraries(libraries, libraryContext);
}
private void applyClientLibrary(Library library) {
switch (library.target()) {
case COMPILE -> addLibrary(Constants.Configurations.MINECRAFT_CLIENT_COMPILE_LIBRARIES, library);
case RUNTIME -> addLibrary(Constants.Configurations.MINECRAFT_CLIENT_RUNTIME_LIBRARIES, library);
case NATIVES -> addLibrary(Constants.Configurations.MINECRAFT_NATIVES, library);
case LOCAL_MOD -> applyLocalModLibrary(library);
}
}
private void provideNativesForLibrary(MinecraftVersionMeta.Library library, boolean overrideLWJGL, boolean isMacOS) {
MinecraftVersionMeta.Download nativeDownload = library.classifierForOS();
if (nativeDownload == null) {
return;
private void applyServerLibrary(Library library) {
switch (library.target()) {
case COMPILE -> addLibrary(Constants.Configurations.MINECRAFT_SERVER_COMPILE_LIBRARIES, library);
case RUNTIME -> addLibrary(Constants.Configurations.MINECRAFT_SERVER_RUNTIME_LIBRARIES, library);
case LOCAL_MOD -> applyLocalModLibrary(library);
default -> throw new IllegalStateException("Target not supported for server library: %s".formatted(library));
}
}
final String path = nativeDownload.path();
final Matcher matcher = NATIVES_PATTERN.matcher(path);
private void applyLocalModLibrary(Library library) {
ExternalModuleDependency dependency = (ExternalModuleDependency) project.getDependencies().create(library.mavenNotation());
dependency.setTransitive(false);
project.getDependencies().add("modLocalRuntime", dependency);
}
if (!matcher.find()) {
project.getLogger().warn("Failed to match regex for natives path : " + path);
return;
private void addLibrary(String configuration, Library library) {
addDependency(configuration, library.mavenNotation());
}
private void addDependency(String configuration, Object dependency) {
final Dependency created = project.getDependencies().add(configuration, dependency);
// The launcher doesn't download transitive deps, so neither will we.
// This will also prevent a LaunchWrapper library dependency from pulling in outdated ASM jars.
if (created instanceof ModuleDependency md) {
md.setTransitive(false);
}
final String group = matcher.group("group").replace("/", ".");
final String name = matcher.group("name");
final String version = matcher.group("version");
final String classifier = matcher.group("classifier");
final String dependencyNotation = "%s:%s:%s:%s".formatted(group, name, version, classifier);
if (overrideLWJGL && isMacOS && "java-objc-bridge".equals(name)) {
// Mojang split out the natives into their own jar, skip over Mojang's jar and use the official jar later on.
return;
}
project.getLogger().debug("Add native dependency '{}'", dependencyNotation);
addDependency(Constants.Configurations.MINECRAFT_NATIVES, dependencyNotation);
}
}

View File

@@ -24,13 +24,12 @@
package net.fabricmc.loom.configuration.providers.minecraft;
import static net.fabricmc.loom.configuration.CompileConfiguration.extendsFrom;
import java.util.List;
import java.util.function.BiConsumer;
import com.google.common.base.Preconditions;
import org.gradle.api.Project;
import org.gradle.api.artifacts.ConfigurationContainer;
import org.gradle.api.plugins.JavaPlugin;
import org.gradle.api.tasks.SourceSet;
import org.gradle.jvm.tasks.Jar;
@@ -48,11 +47,9 @@ public abstract sealed class MinecraftSourceSets permits MinecraftSourceSets.Sin
public abstract void applyDependencies(BiConsumer<String, String> consumer, List<String> targets);
public abstract String getCombinedSourceSetName();
public abstract String getSourceSetForEnv(String env);
protected abstract List<String> getAllSourceSetNames();
protected abstract List<ConfigurationName> getConfigurations();
public void evaluateSplit(Project project) {
final LoomGradleExtension extension = LoomGradleExtension.get(project);
@@ -63,58 +60,72 @@ public abstract sealed class MinecraftSourceSets permits MinecraftSourceSets.Sin
public abstract void afterEvaluate(Project project);
protected void createSourceSets(Project project) {
for (String name : getAllSourceSetNames()) {
project.getConfigurations().register(name, configuration -> configuration.setTransitive(false));
protected void createConfigurations(Project project) {
final ConfigurationContainer configurations = project.getConfigurations();
// All the configurations extend the loader deps.
extendsFrom(name, Constants.Configurations.LOADER_DEPENDENCIES, project);
for (ConfigurationName configurationName : getConfigurations()) {
configurations.register(configurationName.runtime(), configuration -> {
configuration.setTransitive(false);
configuration.extendsFrom(configurations.getByName(configurationName.mcLibsRuntimeName()));
configuration.extendsFrom(configurations.getByName(Constants.Configurations.LOADER_DEPENDENCIES));
configuration.extendsFrom(configurations.getByName(Constants.Configurations.LOOM_DEVELOPMENT_DEPENDENCIES));
});
configurations.register(configurationName.compile(), configuration -> {
configuration.setTransitive(false);
configuration.extendsFrom(configurations.getByName(configurationName.mcLibsCompileName()));
configuration.extendsFrom(configurations.getByName(Constants.Configurations.LOADER_DEPENDENCIES));
});
}
}
protected void extendsFrom(Project project, String name, String extendsFrom) {
final ConfigurationContainer configurations = project.getConfigurations();
configurations.named(name, configuration -> {
configuration.extendsFrom(configurations.getByName(extendsFrom));
});
}
/**
* Used when we have a single source set, either with split or merged jars.
*/
public static final class Single extends MinecraftSourceSets {
private static final String MINECRAFT_NAMED = "minecraftNamed";
private static final ConfigurationName MINECRAFT_NAMED = new ConfigurationName(
"minecraftNamed",
Constants.Configurations.MINECRAFT_COMPILE_LIBRARIES,
Constants.Configurations.MINECRAFT_RUNTIME_LIBRARIES
);
private static final Single INSTANCE = new Single();
@Override
public void applyDependencies(BiConsumer<String, String> consumer, List<String> targets) {
for (String target : targets) {
consumer.accept(MINECRAFT_NAMED, target);
consumer.accept(MINECRAFT_NAMED.compile(), target);
consumer.accept(MINECRAFT_NAMED.runtime(), target);
}
}
@Override
public String getCombinedSourceSetName() {
return MINECRAFT_NAMED;
}
@Override
public String getSourceSetForEnv(String env) {
return SourceSet.MAIN_SOURCE_SET_NAME;
}
@Override
protected List<String> getAllSourceSetNames() {
protected List<ConfigurationName> getConfigurations() {
return List.of(MINECRAFT_NAMED);
}
@Override
public void afterEvaluate(Project project) {
// This is done in afterEvaluate as we need to be sure that split source sets was not enabled.
createSourceSets(project);
createConfigurations(project);
// Default compile and runtime sourcesets.
extendsFrom(List.of(
JavaPlugin.COMPILE_CLASSPATH_CONFIGURATION_NAME,
JavaPlugin.RUNTIME_CLASSPATH_CONFIGURATION_NAME,
JavaPlugin.TEST_COMPILE_CLASSPATH_CONFIGURATION_NAME,
JavaPlugin.TEST_RUNTIME_CLASSPATH_CONFIGURATION_NAME),
MINECRAFT_NAMED, project
);
extendsFrom(project, JavaPlugin.COMPILE_CLASSPATH_CONFIGURATION_NAME, MINECRAFT_NAMED.compile());
extendsFrom(project, JavaPlugin.RUNTIME_CLASSPATH_CONFIGURATION_NAME, MINECRAFT_NAMED.runtime());
extendsFrom(project, JavaPlugin.TEST_COMPILE_CLASSPATH_CONFIGURATION_NAME, MINECRAFT_NAMED.compile());
extendsFrom(project, JavaPlugin.TEST_RUNTIME_CLASSPATH_CONFIGURATION_NAME, MINECRAFT_NAMED.runtime());
}
}
@@ -122,9 +133,17 @@ public abstract sealed class MinecraftSourceSets permits MinecraftSourceSets.Sin
* Used when we have a split client/common source set and split jars.
*/
public static final class Split extends MinecraftSourceSets {
private static final String MINECRAFT_COMMON_NAMED = "minecraftCommonNamed";
private static final String MINECRAFT_CLIENT_ONLY_NAMED = "minecraftClientOnlyNamed";
private static final String MINECRAFT_COMBINED_NAMED = "minecraftCombinedNamed";
private static final ConfigurationName MINECRAFT_COMMON_NAMED = new ConfigurationName(
"minecraftCommonNamed",
Constants.Configurations.MINECRAFT_COMPILE_LIBRARIES,
Constants.Configurations.MINECRAFT_RUNTIME_LIBRARIES
);
// Depends on the Minecraft client libraries.
private static final ConfigurationName MINECRAFT_CLIENT_ONLY_NAMED = new ConfigurationName(
"minecraftClientOnlyNamed",
Constants.Configurations.MINECRAFT_CLIENT_COMPILE_LIBRARIES,
Constants.Configurations.MINECRAFT_CLIENT_RUNTIME_LIBRARIES
);
public static final String CLIENT_ONLY_SOURCE_SET_NAME = "client";
@@ -136,13 +155,10 @@ public abstract sealed class MinecraftSourceSets permits MinecraftSourceSets.Sin
Preconditions.checkArgument(targets.contains("common"));
Preconditions.checkArgument(targets.contains("clientOnly"));
consumer.accept(MINECRAFT_COMMON_NAMED, "common");
consumer.accept(MINECRAFT_CLIENT_ONLY_NAMED, "clientOnly");
}
@Override
public String getCombinedSourceSetName() {
return MINECRAFT_COMBINED_NAMED;
consumer.accept(MINECRAFT_COMMON_NAMED.runtime(), "common");
consumer.accept(MINECRAFT_CLIENT_ONLY_NAMED.runtime(), "clientOnly");
consumer.accept(MINECRAFT_COMMON_NAMED.compile(), "common");
consumer.accept(MINECRAFT_CLIENT_ONLY_NAMED.compile(), "clientOnly");
}
@Override
@@ -151,37 +167,29 @@ public abstract sealed class MinecraftSourceSets permits MinecraftSourceSets.Sin
}
@Override
protected List<String> getAllSourceSetNames() {
return List.of(MINECRAFT_COMMON_NAMED, MINECRAFT_CLIENT_ONLY_NAMED, MINECRAFT_COMBINED_NAMED);
protected List<ConfigurationName> getConfigurations() {
return List.of(MINECRAFT_COMMON_NAMED, MINECRAFT_CLIENT_ONLY_NAMED);
}
// Called during evaluation, when the loom extension method is called.
private void evaluate(Project project) {
final LoomGradleExtension extension = LoomGradleExtension.get(project);
createSourceSets(project);
// Combined extends from the 2 environments.
extendsFrom(MINECRAFT_COMBINED_NAMED, MINECRAFT_COMMON_NAMED, project);
extendsFrom(MINECRAFT_COMBINED_NAMED, MINECRAFT_CLIENT_ONLY_NAMED, project);
createConfigurations(project);
final ConfigurationContainer configurations = project.getConfigurations();
// Register our new client only source set, main becomes common only, with their respective jars.
SourceSet mainSourceSet = SourceSetHelper.getMainSourceSet(project);
SourceSet clientOnlySourceSet = SourceSetHelper.createSourceSet(CLIENT_ONLY_SOURCE_SET_NAME, project);
final SourceSet mainSourceSet = SourceSetHelper.getMainSourceSet(project);
final SourceSet clientOnlySourceSet = SourceSetHelper.createSourceSet(CLIENT_ONLY_SOURCE_SET_NAME, project);
extendsFrom(List.of(
mainSourceSet.getCompileClasspathConfigurationName(),
mainSourceSet.getRuntimeClasspathConfigurationName()
), MINECRAFT_COMMON_NAMED, project
);
// Add Minecraft to the main and client source sets.
extendsFrom(project, mainSourceSet.getCompileClasspathConfigurationName(), MINECRAFT_COMMON_NAMED.compile());
extendsFrom(project, mainSourceSet.getRuntimeClasspathConfigurationName(), MINECRAFT_COMMON_NAMED.runtime());
extendsFrom(project, clientOnlySourceSet.getCompileClasspathConfigurationName(), MINECRAFT_CLIENT_ONLY_NAMED.compile());
extendsFrom(project, clientOnlySourceSet.getRuntimeClasspathConfigurationName(), MINECRAFT_CLIENT_ONLY_NAMED.runtime());
extendsFrom(List.of(
clientOnlySourceSet.getCompileClasspathConfigurationName(),
clientOnlySourceSet.getRuntimeClasspathConfigurationName()
), MINECRAFT_CLIENT_ONLY_NAMED, project
);
// Client source set depends on common.
extendsFrom(project, MINECRAFT_CLIENT_ONLY_NAMED.runtime(), MINECRAFT_COMMON_NAMED.runtime());
extendsFrom(project, MINECRAFT_CLIENT_ONLY_NAMED.compile(), MINECRAFT_COMMON_NAMED.compile());
// Client depends on common.
extendsFrom(MINECRAFT_CLIENT_ONLY_NAMED, MINECRAFT_COMMON_NAMED, project);
clientOnlySourceSet.setCompileClasspath(
clientOnlySourceSet.getCompileClasspath()
.plus(mainSourceSet.getCompileClasspath())
@@ -231,4 +239,14 @@ public abstract sealed class MinecraftSourceSets permits MinecraftSourceSets.Sin
public void afterEvaluate(Project project) {
}
}
private record ConfigurationName(String baseName, String mcLibsCompileName, String mcLibsRuntimeName) {
private String runtime() {
return baseName + "Runtime";
}
private String compile() {
return baseName + "Compile";
}
}
}

View File

@@ -29,8 +29,9 @@ import java.util.List;
import java.util.Map;
import java.util.Objects;
import net.fabricmc.loom.util.Architecture;
import net.fabricmc.loom.util.OperatingSystem;
import org.jetbrains.annotations.Nullable;
import net.fabricmc.loom.util.Platform;
@SuppressWarnings("unused")
public record MinecraftVersionMeta(
@@ -48,6 +49,12 @@ public record MinecraftVersionMeta(
String time,
String type
) {
private static Map<Platform.OperatingSystem, String> OS_NAMES = Map.of(
Platform.OperatingSystem.WINDOWS, "windows",
Platform.OperatingSystem.MAC_OS, "osx",
Platform.OperatingSystem.LINUX, "linux"
);
public Download download(String key) {
return downloads().get(key);
}
@@ -67,7 +74,7 @@ public record MinecraftVersionMeta(
}
public record Library(Downloads downloads, String name, Map<String, String> natives, List<Rule> rules, Object extract) {
public boolean isValidForOS() {
public boolean isValidForOS(Platform platform) {
if (rules == null) {
// No rules allow everything.
return true;
@@ -76,7 +83,7 @@ public record MinecraftVersionMeta(
boolean valid = false;
for (Rule rule : this.rules) {
if (rule.appliesToOS()) {
if (rule.appliesToOS(platform)) {
valid = rule.isAllowed();
}
}
@@ -88,25 +95,38 @@ public record MinecraftVersionMeta(
return this.natives != null;
}
public boolean hasNativesForOS() {
public boolean hasNativesForOS(Platform platform) {
if (!hasNatives()) {
return false;
}
if (classifierForOS() == null) {
if (classifierForOS(platform) == null) {
return false;
}
return isValidForOS();
return isValidForOS(platform);
}
public Download classifierForOS() {
String classifier = natives.get(OperatingSystem.CURRENT_OS);
@Nullable
public Download classifierForOS(Platform platform) {
String classifier = natives.get(OS_NAMES.get(platform.getOperatingSystem()));
if (Architecture.CURRENT.isArm()) {
classifier += "-arm64";
if (classifier == null) {
return null;
}
if (platform.getArchitecture().isArm() && platform.getArchitecture().is64Bit()) {
// Default to the arm64 natives, if not found fallback.
final Download armNative = downloads().classifier(classifier + "-arm64");
if (armNative != null) {
return armNative;
}
}
// Used in the twitch library in 1.7.10
classifier = classifier.replace("${arch}", platform.getArchitecture().is64Bit() ? "64" : "32");
return downloads().classifier(classifier);
}
@@ -120,14 +140,15 @@ public record MinecraftVersionMeta(
}
public record Downloads(Download artifact, Map<String, Download> classifiers) {
@Nullable
public Download classifier(String os) {
return classifiers.get(os);
}
}
public record Rule(String action, OS os) {
public boolean appliesToOS() {
return os() == null || os().isValidForOS();
public boolean appliesToOS(Platform platform) {
return os() == null || os().isValidForOS(platform);
}
public boolean isAllowed() {
@@ -136,8 +157,8 @@ public record MinecraftVersionMeta(
}
public record OS(String name) {
public boolean isValidForOS() {
return name() == null || name().equalsIgnoreCase(OperatingSystem.CURRENT_OS);
public boolean isValidForOS(Platform platform) {
return name() == null || name().equalsIgnoreCase(OS_NAMES.get(platform.getOperatingSystem()));
}
}

View File

@@ -0,0 +1,91 @@
/*
* This file is part of fabric-loom, licensed under the MIT License (MIT).
*
* Copyright (c) 2023 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.minecraft.library;
import org.jetbrains.annotations.Nullable;
public record Library(String group, String name, String version, @Nullable String classifier, Target target) {
public enum Target {
/**
* A runtime only library.
*/
RUNTIME,
/**
* A runtime and compile library.
*/
COMPILE,
/**
* Natives.
*/
NATIVES,
/**
* A mod library that needs remapping.
*/
LOCAL_MOD
}
public static Library fromMaven(String name, Target target) {
String[] split = name.split(":");
assert split.length == 3 || split.length == 4;
return new Library(split[0], split[1], split[2], split.length == 4 ? split[3] : null, target);
}
/**
* Returns true when the group or the group and name match.
*
* @param str Takes a string containing the maven group, or a group and name split by :
* @return true when the group or the group and name match.
*/
public boolean is(String str) {
if (str.contains(":")) {
final String[] split = str.split(":");
assert split.length == 2;
return this.group.equals(split[0]) && this.name.equals(split[1]);
}
return this.group.equals(str);
}
public String mavenNotation() {
if (classifier != null) {
return "%s:%s:%s:%s".formatted(group, name, version, classifier);
}
return "%s:%s:%s".formatted(group, name, version);
}
public Library withVersion(String version) {
return new Library(this.group, this.name, version, this.classifier, this.target);
}
public Library withClassifier(@Nullable String classifier) {
return new Library(this.group, this.name, this.version, classifier, this.target);
}
public Library withTarget(Target target) {
return new Library(this.group, this.name, this.version, this.classifier, target);
}
}

View File

@@ -0,0 +1,115 @@
/*
* This file is part of fabric-loom, licensed under the MIT License (MIT).
*
* Copyright (c) 2023 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.minecraft.library;
import java.util.Arrays;
import org.gradle.api.JavaVersion;
import net.fabricmc.loom.configuration.providers.minecraft.MinecraftVersionMeta;
public final class LibraryContext {
private final MinecraftVersionMeta versionMeta;
private final JavaVersion javaVersion;
public LibraryContext(MinecraftVersionMeta versionMeta, JavaVersion javaVersion) {
this.versionMeta = versionMeta;
this.javaVersion = javaVersion;
}
/**
* @return True when the Minecraft libraries support ARM64 MacOS
*/
public boolean supportsArm64MacOS() {
return versionMeta.libraries().stream()
.anyMatch(library -> library.name().startsWith("org.lwjgl:lwjgl:3") && library.name().endsWith(":natives-macos-arm64"));
}
/**
* @return True when the Minecraft libraries support Java 19 or later
*/
public boolean supportsJava19OrLater() {
return versionMeta.libraries().stream().filter(library -> library.name().startsWith("org.lwjgl:lwjgl:")).anyMatch(library -> {
final String[] split = library.name().split(":");
if (split.length != 3) {
return false;
}
final String version = split[2];
final int[] versionSplit = Arrays.stream(version.split("\\."))
.mapToInt(Integer::parseInt)
.toArray();
// LWJGL 4 or newer
if (versionSplit[0] > 3) {
return true;
}
// LWJGL 3.4 or newer
if (versionSplit[0] == 3 && versionSplit[1] > 3) {
return true;
}
// LWJGL 3.3.2 or newer
if (versionSplit[0] == 3 && versionSplit[1] == 3 && versionSplit[2] >= 2) {
return true;
}
return false;
});
}
/**
* @return True when using LWJGL 3
*/
public boolean usesLWJGL3() {
return versionMeta.libraries().stream()
.anyMatch(library -> library.name().startsWith("org.lwjgl:lwjgl:3"));
}
/**
* @return True when the Minecraft natives are on the classpath, as opposed to being extracted
*/
public boolean hasClasspathNatives() {
return !versionMeta.hasNativesToExtract();
}
/**
* @return True when there is an exact match for this library
*/
public boolean hasLibrary(String name) {
return versionMeta.libraries().stream()
.anyMatch(library -> library.name().equals(name));
}
/**
* @return True when the current Java version is 19 or later
*/
public boolean isJava19OrLater() {
return javaVersion.isCompatibleWith(JavaVersion.VERSION_19);
}
}

View File

@@ -0,0 +1,69 @@
/*
* This file is part of fabric-loom, licensed under the MIT License (MIT).
*
* Copyright (c) 2023 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.minecraft.library;
import java.util.Objects;
import java.util.function.Consumer;
import java.util.function.Predicate;
import org.gradle.api.artifacts.dsl.RepositoryHandler;
import net.fabricmc.loom.util.Platform;
public abstract class LibraryProcessor {
protected static final Predicate<Library> ALLOW_ALL = library -> true;
protected final Platform platform;
protected final LibraryContext context;
public LibraryProcessor(Platform platform, LibraryContext context) {
this.platform = Objects.requireNonNull(platform);
this.context = Objects.requireNonNull(context);
}
public abstract ApplicationResult getApplicationResult();
public Predicate<Library> apply(Consumer<Library> dependencyConsumer) {
return ALLOW_ALL;
}
public void applyRepositories(RepositoryHandler repositories) {
}
public enum ApplicationResult {
/**
* This processor should be applied automatically to enable Minecraft to run on the current platform.
*/
MUST_APPLY,
/**
* This processor can optionally be applied on the current platform.
*/
CAN_APPLY,
/**
* This processor is incompatible with the current platform and should not be applied on the current platform.
*/
DONT_APPLY
}
}

View File

@@ -0,0 +1,127 @@
/*
* This file is part of fabric-loom, licensed under the MIT License (MIT).
*
* Copyright (c) 2023 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.minecraft.library;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.function.BiFunction;
import java.util.function.Predicate;
import org.gradle.api.artifacts.dsl.RepositoryHandler;
import org.jetbrains.annotations.VisibleForTesting;
import net.fabricmc.loom.configuration.providers.minecraft.library.processors.ArmNativesLibraryProcessor;
import net.fabricmc.loom.configuration.providers.minecraft.library.processors.LWJGL2MavenLibraryProcessor;
import net.fabricmc.loom.configuration.providers.minecraft.library.processors.LWJGL3UpgradeLibraryProcessor;
import net.fabricmc.loom.configuration.providers.minecraft.library.processors.LegacyASMLibraryProcessor;
import net.fabricmc.loom.configuration.providers.minecraft.library.processors.LoomNativeSupportLibraryProcessor;
import net.fabricmc.loom.configuration.providers.minecraft.library.processors.ObjcBridgeUpgradeLibraryProcessor;
import net.fabricmc.loom.configuration.providers.minecraft.library.processors.RuntimeLog4jLibraryProcessor;
import net.fabricmc.loom.util.Platform;
public class LibraryProcessorManager {
private static final List<LibraryProcessorFactory<?>> LIBRARY_PROCESSORS = List.of(
ArmNativesLibraryProcessor::new,
LegacyASMLibraryProcessor::new,
LoomNativeSupportLibraryProcessor::new,
LWJGL2MavenLibraryProcessor::new,
LWJGL3UpgradeLibraryProcessor::new,
ObjcBridgeUpgradeLibraryProcessor::new,
RuntimeLog4jLibraryProcessor::new
);
private final Platform platform;
private final RepositoryHandler repositories;
private final List<String> enabledProcessors;
public LibraryProcessorManager(Platform platform, RepositoryHandler repositories, List<String> enabledProcessors) {
this.platform = platform;
this.repositories = repositories;
this.enabledProcessors = enabledProcessors;
}
public LibraryProcessorManager(Platform platform, RepositoryHandler repositories) {
this(platform, repositories, Collections.emptyList());
}
private List<LibraryProcessor> getProcessors(LibraryContext context) {
var processors = new ArrayList<LibraryProcessor>();
for (LibraryProcessorFactory<?> factory : LIBRARY_PROCESSORS) {
final LibraryProcessor processor = factory.apply(platform, context);
final LibraryProcessor.ApplicationResult applicationResult = processor.getApplicationResult();
switch (applicationResult) {
case MUST_APPLY -> {
processors.add(processor);
}
case CAN_APPLY -> {
if (enabledProcessors.contains(processor.getClass().getSimpleName())) {
processors.add(processor);
}
}
case DONT_APPLY -> { }
}
}
return Collections.unmodifiableList(processors);
}
public List<Library> processLibraries(List<Library> librariesIn, LibraryContext libraryContext) {
final List<LibraryProcessor> processors = getProcessors(libraryContext);
if (processors.isEmpty()) {
return librariesIn;
}
return processLibraries(processors, librariesIn);
}
@VisibleForTesting
public List<Library> processLibraries(List<LibraryProcessor> processors, List<Library> librariesIn) {
var libraries = new ArrayList<>(librariesIn);
for (LibraryProcessor processor : processors) {
var processedLibraries = new ArrayList<Library>();
final Predicate<Library> predicate = processor.apply(processedLibraries::add);
for (Library library : libraries) {
if (predicate.test(library)) {
processedLibraries.add(library);
}
}
processor.applyRepositories(repositories);
libraries = processedLibraries;
}
return Collections.unmodifiableList(libraries);
}
public interface LibraryProcessorFactory<T extends LibraryProcessor> extends BiFunction<Platform, LibraryContext, T> {
}
}

View File

@@ -0,0 +1,103 @@
/*
* This file is part of fabric-loom, licensed under the MIT License (MIT).
*
* Copyright (c) 2023 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.minecraft.library;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import net.fabricmc.loom.configuration.providers.BundleMetadata;
import net.fabricmc.loom.configuration.providers.minecraft.MinecraftVersionMeta;
import net.fabricmc.loom.util.Platform;
/**
* Utils to get the Minecraft libraries for a given platform, no processing is applied.
*/
public class MinecraftLibraryHelper {
private static final Pattern NATIVES_PATTERN = Pattern.compile("^(?<group>.*)/(.*?)/(?<version>.*)/((?<name>.*?)-(\\k<version>)-)(?<classifier>.*).jar$");
public static List<Library> getLibrariesForPlatform(MinecraftVersionMeta versionMeta, Platform platform) {
var libraries = new ArrayList<Library>();
for (MinecraftVersionMeta.Library library : versionMeta.libraries()) {
if (!library.isValidForOS(platform)) {
continue;
}
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);
}
if (library.hasNativesForOS(platform)) {
final MinecraftVersionMeta.Download download = library.classifierForOS(platform);
if (download != null) {
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);
if (!matcher.find()) {
throw new IllegalStateException("Failed to match regex for natives path : " + path);
}
final String group = matcher.group("group").replace("/", ".");
final String name = matcher.group("name");
final String version = matcher.group("version");
final String classifier = matcher.group("classifier");
final String dependencyNotation = "%s:%s:%s:%s".formatted(group, name, version, classifier);
return Library.fromMaven(dependencyNotation, Library.Target.NATIVES);
}
public static List<Library> getServerLibraries(BundleMetadata bundleMetadata) {
Objects.requireNonNull(bundleMetadata);
var libraries = new ArrayList<Library>();
for (BundleMetadata.Entry library : bundleMetadata.libraries()) {
libraries.add(Library.fromMaven(library.name(), Library.Target.COMPILE));
}
return libraries;
}
}

View File

@@ -0,0 +1,100 @@
/*
* This file is part of fabric-loom, licensed under the MIT License (MIT).
*
* Copyright (c) 2023 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.minecraft.library.processors;
import java.util.function.Consumer;
import java.util.function.Predicate;
import org.gradle.api.artifacts.dsl.RepositoryHandler;
import net.fabricmc.loom.LoomRepositoryPlugin;
import net.fabricmc.loom.configuration.providers.minecraft.library.Library;
import net.fabricmc.loom.configuration.providers.minecraft.library.LibraryContext;
import net.fabricmc.loom.configuration.providers.minecraft.library.LibraryProcessor;
import net.fabricmc.loom.util.Platform;
/**
* A processor to add support for ARM64.
*/
public class ArmNativesLibraryProcessor extends LibraryProcessor {
private static final String LWJGL_GROUP = "org.lwjgl";
public ArmNativesLibraryProcessor(Platform platform, LibraryContext context) {
super(platform, context);
}
@Override
public ApplicationResult getApplicationResult() {
if (!context.usesLWJGL3()) {
// Only supports LWJGL 3
return ApplicationResult.DONT_APPLY;
}
if (!platform.getArchitecture().isArm() || !platform.getArchitecture().is64Bit()) {
// Not an arm64 platform, can never apply this.
return ApplicationResult.DONT_APPLY;
}
if (platform.getOperatingSystem().isMacOS()) {
if (context.supportsArm64MacOS()) {
// This version already supports arm64 macOS, nothing to do.
return ApplicationResult.DONT_APPLY;
}
// Must upgrade natives to support macos ARM
return ApplicationResult.MUST_APPLY;
}
if (!context.hasClasspathNatives()) {
// Only support updating linux and windows versions that have the natives on the classpath.
return ApplicationResult.DONT_APPLY;
}
// Must add arm 64 to Windows and Linux for versions that use classpath natives.
return ApplicationResult.MUST_APPLY;
}
@Override
public Predicate<Library> apply(Consumer<Library> dependencyConsumer) {
return library -> {
if (library.is(LWJGL_GROUP) && library.target() == Library.Target.NATIVES && (library.classifier() != null && library.classifier().startsWith("natives-"))) {
// Add the arm64 natives.
dependencyConsumer.accept(library.withClassifier(library.classifier() + "-arm64"));
if (!context.hasClasspathNatives()) {
// Remove the none arm64 natives when extracting.
return false;
}
}
return true;
};
}
@Override
public void applyRepositories(RepositoryHandler repositories) {
LoomRepositoryPlugin.forceLWJGLFromMavenCentral(repositories);
}
}

View File

@@ -0,0 +1,63 @@
/*
* This file is part of fabric-loom, licensed under the MIT License (MIT).
*
* Copyright (c) 2023 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.minecraft.library.processors;
import java.util.List;
import org.gradle.api.artifacts.dsl.RepositoryHandler;
import net.fabricmc.loom.LoomRepositoryPlugin;
import net.fabricmc.loom.configuration.providers.minecraft.library.LibraryContext;
import net.fabricmc.loom.configuration.providers.minecraft.library.LibraryProcessor;
import net.fabricmc.loom.util.Platform;
/**
* 1.4.7 contains an LWJGL version with an invalid maven pom, set the metadata sources to not use the pom for this version.
*/
public class LWJGL2MavenLibraryProcessor extends LibraryProcessor {
private static final List<String> LWJGL_LIST = List.of(
"org.lwjgl.lwjgl:lwjgl:2.9.1-nightly-20130708-debug3",
"org.lwjgl.lwjgl:lwjgl:2.9.1-nightly-20131017"
);
public LWJGL2MavenLibraryProcessor(Platform platform, LibraryContext context) {
super(platform, context);
}
@Override
public ApplicationResult getApplicationResult() {
if (context.usesLWJGL3()) {
// Does not support LWJGL 3
return ApplicationResult.DONT_APPLY;
}
return LWJGL_LIST.stream().anyMatch(context::hasLibrary) ? ApplicationResult.MUST_APPLY : ApplicationResult.DONT_APPLY;
}
@Override
public void applyRepositories(RepositoryHandler repositories) {
LoomRepositoryPlugin.setupForLegacyVersions(repositories);
}
}

View File

@@ -0,0 +1,90 @@
/*
* This file is part of fabric-loom, licensed under the MIT License (MIT).
*
* Copyright (c) 2023 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.minecraft.library.processors;
import java.util.function.Consumer;
import java.util.function.Predicate;
import org.gradle.api.artifacts.dsl.RepositoryHandler;
import net.fabricmc.loom.LoomRepositoryPlugin;
import net.fabricmc.loom.configuration.providers.minecraft.library.Library;
import net.fabricmc.loom.configuration.providers.minecraft.library.LibraryContext;
import net.fabricmc.loom.configuration.providers.minecraft.library.LibraryProcessor;
import net.fabricmc.loom.util.Platform;
public class LWJGL3UpgradeLibraryProcessor extends LibraryProcessor {
private static final String LWJGL_GROUP = "org.lwjgl";
private static final String LWJGL_VERSION = "3.3.2";
public LWJGL3UpgradeLibraryProcessor(Platform platform, LibraryContext context) {
super(platform, context);
}
@Override
public ApplicationResult getApplicationResult() {
if (!context.usesLWJGL3()) {
// Only supports LWJGL 3
return ApplicationResult.DONT_APPLY;
}
if (context.isJava19OrLater() && !context.supportsJava19OrLater()) {
// Update LWJGL when Java 19 is not supported
return ApplicationResult.MUST_APPLY;
}
if (upgradeMacOSArm()) {
// Update LWJGL when ARM64 macOS is not supported
return ApplicationResult.MUST_APPLY;
}
// If the developer requests we can still upgrade LWJGL on this platform
return ApplicationResult.CAN_APPLY;
}
@Override
public Predicate<Library> apply(Consumer<Library> dependencyConsumer) {
return library -> {
if (library.is(LWJGL_GROUP) && library.name().startsWith("lwjgl")) {
// Replace the natives with the new version, none natives become runtime only
final Library.Target target = library.target() == Library.Target.NATIVES ? Library.Target.NATIVES : Library.Target.RUNTIME;
final Library upgradedLibrary = library.withVersion(LWJGL_VERSION).withTarget(target);
dependencyConsumer.accept(upgradedLibrary);
}
return true;
};
}
@Override
public void applyRepositories(RepositoryHandler repositories) {
LoomRepositoryPlugin.forceLWJGLFromMavenCentral(repositories);
}
// Add support for macOS
private boolean upgradeMacOSArm() {
return platform.getOperatingSystem().isMacOS() && platform.getArchitecture().isArm() && !context.supportsArm64MacOS() && !context.hasClasspathNatives();
}
}

View File

@@ -0,0 +1,55 @@
/*
* This file is part of fabric-loom, licensed under the MIT License (MIT).
*
* Copyright (c) 2023 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.minecraft.library.processors;
import java.util.function.Consumer;
import java.util.function.Predicate;
import net.fabricmc.loom.configuration.providers.minecraft.library.Library;
import net.fabricmc.loom.configuration.providers.minecraft.library.LibraryContext;
import net.fabricmc.loom.configuration.providers.minecraft.library.LibraryProcessor;
import net.fabricmc.loom.util.Platform;
/**
* Never depend on the legacy "asm-all".
*/
public class LegacyASMLibraryProcessor extends LibraryProcessor {
private static final String LEGACY_ASM = "org.ow2.asm:asm-all";
public LegacyASMLibraryProcessor(Platform platform, LibraryContext context) {
super(platform, context);
}
@Override
public ApplicationResult getApplicationResult() {
// Always attempt to remove
return ApplicationResult.MUST_APPLY;
}
@Override
public Predicate<Library> apply(Consumer<Library> dependencyConsumer) {
return library -> !library.is(LEGACY_ASM);
}
}

View File

@@ -0,0 +1,62 @@
/*
* This file is part of fabric-loom, licensed under the MIT License (MIT).
*
* Copyright (c) 2023 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.minecraft.library.processors;
import java.util.function.Consumer;
import java.util.function.Predicate;
import net.fabricmc.loom.configuration.providers.minecraft.library.Library;
import net.fabricmc.loom.configuration.providers.minecraft.library.LibraryContext;
import net.fabricmc.loom.configuration.providers.minecraft.library.LibraryProcessor;
import net.fabricmc.loom.util.Constants;
import net.fabricmc.loom.util.Platform;
public class LoomNativeSupportLibraryProcessor extends LibraryProcessor {
public LoomNativeSupportLibraryProcessor(Platform platform, LibraryContext context) {
super(platform, context);
}
@Override
public ApplicationResult getApplicationResult() {
if (!context.usesLWJGL3()) {
// Only supports LWJGL 3
return ApplicationResult.DONT_APPLY;
}
if (platform.getOperatingSystem().isMacOS() && platform.getArchitecture().isArm() && !context.supportsArm64MacOS()) {
// Add the loom native support mod when adding ARM64 macOS support
return ApplicationResult.MUST_APPLY;
}
// A developer can opt into this
return ApplicationResult.CAN_APPLY;
}
@Override
public Predicate<Library> apply(Consumer<Library> dependencyConsumer) {
dependencyConsumer.accept(Library.fromMaven(Constants.Dependencies.NATIVE_SUPPORT + Constants.Dependencies.Versions.NATIVE_SUPPORT_VERSION, Library.Target.LOCAL_MOD));
return ALLOW_ALL;
}
}

View File

@@ -0,0 +1,74 @@
/*
* This file is part of fabric-loom, licensed under the MIT License (MIT).
*
* Copyright (c) 2023 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.minecraft.library.processors;
import java.util.function.Consumer;
import java.util.function.Predicate;
import net.fabricmc.loom.configuration.providers.minecraft.library.Library;
import net.fabricmc.loom.configuration.providers.minecraft.library.LibraryContext;
import net.fabricmc.loom.configuration.providers.minecraft.library.LibraryProcessor;
import net.fabricmc.loom.util.Platform;
public class ObjcBridgeUpgradeLibraryProcessor extends LibraryProcessor {
private static final String OBJC_BRIDGE_PREFIX = "ca.weblite:java-objc-bridge";
private static final String OBJC_BRIDGE_VERSION = "1.1";
private static final String OBJC_BRIDGE_NAME = "%s:%s".formatted(OBJC_BRIDGE_PREFIX, OBJC_BRIDGE_VERSION);
public ObjcBridgeUpgradeLibraryProcessor(Platform platform, LibraryContext context) {
super(platform, context);
}
@Override
public ApplicationResult getApplicationResult() {
if (!context.usesLWJGL3()) {
// Only supports LWJGL 3
return ApplicationResult.DONT_APPLY;
}
if (!(platform.getOperatingSystem().isMacOS() && platform.getArchitecture().isArm())) {
// Only supported on arm64 macOS
return ApplicationResult.DONT_APPLY;
}
// Apply when Arm64 macOS is unsupported by Minecraft
return context.supportsArm64MacOS() ? ApplicationResult.DONT_APPLY : ApplicationResult.MUST_APPLY;
}
@Override
public Predicate<Library> apply(Consumer<Library> dependencyConsumer) {
// Add the updated library on the runtime classpath.
dependencyConsumer.accept(Library.fromMaven(OBJC_BRIDGE_NAME, Library.Target.RUNTIME));
return library -> {
if (library.is(OBJC_BRIDGE_PREFIX)) {
// Remove the natives, as they are included in the dep library we added to the runtime classpath above.
return library.target() != Library.Target.NATIVES;
}
return true;
};
}
}

View File

@@ -0,0 +1,58 @@
/*
* This file is part of fabric-loom, licensed under the MIT License (MIT).
*
* Copyright (c) 2023 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.minecraft.library.processors;
import java.util.function.Consumer;
import java.util.function.Predicate;
import net.fabricmc.loom.configuration.providers.minecraft.library.Library;
import net.fabricmc.loom.configuration.providers.minecraft.library.LibraryContext;
import net.fabricmc.loom.configuration.providers.minecraft.library.LibraryProcessor;
import net.fabricmc.loom.util.Platform;
public class RuntimeLog4jLibraryProcessor extends LibraryProcessor {
private static final String LOG4J_GROUP = "org.apache.logging.log4j";
public RuntimeLog4jLibraryProcessor(Platform platform, LibraryContext context) {
super(platform, context);
}
@Override
public ApplicationResult getApplicationResult() {
return ApplicationResult.CAN_APPLY;
}
@Override
public Predicate<Library> apply(Consumer<Library> dependencyConsumer) {
return library -> {
if (library.is(LOG4J_GROUP)) {
dependencyConsumer.accept(library.withTarget(Library.Target.RUNTIME));
return false;
}
return true;
};
}
}

View File

@@ -183,7 +183,7 @@ public abstract class AbstractMappedMinecraftProvider<M extends MinecraftProvide
try (OutputConsumerPath outputConsumer = new OutputConsumerPath.Builder(remappedJars.outputJarPath()).build()) {
outputConsumer.addNonClassFiles(remappedJars.inputJar());
remapper.readClassPath(TinyRemapperHelper.getMinecraftDependencies(getProject()));
remapper.readClassPath(TinyRemapperHelper.getMinecraftCompileLibraries(getProject()));
for (Path path : remappedJars.remapClasspath()) {
remapper.readClassPath(path);

View File

@@ -0,0 +1,271 @@
/*
* This file is part of fabric-loom, licensed under the MIT License (MIT).
*
* Copyright (c) 2023 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.kotlin.remapping;
import java.util.List;
import kotlinx.metadata.KmAnnotation;
import kotlinx.metadata.KmProperty;
import kotlinx.metadata.internal.extensions.KmClassExtension;
import kotlinx.metadata.internal.extensions.KmConstructorExtension;
import kotlinx.metadata.internal.extensions.KmFunctionExtension;
import kotlinx.metadata.internal.extensions.KmPackageExtension;
import kotlinx.metadata.internal.extensions.KmPropertyExtension;
import kotlinx.metadata.internal.extensions.KmTypeExtension;
import kotlinx.metadata.internal.extensions.KmTypeParameterExtension;
import kotlinx.metadata.jvm.JvmFieldSignature;
import kotlinx.metadata.jvm.JvmMethodSignature;
import kotlinx.metadata.jvm.internal.JvmClassExtension;
import kotlinx.metadata.jvm.internal.JvmConstructorExtension;
import kotlinx.metadata.jvm.internal.JvmFunctionExtension;
import kotlinx.metadata.jvm.internal.JvmPackageExtension;
import kotlinx.metadata.jvm.internal.JvmPropertyExtension;
import kotlinx.metadata.jvm.internal.JvmTypeExtension;
import kotlinx.metadata.jvm.internal.JvmTypeParameterExtension;
import org.jetbrains.annotations.Nullable;
/*
* This is a fun meme. All of these kotlin classes are marked as "internal" so Kotlin code cannot compile against them.
* However, luckily for us the Java compiler has no idea about this, so they can compile against it :D
*
* This file contains Java wrappers around Kotlin classes, to used by Kotlin.
*/
public interface JvmExtensionWrapper {
record Class(JvmClassExtension extension) implements JvmExtensionWrapper {
@Nullable
public static Class get(KmClassExtension classExtension) {
if (classExtension instanceof JvmClassExtension jvmClassExtension) {
return new Class(jvmClassExtension);
}
return null;
}
public List<KmProperty> getLocalDelegatedProperties() {
return extension.getLocalDelegatedProperties();
}
@Nullable
public String getModuleName() {
return extension.getModuleName();
}
public void setModuleName(@Nullable String name) {
extension.setModuleName(name);
}
@Nullable
public String getAnonymousObjectOriginName() {
return extension.getAnonymousObjectOriginName();
}
public void setAnonymousObjectOriginName(@Nullable String name) {
extension.setAnonymousObjectOriginName(name);
}
public int getJvmFlags() {
return extension.getJvmFlags();
}
public void setJvmFlags(int flags) {
extension.setJvmFlags(flags);
}
}
record Package(JvmPackageExtension extension) {
@Nullable
public static Package get(KmPackageExtension packageExtension) {
if (packageExtension instanceof JvmPackageExtension jvmPackageExtension) {
return new Package(jvmPackageExtension);
}
return null;
}
public List<KmProperty> getLocalDelegatedProperties() {
return extension.getLocalDelegatedProperties();
}
@Nullable
public String getModuleName() {
return extension.getModuleName();
}
public void setModuleName(@Nullable String name) {
extension.setModuleName(name);
}
}
record Function(JvmFunctionExtension extension) {
@Nullable
public static Function get(KmFunctionExtension functionExtension) {
if (functionExtension instanceof JvmFunctionExtension jvmFunctionExtension) {
return new Function(jvmFunctionExtension);
}
return null;
}
@Nullable
public JvmMethodSignature getSignature() {
return extension.getSignature();
}
public void setSignature(@Nullable JvmMethodSignature signature) {
extension.setSignature(signature);
}
@Nullable
public String getLambdaClassOriginName() {
return extension.getLambdaClassOriginName();
}
public void setLambdaClassOriginName(@Nullable String name) {
extension.setLambdaClassOriginName(name);
}
}
record Property(JvmPropertyExtension extension) {
@Nullable
public static Property get(KmPropertyExtension propertyExtension) {
if (propertyExtension instanceof JvmPropertyExtension jvmPropertyExtension) {
return new Property(jvmPropertyExtension);
}
return null;
}
public int getJvmFlags() {
return extension.getJvmFlags();
}
public void setJvmFlags(int flags) {
extension.setJvmFlags(flags);
}
@Nullable
public JvmFieldSignature getFieldSignature() {
return extension.getFieldSignature();
}
public void setFieldSignature(@Nullable JvmFieldSignature signature) {
extension.setFieldSignature(signature);
}
@Nullable
public JvmMethodSignature getGetterSignature() {
return extension.getGetterSignature();
}
public void setGetterSignature(@Nullable JvmMethodSignature signature) {
extension.setGetterSignature(signature);
}
@Nullable
public JvmMethodSignature getSetterSignature() {
return extension.getSetterSignature();
}
public void setSetterSignature(@Nullable JvmMethodSignature signature) {
extension.setSetterSignature(signature);
}
@Nullable
public JvmMethodSignature getSyntheticMethodForAnnotations() {
return extension.getSyntheticMethodForAnnotations();
}
public void setSyntheticMethodForAnnotations(@Nullable JvmMethodSignature signature) {
extension.setSyntheticMethodForAnnotations(signature);
}
@Nullable
public JvmMethodSignature getSyntheticMethodForDelegate() {
return extension.getSyntheticMethodForDelegate();
}
public void setSyntheticMethodForDelegate(@Nullable JvmMethodSignature signature) {
extension.setSyntheticMethodForDelegate(signature);
}
}
record Constructor(JvmConstructorExtension extension) {
@Nullable
public static Constructor get(KmConstructorExtension constructorExtension) {
if (constructorExtension instanceof JvmConstructorExtension jvmConstructorExtension) {
return new Constructor(jvmConstructorExtension);
}
return null;
}
@Nullable
public JvmMethodSignature getSignature() {
return extension.getSignature();
}
public void setSignature(@Nullable JvmMethodSignature signature) {
extension.setSignature(signature);
}
}
record TypeParameter(JvmTypeParameterExtension extension) {
@Nullable
public static TypeParameter get(KmTypeParameterExtension typeParameterExtension) {
if (typeParameterExtension instanceof JvmTypeParameterExtension jvmTypeParameterExtension) {
return new TypeParameter(jvmTypeParameterExtension);
}
return null;
}
public List<KmAnnotation> getAnnotations() {
return extension.getAnnotations();
}
}
record Type(JvmTypeExtension extension) {
@Nullable
public static Type get(KmTypeExtension typeExtension) {
if (typeExtension instanceof JvmTypeExtension jvmTypeExtension) {
return new Type(jvmTypeExtension);
}
return null;
}
public boolean isRaw() {
return extension.isRaw();
}
public void setRaw(boolean raw) {
extension.setRaw(raw);
}
public List<KmAnnotation> getAnnotations() {
return extension.getAnnotations();
}
}
}

View File

@@ -38,23 +38,18 @@ import java.util.stream.Collectors;
import org.gradle.api.Project;
import org.gradle.api.file.ConfigurableFileCollection;
import org.gradle.api.file.FileCollection;
import org.gradle.api.provider.ListProperty;
import org.gradle.api.specs.Spec;
import org.gradle.api.tasks.JavaExec;
import org.jetbrains.annotations.NotNull;
import net.fabricmc.loom.configuration.ide.RunConfig;
import net.fabricmc.loom.util.Constants;
import net.fabricmc.loom.util.gradle.GradleUtils;
public abstract class AbstractRunTask extends JavaExec {
private final RunConfig config;
// We control the classpath, as we use a ArgFile to pass it over the command line: https://docs.oracle.com/javase/7/docs/technotes/tools/windows/javac.html#commandlineargfile
private final ConfigurableFileCollection classpath = getProject().getObjects().fileCollection();
// TODO remove when updating loom to Gradle 8.1
private static final boolean setJvmArgsProperty = GradleUtils.JavaExecSpec_getJvmArguments != null;
public AbstractRunTask(Function<Project, RunConfig> configProvider) {
super();
setGroup(Constants.TaskGroup.FABRIC);
@@ -65,17 +60,7 @@ public abstract class AbstractRunTask extends JavaExec {
args(config.programArgs);
getMainClass().set(config.mainClass);
// TODO replace with a direct call when updating loom to Gradle 8.1
if (setJvmArgsProperty) {
try {
assert GradleUtils.JavaExecSpec_getJvmArguments != null;
//noinspection unchecked
ListProperty<String> jvmArguments = (ListProperty<String>) GradleUtils.JavaExecSpec_getJvmArguments.invoke(this);
jvmArguments.addAll(getProject().provider(this::getGameJvmArgs));
} catch (Throwable e) {
throw new RuntimeException("Failed to set jvm args", e);
}
}
getJvmArguments().addAll(getProject().provider(this::getGameJvmArgs));
}
private boolean canUseArgFile() {
@@ -110,25 +95,6 @@ public abstract class AbstractRunTask extends JavaExec {
super.setWorkingDir(dir);
}
@Override
// TODO remove when updating loom to Gradle 8.1
public List<String> getJvmArgs() {
final List<String> superArgs = super.getJvmArgs();
if (setJvmArgsProperty) {
// Don't do anything here when on Gradle 8.1
return superArgs;
}
final List<String> args = new ArrayList<>(getGameJvmArgs());
if (superArgs != null) {
args.addAll(superArgs);
}
return args;
}
private List<String> getGameJvmArgs() {
final List<String> args = new ArrayList<>();

View File

@@ -75,7 +75,7 @@ import net.fabricmc.loom.decompilers.linemap.LineMapVisitor;
import net.fabricmc.loom.util.Constants;
import net.fabricmc.loom.util.FileSystemUtil;
import net.fabricmc.loom.util.IOStringConsumer;
import net.fabricmc.loom.util.OperatingSystem;
import net.fabricmc.loom.util.Platform;
import net.fabricmc.loom.util.gradle.ThreadedProgressLoggerConsumer;
import net.fabricmc.loom.util.gradle.ThreadedSimpleProgressLogger;
import net.fabricmc.loom.util.gradle.WorkerDaemonClientsManagerHelper;
@@ -128,11 +128,13 @@ public abstract class GenerateSourcesTask extends AbstractLoomTask {
@TaskAction
public void run() throws IOException {
if (!OperatingSystem.is64Bit()) {
final Platform platform = Platform.CURRENT;
if (!platform.getArchitecture().is64Bit()) {
throw new UnsupportedOperationException("GenSources task requires a 64bit JVM to run due to the memory requirements.");
}
if (!OperatingSystem.isUnixDomainSocketsSupported()) {
if (!platform.supportsUnixDomainSockets()) {
getProject().getLogger().warn("Decompile worker logging disabled as Unix Domain Sockets is not supported on your operating system.");
doWork(null);
@@ -178,7 +180,7 @@ public abstract class GenerateSourcesTask extends AbstractLoomTask {
params.getIPCPath().set(ipcServer.getPath().toFile());
}
params.getClassPath().setFrom(getProject().getConfigurations().getByName(Constants.Configurations.MINECRAFT_DEPENDENCIES));
params.getClassPath().setFrom(getProject().getConfigurations().getByName(Constants.Configurations.MINECRAFT_COMPILE_LIBRARIES));
// Architectury
params.getForge().set(getExtension().isForge());
@@ -206,7 +208,7 @@ public abstract class GenerateSourcesTask extends AbstractLoomTask {
return getWorkerExecutor().processIsolation(spec -> {
spec.forkOptions(forkOptions -> {
forkOptions.setMinHeapSize("512m");
forkOptions.setMinHeapSize(String.format(Locale.ENGLISH, "%dm", Math.min(512, decompilerOptions.getMemory().get())));
forkOptions.setMaxHeapSize(String.format(Locale.ENGLISH, "%dm", decompilerOptions.getMemory().get()));
forkOptions.systemProperty(WorkerDaemonClientsManagerHelper.MARKER_PROP, jvmMarkerValue);
});
@@ -240,7 +242,7 @@ public abstract class GenerateSourcesTask extends AbstractLoomTask {
public abstract static class DecompileAction implements WorkAction<DecompileParams> {
@Override
public void execute() {
if (!getParameters().getIPCPath().isPresent() || !OperatingSystem.isUnixDomainSocketsSupported()) {
if (!getParameters().getIPCPath().isPresent() || !Platform.CURRENT.supportsUnixDomainSockets()) {
// Does not support unix domain sockets, print to sout.
doDecompile(System.out::println);
return;

View File

@@ -68,7 +68,7 @@ public abstract class UnpickJarTask extends JavaExec {
getMainClass().set("daomephsta.unpick.cli.Main");
getConstantJar().setFrom(getProject().getConfigurations().getByName(Constants.Configurations.MAPPING_CONSTANTS));
getUnpickClasspath().setFrom(getProject().getConfigurations().getByName(Constants.Configurations.MINECRAFT_DEPENDENCIES));
getUnpickClasspath().setFrom(getProject().getConfigurations().getByName(Constants.Configurations.MINECRAFT_COMPILE_LIBRARIES));
getUnpickClasspath().from(getProject().getConfigurations().getByName(Constants.Configurations.MOD_COMPILE_CLASSPATH_MAPPED));
}

View File

@@ -54,7 +54,7 @@ public abstract class GenerateRemapClasspathTask extends AbstractLoomTask {
public GenerateRemapClasspathTask() {
final ConfigurationContainer configurations = getProject().getConfigurations();
getRemapClasspath().from(configurations.named(Constants.Configurations.LOADER_DEPENDENCIES));
getRemapClasspath().from(configurations.named(Constants.Configurations.MINECRAFT_COMPILE_LIBRARIES));
getExtension().getRuntimeRemapConfigurations().stream()
.map(RemapConfigurationSettings::getName)
.map(configurations::named)

View File

@@ -47,15 +47,24 @@ public class Constants {
public static final String MOD_COMPILE_CLASSPATH_MAPPED = "modCompileClasspathMapped";
public static final String INCLUDE = "include";
public static final String MINECRAFT = "minecraft";
public static final String MINECRAFT_COMPILE_LIBRARIES = "minecraftLibraries";
public static final String MINECRAFT_RUNTIME_LIBRARIES = "minecraftRuntimeLibraries";
/**
* The server specific configuration will be empty when using a legacy (pre 21w38a server jar)
* These configurations contain the minecraft client libraries.
*/
public static final String MINECRAFT_CLIENT_COMPILE_LIBRARIES = "minecraftClientLibraries";
public static final String MINECRAFT_CLIENT_RUNTIME_LIBRARIES = "minecraftClientRuntimeLibraries";
/**
* The server specific configurations will be empty when using a legacy (pre 21w38a server jar)
* find the client only dependencies on the "minecraftLibraries" config.
*/
public static final String MINECRAFT_SERVER_DEPENDENCIES = "minecraftServerLibraries";
public static final String MINECRAFT_DEPENDENCIES = "minecraftLibraries";
public static final String MINECRAFT_RUNTIME_DEPENDENCIES = "minecraftRuntimeOnlyLibraries";
public static final String MINECRAFT_SERVER_COMPILE_LIBRARIES = "minecraftServerLibraries";
public static final String MINECRAFT_SERVER_RUNTIME_LIBRARIES = "minecraftServerRuntimeLibraries";
/**
* Not used on Minecraft 1.19-pre1 or later. Natives are all loaded from the classpath.
* Before Minecraft 1.19-pre1 this contains libraries that need to be extracted otherwise this goes on the runtime classpath.
*/
public static final String MINECRAFT_NATIVES = "minecraftNatives";
public static final String MAPPINGS = "mappings";
@@ -126,7 +135,7 @@ public class Constants {
public static final String MIXIN_COMPILE_EXTENSIONS = "0.6.0";
public static final String DEV_LAUNCH_INJECTOR = "0.2.1+build.8";
public static final String TERMINAL_CONSOLE_APPENDER = "1.2.0";
public static final String JETBRAINS_ANNOTATIONS = "24.0.0";
public static final String JETBRAINS_ANNOTATIONS = "24.0.1";
public static final String NATIVE_SUPPORT_VERSION = "1.0.1";
public static final String JAVAX_ANNOTATIONS = "3.0.2";
public static final String FORGE_RUNTIME = "1.1.8";
@@ -178,6 +187,7 @@ public class Constants {
public static final String DONT_REMAP = "fabric.loom.dontRemap";
public static final String DISABLE_REMAPPED_VARIANTS = "fabric.loom.disableRemappedVariants";
public static final String DISABLE_PROJECT_DEPENDENT_MODS = "fabric.loom.disableProjectDependentMods";
public static final String LIBRARY_PROCESSORS = "fabric.loom.libraryProcessors";
}
public static final class Forge {

View File

@@ -1,7 +1,7 @@
/*
* This file is part of fabric-loom, licensed under the MIT License (MIT).
*
* Copyright (c) 2016-2021 FabricMC
* Copyright (c) 2023 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
@@ -29,42 +29,52 @@ import java.io.UncheckedIOException;
import java.net.StandardProtocolFamily;
import java.nio.channels.ServerSocketChannel;
public class OperatingSystem {
public static final String WINDOWS = "windows";
public static final String MAC_OS = "osx";
public static final String LINUX = "linux";
final class CurrentPlatform implements Platform {
static final Platform INSTANCE = new CurrentPlatform();
public static final String CURRENT_OS = getOS();
private final OperatingSystem operatingSystem;
private final Architecture architecture;
private final boolean supportsUnixDomainSockets;
private static String getOS() {
String osName = System.getProperty("os.name").toLowerCase();
private CurrentPlatform() {
this.operatingSystem = getCurrentOperatingSystem();
this.architecture = getCurrentArchitecture();
this.supportsUnixDomainSockets = isUnixDomainSocketsSupported();
}
private static OperatingSystem getCurrentOperatingSystem() {
final String osName = System.getProperty("os.name").toLowerCase();
if (osName.contains("win")) {
return WINDOWS;
return OperatingSystem.WINDOWS;
} else if (osName.contains("mac")) {
return MAC_OS;
return OperatingSystem.MAC_OS;
} else {
return LINUX;
// Or unknown
return OperatingSystem.LINUX;
}
}
public static boolean is64Bit() {
return System.getProperty("sun.arch.data.model").contains("64");
}
private static Architecture getCurrentArchitecture() {
final String arch = System.getProperty("os.arch");
final boolean is64Bit = arch.contains("64") || arch.startsWith("armv8");
final boolean isArm = arch.startsWith("arm") || arch.startsWith("aarch64");
public static boolean isCIBuild() {
String loomProperty = System.getProperty("fabric.loom.ci");
return new Architecture() {
@Override
public boolean is64Bit() {
return is64Bit;
}
if (loomProperty != null) {
return loomProperty.equalsIgnoreCase("true");
}
// CI seems to be set by most popular CI services
return System.getenv("CI") != null;
@Override
public boolean isArm() {
return isArm;
}
};
}
// Requires Unix, or Windows 10 17063 or later. See: https://devblogs.microsoft.com/commandline/af_unix-comes-to-windows/
public static boolean isUnixDomainSocketsSupported() {
private static boolean isUnixDomainSocketsSupported() {
try (ServerSocketChannel serverChannel = ServerSocketChannel.open(StandardProtocolFamily.UNIX)) {
return true;
} catch (UnsupportedOperationException e) {
@@ -73,4 +83,19 @@ public class OperatingSystem {
throw new UncheckedIOException(e);
}
}
@Override
public OperatingSystem getOperatingSystem() {
return operatingSystem;
}
@Override
public Architecture getArchitecture() {
return architecture;
}
@Override
public boolean supportsUnixDomainSockets() {
return supportsUnixDomainSockets;
}
}

View File

@@ -1,7 +1,7 @@
/*
* This file is part of fabric-loom, licensed under the MIT License (MIT).
*
* Copyright (c) 2021 FabricMC
* Copyright (c) 2023 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
@@ -24,14 +24,36 @@
package net.fabricmc.loom.util;
public record Architecture(String name) {
public static final Architecture CURRENT = new Architecture(System.getProperty("os.arch"));
public interface Platform {
Platform CURRENT = CurrentPlatform.INSTANCE;
public boolean is64Bit() {
return name.contains("64") || name.startsWith("armv8");
enum OperatingSystem {
WINDOWS,
MAC_OS,
LINUX; // Or Unknown
public boolean isWindows() {
return this == WINDOWS;
}
public boolean isMacOS() {
return this == MAC_OS;
}
public boolean isLinux() {
return this == LINUX;
}
}
public boolean isArm() {
return name.startsWith("arm") || name.startsWith("aarch64");
OperatingSystem getOperatingSystem();
interface Architecture {
boolean is64Bit();
boolean isArm();
}
Architecture getArchitecture();
boolean supportsUnixDomainSockets();
}

View File

@@ -263,7 +263,7 @@ public class SourceRemapper {
final List<Path> classPath = new ArrayList<>();
for (File file : project.getConfigurations().getByName(Constants.Configurations.LOADER_DEPENDENCIES).getFiles()) {
for (File file : project.getConfigurations().getByName(Constants.Configurations.MINECRAFT_COMPILE_LIBRARIES).getFiles()) {
classPath.add(file.toPath());
}

View File

@@ -110,8 +110,8 @@ public final class TinyRemapperHelper {
return builder.build();
}
public static Path[] getMinecraftDependencies(Project project) {
return project.getConfigurations().getByName(Constants.Configurations.MINECRAFT_DEPENDENCIES).getFiles()
public static Path[] getMinecraftCompileLibraries(Project project) {
return project.getConfigurations().getByName(Constants.Configurations.MINECRAFT_COMPILE_LIBRARIES).getFiles()
.stream().map(File::toPath).toArray(Path[]::new);
}

View File

@@ -55,6 +55,6 @@ public class KotlinPluginUtils {
}
public static String getKotlinMetadataVersion() {
return KotlinClassMetadata.class.getPackage().getImplementationVersion();
return KotlinClassMetadata.class.getPackage().getImplementationVersion().split("-")[0];
}
}

View File

@@ -31,6 +31,7 @@ import java.util.List;
import java.util.stream.Stream;
import net.fabricmc.loom.LoomGradlePlugin;
import net.fabricmc.loom.kotlin.remapping.JvmExtensionWrapper;
import net.fabricmc.loom.kotlin.remapping.KotlinMetadataTinyRemapperExtensionImpl;
/**
@@ -61,7 +62,8 @@ public class KotlinRemapperClassloader extends URLClassLoader {
public static KotlinRemapperClassloader create(KotlinClasspath classpathProvider) {
// Include the libraries that are not on the kotlin classpath.
final Stream<URL> loomUrls = getClassUrls(
KotlinMetadataTinyRemapperExtensionImpl.class // Loom
KotlinMetadataTinyRemapperExtensionImpl.class, // Loom (Kotlin)
JvmExtensionWrapper.class // Loom (Java)
);
final URL[] urls = Stream.concat(

View File

@@ -1,7 +1,7 @@
/*
* This file is part of fabric-loom, licensed under the MIT License (MIT).
*
* Copyright (c) 2022 FabricMC
* Copyright (c) 2022-2023 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
@@ -24,8 +24,8 @@
package net.fabricmc.loom.kotlin.remapping
import kotlinx.metadata.jvm.KotlinClassHeader
import kotlinx.metadata.jvm.KotlinClassMetadata
import kotlinx.metadata.jvm.Metadata
import org.objectweb.asm.AnnotationVisitor
import org.objectweb.asm.Opcodes
import org.objectweb.asm.commons.Remapper
@@ -58,20 +58,18 @@ class KotlinClassMetadataRemappingAnnotationVisitor(private val remapper: Remapp
when (val metadata = KotlinClassMetadata.read(header)) {
is KotlinClassMetadata.Class -> {
val klass = metadata.toKmClass()
val writer = KotlinClassMetadata.Class.Writer()
klass.accept(RemappingKmVisitors(remapper).RemappingKmClassVisitor(writer))
val remapped = writer.write(header.metadataVersion, header.extraInt).header
var klass = metadata.toKmClass()
klass = KotlinClassRemapper(remapper).remap(klass)
val remapped = KotlinClassMetadata.writeClass(klass, header.metadataVersion, header.extraInt).annotationData
writeClassHeader(remapped)
validateKotlinClassHeader(remapped, header)
}
is KotlinClassMetadata.SyntheticClass -> {
val klambda = metadata.toKmLambda()
var klambda = metadata.toKmLambda()
if (klambda != null) {
val writer = KotlinClassMetadata.SyntheticClass.Writer()
klambda.accept(RemappingKmVisitors(remapper).RemappingKmLambdaVisitor(writer))
val remapped = writer.write(header.metadataVersion, header.extraInt).header
klambda = KotlinClassRemapper(remapper).remap(klambda)
val remapped = KotlinClassMetadata.writeLambda(klambda, header.metadataVersion, header.extraInt).annotationData
writeClassHeader(remapped)
validateKotlinClassHeader(remapped, header)
} else {
@@ -79,18 +77,16 @@ class KotlinClassMetadataRemappingAnnotationVisitor(private val remapper: Remapp
}
}
is KotlinClassMetadata.FileFacade -> {
val kpackage = metadata.toKmPackage()
val writer = KotlinClassMetadata.FileFacade.Writer()
kpackage.accept(RemappingKmVisitors(remapper).RemappingKmPackageVisitor(writer))
val remapped = writer.write(header.metadataVersion, header.extraInt).header
var kpackage = metadata.toKmPackage()
kpackage = KotlinClassRemapper(remapper).remap(kpackage)
val remapped = KotlinClassMetadata.writeFileFacade(kpackage, header.metadataVersion, header.extraInt).annotationData
writeClassHeader(remapped)
validateKotlinClassHeader(remapped, header)
}
is KotlinClassMetadata.MultiFileClassPart -> {
val kpackage = metadata.toKmPackage()
val writer = KotlinClassMetadata.MultiFileClassPart.Writer()
kpackage.accept(RemappingKmVisitors(remapper).RemappingKmPackageVisitor(writer))
val remapped = writer.write(metadata.facadeClassName, metadata.header.metadataVersion, metadata.header.extraInt).header
var kpackage = metadata.toKmPackage()
kpackage = KotlinClassRemapper(remapper).remap(kpackage)
val remapped = KotlinClassMetadata.writeMultiFileClassPart(kpackage, metadata.facadeClassName, metadata.annotationData.metadataVersion, metadata.annotationData.extraInt).annotationData
writeClassHeader(remapped)
validateKotlinClassHeader(remapped, header)
}
@@ -102,7 +98,7 @@ class KotlinClassMetadataRemappingAnnotationVisitor(private val remapper: Remapp
}
@Suppress("UNCHECKED_CAST")
private fun readHeader(): KotlinClassHeader? {
private fun readHeader(): Metadata? {
var kind: Int? = null
var metadataVersion: IntArray? = null
var data1: Array<String>? = null
@@ -127,10 +123,10 @@ class KotlinClassMetadataRemappingAnnotationVisitor(private val remapper: Remapp
}
}
return KotlinClassHeader(kind, metadataVersion, data1, data2, extraString, packageName, extraInt)
return Metadata(kind, metadataVersion, data1, data2, extraString, packageName, extraInt)
}
private fun writeClassHeader(header: KotlinClassHeader) {
private fun writeClassHeader(header: Metadata) {
val newNode = AnnotationNode(api, desc)
newNode.values = this.values.toMutableList()
@@ -151,7 +147,7 @@ class KotlinClassMetadataRemappingAnnotationVisitor(private val remapper: Remapp
newNode.accept(next)
}
private fun validateKotlinClassHeader(remapped: KotlinClassHeader, original: KotlinClassHeader) {
private fun validateKotlinClassHeader(remapped: Metadata, original: Metadata) {
// This can happen when the remapper is ran on a kotlin version that does not match the version the class was compiled with.
if (remapped.data2.size != original.data2.size) {
logger.info("Kotlin class metadata size mismatch: data2 size does not match original in class $className. New: ${remapped.data2.size} Old: ${original.data2.size}")

View File

@@ -0,0 +1,250 @@
/*
* This file is part of fabric-loom, licensed under the MIT License (MIT).
*
* Copyright (c) 2023 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.kotlin.remapping
import kotlinx.metadata.ClassName
import kotlinx.metadata.ExperimentalContextReceivers
import kotlinx.metadata.KmAnnotation
import kotlinx.metadata.KmClass
import kotlinx.metadata.KmClassifier
import kotlinx.metadata.KmConstructor
import kotlinx.metadata.KmFlexibleTypeUpperBound
import kotlinx.metadata.KmFunction
import kotlinx.metadata.KmLambda
import kotlinx.metadata.KmPackage
import kotlinx.metadata.KmProperty
import kotlinx.metadata.KmType
import kotlinx.metadata.KmTypeAlias
import kotlinx.metadata.KmTypeParameter
import kotlinx.metadata.KmTypeProjection
import kotlinx.metadata.KmValueParameter
import kotlinx.metadata.internal.extensions.KmClassExtension
import kotlinx.metadata.internal.extensions.KmConstructorExtension
import kotlinx.metadata.internal.extensions.KmFunctionExtension
import kotlinx.metadata.internal.extensions.KmPackageExtension
import kotlinx.metadata.internal.extensions.KmPropertyExtension
import kotlinx.metadata.internal.extensions.KmTypeAliasExtension
import kotlinx.metadata.internal.extensions.KmTypeExtension
import kotlinx.metadata.internal.extensions.KmTypeParameterExtension
import kotlinx.metadata.internal.extensions.KmValueParameterExtension
import kotlinx.metadata.isLocal
import kotlinx.metadata.jvm.JvmFieldSignature
import kotlinx.metadata.jvm.JvmMethodSignature
import kotlinx.metadata.jvm.jvmInternalName
import org.objectweb.asm.commons.Remapper
@OptIn(ExperimentalContextReceivers::class)
class KotlinClassRemapper(private val remapper: Remapper) {
fun remap(clazz: KmClass): KmClass {
clazz.name = remap(clazz.name)
clazz.typeParameters.replaceAll(this::remap)
clazz.supertypes.replaceAll(this::remap)
clazz.functions.replaceAll(this::remap)
clazz.properties.replaceAll(this::remap)
clazz.typeAliases.replaceAll(this::remap)
clazz.constructors.replaceAll(this::remap)
clazz.nestedClasses.replaceAll(this::remap)
clazz.sealedSubclasses.replaceAll(this::remap)
clazz.contextReceiverTypes.replaceAll(this::remap)
clazz.getExtensions().replaceAll(this::remap)
return clazz
}
fun remap(lambda: KmLambda): KmLambda {
lambda.function = remap(lambda.function)
return lambda
}
fun remap(pkg: KmPackage): KmPackage {
pkg.functions.replaceAll(this::remap)
pkg.properties.replaceAll(this::remap)
pkg.typeAliases.replaceAll(this::remap)
pkg.getExtensions().replaceAll(this::remap)
return pkg
}
private fun remap(name: ClassName): ClassName {
val local = name.isLocal
val remapped = remapper.map(name.jvmInternalName).replace('$', '.')
if (local) {
return ".$remapped"
}
return remapped
}
private fun remap(type: KmType): KmType {
type.classifier = when (val classifier = type.classifier) {
is KmClassifier.Class -> KmClassifier.Class(remap(classifier.name))
is KmClassifier.TypeParameter -> KmClassifier.TypeParameter(classifier.id)
is KmClassifier.TypeAlias -> KmClassifier.TypeAlias(remap(classifier.name))
}
type.arguments.replaceAll(this::remap)
type.abbreviatedType = type.abbreviatedType?.let { remap(it) }
type.outerType = type.outerType?.let { remap(it) }
type.flexibleTypeUpperBound = type.flexibleTypeUpperBound?.let { remap(it) }
type.getExtensions().replaceAll(this::remap)
return type
}
private fun remap(function: KmFunction): KmFunction {
function.typeParameters.replaceAll(this::remap)
function.receiverParameterType = function.receiverParameterType?.let { remap(it) }
function.contextReceiverTypes.replaceAll(this::remap)
function.valueParameters.replaceAll(this::remap)
function.returnType = remap(function.returnType)
function.getExtensions().replaceAll(this::remap)
return function
}
private fun remap(property: KmProperty): KmProperty {
property.typeParameters.replaceAll(this::remap)
property.receiverParameterType = property.receiverParameterType?.let { remap(it) }
property.contextReceiverTypes.replaceAll(this::remap)
property.setterParameter = property.setterParameter?.let { remap(it) }
property.returnType = remap(property.returnType)
property.getExtensions().replaceAll(this::remap)
return property
}
private fun remap(typeAlias: KmTypeAlias): KmTypeAlias {
typeAlias.typeParameters.replaceAll(this::remap)
typeAlias.underlyingType = remap(typeAlias.underlyingType)
typeAlias.expandedType = remap(typeAlias.expandedType)
typeAlias.annotations.replaceAll(this::remap)
typeAlias.getExtensions().replaceAll(this::remap)
return typeAlias
}
private fun remap(constructor: KmConstructor): KmConstructor {
constructor.valueParameters.replaceAll(this::remap)
constructor.getExtensions().replaceAll(this::remap)
return constructor
}
private fun remap(typeParameter: KmTypeParameter): KmTypeParameter {
typeParameter.upperBounds.replaceAll(this::remap)
typeParameter.getExtensions().replaceAll(this::remap)
return typeParameter
}
private fun remap(typeProjection: KmTypeProjection): KmTypeProjection {
return KmTypeProjection(typeProjection.variance, typeProjection.type?.let { remap(it) })
}
private fun remap(flexibleTypeUpperBound: KmFlexibleTypeUpperBound): KmFlexibleTypeUpperBound {
return KmFlexibleTypeUpperBound(remap(flexibleTypeUpperBound.type), flexibleTypeUpperBound.typeFlexibilityId)
}
private fun remap(valueParameter: KmValueParameter): KmValueParameter {
valueParameter.type = remap(valueParameter.type)
valueParameter.varargElementType = valueParameter.varargElementType?.let { remap(it) }
valueParameter.getExtensions().replaceAll(this::remap)
return valueParameter
}
private fun remap(annotation: KmAnnotation): KmAnnotation {
return KmAnnotation(remap(annotation.className), annotation.arguments)
}
private fun remap(classExtension: KmClassExtension): KmClassExtension {
JvmExtensionWrapper.Class.get(classExtension)?.let {
it.localDelegatedProperties.replaceAll(this::remap)
return it.extension
}
return classExtension
}
private fun remap(packageExtension: KmPackageExtension): KmPackageExtension {
JvmExtensionWrapper.Package.get(packageExtension)?.let {
it.localDelegatedProperties.replaceAll(this::remap)
return it.extension
}
return packageExtension
}
private fun remap(typeExtension: KmTypeExtension): KmTypeExtension {
JvmExtensionWrapper.Type.get(typeExtension)?.let {
it.annotations.replaceAll(this::remap)
return it.extension
}
return typeExtension
}
private fun remap(functionExtension: KmFunctionExtension): KmFunctionExtension {
JvmExtensionWrapper.Function.get(functionExtension)?.let {
it.signature = it.signature?.let { sig -> remap(sig) }
return it.extension
}
return functionExtension
}
private fun remap(propertyExtension: KmPropertyExtension): KmPropertyExtension {
JvmExtensionWrapper.Property.get(propertyExtension)?.let {
it.fieldSignature = it.fieldSignature?.let { sig -> remap(sig) }
it.getterSignature = it.getterSignature?.let { sig -> remap(sig) }
it.setterSignature = it.setterSignature?.let { sig -> remap(sig) }
it.syntheticMethodForAnnotations = it.syntheticMethodForAnnotations?.let { sig -> remap(sig) }
it.syntheticMethodForDelegate = it.syntheticMethodForDelegate?.let { sig -> remap(sig) }
return it.extension
}
return propertyExtension
}
private fun remap(typeAliasExtension: KmTypeAliasExtension): KmTypeAliasExtension {
return typeAliasExtension
}
private fun remap(typeParameterExtension: KmTypeParameterExtension): KmTypeParameterExtension {
return typeParameterExtension
}
private fun remap(valueParameterExtension: KmValueParameterExtension): KmValueParameterExtension {
return valueParameterExtension
}
private fun remap(constructorExtension: KmConstructorExtension): KmConstructorExtension {
JvmExtensionWrapper.Constructor.get(constructorExtension)?.let {
it.signature = it.signature?.let { sig -> remap(sig) }
return it.extension
}
return constructorExtension
}
private fun remap(signature: JvmMethodSignature): JvmMethodSignature {
return JvmMethodSignature(signature.name, remapper.mapMethodDesc(signature.desc))
}
private fun remap(signature: JvmFieldSignature): JvmFieldSignature {
return JvmFieldSignature(signature.name, remapper.mapDesc(signature.desc))
}
}

View File

@@ -0,0 +1,100 @@
/*
* This file is part of fabric-loom, licensed under the MIT License (MIT).
*
* Copyright (c) 2023 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.
*/
@file:Suppress("UNCHECKED_CAST")
package net.fabricmc.loom.kotlin.remapping
import kotlinx.metadata.KmClass
import kotlinx.metadata.KmConstructor
import kotlinx.metadata.KmFunction
import kotlinx.metadata.KmPackage
import kotlinx.metadata.KmProperty
import kotlinx.metadata.KmType
import kotlinx.metadata.KmTypeAlias
import kotlinx.metadata.KmTypeParameter
import kotlinx.metadata.KmValueParameter
import kotlinx.metadata.internal.extensions.KmClassExtension
import kotlinx.metadata.internal.extensions.KmConstructorExtension
import kotlinx.metadata.internal.extensions.KmFunctionExtension
import kotlinx.metadata.internal.extensions.KmPackageExtension
import kotlinx.metadata.internal.extensions.KmPropertyExtension
import kotlinx.metadata.internal.extensions.KmTypeAliasExtension
import kotlinx.metadata.internal.extensions.KmTypeExtension
import kotlinx.metadata.internal.extensions.KmTypeParameterExtension
import kotlinx.metadata.internal.extensions.KmValueParameterExtension
import java.lang.reflect.Field
import kotlin.reflect.KClass
val KM_CLASS_EXTENSIONS = getField(KmClass::class)
val KM_PACKAGE_EXTENSIONS = getField(KmPackage::class)
val KM_TYPE_EXTENSIONS = getField(KmType::class)
val KM_FUNCTION_EXTENSIONS = getField(KmFunction::class)
val KM_PROPERTY_EXTENSIONS = getField(KmProperty::class)
val KM_TYPE_ALIAS_EXTENSIONS = getField(KmTypeAlias::class)
val KM_TYPE_PARAMETER_EXTENSIONS = getField(KmTypeParameter::class)
val KM_VALUE_PARAMETER_EXTENSIONS = getField(KmValueParameter::class)
val KM_CONSTRUCTOR_EXTENSIONS = getField(KmConstructor::class)
fun KmClass.getExtensions(): MutableList<KmClassExtension> {
return KM_CLASS_EXTENSIONS.get(this) as MutableList<KmClassExtension>
}
fun KmPackage.getExtensions(): MutableList<KmPackageExtension> {
return KM_PACKAGE_EXTENSIONS.get(this) as MutableList<KmPackageExtension>
}
fun KmType.getExtensions(): MutableList<KmTypeExtension> {
return KM_TYPE_EXTENSIONS.get(this) as MutableList<KmTypeExtension>
}
fun KmFunction.getExtensions(): MutableList<KmFunctionExtension> {
return KM_FUNCTION_EXTENSIONS.get(this) as MutableList<KmFunctionExtension>
}
fun KmProperty.getExtensions(): MutableList<KmPropertyExtension> {
return KM_PROPERTY_EXTENSIONS.get(this) as MutableList<KmPropertyExtension>
}
fun KmTypeAlias.getExtensions(): MutableList<KmTypeAliasExtension> {
return KM_TYPE_ALIAS_EXTENSIONS.get(this) as MutableList<KmTypeAliasExtension>
}
fun KmTypeParameter.getExtensions(): MutableList<KmTypeParameterExtension> {
return KM_TYPE_PARAMETER_EXTENSIONS.get(this) as MutableList<KmTypeParameterExtension>
}
fun KmValueParameter.getExtensions(): MutableList<KmValueParameterExtension> {
return KM_VALUE_PARAMETER_EXTENSIONS.get(this) as MutableList<KmValueParameterExtension>
}
fun KmConstructor.getExtensions(): MutableList<KmConstructorExtension> {
return KM_CONSTRUCTOR_EXTENSIONS.get(this) as MutableList<KmConstructorExtension>
}
private fun getField(clazz: KClass<*>): Field {
val field = clazz.java.getDeclaredField("extensions")
field.isAccessible = true
return field
}

View File

@@ -1,405 +0,0 @@
/*
* 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.kotlin.remapping
import kotlinx.metadata.ClassName
import kotlinx.metadata.Flags
import kotlinx.metadata.KmAnnotation
import kotlinx.metadata.KmClassExtensionVisitor
import kotlinx.metadata.KmClassVisitor
import kotlinx.metadata.KmConstructorExtensionVisitor
import kotlinx.metadata.KmConstructorVisitor
import kotlinx.metadata.KmContractVisitor
import kotlinx.metadata.KmEffectExpressionVisitor
import kotlinx.metadata.KmEffectInvocationKind
import kotlinx.metadata.KmEffectType
import kotlinx.metadata.KmEffectVisitor
import kotlinx.metadata.KmExtensionType
import kotlinx.metadata.KmFunctionExtensionVisitor
import kotlinx.metadata.KmFunctionVisitor
import kotlinx.metadata.KmLambdaVisitor
import kotlinx.metadata.KmPackageExtensionVisitor
import kotlinx.metadata.KmPackageVisitor
import kotlinx.metadata.KmPropertyExtensionVisitor
import kotlinx.metadata.KmPropertyVisitor
import kotlinx.metadata.KmTypeAliasVisitor
import kotlinx.metadata.KmTypeExtensionVisitor
import kotlinx.metadata.KmTypeParameterExtensionVisitor
import kotlinx.metadata.KmTypeParameterVisitor
import kotlinx.metadata.KmTypeVisitor
import kotlinx.metadata.KmValueParameterVisitor
import kotlinx.metadata.KmVariance
import kotlinx.metadata.jvm.JvmClassExtensionVisitor
import kotlinx.metadata.jvm.JvmConstructorExtensionVisitor
import kotlinx.metadata.jvm.JvmFieldSignature
import kotlinx.metadata.jvm.JvmFunctionExtensionVisitor
import kotlinx.metadata.jvm.JvmMethodSignature
import kotlinx.metadata.jvm.JvmPackageExtensionVisitor
import kotlinx.metadata.jvm.JvmPropertyExtensionVisitor
import kotlinx.metadata.jvm.JvmTypeExtensionVisitor
import kotlinx.metadata.jvm.JvmTypeParameterExtensionVisitor
import org.objectweb.asm.commons.Remapper
class RemappingKmVisitors(private val remapper: Remapper) {
private fun remapJvmMethodSignature(signature: JvmMethodSignature?): JvmMethodSignature? {
if (signature != null) {
return JvmMethodSignature(signature.name, remapper.mapMethodDesc(signature.desc))
}
return null
}
private fun remapJvmFieldSignature(signature: JvmFieldSignature?): JvmFieldSignature? {
if (signature != null) {
return JvmFieldSignature(signature.name, remapper.mapDesc(signature.desc))
}
return null
}
inner class RemappingKmClassVisitor(delegate: KmClassVisitor?) : KmClassVisitor(delegate) {
override fun visit(flags: Flags, name: ClassName) {
super.visit(flags, remapper.map(name))
}
override fun visitNestedClass(name: String) {
super.visitNestedClass(remapper.map(name))
}
override fun visitSealedSubclass(name: ClassName) {
super.visitSealedSubclass(remapper.map(name))
}
override fun visitSupertype(flags: Flags): KmTypeVisitor {
return RemappingKmTypeVisitor(super.visitSupertype(flags))
}
override fun visitFunction(flags: Flags, name: String): KmFunctionVisitor {
return RemappingKmFunctionVisitor(super.visitFunction(flags, name))
}
override fun visitInlineClassUnderlyingType(flags: Flags): KmTypeVisitor {
return RemappingKmTypeVisitor(super.visitInlineClassUnderlyingType(flags))
}
override fun visitProperty(flags: Flags, name: String, getterFlags: Flags, setterFlags: Flags): KmPropertyVisitor {
return RemappingKmPropertyVisitor(super.visitProperty(flags, name, getterFlags, setterFlags))
}
override fun visitTypeAlias(flags: Flags, name: String): KmTypeAliasVisitor {
return RemappingKmTypeAliasVisitor(super.visitTypeAlias(flags, name))
}
override fun visitConstructor(flags: Flags): KmConstructorVisitor {
return RemappingKmConstructorVisitor(super.visitConstructor(flags))
}
override fun visitExtensions(type: KmExtensionType): KmClassExtensionVisitor {
return RemappingJvmClassExtensionVisitor(super.visitExtensions(type) as JvmClassExtensionVisitor?)
}
override fun visitTypeParameter(
flags: Flags,
name: String,
id: Int,
variance: KmVariance,
): KmTypeParameterVisitor {
return RemappingKmTypeParameterVisitor(super.visitTypeParameter(flags, name, id, variance))
}
}
inner class RemappingKmLambdaVisitor(delegate: KmLambdaVisitor?) : KmLambdaVisitor(delegate) {
override fun visitFunction(flags: Flags, name: String): KmFunctionVisitor {
return RemappingKmFunctionVisitor(super.visitFunction(flags, name))
}
}
inner class RemappingKmTypeVisitor(delegate: KmTypeVisitor?) : KmTypeVisitor(delegate) {
override fun visitClass(name: ClassName) {
super.visitClass(remapper.map(name))
}
override fun visitTypeAlias(name: ClassName) {
super.visitTypeAlias(remapper.map(name))
}
override fun visitAbbreviatedType(flags: Flags): KmTypeVisitor {
return RemappingKmTypeVisitor(super.visitAbbreviatedType(flags))
}
override fun visitArgument(flags: Flags, variance: KmVariance): KmTypeVisitor {
return RemappingKmTypeVisitor(super.visitArgument(flags, variance))
}
override fun visitOuterType(flags: Flags): KmTypeVisitor {
return RemappingKmTypeVisitor(super.visitOuterType(flags))
}
override fun visitFlexibleTypeUpperBound(flags: Flags, typeFlexibilityId: String?): KmTypeVisitor {
return RemappingKmTypeVisitor(super.visitFlexibleTypeUpperBound(flags, typeFlexibilityId))
}
override fun visitExtensions(type: KmExtensionType): KmTypeExtensionVisitor {
return RemappingJvmTypeExtensionVisitor(super.visitExtensions(type) as JvmTypeExtensionVisitor?)
}
}
inner class RemappingJvmTypeExtensionVisitor(delegate: JvmTypeExtensionVisitor?) : JvmTypeExtensionVisitor(delegate) {
override fun visitAnnotation(annotation: KmAnnotation) {
super.visitAnnotation(KmAnnotation(remapper.map(annotation.className), annotation.arguments))
}
}
inner class RemappingKmFunctionVisitor(delegate: KmFunctionVisitor?) : KmFunctionVisitor(delegate) {
override fun visitReceiverParameterType(flags: Flags): KmTypeVisitor {
return RemappingKmTypeVisitor(super.visitReceiverParameterType(flags))
}
override fun visitReturnType(flags: Flags): KmTypeVisitor {
return RemappingKmTypeVisitor(super.visitReturnType(flags))
}
override fun visitValueParameter(flags: Flags, name: String): KmValueParameterVisitor {
return RemappingKmValueParameterVisitor(super.visitValueParameter(flags, name))
}
override fun visitExtensions(type: KmExtensionType): KmFunctionExtensionVisitor {
return RemappingJvmFunctionExtensionVisitor(super.visitExtensions(type) as JvmFunctionExtensionVisitor)
}
override fun visitContract(): KmContractVisitor {
return RemappingKmContractVisitor(super.visitContract())
}
override fun visitTypeParameter(
flags: Flags,
name: String,
id: Int,
variance: KmVariance,
): KmTypeParameterVisitor {
return RemappingKmTypeParameterVisitor(super.visitTypeParameter(flags, name, id, variance))
}
}
inner class RemappingKmContractVisitor(delegate: KmContractVisitor?) : KmContractVisitor(delegate) {
override fun visitEffect(type: KmEffectType, invocationKind: KmEffectInvocationKind?): KmEffectVisitor {
return RemappingKmEffectVisitor(super.visitEffect(type, invocationKind))
}
}
inner class RemappingKmEffectVisitor(delegate: KmEffectVisitor?) : KmEffectVisitor(delegate) {
override fun visitConclusionOfConditionalEffect(): KmEffectExpressionVisitor {
return RemappingKmEffectExpressionVisitor(super.visitConclusionOfConditionalEffect())
}
override fun visitConstructorArgument(): KmEffectExpressionVisitor {
return RemappingKmEffectExpressionVisitor(super.visitConclusionOfConditionalEffect())
}
}
inner class RemappingKmEffectExpressionVisitor(delegate: KmEffectExpressionVisitor?) : KmEffectExpressionVisitor(delegate) {
override fun visitAndArgument(): KmEffectExpressionVisitor {
return RemappingKmEffectExpressionVisitor(super.visitAndArgument())
}
override fun visitIsInstanceType(flags: Flags): KmTypeVisitor {
return RemappingKmTypeVisitor(super.visitIsInstanceType(flags))
}
override fun visitOrArgument(): KmEffectExpressionVisitor {
return RemappingKmEffectExpressionVisitor(super.visitOrArgument())
}
}
inner class RemappingKmPropertyVisitor(delegate: KmPropertyVisitor?) : KmPropertyVisitor(delegate) {
override fun visitReceiverParameterType(flags: Flags): KmTypeVisitor {
return RemappingKmTypeVisitor(super.visitReceiverParameterType(flags))
}
override fun visitReturnType(flags: Flags): KmTypeVisitor {
return RemappingKmTypeVisitor(super.visitReturnType(flags))
}
override fun visitSetterParameter(flags: Flags, name: String): KmValueParameterVisitor {
return RemappingKmValueParameterVisitor(super.visitSetterParameter(flags, name))
}
override fun visitExtensions(type: KmExtensionType): KmPropertyExtensionVisitor {
return RemappingJvmPropertyExtensionVisitor(super.visitExtensions(type) as JvmPropertyExtensionVisitor?)
}
override fun visitTypeParameter(
flags: Flags,
name: String,
id: Int,
variance: KmVariance,
): KmTypeParameterVisitor {
return RemappingKmTypeParameterVisitor(super.visitTypeParameter(flags, name, id, variance))
}
}
inner class RemappingJvmPropertyExtensionVisitor(delegate: JvmPropertyExtensionVisitor?) : JvmPropertyExtensionVisitor(delegate) {
override fun visit(
jvmFlags: Flags,
fieldSignature: JvmFieldSignature?,
getterSignature: JvmMethodSignature?,
setterSignature: JvmMethodSignature?,
) {
super.visit(jvmFlags, remapJvmFieldSignature(fieldSignature), remapJvmMethodSignature(getterSignature), remapJvmMethodSignature(setterSignature))
}
override fun visitSyntheticMethodForAnnotations(signature: JvmMethodSignature?) {
super.visitSyntheticMethodForAnnotations(remapJvmMethodSignature(signature))
}
override fun visitSyntheticMethodForDelegate(signature: JvmMethodSignature?) {
super.visitSyntheticMethodForDelegate(remapJvmMethodSignature(signature))
}
}
inner class RemappingKmTypeParameterVisitor(delegate: KmTypeParameterVisitor?) : KmTypeParameterVisitor(delegate) {
override fun visitExtensions(type: KmExtensionType): KmTypeParameterExtensionVisitor {
return RemappingJvmTypeParameterExtensionVisitor(super.visitExtensions(type) as JvmTypeParameterExtensionVisitor?)
}
override fun visitUpperBound(flags: Flags): KmTypeVisitor {
return RemappingKmTypeVisitor(super.visitUpperBound(flags))
}
}
inner class RemappingJvmTypeParameterExtensionVisitor(delegate: JvmTypeParameterExtensionVisitor?) : JvmTypeParameterExtensionVisitor(delegate) {
override fun visitAnnotation(annotation: KmAnnotation) {
super.visitAnnotation(KmAnnotation(remapper.map(annotation.className), annotation.arguments))
}
}
inner class RemappingKmValueParameterVisitor(delegate: KmValueParameterVisitor?) : KmValueParameterVisitor(delegate) {
override fun visitType(flags: Flags): KmTypeVisitor {
return RemappingKmTypeVisitor(super.visitType(flags))
}
override fun visitVarargElementType(flags: Flags): KmTypeVisitor {
return RemappingKmTypeVisitor(super.visitVarargElementType(flags))
}
}
inner class RemappingKmTypeAliasVisitor(delegate: KmTypeAliasVisitor?) : KmTypeAliasVisitor(delegate) {
override fun visitExpandedType(flags: Flags): KmTypeVisitor {
return RemappingKmTypeVisitor(super.visitExpandedType(flags))
}
override fun visitTypeParameter(
flags: Flags,
name: String,
id: Int,
variance: KmVariance,
): KmTypeParameterVisitor {
return RemappingKmTypeParameterVisitor(super.visitTypeParameter(flags, name, id, variance))
}
override fun visitUnderlyingType(flags: Flags): KmTypeVisitor {
return RemappingKmTypeVisitor(super.visitUnderlyingType(flags))
}
override fun visitAnnotation(annotation: KmAnnotation) {
super.visitAnnotation(KmAnnotation(remapper.map(annotation.className), annotation.arguments))
}
}
inner class RemappingJvmFunctionExtensionVisitor(delegate: JvmFunctionExtensionVisitor?) : JvmFunctionExtensionVisitor(delegate) {
override fun visit(signature: JvmMethodSignature?) {
super.visit(remapJvmMethodSignature(signature))
}
override fun visitLambdaClassOriginName(internalName: String) {
super.visitLambdaClassOriginName(remapper.map(internalName))
}
}
inner class RemappingJvmClassExtensionVisitor(delegate: JvmClassExtensionVisitor?) : JvmClassExtensionVisitor(delegate) {
override fun visitAnonymousObjectOriginName(internalName: String) {
super.visitAnonymousObjectOriginName(remapper.map(internalName))
}
override fun visitLocalDelegatedProperty(
flags: Flags,
name: String,
getterFlags: Flags,
setterFlags: Flags,
): KmPropertyVisitor {
return RemappingKmPropertyVisitor(super.visitLocalDelegatedProperty(flags, name, getterFlags, setterFlags))
}
}
inner class RemappingKmConstructorVisitor(delegate: KmConstructorVisitor?) : KmConstructorVisitor(delegate) {
override fun visitExtensions(type: KmExtensionType): KmConstructorExtensionVisitor {
return RemappingJvmConstructorExtensionVisitor(super.visitExtensions(type) as JvmConstructorExtensionVisitor?)
}
override fun visitValueParameter(flags: Flags, name: String): KmValueParameterVisitor {
return RemappingKmValueParameterVisitor(super.visitValueParameter(flags, name))
}
}
inner class RemappingJvmConstructorExtensionVisitor(delegate: JvmConstructorExtensionVisitor?) : JvmConstructorExtensionVisitor(delegate) {
override fun visit(signature: JvmMethodSignature?) {
super.visit(remapJvmMethodSignature(signature))
}
}
inner class RemappingKmPackageVisitor(delegate: KmPackageVisitor?) : KmPackageVisitor(delegate) {
override fun visitExtensions(type: KmExtensionType): KmPackageExtensionVisitor {
return RemappingJvmPackageExtensionVisitor(super.visitExtensions(type) as JvmPackageExtensionVisitor?)
}
override fun visitFunction(flags: Flags, name: String): KmFunctionVisitor {
return RemappingKmFunctionVisitor(super.visitFunction(flags, name))
}
override fun visitProperty(
flags: Flags,
name: String,
getterFlags: Flags,
setterFlags: Flags,
): KmPropertyVisitor {
return RemappingKmPropertyVisitor(super.visitProperty(flags, name, getterFlags, setterFlags))
}
override fun visitTypeAlias(flags: Flags, name: String): KmTypeAliasVisitor {
return RemappingKmTypeAliasVisitor(super.visitTypeAlias(flags, name))
}
}
inner class RemappingJvmPackageExtensionVisitor(delegate: JvmPackageExtensionVisitor?) : JvmPackageExtensionVisitor(delegate) {
override fun visitLocalDelegatedProperty(
flags: Flags,
name: String,
getterFlags: Flags,
setterFlags: Flags,
): KmPropertyVisitor {
return RemappingKmPropertyVisitor(super.visitLocalDelegatedProperty(flags, name, getterFlags, setterFlags))
}
}
}

View File

@@ -32,16 +32,13 @@ class LoomTestConstants {
// Test against the version of Gradle being used to build loom
public final static String DEFAULT_GRADLE = GradleVersion.current().getVersion()
// Test against Gradle 8
public final static String GRADLE_8 = "8.1"
// Tests that depend specifically on the nightly will run on the current version when the nightly is not available.
public final static String PRE_RELEASE_GRADLE = NIGHTLY_EXISTS ? NIGHTLY_VERSION : DEFAULT_GRADLE
// Randomly sorted to ensure that all versions can run with a clean gradle home.
public final static String[] STANDARD_TEST_VERSIONS = (NIGHTLY_EXISTS ? [
public final static List<String> STANDARD_TEST_VERSIONS = (NIGHTLY_EXISTS ? [
DEFAULT_GRADLE,
GRADLE_8,
PRE_RELEASE_GRADLE
] : [DEFAULT_GRADLE, GRADLE_8]).shuffled().toArray()
] : [DEFAULT_GRADLE]).shuffled().toArray()
public static final File TEST_DIR = new File("./.gradle/test-files")

View File

@@ -45,7 +45,7 @@ class FabricAPITest extends Specification implements GradleProjectTestTrait {
setup:
def gradle = gradleProject(
repo: "https://github.com/FabricMC/fabric.git",
commit: "2facd446984085376bd23245410ebf2dc0881b02",
commit: "01af69c8709f00b6c1aaf10c3f528fed93a29cfd",
version: version,
patch: "fabric_api"
)
@@ -57,7 +57,7 @@ class FabricAPITest extends Specification implements GradleProjectTestTrait {
.replace('id "fabric-loom" version "0.9.50"', 'id "dev.architectury.loom"')
.replace('"fabric-loom"', '"dev.architectury.loom"')
def server = ServerRunner.create(gradle.projectDir, "1.19.3")
def server = ServerRunner.create(gradle.projectDir, "1.19.4")
.withMod(gradle.getOutputFile("fabric-api-${API_VERSION}.jar"))
when:
def result = gradle.run(tasks: [
@@ -79,8 +79,8 @@ class FabricAPITest extends Specification implements GradleProjectTestTrait {
result.task(":build").outcome == SUCCESS
result.task(":prepareRemapJar").outcome == SUCCESS
new File(gradle.mavenLocalDir, "net/fabricmc/fabric-api/fabric-biome-api-v1/12.1.0/fabric-biome-api-v1-12.1.0.jar").exists()
new File(gradle.mavenLocalDir, "net/fabricmc/fabric-api/fabric-biome-api-v1/12.1.0/fabric-biome-api-v1-12.1.0-sources.jar").exists()
new File(gradle.mavenLocalDir, "net/fabricmc/fabric-api/fabric-biome-api-v1/13.0.6/fabric-biome-api-v1-13.0.6.jar").exists()
new File(gradle.mavenLocalDir, "net/fabricmc/fabric-api/fabric-biome-api-v1/13.0.6/fabric-biome-api-v1-13.0.6-sources.jar").exists()
serverResult.successful()
serverResult.output.contains("- fabric-api $API_VERSION")

View File

@@ -35,10 +35,17 @@ import static org.gradle.testkit.runner.TaskOutcome.SUCCESS
// This test runs a mod that exits on mod init
class RunConfigTest extends Specification implements GradleProjectTestTrait {
private static List<String> tasks = [
"runClient",
"runServer",
"runTestmodClient",
"runTestmodServer",
"runAutoTestServer"
]
@Unroll
def "Run config #task"() {
def "Run config #task (gradle #version)"() {
setup:
def gradle = gradleProject(project: "runconfigs", sharedFiles: true)
def gradle = gradleProject(project: "runconfigs", sharedFiles: true, version: version)
when:
def result = gradle.run(task: task)
@@ -48,12 +55,8 @@ class RunConfigTest extends Specification implements GradleProjectTestTrait {
result.output.contains("This contains a space")
where:
task | _
'runClient' | _
'runServer' | _
'runTestmodClient' | _
'runTestmodServer' | _
'runAutoTestServer' | _
version << STANDARD_TEST_VERSIONS * tasks.size()
task << tasks * STANDARD_TEST_VERSIONS.size()
}
@RestoreSystemProperties

View File

@@ -0,0 +1,134 @@
/*
* This file is part of fabric-loom, licensed under the MIT License (MIT).
*
* Copyright (c) 2023 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.test.unit.library
import org.gradle.api.JavaVersion
import spock.lang.Specification
import net.fabricmc.loom.configuration.providers.minecraft.MinecraftVersionMeta
import net.fabricmc.loom.configuration.providers.minecraft.library.LibraryContext
import net.fabricmc.loom.test.util.MinecraftTestUtils
class LibraryContextTest extends Specification {
def "Supports ARM64 macOS"() {
when:
def context = new LibraryContext(MinecraftTestUtils.getVersionMeta(id), JavaVersion.VERSION_17)
then:
context.supportsArm64MacOS() == supported
where:
id || supported
"1.19.4" || true
"1.18.2" || false
"1.16.5" || false
"1.4.7" || false
}
def "Uses LWJGL 3"() {
when:
def context = new LibraryContext(MinecraftTestUtils.getVersionMeta(id), JavaVersion.VERSION_17)
then:
context.usesLWJGL3() == lwjgl3
where:
id || lwjgl3
"1.19.4" || true
"1.18.2" || true
"1.16.5" || true
"1.12.2" || false
"1.8.9" || false
"1.4.7" || false
}
def "Has classpath natives"() {
when:
def context = new LibraryContext(MinecraftTestUtils.getVersionMeta(id), JavaVersion.VERSION_17)
then:
context.hasClasspathNatives() == hasClasspathNatives
where:
id || hasClasspathNatives
"1.19.4" || true
"1.18.2" || false
"1.16.5" || false
"1.12.2" || false
"1.8.9" || false
"1.4.7" || false
}
def "Has library"() {
when:
def context = new LibraryContext(MinecraftTestUtils.getVersionMeta("1.19.4"), JavaVersion.VERSION_17)
then:
context.hasLibrary("commons-io:commons-io:2.11.0")
!context.hasLibrary("net.fabricmc:fabric-loader")
}
def "Is runtime Java 19 or later"() {
when:
def context = new LibraryContext(MinecraftTestUtils.getVersionMeta("1.19.4"), javaVersion)
then:
context.isJava19OrLater() == isJava19OrLater
where:
javaVersion || isJava19OrLater
JavaVersion.VERSION_17 || false
JavaVersion.VERSION_19 || true
JavaVersion.VERSION_20 || true
}
def "Supports Java 19 or later"() {
when:
def metaJson = """
{
"libraries": [
{
"name": "org.lwjgl:lwjgl:${lwjglVersion}"
}
]
}"""
def context = new LibraryContext(MinecraftTestUtils.OBJECT_MAPPER.readValue(metaJson, MinecraftVersionMeta.class), JavaVersion.VERSION_17)
then:
context.supportsJava19OrLater() == supportsJava19OrLater
where:
lwjglVersion || supportsJava19OrLater
"2.1.2" || false
"3.0.0" || false
"3.0.5" || false
"3.1.5" || false
"3.3.1" || false
"3.3.2" || true
"3.3.3" || true
"3.4.0" || true
"4.0.0" || true
}
}

View File

@@ -0,0 +1,95 @@
/*
* This file is part of fabric-loom, licensed under the MIT License (MIT).
*
* Copyright (c) 2023 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.test.unit.library
import net.fabricmc.loom.configuration.providers.minecraft.library.Library
import net.fabricmc.loom.configuration.providers.minecraft.library.LibraryProcessorManager
import net.fabricmc.loom.configuration.providers.minecraft.library.processors.RuntimeLog4jLibraryProcessor
import net.fabricmc.loom.test.unit.library.processors.LibraryProcessorTest
import net.fabricmc.loom.test.util.GradleTestUtil
import net.fabricmc.loom.test.util.PlatformTestUtils
class LibraryProcessorManagerTest extends LibraryProcessorTest {
// A test to ensure that we can add macOS ARM64 support on an unsupported version
def "macOS arm64"() {
when:
def platform = PlatformTestUtils.MAC_OS_ARM64
def (original, context) = getLibs("1.18.2", platform)
def processed = new LibraryProcessorManager(platform, GradleTestUtil.mockRepositoryHandler()).processLibraries(original, context)
then:
// Test to make sure that we compile against the original version
original.find { it.is("org.lwjgl:lwjgl-glfw") && it.target() == Library.Target.COMPILE }.version() == "3.2.1"
processed.find { it.is("org.lwjgl:lwjgl-glfw") && it.target() == Library.Target.COMPILE }.version() == "3.2.1"
// And at runtime we have the new version.
processed.find { it.is("org.lwjgl:lwjgl-glfw") && it.target() == Library.Target.RUNTIME }.version() == "3.3.2"
// Test to make sure that the natives were upgraded.
original.find { it.is("org.lwjgl:lwjgl-glfw") && it.target() == Library.Target.NATIVES }.version() == "3.2.1"
processed.find { it.is("org.lwjgl:lwjgl-glfw") && it.target() == Library.Target.NATIVES }.version() == "3.3.2"
// Test to make sure that the natives were replaced.
original.find { it.is("org.lwjgl:lwjgl-glfw") && it.target() == Library.Target.NATIVES }.classifier() == "natives-macos"
processed.find { it.is("org.lwjgl:lwjgl-glfw") && it.target() == Library.Target.NATIVES }.classifier() == "natives-macos-arm64"
}
// Test to make sure that we dont upgrade LWJGL on an x64 mac
def "macOS x64"() {
when:
def platform = PlatformTestUtils.MAC_OS_X64
def (original, context) = getLibs("1.18.2", platform)
def processed = new LibraryProcessorManager(platform, GradleTestUtil.mockRepositoryHandler()).processLibraries(original, context)
then:
// Test to make sure that we compile against the original version
original.find { it.is("org.lwjgl:lwjgl-glfw") && it.target() == Library.Target.COMPILE }.version() == "3.2.1"
processed.find { it.is("org.lwjgl:lwjgl-glfw") && it.target() == Library.Target.COMPILE }.version() == "3.2.1"
// Make sure that there isn't a runtime library
processed.find { it.is("org.lwjgl:lwjgl-glfw") && it.target() == Library.Target.RUNTIME } == null
// Test to make sure that the natives were not upgraded.
original.find { it.is("org.lwjgl:lwjgl-glfw") && it.target() == Library.Target.NATIVES }.version() == "3.2.1"
processed.find { it.is("org.lwjgl:lwjgl-glfw") && it.target() == Library.Target.NATIVES }.version() == "3.2.1"
// Test to make sure that the natives were not replaced.
original.find { it.is("org.lwjgl:lwjgl-glfw") && it.target() == Library.Target.NATIVES }.classifier() == "natives-macos"
processed.find { it.is("org.lwjgl:lwjgl-glfw") && it.target() == Library.Target.NATIVES }.classifier() == "natives-macos"
}
def "runtime log4j"() {
when:
def platform = PlatformTestUtils.WINDOWS_X64
def (original, context) = getLibs("1.19.2", platform)
def processed = new LibraryProcessorManager(platform, GradleTestUtil.mockRepositoryHandler(), [
RuntimeLog4jLibraryProcessor.class.simpleName
]).processLibraries(original, context)
then:
original.find { it.is("org.apache.logging.log4j") && it.target() == Library.Target.COMPILE } != null
processed.find { it.is("org.apache.logging.log4j") && it.target() == Library.Target.RUNTIME } != null
processed.find { it.is("org.apache.logging.log4j") && it.target() == Library.Target.COMPILE } == null
}
}

View File

@@ -0,0 +1,79 @@
/*
* This file is part of fabric-loom, licensed under the MIT License (MIT).
*
* Copyright (c) 2023 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.test.unit.library
import spock.lang.Specification
import net.fabricmc.loom.configuration.providers.minecraft.library.Library
import net.fabricmc.loom.configuration.providers.minecraft.library.MinecraftLibraryHelper
import net.fabricmc.loom.test.util.MinecraftTestUtils
import net.fabricmc.loom.test.util.PlatformTestUtils
class MinecraftLibraryHelperTest extends Specification {
static List<String> VERSIONS = [
"1.19.4",
"1.18.2",
"1.16.5",
"1.13.2",
"1.8.9",
"1.4.7",
"1.2.5",
"b1.8.1",
"a1.2.5"
]
def "get libraries"() {
// A quick test to make sure that nothing fails when getting the libraries for all platforms on a range of versions.
when:
def meta = MinecraftTestUtils.getVersionMeta(id)
def libraries = MinecraftLibraryHelper.getLibrariesForPlatform(meta, platform)
then:
libraries.size() > 0
where:
platform << PlatformTestUtils.ALL * VERSIONS.size()
id << VERSIONS * PlatformTestUtils.ALL.size()
}
def "find macos natives"() {
when:
def meta = MinecraftTestUtils.getVersionMeta("1.18.2")
def libraries = MinecraftLibraryHelper.getLibrariesForPlatform(meta, PlatformTestUtils.MAC_OS_X64)
then:
libraries.find { it.is("ca.weblite:java-objc-bridge") && it.target() == Library.Target.NATIVES } != null
libraries.find { it.is("org.lwjgl:lwjgl-glfw") && it.target() == Library.Target.NATIVES }.classifier() == "natives-macos"
}
def "dont find macos natives"() {
when:
def meta = MinecraftTestUtils.getVersionMeta("1.18.2")
def libraries = MinecraftLibraryHelper.getLibrariesForPlatform(meta, PlatformTestUtils.WINDOWS_X64)
then:
libraries.find { it.is("ca.weblite:java-objc-bridge") && it.target() == Library.Target.NATIVES } == null
}
}

View File

@@ -0,0 +1,153 @@
/*
* This file is part of fabric-loom, licensed under the MIT License (MIT).
*
* Copyright (c) 2023 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.test.unit.library.processors
import net.fabricmc.loom.configuration.providers.minecraft.library.Library
import net.fabricmc.loom.configuration.providers.minecraft.library.LibraryProcessor
import net.fabricmc.loom.configuration.providers.minecraft.library.processors.ArmNativesLibraryProcessor
import net.fabricmc.loom.test.util.PlatformTestUtils
class ArmNativesLibraryProcessorTest extends LibraryProcessorTest {
def "Apply when adding macOS ARM64 support"() {
when:
def (_, context) = getLibs(id, PlatformTestUtils.MAC_OS_ARM64)
def processor = new ArmNativesLibraryProcessor(PlatformTestUtils.MAC_OS_ARM64, context)
then:
processor.applicationResult == result
where:
id || result
"1.19.4" || LibraryProcessor.ApplicationResult.DONT_APPLY
"1.18.2" || LibraryProcessor.ApplicationResult.MUST_APPLY
"1.17.1" || LibraryProcessor.ApplicationResult.MUST_APPLY
"1.16.5" || LibraryProcessor.ApplicationResult.MUST_APPLY
"1.15.2" || LibraryProcessor.ApplicationResult.MUST_APPLY
"1.14.4" || LibraryProcessor.ApplicationResult.MUST_APPLY
"1.12.2" || LibraryProcessor.ApplicationResult.DONT_APPLY // Not LWJGL 3
}
def "Apply to Windows arm64"() {
when:
def (_, context) = getLibs(id, PlatformTestUtils.WINDOWS_ARM64)
def processor = new ArmNativesLibraryProcessor(PlatformTestUtils.WINDOWS_ARM64, context)
then:
processor.applicationResult == result
where:
id || result
"1.19.4" || LibraryProcessor.ApplicationResult.MUST_APPLY
"1.18.2" || LibraryProcessor.ApplicationResult.DONT_APPLY // Only support versions with classpath natives.
"1.12.2" || LibraryProcessor.ApplicationResult.DONT_APPLY // Not LWJGL 3
}
def "Apply to Linux arm64"() {
when:
def (_, context) = getLibs(id, PlatformTestUtils.LINUX_ARM64)
def processor = new ArmNativesLibraryProcessor(PlatformTestUtils.LINUX_ARM64, context)
then:
processor.applicationResult == result
where:
id || result
"1.19.4" || LibraryProcessor.ApplicationResult.MUST_APPLY
"1.18.2" || LibraryProcessor.ApplicationResult.DONT_APPLY // Only support versions with classpath natives.
"1.12.2" || LibraryProcessor.ApplicationResult.DONT_APPLY // Not LWJGL 3
}
def "Never apply on none arm64 platforms"() {
when:
def (_, context) = getLibs(id, platform)
def processor = new ArmNativesLibraryProcessor(platform, context)
then:
processor.applicationResult == LibraryProcessor.ApplicationResult.DONT_APPLY
where:
id | platform
"1.19.4" | PlatformTestUtils.MAC_OS_X64
"1.18.2" | PlatformTestUtils.WINDOWS_X64
"1.17.1" | PlatformTestUtils.MAC_OS_X64
"1.16.5" | PlatformTestUtils.MAC_OS_X64
"1.15.2" | PlatformTestUtils.LINUX_X64
"1.14.4" | PlatformTestUtils.MAC_OS_X64
"1.12.2" | PlatformTestUtils.WINDOWS_X64
}
def "Add macOS arm64 natives"() {
when:
def (original, context) = getLibs(id, PlatformTestUtils.MAC_OS_ARM64)
def processor = new ArmNativesLibraryProcessor(PlatformTestUtils.MAC_OS_ARM64, context)
def processed = mockLibraryProcessorManager().processLibraries([processor], original)
then:
// Test that the natives are replaced when upgrading on macos
def originalNatives = original.findAll { it.is("org.lwjgl") && it.target() == Library.Target.NATIVES }
originalNatives.every { it.classifier() == "natives-macos" }
def processedNatives = processed.findAll { it.is("org.lwjgl") && it.target() == Library.Target.NATIVES }
processedNatives.every { it.classifier() == "natives-macos-arm64" }
where:
id | _
"1.18.2" | _
"1.17.1" | _
"1.16.5" | _
"1.15.2" | _
"1.14.4" | _
}
def "Add windows arm64 natives"() {
when:
def (original, context) = getLibs("1.19.4", PlatformTestUtils.WINDOWS_ARM64)
def processor = new ArmNativesLibraryProcessor(PlatformTestUtils.WINDOWS_ARM64, context)
def processed = mockLibraryProcessorManager().processLibraries([processor], original)
then:
// Test that the arm64 natives are added alongside the existing ones
def originalNatives = original.findAll { it.is("org.lwjgl") && it.target() == Library.Target.NATIVES }
originalNatives.count { it.classifier() == "natives-windows-arm64" } == 0
originalNatives.count { it.classifier() == "natives-windows" } > 0
def processedNatives = processed.findAll { it.is("org.lwjgl") && it.target() == Library.Target.NATIVES }
processedNatives.count { it.classifier() == "natives-windows-arm64" } > 0
processedNatives.count { it.classifier() == "natives-windows" } > 0
}
def "Add linux arm64 natives"() {
when:
def (original, context) = getLibs("1.19.4", PlatformTestUtils.LINUX_ARM64)
def processor = new ArmNativesLibraryProcessor(PlatformTestUtils.LINUX_ARM64, context)
def processed = mockLibraryProcessorManager().processLibraries([processor], original)
then:
// Test that the arm64 natives are added alongside the existing ones
def originalNatives = original.findAll { it.is("org.lwjgl") && it.target() == Library.Target.NATIVES }
originalNatives.count { it.classifier() == "natives-linux-arm64" } == 0
originalNatives.count { it.classifier() == "natives-linux" } > 0
def processedNatives = processed.findAll { it.is("org.lwjgl") && it.target() == Library.Target.NATIVES }
processedNatives.count { it.classifier() == "natives-linux-arm64" } > 0
processedNatives.count { it.classifier() == "natives-linux" } > 0
}
}

View File

@@ -0,0 +1,122 @@
/*
* This file is part of fabric-loom, licensed under the MIT License (MIT).
*
* Copyright (c) 2023 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.test.unit.library.processors
import org.gradle.api.JavaVersion
import net.fabricmc.loom.configuration.providers.minecraft.library.Library
import net.fabricmc.loom.configuration.providers.minecraft.library.LibraryProcessor
import net.fabricmc.loom.configuration.providers.minecraft.library.processors.LWJGL3UpgradeLibraryProcessor
import net.fabricmc.loom.test.util.PlatformTestUtils
class LWJGL3UpgradeLibraryProcessorTest extends LibraryProcessorTest {
def "Only apply to LWJGL3"() {
when:
def (_, context) = getLibs(id, PlatformTestUtils.WINDOWS_X64)
def processor = new LWJGL3UpgradeLibraryProcessor(PlatformTestUtils.WINDOWS_X64, context)
then:
processor.applicationResult == result
where:
id || result
"1.19.2" || LibraryProcessor.ApplicationResult.CAN_APPLY
"1.18.2" || LibraryProcessor.ApplicationResult.CAN_APPLY
"1.17.1" || LibraryProcessor.ApplicationResult.CAN_APPLY
"1.16.5" || LibraryProcessor.ApplicationResult.CAN_APPLY
"1.15.2" || LibraryProcessor.ApplicationResult.CAN_APPLY
"1.14.4" || LibraryProcessor.ApplicationResult.CAN_APPLY
"1.12.2" || LibraryProcessor.ApplicationResult.DONT_APPLY // Not LWJGL 3
}
// TODO once Minecraft updates to LWJGL 3.3.2 add a new test for this that uses that mc version
def "Apply when using Java 19 or later"() {
when:
def (_, context) = getLibs("1.19.4", PlatformTestUtils.WINDOWS_X64, version)
def processor = new LWJGL3UpgradeLibraryProcessor(PlatformTestUtils.WINDOWS_X64, context)
then:
processor.applicationResult == result
where:
version || result
JavaVersion.VERSION_20 || LibraryProcessor.ApplicationResult.MUST_APPLY
JavaVersion.VERSION_19 || LibraryProcessor.ApplicationResult.MUST_APPLY
JavaVersion.VERSION_17 || LibraryProcessor.ApplicationResult.CAN_APPLY
JavaVersion.VERSION_1_8 || LibraryProcessor.ApplicationResult.CAN_APPLY
}
def "Apply when adding macOS ARM64 support"() {
when:
def (_, context) = getLibs(id, PlatformTestUtils.MAC_OS_ARM64)
def processor = new LWJGL3UpgradeLibraryProcessor(PlatformTestUtils.MAC_OS_ARM64, context)
then:
processor.applicationResult == result
where:
id || result
"1.19.2" || LibraryProcessor.ApplicationResult.CAN_APPLY
"1.18.2" || LibraryProcessor.ApplicationResult.MUST_APPLY
"1.17.1" || LibraryProcessor.ApplicationResult.MUST_APPLY
"1.16.5" || LibraryProcessor.ApplicationResult.MUST_APPLY
"1.15.2" || LibraryProcessor.ApplicationResult.MUST_APPLY
"1.14.4" || LibraryProcessor.ApplicationResult.MUST_APPLY
"1.12.2" || LibraryProcessor.ApplicationResult.DONT_APPLY // Not LWJGL 3
}
def "Upgrade LWJGL classpath natives"() {
when:
def (original, context) = getLibs("1.19.4", PlatformTestUtils.MAC_OS_X64, JavaVersion.VERSION_20)
def processor = new LWJGL3UpgradeLibraryProcessor(PlatformTestUtils.MAC_OS_X64, context)
def processed = mockLibraryProcessorManager().processLibraries([processor], original)
then:
// Test to make sure that we compile against the original version
original.find { it.is("org.lwjgl:lwjgl-glfw") && it.target() == Library.Target.COMPILE }.version() == "3.3.1"
processed.find { it.is("org.lwjgl:lwjgl-glfw") && it.target() == Library.Target.COMPILE }.version() == "3.3.1"
// And at runtime we have the new version.
processed.find { it.is("org.lwjgl:lwjgl-glfw") && it.target() == Library.Target.RUNTIME }.version() == "3.3.2"
// Test to make sure that the natives were replaced.
original.find { it.is("org.lwjgl:lwjgl-glfw") && it.target() == Library.Target.NATIVES }.version() == "3.3.1"
processed.find { it.is("org.lwjgl:lwjgl-glfw") && it.target() == Library.Target.NATIVES }.version() == "3.3.2"
}
def "Upgrade LWJGL extracted natives"() {
when:
def (original, context) = getLibs("1.18.2", PlatformTestUtils.MAC_OS_X64, JavaVersion.VERSION_20)
def processor = new LWJGL3UpgradeLibraryProcessor(PlatformTestUtils.MAC_OS_X64, context)
def processed = mockLibraryProcessorManager().processLibraries([processor], original)
then:
// Test to make sure that we compile against the original version
original.find { it.is("org.lwjgl:lwjgl-glfw") && it.target() == Library.Target.COMPILE }.version() == "3.2.1"
processed.find { it.is("org.lwjgl:lwjgl-glfw") && it.target() == Library.Target.COMPILE }.version() == "3.2.1"
// And at runtime we have the new version.
processed.find { it.is("org.lwjgl:lwjgl-glfw") && it.target() == Library.Target.RUNTIME }.version() == "3.3.2"
// Test to make sure that the natives were replaced.
original.find { it.is("org.lwjgl:lwjgl-glfw") && it.target() == Library.Target.NATIVES }.version() == "3.2.1"
processed.find { it.is("org.lwjgl:lwjgl-glfw") && it.target() == Library.Target.NATIVES }.version() == "3.3.2"
}
}

View File

@@ -0,0 +1,44 @@
/*
* This file is part of fabric-loom, licensed under the MIT License (MIT).
*
* Copyright (c) 2023 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.test.unit.library.processors
import net.fabricmc.loom.configuration.providers.minecraft.library.LibraryProcessor
import net.fabricmc.loom.configuration.providers.minecraft.library.processors.LegacyASMLibraryProcessor
import net.fabricmc.loom.test.util.PlatformTestUtils
class LegacyASMLibraryProcessorTest extends LibraryProcessorTest {
def "Removes legacy asm-all"() {
when:
def (original, context) = getLibs("1.4.7", PlatformTestUtils.MAC_OS_X64)
def processor = new LegacyASMLibraryProcessor(PlatformTestUtils.MAC_OS_X64, context)
def processed = mockLibraryProcessorManager().processLibraries([processor], original)
then:
processor.applicationResult == LibraryProcessor.ApplicationResult.MUST_APPLY
hasLibrary("org.ow2.asm:asm-all", original)
!hasLibrary("org.ow2.asm:asm-all", processed)
}
}

View File

@@ -0,0 +1,58 @@
/*
* This file is part of fabric-loom, licensed under the MIT License (MIT).
*
* Copyright (c) 2023 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.test.unit.library.processors
import org.gradle.api.JavaVersion
import spock.lang.Specification
import net.fabricmc.loom.configuration.providers.minecraft.library.Library
import net.fabricmc.loom.configuration.providers.minecraft.library.LibraryContext
import net.fabricmc.loom.configuration.providers.minecraft.library.LibraryProcessorManager
import net.fabricmc.loom.configuration.providers.minecraft.library.MinecraftLibraryHelper
import net.fabricmc.loom.test.util.GradleTestUtil
import net.fabricmc.loom.test.util.MinecraftTestUtils
import net.fabricmc.loom.util.Platform
abstract class LibraryProcessorTest extends Specification {
def getLibs(String id, Platform platform, JavaVersion javaVersion = JavaVersion.VERSION_17) {
def meta = MinecraftTestUtils.getVersionMeta(id)
def libraries = MinecraftLibraryHelper.getLibrariesForPlatform(meta, platform)
def context = new LibraryContext(meta, javaVersion)
return [libraries, context]
}
boolean hasLibrary(String name, List<Library> libraries) {
libraries.any { it.is(name) }
}
Library findLibrary(String name, List<Library> libraries) {
libraries.find { it.is(name) }
}
LibraryProcessorManager mockLibraryProcessorManager() {
def libraryProcessorManager = new LibraryProcessorManager(null, GradleTestUtil.mockRepositoryHandler())
return libraryProcessorManager
}
}

View File

@@ -0,0 +1,80 @@
/*
* This file is part of fabric-loom, licensed under the MIT License (MIT).
*
* Copyright (c) 2023 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.test.unit.library.processors
import net.fabricmc.loom.configuration.providers.minecraft.library.Library
import net.fabricmc.loom.configuration.providers.minecraft.library.LibraryProcessor
import net.fabricmc.loom.configuration.providers.minecraft.library.processors.LoomNativeSupportLibraryProcessor
import net.fabricmc.loom.test.util.PlatformTestUtils
class LoomNativeSupportLibraryProcessorTest extends LibraryProcessorTest {
def "Apply when adding macOS ARM64 support"() {
when:
def (_, context) = getLibs(id, PlatformTestUtils.MAC_OS_ARM64)
def processor = new LoomNativeSupportLibraryProcessor(PlatformTestUtils.MAC_OS_ARM64, context)
then:
processor.applicationResult == result
where:
id || result
"1.19.4" || LibraryProcessor.ApplicationResult.CAN_APPLY
"1.18.2" || LibraryProcessor.ApplicationResult.MUST_APPLY
"1.17.1" || LibraryProcessor.ApplicationResult.MUST_APPLY
"1.16.5" || LibraryProcessor.ApplicationResult.MUST_APPLY
"1.15.2" || LibraryProcessor.ApplicationResult.MUST_APPLY
"1.14.4" || LibraryProcessor.ApplicationResult.MUST_APPLY
"1.12.2" || LibraryProcessor.ApplicationResult.DONT_APPLY // Not LWJGL 3
}
def "Can apply on other platforms"() {
when:
def (_, context) = getLibs(id, platform)
def processor = new LoomNativeSupportLibraryProcessor(platform, context)
then:
processor.applicationResult == LibraryProcessor.ApplicationResult.CAN_APPLY
where:
id | platform
"1.19.4" | PlatformTestUtils.MAC_OS_ARM64
"1.18.2" | PlatformTestUtils.WINDOWS_X64
"1.17.1" | PlatformTestUtils.MAC_OS_X64
"1.16.5" | PlatformTestUtils.WINDOWS_ARM64
"1.15.2" | PlatformTestUtils.LINUX_X64
"1.14.4" | PlatformTestUtils.MAC_OS_X64
"1.19.4" | PlatformTestUtils.WINDOWS_X64
}
def "Add native support mod"() {
when:
def (original, context) = getLibs("1.18.2", PlatformTestUtils.MAC_OS_X64)
def processor = new LoomNativeSupportLibraryProcessor(PlatformTestUtils.MAC_OS_X64, context)
def processed = mockLibraryProcessorManager().processLibraries([processor], original)
then:
// Test to ensure that we added the mod
original.find { it.is("net.fabricmc:fabric-loom-native-support") && it.target() == Library.Target.LOCAL_MOD } == null
processed.find { it.is("net.fabricmc:fabric-loom-native-support") && it.target() == Library.Target.LOCAL_MOD } != null
}
}

View File

@@ -0,0 +1,94 @@
/*
* This file is part of fabric-loom, licensed under the MIT License (MIT).
*
* Copyright (c) 2023 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.test.unit.library.processors
import net.fabricmc.loom.configuration.providers.minecraft.library.Library
import net.fabricmc.loom.configuration.providers.minecraft.library.LibraryProcessor
import net.fabricmc.loom.configuration.providers.minecraft.library.processors.ObjcBridgeUpgradeLibraryProcessor
import net.fabricmc.loom.test.util.PlatformTestUtils
class ObjcBridgeUpgradeLibraryProcessorTest extends LibraryProcessorTest {
def "Only apply to arm64 macOS"() {
when:
def (_, context) = getLibs("1.18.2", platform)
def processor = new ObjcBridgeUpgradeLibraryProcessor(platform, context)
then:
processor.applicationResult == result
where:
platform || result
PlatformTestUtils.MAC_OS_ARM64 || LibraryProcessor.ApplicationResult.MUST_APPLY
PlatformTestUtils.MAC_OS_X64 || LibraryProcessor.ApplicationResult.DONT_APPLY
PlatformTestUtils.LINUX_ARM64 || LibraryProcessor.ApplicationResult.DONT_APPLY
PlatformTestUtils.LINUX_X64 || LibraryProcessor.ApplicationResult.DONT_APPLY
PlatformTestUtils.WINDOWS_ARM64 || LibraryProcessor.ApplicationResult.DONT_APPLY
PlatformTestUtils.WINDOWS_X64 || LibraryProcessor.ApplicationResult.DONT_APPLY
}
def "only apply to unsupported versions"() {
when:
def (_, context) = getLibs(id, PlatformTestUtils.MAC_OS_ARM64)
def processor = new ObjcBridgeUpgradeLibraryProcessor(PlatformTestUtils.MAC_OS_ARM64, context)
then:
processor.applicationResult == result
where:
id || result
"1.19.2" || LibraryProcessor.ApplicationResult.DONT_APPLY
"1.18.2" || LibraryProcessor.ApplicationResult.MUST_APPLY
"1.17.1" || LibraryProcessor.ApplicationResult.MUST_APPLY
"1.16.5" || LibraryProcessor.ApplicationResult.MUST_APPLY
"1.15.2" || LibraryProcessor.ApplicationResult.MUST_APPLY
"1.14.4" || LibraryProcessor.ApplicationResult.MUST_APPLY
"1.12.2" || LibraryProcessor.ApplicationResult.DONT_APPLY // None LWJGL 3
}
def "Upgrade objc bridge"() {
when:
def (original, context) = getLibs(id, PlatformTestUtils.MAC_OS_ARM64)
def processor = new ObjcBridgeUpgradeLibraryProcessor(PlatformTestUtils.MAC_OS_ARM64, context)
def processed = mockLibraryProcessorManager().processLibraries([processor], original)
then:
// Test that we always compile against the original version
original.find { it.is("ca.weblite:java-objc-bridge") && it.target() == Library.Target.COMPILE }.version() == "1.0.0"
processed.find { it.is("ca.weblite:java-objc-bridge") && it.target() == Library.Target.COMPILE }.version() == "1.0.0"
// Test that we use 1.1 at runtime
processed.find { it.is("ca.weblite:java-objc-bridge") && it.target() == Library.Target.RUNTIME }.version() == "1.1"
// Test that we removed the natives, as they are included in the jar on the runtime classpath
original.find { it.is("ca.weblite:java-objc-bridge") && it.target() == Library.Target.NATIVES } != null
processed.find { it.is("ca.weblite:java-objc-bridge") && it.target() == Library.Target.NATIVES } == null
where:
id | _
"1.18.2" | _
"1.17.1" | _
"1.16.5" | _
"1.15.2" | _
"1.14.4" | _
}
}

View File

@@ -0,0 +1,45 @@
/*
* This file is part of fabric-loom, licensed under the MIT License (MIT).
*
* Copyright (c) 2023 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.test.unit.library.processors
import net.fabricmc.loom.configuration.providers.minecraft.library.Library
import net.fabricmc.loom.configuration.providers.minecraft.library.LibraryProcessor
import net.fabricmc.loom.configuration.providers.minecraft.library.processors.RuntimeLog4jLibraryProcessor
import net.fabricmc.loom.test.util.PlatformTestUtils
class RuntimeLog4jLibraryProcessorTest extends LibraryProcessorTest {
def "Make log4j runtime"() {
when:
def (original, context) = getLibs("1.19.4", PlatformTestUtils.MAC_OS_X64)
def processor = new RuntimeLog4jLibraryProcessor(PlatformTestUtils.MAC_OS_X64, context)
def processed = mockLibraryProcessorManager().processLibraries([processor], original)
then:
processor.applicationResult == LibraryProcessor.ApplicationResult.CAN_APPLY
findLibrary("org.apache.logging.log4j", original).target() == Library.Target.COMPILE
findLibrary("org.apache.logging.log4j", processed).target() == Library.Target.RUNTIME
}
}

View File

@@ -25,6 +25,7 @@
package net.fabricmc.loom.test.util
import org.gradle.api.Project
import org.gradle.api.artifacts.dsl.RepositoryHandler
import org.gradle.api.file.RegularFile
import org.gradle.api.file.RegularFileProperty
import org.gradle.api.file.SourceDirectorySet
@@ -115,4 +116,9 @@ class GradleTestUtil {
when(mock.isPresent()).thenReturn(true)
return mock
}
static RepositoryHandler mockRepositoryHandler() {
def mock = mock(RepositoryHandler.class)
return mock
}
}

View File

@@ -0,0 +1,56 @@
/*
* This file is part of fabric-loom, licensed under the MIT License (MIT).
*
* Copyright (c) 2023 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.test.util
import java.time.Duration
import com.fasterxml.jackson.databind.DeserializationFeature
import com.fasterxml.jackson.databind.ObjectMapper
import net.fabricmc.loom.configuration.providers.minecraft.ManifestVersion
import net.fabricmc.loom.configuration.providers.minecraft.MinecraftVersionMeta
import net.fabricmc.loom.test.LoomTestConstants
import net.fabricmc.loom.util.Constants
import net.fabricmc.loom.util.download.Download
class MinecraftTestUtils {
private static final File TEST_DIR = new File(LoomTestConstants.TEST_DIR, "minecraft")
public static final ObjectMapper OBJECT_MAPPER = new ObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
static MinecraftVersionMeta getVersionMeta(String id) {
def versionManifest = download(Constants.VERSION_MANIFESTS, "version_manifest.json")
def manifest = OBJECT_MAPPER.readValue(versionManifest, ManifestVersion.class)
def version = manifest.versions().find { it.id == id }
def metaJson = download(version.url, "${id}.json")
OBJECT_MAPPER.readValue(metaJson, MinecraftVersionMeta.class)
}
static String download(String url, String name) {
Download.create(url)
.maxAge(Duration.ofDays(31))
.downloadString(new File(TEST_DIR, name).toPath())
}
}

View File

@@ -0,0 +1,76 @@
/*
* This file is part of fabric-loom, licensed under the MIT License (MIT).
*
* Copyright (c) 2023 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.test.util
import groovy.transform.Immutable
import net.fabricmc.loom.util.Platform
@Immutable
class PlatformTestUtils implements Platform {
public static final Platform WINDOWS_X64 = platform(OperatingSystem.WINDOWS, false)
public static final Platform WINDOWS_ARM64 = platform(OperatingSystem.WINDOWS, true)
public static final Platform LINUX_X64 = platform(OperatingSystem.LINUX, false)
public static final Platform LINUX_ARM64 = platform(OperatingSystem.LINUX, true)
public static final Platform MAC_OS_X64 = platform(OperatingSystem.MAC_OS, false)
public static final Platform MAC_OS_ARM64 = platform(OperatingSystem.MAC_OS, true)
public static final List<Platform> ALL = [
WINDOWS_X64,
WINDOWS_ARM64,
LINUX_X64,
LINUX_ARM64,
MAC_OS_X64,
MAC_OS_ARM64
]
private static Platform platform(OperatingSystem operatingSystem, boolean isArm = false, boolean is64Bit = true) {
new PlatformTestUtils(operatingSystem: operatingSystem, architecture: new TestArchitecture(is64Bit: is64Bit, isArm: isArm), supportsUnixDomainSockets: true)
}
OperatingSystem operatingSystem
TestArchitecture architecture
boolean supportsUnixDomainSockets
@Override
boolean supportsUnixDomainSockets() {
supportsUnixDomainSockets
}
@Immutable
static class TestArchitecture implements Architecture {
boolean is64Bit
boolean isArm
@Override
boolean is64Bit() {
is64Bit
}
@Override
boolean isArm() {
isArm
}
}
}

View File

@@ -31,7 +31,7 @@ import groovy.transform.Immutable
import net.fabricmc.loom.util.download.Download
class ServerRunner {
static final String LOADER_VERSION = "0.14.12"
static final String LOADER_VERSION = "0.14.19"
static final String INSTALLER_VERSION = "0.11.1"
static final Map<String, String> FABRIC_API_URLS = [
"1.16.5": "https://github.com/FabricMC/fabric/releases/download/0.37.1%2B1.16/fabric-api-0.37.1+1.16.jar",

View File

@@ -1,7 +1,7 @@
diff --git a/build.gradle b/build.gradle
--- a/build.gradle (revision 5cda40cfe1ddb507dd509c89117b0801a6ab79d9)
+++ b/build.gradle (date 1659386544411)
@@ -33,17 +33,7 @@
--- a/build.gradle (revision 01af69c8709f00b6c1aaf10c3f528fed93a29cfd)
+++ b/build.gradle (date 1681671870023)
@@ -34,17 +34,7 @@
throw new NullPointerException("Could not find version for " + project.name)
}
@@ -20,3 +20,30 @@ diff --git a/build.gradle b/build.gradle
}
def getBranch() {
@@ -410,7 +400,7 @@
productionRuntime {
extendsFrom configurations.minecraftLibraries
extendsFrom configurations.loaderLibraries
- extendsFrom configurations.minecraftRuntimeOnlyLibraries
+ extendsFrom configurations.minecraftRuntimeLibraries
}
productionRuntimeServer
}
@@ -422,8 +412,6 @@
productionRuntimeServer "net.fabricmc:fabric-installer:${project.installer_version}:server"
}
-import net.fabricmc.loom.util.OperatingSystem
-
// This is very far beyond loom's API if you copy this, you're on your own.
task runProductionAutoTestClient(type: JavaExec, dependsOn: [remapJar, remapTestmodJar]) {
classpath.from configurations.productionRuntime
@@ -444,7 +432,7 @@
"--gameDir", workingDir.absolutePath
)
- if (OperatingSystem.CURRENT_OS == OperatingSystem.MAC_OS) {
+ if (false) {
jvmArgs(
"-XstartOnFirstThread"
)

View File

@@ -28,7 +28,6 @@ allprojects {
modImplementation "net.fabricmc:fabric-loader:0.11.2"
modImplementation "net.fabricmc.fabric-api:fabric-api:0.31.0+1.16"
}
jar {