diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index e654b3ef..af9adc9b 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -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 }} diff --git a/bootstrap/src/main/java/net/fabricmc/loom/bootstrap/LoomGradlePluginBootstrap.java b/bootstrap/src/main/java/net/fabricmc/loom/bootstrap/LoomGradlePluginBootstrap.java index 804f486b..c8a45de0 100644 --- a/bootstrap/src/main/java/net/fabricmc/loom/bootstrap/LoomGradlePluginBootstrap.java +++ b/bootstrap/src/main/java/net/fabricmc/loom/bootstrap/LoomGradlePluginBootstrap.java @@ -14,7 +14,7 @@ import org.gradle.util.GradleVersion; */ @SuppressWarnings("unused") public class LoomGradlePluginBootstrap implements Plugin { - 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 { List 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 { } 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 { 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(); diff --git a/build.gradle b/build.gradle index 626b2ef8..7f27e437 100644 --- a/build.gradle +++ b/build.gradle @@ -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" diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 249e5832..c1962a79 100644 Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 8fad3f5a..a21c6ebe 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -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 diff --git a/gradlew b/gradlew index a69d9cb6..aeb74cbb 100755 --- a/gradlew +++ b/gradlew @@ -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 diff --git a/gradlew.bat b/gradlew.bat index f127cfd4..93e3f59f 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -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% diff --git a/src/main/java/net/fabricmc/loom/LoomGradlePlugin.java b/src/main/java/net/fabricmc/loom/LoomGradlePlugin.java index 0184f581..40751f45 100644 --- a/src/main/java/net/fabricmc/loom/LoomGradlePlugin.java +++ b/src/main/java/net/fabricmc/loom/LoomGradlePlugin.java @@ -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); diff --git a/src/main/java/net/fabricmc/loom/LoomRepositoryPlugin.java b/src/main/java/net/fabricmc/loom/LoomRepositoryPlugin.java index 5b67af32..785383f7 100644 --- a/src/main/java/net/fabricmc/loom/LoomRepositoryPlugin.java +++ b/src/main/java/net/fabricmc/loom/LoomRepositoryPlugin.java @@ -135,9 +135,9 @@ public class LoomRepositoryPlugin implements Plugin { }); } - 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 { }); } - 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 { }); }); - project.getRepositories().exclusiveContent(repository -> { + repositories.exclusiveContent(repository -> { repository.forRepositories(central); repository.filter(filter -> { filter.includeGroup("org.lwjgl"); diff --git a/src/main/java/net/fabricmc/loom/configuration/CompileConfiguration.java b/src/main/java/net/fabricmc/loom/configuration/CompileConfiguration.java index cfd214b6..e4596387 100644 --- a/src/main/java/net/fabricmc/loom/configuration/CompileConfiguration.java +++ b/src/main/java/net/fabricmc/loom/configuration/CompileConfiguration.java @@ -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 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 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 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))); } diff --git a/src/main/java/net/fabricmc/loom/configuration/ide/RunConfig.java b/src/main/java/net/fabricmc/loom/configuration/ide/RunConfig.java index 3771b617..5e5b575d 100644 --- a/src/main/java/net/fabricmc/loom/configuration/ide/RunConfig.java +++ b/src/main/java/net/fabricmc/loom/configuration/ide/RunConfig.java @@ -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 allLibraries = getArtifacts(project, Constants.Configurations.MINECRAFT_DEPENDENCIES); - final Set serverLibraries = getArtifacts(project, Constants.Configurations.MINECRAFT_SERVER_DEPENDENCIES); + final Set clientLibraries = getArtifacts(project, Constants.Configurations.MINECRAFT_CLIENT_RUNTIME_LIBRARIES); + final Set serverLibraries = getArtifacts(project, Constants.Configurations.MINECRAFT_SERVER_RUNTIME_LIBRARIES); final List 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 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 artifacts, ModuleVersionIdentifier identifier) { diff --git a/src/main/java/net/fabricmc/loom/configuration/ide/RunConfigSettings.java b/src/main/java/net/fabricmc/loom/configuration/ide/RunConfigSettings.java index cbcb6b5d..8122b103 100644 --- a/src/main/java/net/fabricmc/loom/configuration/ide/RunConfigSettings.java +++ b/src/main/java/net/fabricmc/loom/configuration/ide/RunConfigSettings.java @@ -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"); } } diff --git a/src/main/java/net/fabricmc/loom/configuration/ide/idea/IdeaSyncTask.java b/src/main/java/net/fabricmc/loom/configuration/ide/idea/IdeaSyncTask.java index cc21c03f..5da1061f 100644 --- a/src/main/java/net/fabricmc/loom/configuration/ide/idea/IdeaSyncTask.java +++ b/src/main/java/net/fabricmc/loom/configuration/ide/idea/IdeaSyncTask.java @@ -101,12 +101,10 @@ public abstract class IdeaSyncTask extends AbstractLoomTask { final List 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); } } } diff --git a/src/main/java/net/fabricmc/loom/configuration/mods/ModConfigurationRemapper.java b/src/main/java/net/fabricmc/loom/configuration/mods/ModConfigurationRemapper.java index 831676a9..ed5678a9 100644 --- a/src/main/java/net/fabricmc/loom/configuration/mods/ModConfigurationRemapper.java +++ b/src/main/java/net/fabricmc/loom/configuration/mods/ModConfigurationRemapper.java @@ -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 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; + } } diff --git a/src/main/java/net/fabricmc/loom/configuration/mods/ModProcessor.java b/src/main/java/net/fabricmc/loom/configuration/mods/ModProcessor.java index 9a574ff4..54402cac 100644 --- a/src/main/java/net/fabricmc/loom/configuration/mods/ModProcessor.java +++ b/src/main/java/net/fabricmc/loom/configuration/mods/ModProcessor.java @@ -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(); diff --git a/src/main/java/net/fabricmc/loom/configuration/processors/ContextImplHelper.java b/src/main/java/net/fabricmc/loom/configuration/processors/ContextImplHelper.java index 570ee246..12bd05cb 100644 --- a/src/main/java/net/fabricmc/loom/configuration/processors/ContextImplHelper.java +++ b/src/main/java/net/fabricmc/loom/configuration/processors/ContextImplHelper.java @@ -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); diff --git a/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/LWJGLVersionOverride.java b/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/LWJGLVersionOverride.java deleted file mode 100644 index f06f613d..00000000 --- a/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/LWJGLVersionOverride.java +++ /dev/null @@ -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 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 NATIVES = DEPENDENCIES.stream().map(s -> s + ":" + NATIVE_CLASSIFIER).toList(); - - public static final List 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 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"; - } -} diff --git a/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/MinecraftLibraryProvider.java b/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/MinecraftLibraryProvider.java index ff8dc56e..8c1dc700 100644 --- a/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/MinecraftLibraryProvider.java +++ b/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/MinecraftLibraryProvider.java @@ -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("^(?.*)/(.*?)/(?.*)/((?.*?)-(\\k)-)(?.*).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 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(); + + if (extension.getRuntimeOnlyLog4j().get()) { + enabledProcessors.add(RuntimeLog4jLibraryProcessor.class.getSimpleName()); } + + final Provider 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 libraries = MinecraftLibraryHelper.getLibrariesForPlatform(minecraftProvider.getVersionInfo(), platform); + final List 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 libraries = MinecraftLibraryHelper.getServerLibraries(serverBundleMetadata); + final List processLibraries = processLibraries(libraries); + processLibraries.forEach(this::applyServerLibrary); + } + + private List processLibraries(List 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); } } diff --git a/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/MinecraftSourceSets.java b/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/MinecraftSourceSets.java index b0c6b204..c12e1ce3 100644 --- a/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/MinecraftSourceSets.java +++ b/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/MinecraftSourceSets.java @@ -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 consumer, List targets); - public abstract String getCombinedSourceSetName(); - public abstract String getSourceSetForEnv(String env); - protected abstract List getAllSourceSetNames(); + protected abstract List 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 consumer, List 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 getAllSourceSetNames() { + protected List 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 getAllSourceSetNames() { - return List.of(MINECRAFT_COMMON_NAMED, MINECRAFT_CLIENT_ONLY_NAMED, MINECRAFT_COMBINED_NAMED); + protected List 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"; + } + } } diff --git a/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/MinecraftVersionMeta.java b/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/MinecraftVersionMeta.java index 6e38296f..7a311fbb 100644 --- a/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/MinecraftVersionMeta.java +++ b/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/MinecraftVersionMeta.java @@ -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 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 natives, List 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 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())); } } diff --git a/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/library/Library.java b/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/library/Library.java new file mode 100644 index 00000000..57778abb --- /dev/null +++ b/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/library/Library.java @@ -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); + } +} diff --git a/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/library/LibraryContext.java b/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/library/LibraryContext.java new file mode 100644 index 00000000..0b80189a --- /dev/null +++ b/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/library/LibraryContext.java @@ -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); + } +} diff --git a/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/library/LibraryProcessor.java b/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/library/LibraryProcessor.java new file mode 100644 index 00000000..835bc82e --- /dev/null +++ b/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/library/LibraryProcessor.java @@ -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 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 apply(Consumer 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 + } +} diff --git a/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/library/LibraryProcessorManager.java b/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/library/LibraryProcessorManager.java new file mode 100644 index 00000000..a6782af3 --- /dev/null +++ b/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/library/LibraryProcessorManager.java @@ -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> 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 enabledProcessors; + + public LibraryProcessorManager(Platform platform, RepositoryHandler repositories, List enabledProcessors) { + this.platform = platform; + this.repositories = repositories; + this.enabledProcessors = enabledProcessors; + } + + public LibraryProcessorManager(Platform platform, RepositoryHandler repositories) { + this(platform, repositories, Collections.emptyList()); + } + + private List getProcessors(LibraryContext context) { + var processors = new ArrayList(); + + 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 processLibraries(List librariesIn, LibraryContext libraryContext) { + final List processors = getProcessors(libraryContext); + + if (processors.isEmpty()) { + return librariesIn; + } + + return processLibraries(processors, librariesIn); + } + + @VisibleForTesting + public List processLibraries(List processors, List librariesIn) { + var libraries = new ArrayList<>(librariesIn); + + for (LibraryProcessor processor : processors) { + var processedLibraries = new ArrayList(); + final Predicate 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 extends BiFunction { + } +} diff --git a/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/library/MinecraftLibraryHelper.java b/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/library/MinecraftLibraryHelper.java new file mode 100644 index 00000000..d17e213d --- /dev/null +++ b/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/library/MinecraftLibraryHelper.java @@ -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("^(?.*)/(.*?)/(?.*)/((?.*?)-(\\k)-)(?.*).jar$"); + + public static List getLibrariesForPlatform(MinecraftVersionMeta versionMeta, Platform platform) { + var libraries = new ArrayList(); + + 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 getServerLibraries(BundleMetadata bundleMetadata) { + Objects.requireNonNull(bundleMetadata); + + var libraries = new ArrayList(); + + for (BundleMetadata.Entry library : bundleMetadata.libraries()) { + libraries.add(Library.fromMaven(library.name(), Library.Target.COMPILE)); + } + + return libraries; + } +} diff --git a/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/library/processors/ArmNativesLibraryProcessor.java b/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/library/processors/ArmNativesLibraryProcessor.java new file mode 100644 index 00000000..7763c7cb --- /dev/null +++ b/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/library/processors/ArmNativesLibraryProcessor.java @@ -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 apply(Consumer 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); + } +} diff --git a/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/library/processors/LWJGL2MavenLibraryProcessor.java b/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/library/processors/LWJGL2MavenLibraryProcessor.java new file mode 100644 index 00000000..e3bfc186 --- /dev/null +++ b/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/library/processors/LWJGL2MavenLibraryProcessor.java @@ -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 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); + } +} diff --git a/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/library/processors/LWJGL3UpgradeLibraryProcessor.java b/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/library/processors/LWJGL3UpgradeLibraryProcessor.java new file mode 100644 index 00000000..d238fd6c --- /dev/null +++ b/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/library/processors/LWJGL3UpgradeLibraryProcessor.java @@ -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 apply(Consumer 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(); + } +} diff --git a/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/library/processors/LegacyASMLibraryProcessor.java b/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/library/processors/LegacyASMLibraryProcessor.java new file mode 100644 index 00000000..0e6da96b --- /dev/null +++ b/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/library/processors/LegacyASMLibraryProcessor.java @@ -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 apply(Consumer dependencyConsumer) { + return library -> !library.is(LEGACY_ASM); + } +} diff --git a/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/library/processors/LoomNativeSupportLibraryProcessor.java b/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/library/processors/LoomNativeSupportLibraryProcessor.java new file mode 100644 index 00000000..7c195024 --- /dev/null +++ b/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/library/processors/LoomNativeSupportLibraryProcessor.java @@ -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 apply(Consumer dependencyConsumer) { + dependencyConsumer.accept(Library.fromMaven(Constants.Dependencies.NATIVE_SUPPORT + Constants.Dependencies.Versions.NATIVE_SUPPORT_VERSION, Library.Target.LOCAL_MOD)); + return ALLOW_ALL; + } +} diff --git a/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/library/processors/ObjcBridgeUpgradeLibraryProcessor.java b/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/library/processors/ObjcBridgeUpgradeLibraryProcessor.java new file mode 100644 index 00000000..0d55a887 --- /dev/null +++ b/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/library/processors/ObjcBridgeUpgradeLibraryProcessor.java @@ -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 apply(Consumer 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; + }; + } +} diff --git a/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/library/processors/RuntimeLog4jLibraryProcessor.java b/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/library/processors/RuntimeLog4jLibraryProcessor.java new file mode 100644 index 00000000..580b26b1 --- /dev/null +++ b/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/library/processors/RuntimeLog4jLibraryProcessor.java @@ -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 apply(Consumer dependencyConsumer) { + return library -> { + if (library.is(LOG4J_GROUP)) { + dependencyConsumer.accept(library.withTarget(Library.Target.RUNTIME)); + return false; + } + + return true; + }; + } +} diff --git a/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/mapped/AbstractMappedMinecraftProvider.java b/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/mapped/AbstractMappedMinecraftProvider.java index 4713510e..ab583785 100644 --- a/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/mapped/AbstractMappedMinecraftProvider.java +++ b/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/mapped/AbstractMappedMinecraftProvider.java @@ -183,7 +183,7 @@ public abstract class AbstractMappedMinecraftProvider 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 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 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 getAnnotations() { + return extension.getAnnotations(); + } + } +} diff --git a/src/main/java/net/fabricmc/loom/task/AbstractRunTask.java b/src/main/java/net/fabricmc/loom/task/AbstractRunTask.java index db24f740..d5ca8e2c 100644 --- a/src/main/java/net/fabricmc/loom/task/AbstractRunTask.java +++ b/src/main/java/net/fabricmc/loom/task/AbstractRunTask.java @@ -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 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 jvmArguments = (ListProperty) 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 getJvmArgs() { - final List superArgs = super.getJvmArgs(); - - if (setJvmArgsProperty) { - // Don't do anything here when on Gradle 8.1 - return superArgs; - } - - final List args = new ArrayList<>(getGameJvmArgs()); - - if (superArgs != null) { - args.addAll(superArgs); - } - - return args; - } - private List getGameJvmArgs() { final List args = new ArrayList<>(); diff --git a/src/main/java/net/fabricmc/loom/task/GenerateSourcesTask.java b/src/main/java/net/fabricmc/loom/task/GenerateSourcesTask.java index 4940e9d6..8a45210e 100644 --- a/src/main/java/net/fabricmc/loom/task/GenerateSourcesTask.java +++ b/src/main/java/net/fabricmc/loom/task/GenerateSourcesTask.java @@ -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 { @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; diff --git a/src/main/java/net/fabricmc/loom/task/UnpickJarTask.java b/src/main/java/net/fabricmc/loom/task/UnpickJarTask.java index 22825794..d3c52e72 100644 --- a/src/main/java/net/fabricmc/loom/task/UnpickJarTask.java +++ b/src/main/java/net/fabricmc/loom/task/UnpickJarTask.java @@ -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)); } diff --git a/src/main/java/net/fabricmc/loom/task/launch/GenerateRemapClasspathTask.java b/src/main/java/net/fabricmc/loom/task/launch/GenerateRemapClasspathTask.java index 8077cd35..388c8566 100644 --- a/src/main/java/net/fabricmc/loom/task/launch/GenerateRemapClasspathTask.java +++ b/src/main/java/net/fabricmc/loom/task/launch/GenerateRemapClasspathTask.java @@ -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) diff --git a/src/main/java/net/fabricmc/loom/util/Constants.java b/src/main/java/net/fabricmc/loom/util/Constants.java index fde2e1c7..9c37b7d8 100644 --- a/src/main/java/net/fabricmc/loom/util/Constants.java +++ b/src/main/java/net/fabricmc/loom/util/Constants.java @@ -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 { diff --git a/src/main/java/net/fabricmc/loom/util/OperatingSystem.java b/src/main/java/net/fabricmc/loom/util/CurrentPlatform.java similarity index 55% rename from src/main/java/net/fabricmc/loom/util/OperatingSystem.java rename to src/main/java/net/fabricmc/loom/util/CurrentPlatform.java index 1e9bdc96..fdd7e3cb 100644 --- a/src/main/java/net/fabricmc/loom/util/OperatingSystem.java +++ b/src/main/java/net/fabricmc/loom/util/CurrentPlatform.java @@ -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; + } } diff --git a/src/main/java/net/fabricmc/loom/util/Architecture.java b/src/main/java/net/fabricmc/loom/util/Platform.java similarity index 69% rename from src/main/java/net/fabricmc/loom/util/Architecture.java rename to src/main/java/net/fabricmc/loom/util/Platform.java index afebd26c..c21c5544 100644 --- a/src/main/java/net/fabricmc/loom/util/Architecture.java +++ b/src/main/java/net/fabricmc/loom/util/Platform.java @@ -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(); } diff --git a/src/main/java/net/fabricmc/loom/util/SourceRemapper.java b/src/main/java/net/fabricmc/loom/util/SourceRemapper.java index 22e811f0..31a979ac 100644 --- a/src/main/java/net/fabricmc/loom/util/SourceRemapper.java +++ b/src/main/java/net/fabricmc/loom/util/SourceRemapper.java @@ -263,7 +263,7 @@ public class SourceRemapper { final List 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()); } diff --git a/src/main/java/net/fabricmc/loom/util/TinyRemapperHelper.java b/src/main/java/net/fabricmc/loom/util/TinyRemapperHelper.java index 6e2b32a6..3abd1ec7 100644 --- a/src/main/java/net/fabricmc/loom/util/TinyRemapperHelper.java +++ b/src/main/java/net/fabricmc/loom/util/TinyRemapperHelper.java @@ -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); } diff --git a/src/main/java/net/fabricmc/loom/util/kotlin/KotlinPluginUtils.java b/src/main/java/net/fabricmc/loom/util/kotlin/KotlinPluginUtils.java index 367a947b..aab439a6 100644 --- a/src/main/java/net/fabricmc/loom/util/kotlin/KotlinPluginUtils.java +++ b/src/main/java/net/fabricmc/loom/util/kotlin/KotlinPluginUtils.java @@ -55,6 +55,6 @@ public class KotlinPluginUtils { } public static String getKotlinMetadataVersion() { - return KotlinClassMetadata.class.getPackage().getImplementationVersion(); + return KotlinClassMetadata.class.getPackage().getImplementationVersion().split("-")[0]; } } diff --git a/src/main/java/net/fabricmc/loom/util/kotlin/KotlinRemapperClassloader.java b/src/main/java/net/fabricmc/loom/util/kotlin/KotlinRemapperClassloader.java index e43fdcf1..cb034785 100644 --- a/src/main/java/net/fabricmc/loom/util/kotlin/KotlinRemapperClassloader.java +++ b/src/main/java/net/fabricmc/loom/util/kotlin/KotlinRemapperClassloader.java @@ -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 loomUrls = getClassUrls( - KotlinMetadataTinyRemapperExtensionImpl.class // Loom + KotlinMetadataTinyRemapperExtensionImpl.class, // Loom (Kotlin) + JvmExtensionWrapper.class // Loom (Java) ); final URL[] urls = Stream.concat( diff --git a/src/main/kotlin/net/fabricmc/loom/kotlin/remapping/KotlinClassMetadataRemappingAnnotationVisitor.kt b/src/main/kotlin/net/fabricmc/loom/kotlin/remapping/KotlinClassMetadataRemappingAnnotationVisitor.kt index b8a10620..c20820fa 100644 --- a/src/main/kotlin/net/fabricmc/loom/kotlin/remapping/KotlinClassMetadataRemappingAnnotationVisitor.kt +++ b/src/main/kotlin/net/fabricmc/loom/kotlin/remapping/KotlinClassMetadataRemappingAnnotationVisitor.kt @@ -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? = 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}") diff --git a/src/main/kotlin/net/fabricmc/loom/kotlin/remapping/KotlinClassRemapper.kt b/src/main/kotlin/net/fabricmc/loom/kotlin/remapping/KotlinClassRemapper.kt new file mode 100644 index 00000000..416a0bde --- /dev/null +++ b/src/main/kotlin/net/fabricmc/loom/kotlin/remapping/KotlinClassRemapper.kt @@ -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)) + } +} diff --git a/src/main/kotlin/net/fabricmc/loom/kotlin/remapping/KotlinMetadataExtensions.kt b/src/main/kotlin/net/fabricmc/loom/kotlin/remapping/KotlinMetadataExtensions.kt new file mode 100644 index 00000000..e3061018 --- /dev/null +++ b/src/main/kotlin/net/fabricmc/loom/kotlin/remapping/KotlinMetadataExtensions.kt @@ -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 { + return KM_CLASS_EXTENSIONS.get(this) as MutableList +} + +fun KmPackage.getExtensions(): MutableList { + return KM_PACKAGE_EXTENSIONS.get(this) as MutableList +} + +fun KmType.getExtensions(): MutableList { + return KM_TYPE_EXTENSIONS.get(this) as MutableList +} + +fun KmFunction.getExtensions(): MutableList { + return KM_FUNCTION_EXTENSIONS.get(this) as MutableList +} + +fun KmProperty.getExtensions(): MutableList { + return KM_PROPERTY_EXTENSIONS.get(this) as MutableList +} + +fun KmTypeAlias.getExtensions(): MutableList { + return KM_TYPE_ALIAS_EXTENSIONS.get(this) as MutableList +} + +fun KmTypeParameter.getExtensions(): MutableList { + return KM_TYPE_PARAMETER_EXTENSIONS.get(this) as MutableList +} + +fun KmValueParameter.getExtensions(): MutableList { + return KM_VALUE_PARAMETER_EXTENSIONS.get(this) as MutableList +} + +fun KmConstructor.getExtensions(): MutableList { + return KM_CONSTRUCTOR_EXTENSIONS.get(this) as MutableList +} + +private fun getField(clazz: KClass<*>): Field { + val field = clazz.java.getDeclaredField("extensions") + field.isAccessible = true + return field +} diff --git a/src/main/kotlin/net/fabricmc/loom/kotlin/remapping/RemappingKmVisitors.kt b/src/main/kotlin/net/fabricmc/loom/kotlin/remapping/RemappingKmVisitors.kt deleted file mode 100644 index a777adef..00000000 --- a/src/main/kotlin/net/fabricmc/loom/kotlin/remapping/RemappingKmVisitors.kt +++ /dev/null @@ -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)) - } - } -} diff --git a/src/test/groovy/net/fabricmc/loom/test/LoomTestConstants.groovy b/src/test/groovy/net/fabricmc/loom/test/LoomTestConstants.groovy index 1c7ed660..1db061a2 100644 --- a/src/test/groovy/net/fabricmc/loom/test/LoomTestConstants.groovy +++ b/src/test/groovy/net/fabricmc/loom/test/LoomTestConstants.groovy @@ -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 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") diff --git a/src/test/groovy/net/fabricmc/loom/test/integration/FabricAPITest.groovy b/src/test/groovy/net/fabricmc/loom/test/integration/FabricAPITest.groovy index 95b2fe73..adff00f3 100644 --- a/src/test/groovy/net/fabricmc/loom/test/integration/FabricAPITest.groovy +++ b/src/test/groovy/net/fabricmc/loom/test/integration/FabricAPITest.groovy @@ -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") diff --git a/src/test/groovy/net/fabricmc/loom/test/integration/RunConfigTest.groovy b/src/test/groovy/net/fabricmc/loom/test/integration/RunConfigTest.groovy index 9a255b59..38438e8b 100644 --- a/src/test/groovy/net/fabricmc/loom/test/integration/RunConfigTest.groovy +++ b/src/test/groovy/net/fabricmc/loom/test/integration/RunConfigTest.groovy @@ -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 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 diff --git a/src/test/groovy/net/fabricmc/loom/test/unit/library/LibraryContextTest.groovy b/src/test/groovy/net/fabricmc/loom/test/unit/library/LibraryContextTest.groovy new file mode 100644 index 00000000..458ac837 --- /dev/null +++ b/src/test/groovy/net/fabricmc/loom/test/unit/library/LibraryContextTest.groovy @@ -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 + } +} diff --git a/src/test/groovy/net/fabricmc/loom/test/unit/library/LibraryProcessorManagerTest.groovy b/src/test/groovy/net/fabricmc/loom/test/unit/library/LibraryProcessorManagerTest.groovy new file mode 100644 index 00000000..62ac6ab1 --- /dev/null +++ b/src/test/groovy/net/fabricmc/loom/test/unit/library/LibraryProcessorManagerTest.groovy @@ -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 + } +} diff --git a/src/test/groovy/net/fabricmc/loom/test/unit/library/MinecraftLibraryHelperTest.groovy b/src/test/groovy/net/fabricmc/loom/test/unit/library/MinecraftLibraryHelperTest.groovy new file mode 100644 index 00000000..30e39051 --- /dev/null +++ b/src/test/groovy/net/fabricmc/loom/test/unit/library/MinecraftLibraryHelperTest.groovy @@ -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 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 + } +} diff --git a/src/test/groovy/net/fabricmc/loom/test/unit/library/processors/ArmNativesLibraryProcessorTest.groovy b/src/test/groovy/net/fabricmc/loom/test/unit/library/processors/ArmNativesLibraryProcessorTest.groovy new file mode 100644 index 00000000..d1897064 --- /dev/null +++ b/src/test/groovy/net/fabricmc/loom/test/unit/library/processors/ArmNativesLibraryProcessorTest.groovy @@ -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 + } +} diff --git a/src/test/groovy/net/fabricmc/loom/test/unit/library/processors/LWJGL3UpgradeLibraryProcessorTest.groovy b/src/test/groovy/net/fabricmc/loom/test/unit/library/processors/LWJGL3UpgradeLibraryProcessorTest.groovy new file mode 100644 index 00000000..46530d57 --- /dev/null +++ b/src/test/groovy/net/fabricmc/loom/test/unit/library/processors/LWJGL3UpgradeLibraryProcessorTest.groovy @@ -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" + } +} diff --git a/src/test/groovy/net/fabricmc/loom/test/unit/library/processors/LegacyASMLibraryProcessorTest.groovy b/src/test/groovy/net/fabricmc/loom/test/unit/library/processors/LegacyASMLibraryProcessorTest.groovy new file mode 100644 index 00000000..beb7536c --- /dev/null +++ b/src/test/groovy/net/fabricmc/loom/test/unit/library/processors/LegacyASMLibraryProcessorTest.groovy @@ -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) + } +} diff --git a/src/test/groovy/net/fabricmc/loom/test/unit/library/processors/LibraryProcessorTest.groovy b/src/test/groovy/net/fabricmc/loom/test/unit/library/processors/LibraryProcessorTest.groovy new file mode 100644 index 00000000..547c2c46 --- /dev/null +++ b/src/test/groovy/net/fabricmc/loom/test/unit/library/processors/LibraryProcessorTest.groovy @@ -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 libraries) { + libraries.any { it.is(name) } + } + + Library findLibrary(String name, List libraries) { + libraries.find { it.is(name) } + } + + LibraryProcessorManager mockLibraryProcessorManager() { + def libraryProcessorManager = new LibraryProcessorManager(null, GradleTestUtil.mockRepositoryHandler()) + return libraryProcessorManager + } +} \ No newline at end of file diff --git a/src/test/groovy/net/fabricmc/loom/test/unit/library/processors/LoomNativeSupportLibraryProcessorTest.groovy b/src/test/groovy/net/fabricmc/loom/test/unit/library/processors/LoomNativeSupportLibraryProcessorTest.groovy new file mode 100644 index 00000000..e8076d46 --- /dev/null +++ b/src/test/groovy/net/fabricmc/loom/test/unit/library/processors/LoomNativeSupportLibraryProcessorTest.groovy @@ -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 + } +} diff --git a/src/test/groovy/net/fabricmc/loom/test/unit/library/processors/ObjcBridgeUpgradeLibraryProcessorTest.groovy b/src/test/groovy/net/fabricmc/loom/test/unit/library/processors/ObjcBridgeUpgradeLibraryProcessorTest.groovy new file mode 100644 index 00000000..00f28ff9 --- /dev/null +++ b/src/test/groovy/net/fabricmc/loom/test/unit/library/processors/ObjcBridgeUpgradeLibraryProcessorTest.groovy @@ -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" | _ + } +} diff --git a/src/test/groovy/net/fabricmc/loom/test/unit/library/processors/RuntimeLog4jLibraryProcessorTest.groovy b/src/test/groovy/net/fabricmc/loom/test/unit/library/processors/RuntimeLog4jLibraryProcessorTest.groovy new file mode 100644 index 00000000..07a59576 --- /dev/null +++ b/src/test/groovy/net/fabricmc/loom/test/unit/library/processors/RuntimeLog4jLibraryProcessorTest.groovy @@ -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 + } +} diff --git a/src/test/groovy/net/fabricmc/loom/test/util/GradleTestUtil.groovy b/src/test/groovy/net/fabricmc/loom/test/util/GradleTestUtil.groovy index 7b489031..423201cf 100644 --- a/src/test/groovy/net/fabricmc/loom/test/util/GradleTestUtil.groovy +++ b/src/test/groovy/net/fabricmc/loom/test/util/GradleTestUtil.groovy @@ -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 + } } diff --git a/src/test/groovy/net/fabricmc/loom/test/util/MinecraftTestUtils.groovy b/src/test/groovy/net/fabricmc/loom/test/util/MinecraftTestUtils.groovy new file mode 100644 index 00000000..f1d45bfd --- /dev/null +++ b/src/test/groovy/net/fabricmc/loom/test/util/MinecraftTestUtils.groovy @@ -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()) + } +} diff --git a/src/test/groovy/net/fabricmc/loom/test/util/PlatformTestUtils.groovy b/src/test/groovy/net/fabricmc/loom/test/util/PlatformTestUtils.groovy new file mode 100644 index 00000000..4bc83eb2 --- /dev/null +++ b/src/test/groovy/net/fabricmc/loom/test/util/PlatformTestUtils.groovy @@ -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 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 + } + } +} diff --git a/src/test/groovy/net/fabricmc/loom/test/util/ServerRunner.groovy b/src/test/groovy/net/fabricmc/loom/test/util/ServerRunner.groovy index 362cc488..4748bedc 100644 --- a/src/test/groovy/net/fabricmc/loom/test/util/ServerRunner.groovy +++ b/src/test/groovy/net/fabricmc/loom/test/util/ServerRunner.groovy @@ -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 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", diff --git a/src/test/resources/patches/fabric_api.patch b/src/test/resources/patches/fabric_api.patch index 66042ce3..bb6f7077 100644 --- a/src/test/resources/patches/fabric_api.patch +++ b/src/test/resources/patches/fabric_api.patch @@ -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" + ) diff --git a/src/test/resources/projects/multiproject/build.gradle b/src/test/resources/projects/multiproject/build.gradle index 57bdefec..97868562 100644 --- a/src/test/resources/projects/multiproject/build.gradle +++ b/src/test/resources/projects/multiproject/build.gradle @@ -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 {