Merge remote-tracking branch 'upstream/dev/1.4' into dev/1.4

This commit is contained in:
shedaniel
2023-10-24 11:19:58 +08:00
9 changed files with 342 additions and 16 deletions

View File

@@ -1,7 +1,7 @@
/*
* This file is part of fabric-loom, licensed under the MIT License (MIT).
*
* Copyright (c) 2020 FabricMC
* Copyright (c) 2020-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
@@ -34,19 +34,33 @@ import javax.inject.Inject;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.gradle.api.Action;
import org.gradle.api.Project;
import org.gradle.api.artifacts.ConfigurationContainer;
import org.gradle.api.artifacts.Dependency;
import org.gradle.api.file.RegularFileProperty;
import org.gradle.api.plugins.JavaPlugin;
import org.gradle.api.provider.Property;
import org.gradle.api.tasks.Delete;
import org.gradle.api.tasks.SourceSet;
import org.gradle.api.tasks.SourceSetContainer;
import org.gradle.api.tasks.TaskContainer;
import org.gradle.jvm.tasks.Jar;
import org.gradle.language.base.plugins.LifecycleBasePlugin;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import net.fabricmc.loom.LoomGradleExtension;
import net.fabricmc.loom.util.download.DownloadException;
import net.fabricmc.loom.util.gradle.SourceSetHelper;
public abstract class FabricApiExtension {
@Inject
public abstract Project getProject();
private static final String DATAGEN_SOURCESET_NAME = "datagen";
private static final HashMap<String, Map<String, String>> moduleVersionCache = new HashMap<>();
private static final HashMap<String, Map<String, String>> deprecatedModuleVersionCache = new HashMap<>();
@@ -73,6 +87,138 @@ public abstract class FabricApiExtension {
return moduleVersion;
}
/**
* Configure data generation with the default options.
*/
public void configureDataGeneration() {
configureDataGeneration(dataGenerationSettings -> { });
}
/**
* Configure data generation with custom options.
*/
public void configureDataGeneration(Action<DataGenerationSettings> action) {
final LoomGradleExtension extension = LoomGradleExtension.get(getProject());
final TaskContainer taskContainer = getProject().getTasks();
DataGenerationSettings settings = getProject().getObjects().newInstance(DataGenerationSettings.class);
settings.getOutputDirectory().set(getProject().file("src/main/generated"));
settings.getCreateRunConfiguration().convention(true);
settings.getCreateSourceSet().convention(true);
settings.getCreateSourceSet().convention(false);
settings.getStrictValidation().convention(false);
settings.getAddToResources().convention(true);
action.execute(settings);
final SourceSet mainSourceSet = SourceSetHelper.getMainSourceSet(getProject());
final File outputDirectory = settings.getOutputDirectory().getAsFile().get();
if (settings.getAddToResources().get()) {
mainSourceSet.resources(files -> {
// Add the src/main/generated to the main sourceset's resources.
files.getSrcDirs().add(outputDirectory);
});
}
// Exclude the cache dir from the output jar to ensure reproducibility.
taskContainer.getByName(JavaPlugin.JAR_TASK_NAME, task -> {
Jar jar = (Jar) task;
jar.exclude(".cache/**");
});
taskContainer.getByName(LifecycleBasePlugin.CLEAN_TASK_NAME, task -> {
Delete clean = (Delete) task;
clean.delete(outputDirectory);
});
if (settings.getCreateSourceSet().get()) {
if (!settings.getModId().isPresent()) {
throw new IllegalStateException("DataGenerationSettings.getModId() must be set when using split sources.");
}
SourceSetContainer sourceSets = SourceSetHelper.getSourceSets(getProject());
// Create the new datagen sourceset, depend on the main sourceset.
sourceSets.create(DATAGEN_SOURCESET_NAME, sourceSet -> {
sourceSet.setCompileClasspath(
sourceSet.getCompileClasspath()
.plus(mainSourceSet.getOutput())
);
sourceSet.setRuntimeClasspath(
sourceSet.getRuntimeClasspath()
.plus(mainSourceSet.getOutput())
);
extendsFrom(getProject(), sourceSet.getCompileClasspathConfigurationName(), mainSourceSet.getCompileClasspathConfigurationName());
extendsFrom(getProject(), sourceSet.getRuntimeClasspathConfigurationName(), mainSourceSet.getRuntimeClasspathConfigurationName());
});
extension.getMods().create(settings.getModId().get(), mod -> {
// Create a classpath group for this mod. Assume that the main sourceset is already in a group.
mod.sourceSet(DATAGEN_SOURCESET_NAME);
});
}
if (settings.getCreateRunConfiguration().get()) {
extension.getRunConfigs().create("datagen", run -> {
run.name("Data Generation");
run.inherit(extension.getRunConfigs().getByName("server"));
run.property("fabric-api.datagen");
run.property("fabric-api.datagen.output-dir", outputDirectory.getAbsolutePath());
run.runDir("build/datagen");
if (settings.getModId().isPresent()) {
run.property("fabric-api.datagen.modid", settings.getModId().get());
}
if (settings.getStrictValidation().get()) {
run.property("fabric-api.datagen.strict-validation", "true");
}
if (settings.getCreateSourceSet().get()) {
run.source(DATAGEN_SOURCESET_NAME);
}
});
}
}
public interface DataGenerationSettings {
/**
* Contains the output directory where generated data files will be stored.
*/
RegularFileProperty getOutputDirectory();
/**
* Contains a boolean indicating whether a run configuration should be created for the data generation process.
*/
Property<Boolean> getCreateRunConfiguration();
/**
* Contains a boolean property indicating whether a new source set should be created for the data generation process.
*/
Property<Boolean> getCreateSourceSet();
/**
* Contains a string property representing the mod ID associated with the data generation process.
*
* <p>This must be set when {@link #getCreateRunConfiguration()} is set.
*/
Property<String> getModId();
/**
* Contains a boolean property indicating whether strict validation is enabled.
*/
Property<Boolean> getStrictValidation();
/**
* Contains a boolean property indicating whether the generated resources will be automatically added to the main sourceset.
*/
Property<Boolean> getAddToResources();
}
private String getDependencyNotation(String moduleName, String fabricApiVersion) {
return String.format("net.fabricmc.fabric-api:%s:%s", moduleName, moduleVersion(moduleName, fabricApiVersion));
}
@@ -154,4 +300,12 @@ public abstract class FabricApiExtension {
super(cause);
}
}
private static void extendsFrom(Project project, String name, String extendsFrom) {
final ConfigurationContainer configurations = project.getConfigurations();
configurations.named(name, configuration -> {
configuration.extendsFrom(configurations.getByName(extendsFrom));
});
}
}

View File

@@ -199,15 +199,16 @@ public abstract sealed class MinecraftSourceSets permits MinecraftSourceSets.Sin
clientOnlySourceSet.setCompileClasspath(
clientOnlySourceSet.getCompileClasspath()
.plus(mainSourceSet.getCompileClasspath())
.plus(mainSourceSet.getOutput())
);
clientOnlySourceSet.setRuntimeClasspath(
clientOnlySourceSet.getRuntimeClasspath()
.plus(mainSourceSet.getRuntimeClasspath())
.plus(mainSourceSet.getOutput())
);
extendsFrom(project, clientOnlySourceSet.getCompileClasspathConfigurationName(), mainSourceSet.getCompileClasspathConfigurationName());
extendsFrom(project, clientOnlySourceSet.getRuntimeClasspathConfigurationName(), mainSourceSet.getRuntimeClasspathConfigurationName());
RemapConfigurations.configureClientConfigurations(project, clientOnlySourceSet);
// Include the client only output in the jars

View File

@@ -50,6 +50,11 @@ public class LoomNativeSupportLibraryProcessor extends LibraryProcessor {
return ApplicationResult.MUST_APPLY;
}
if (platform.getOperatingSystem().isMacOS() && context.isJava19OrLater() && !context.supportsJava19OrLater()) {
// Apply when LWJGL has been updated on MacOS to support Java 19
return ApplicationResult.MUST_APPLY;
}
// A developer can opt into this
return ApplicationResult.CAN_APPLY;
}

View File

@@ -40,6 +40,8 @@ public abstract class ExtractNativesTask extends Sync {
for (File nativeFile : getProject().getConfigurations().getByName(Constants.Configurations.MINECRAFT_NATIVES).getFiles()) {
from(getProject().zipTree(nativeFile), copySpec -> {
copySpec.exclude("META-INF/**");
// Fix pre LWJGL 3 versions on Macos. See: https://github.com/FabricMC/fabric-loom/issues/955
copySpec.rename(s -> s.replace(".jnilib", ".dylib"));
});
}

View File

@@ -25,6 +25,7 @@
package net.fabricmc.loom.task.service;
import java.io.Serializable;
import java.util.Comparator;
import java.util.Map;
import java.util.Optional;
import java.util.jar.Attributes;
@@ -74,12 +75,19 @@ public abstract class JarManifestService implements BuildService<JarManifestServ
}
public void apply(Manifest manifest, Map<String, String> extraValues) {
// Don't set when running the reproducible build tests as it will break them when anything updates
Attributes attributes = manifest.getMainAttributes();
extraValues.entrySet().stream()
.sorted(Comparator.comparing(Map.Entry::getKey))
.forEach(entry -> {
attributes.putValue(entry.getKey(), entry.getValue());
});
// Don't set version attributes when running the reproducible build tests as it will break them when anything updates
if (Boolean.getBoolean("loom.test.reproducible")) {
return;
}
Attributes attributes = manifest.getMainAttributes();
Params p = getParameters();
attributes.putValue("Fabric-Gradle-Version", p.getGradleVersion().get());
@@ -94,10 +102,6 @@ public abstract class JarManifestService implements BuildService<JarManifestServ
attributes.putValue("Fabric-Mixin-Version", p.getMixinVersion().get().version());
attributes.putValue("Fabric-Mixin-Group", p.getMixinVersion().get().group());
}
for (Map.Entry<String, String> entry : extraValues.entrySet()) {
attributes.putValue(entry.getKey(), entry.getValue());
}
}
private record MixinVersion(String group, String version) implements Serializable { }

View File

@@ -0,0 +1,99 @@
/*
* 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.integration
import spock.lang.Specification
import spock.lang.Unroll
import net.fabricmc.loom.test.util.GradleProjectTestTrait
import static net.fabricmc.loom.test.LoomTestConstants.STANDARD_TEST_VERSIONS
import static org.gradle.testkit.runner.TaskOutcome.SUCCESS
class DataGenerationTest extends Specification implements GradleProjectTestTrait {
@Unroll
def "dataGeneration (gradle #version)"() {
setup:
def gradle = gradleProject(project: "minimalBase", version: version)
gradle.buildGradle << '''
fabricApi {
configureDataGeneration()
}
dependencies {
minecraft "com.mojang:minecraft:1.20.2"
mappings "net.fabricmc:yarn:1.20.2+build.4:v2"
modImplementation "net.fabricmc:fabric-loader:0.14.23"
modImplementation "net.fabricmc.fabric-api:fabric-api:0.90.0+1.20.2"
}
'''
when:
def result = gradle.run(task: "runDatagen")
then:
result.task(":runDatagen").outcome == SUCCESS
where:
version << STANDARD_TEST_VERSIONS
}
@Unroll
def "dataGeneration sourceset (gradle #version)"() {
setup:
def gradle = gradleProject(project: "minimalBase", version: version)
gradle.buildGradle << '''
// Must configure the main mod
loom.mods {
"example" {
sourceSet sourceSets.main
}
}
fabricApi {
configureDataGeneration {
createSourceSet = true
createRunConfiguration = true
modId = "example-datagen"
strictValidation = true
}
}
dependencies {
minecraft "com.mojang:minecraft:1.20.2"
mappings "net.fabricmc:yarn:1.20.2+build.4:v2"
modImplementation "net.fabricmc:fabric-loader:0.14.23"
modImplementation "net.fabricmc.fabric-api:fabric-api:0.90.0+1.20.2"
}
'''
when:
def result = gradle.run(task: "runDatagen")
then:
result.task(":runDatagen").outcome == SUCCESS
where:
version << STANDARD_TEST_VERSIONS
}
}

View File

@@ -55,13 +55,13 @@ class ReproducibleBuildTest extends Specification implements GradleProjectTestTr
where:
version | modHash | sourceHash
DEFAULT_GRADLE | "97240b42385adfaa1952e9c4ea942f71" | [
"61438feb9bd548788bbc637637d202fc",
"185ad8396d89b726064682bf22572036"
DEFAULT_GRADLE | "4bb8acb5e575a4080a8fe1282f8e1994" | [
"8e8fac2a5e32fc872e6cf0f9ccc55cfd",
"ed331b6fae5677797a0104eba014e255"
]
PRE_RELEASE_GRADLE | "97240b42385adfaa1952e9c4ea942f71" | [
"61438feb9bd548788bbc637637d202fc",
"185ad8396d89b726064682bf22572036"
PRE_RELEASE_GRADLE | "4bb8acb5e575a4080a8fe1282f8e1994" | [
"8e8fac2a5e32fc872e6cf0f9ccc55cfd",
"ed331b6fae5677797a0104eba014e255"
]
}

View File

@@ -50,7 +50,6 @@ class LWJGL3UpgradeLibraryProcessorTest extends LibraryProcessorTest {
"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)
@@ -66,6 +65,21 @@ class LWJGL3UpgradeLibraryProcessorTest extends LibraryProcessorTest {
JavaVersion.VERSION_1_8 || LibraryProcessor.ApplicationResult.CAN_APPLY
}
def "Dont apply when using Java 19 or later on supported LWJGL version"() {
when:
def (_, context) = getLibs("1.20.2", PlatformTestUtils.WINDOWS_X64, version)
def processor = new LWJGL3UpgradeLibraryProcessor(PlatformTestUtils.WINDOWS_X64, context)
then:
processor.applicationResult == result
where:
version || result
JavaVersion.VERSION_20 || LibraryProcessor.ApplicationResult.CAN_APPLY
JavaVersion.VERSION_19 || LibraryProcessor.ApplicationResult.CAN_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)

View File

@@ -24,6 +24,8 @@
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.LoomNativeSupportLibraryProcessor
@@ -48,6 +50,51 @@ class LoomNativeSupportLibraryProcessorTest extends LibraryProcessorTest {
"1.12.2" || LibraryProcessor.ApplicationResult.DONT_APPLY // Not LWJGL 3
}
def "Apply when using Java 19 or later on macOS"() {
when:
def (_, context) = getLibs("1.19.4", PlatformTestUtils.MAC_OS_X64, version)
def processor = new LoomNativeSupportLibraryProcessor(PlatformTestUtils.MAC_OS_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 "Dont apply when using Java 19 or later on macOS with supported version"() {
when:
def (_, context) = getLibs("1.20.2", PlatformTestUtils.MAC_OS_X64, version)
def processor = new LoomNativeSupportLibraryProcessor(PlatformTestUtils.MAC_OS_X64, context)
then:
processor.applicationResult == result
where:
version || result
JavaVersion.VERSION_20 || LibraryProcessor.ApplicationResult.CAN_APPLY
JavaVersion.VERSION_19 || LibraryProcessor.ApplicationResult.CAN_APPLY
JavaVersion.VERSION_17 || LibraryProcessor.ApplicationResult.CAN_APPLY
JavaVersion.VERSION_1_8 || LibraryProcessor.ApplicationResult.CAN_APPLY
}
def "Can apply when using Java 19 or later on other platforms"() {
when:
def (_, context) = getLibs("1.19.4", PlatformTestUtils.WINDOWS_ARM64, version)
def processor = new LoomNativeSupportLibraryProcessor(PlatformTestUtils.WINDOWS_ARM64, context)
then:
processor.applicationResult == result
where:
version || result
JavaVersion.VERSION_20 || LibraryProcessor.ApplicationResult.CAN_APPLY
JavaVersion.VERSION_19 || LibraryProcessor.ApplicationResult.CAN_APPLY
JavaVersion.VERSION_17 || LibraryProcessor.ApplicationResult.CAN_APPLY
JavaVersion.VERSION_1_8 || LibraryProcessor.ApplicationResult.CAN_APPLY
}
def "Can apply on other platforms"() {
when:
def (_, context) = getLibs(id, platform)