[Non-Obf]: Support JIJ with the regular jar task (#1425)

* Implement JIJ for jar task

* Implement JIJ for jar task, now without beeing a dumbass

* Reimplement old task, decouple

* reimplement last missing functionality

* fix checkstyle

* fix checkstyle v2

* fix checkstyle v3

* Remove dead / unneccesary check

* Cleanup / Code-Style

* Cleanup / Code-Style v2
This commit is contained in:
Finn Rades
2025-11-07 20:10:28 +01:00
committed by GitHub
parent e50fce87cc
commit 3a2a67bffe
9 changed files with 239 additions and 8 deletions

View File

@@ -0,0 +1,76 @@
/*
* This file is part of fabric-loom, licensed under the MIT License (MIT).
*
* Copyright (c) 2016-2021 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.task;
import java.io.File;
import java.io.Serializable;
import java.util.Arrays;
import org.gradle.api.Action;
import org.gradle.api.Task;
import org.gradle.api.file.Directory;
import org.gradle.api.provider.Provider;
import org.gradle.jvm.tasks.Jar;
import org.jetbrains.annotations.NotNull;
import net.fabricmc.loom.build.nesting.JarNester;
/**
* Configuration-cache-compatible action for nesting jars.
* Uses a provider to avoid capturing task references at configuration time.
* Do NOT turn me into a record!
*/
class NestJarsAction implements Action<Task>, Serializable {
private final Provider<Directory> nestedJarsDir;
NestJarsAction(Provider<Directory> nestedJarsDir) {
this.nestedJarsDir = nestedJarsDir;
}
@Override
public void execute(@NotNull Task t) {
final Jar jarTask = (Jar) t;
final File jarFile = jarTask.getArchiveFile().get().getAsFile();
if (!nestedJarsDir.isPresent()) {
return;
}
final File outputDir = nestedJarsDir.get().getAsFile();
if (outputDir.exists() && outputDir.isDirectory()) {
final File[] jars = outputDir.listFiles((dir, name) -> name.endsWith(".jar"));
if (jars != null && jars.length > 0) {
JarNester.nestJars(
Arrays.asList(jars),
jarFile,
jarTask.getLogger()
);
jarTask.getLogger().lifecycle("Nested {} jar(s) into {}", jars.length, jarFile.getName());
}
}
}
}

View File

@@ -0,0 +1,61 @@
/*
* This file is part of fabric-loom, licensed under the MIT License (MIT).
*
* Copyright (c) 2016-2021 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.task;
import org.gradle.api.Project;
import org.gradle.api.plugins.JavaPlugin;
import org.gradle.api.tasks.TaskProvider;
import org.gradle.jvm.tasks.Jar;
import net.fabricmc.loom.LoomGradleExtension;
import net.fabricmc.loom.build.nesting.NestableJarGenerationTask;
/**
* Configures the jar task for non-remapped (non-obfuscated) output.
* Used when remapping is disabled via dontRemapOutputs().
*/
public class NonRemappedJarTaskConfiguration {
private final Project project;
private final LoomGradleExtension extension;
private final TaskProvider<NestableJarGenerationTask> processIncludeJarsTask;
public NonRemappedJarTaskConfiguration(Project project, LoomGradleExtension extension, TaskProvider<NestableJarGenerationTask> processIncludeJarsTask) {
this.project = project;
this.extension = extension;
this.processIncludeJarsTask = processIncludeJarsTask;
}
public void configure() {
// No remapping needed - use simplified JIJ approach directly on jar task
project.getTasks().named(JavaPlugin.JAR_TASK_NAME, Jar.class).configure(task -> {
task.dependsOn(processIncludeJarsTask);
// Use JarNester to properly add jars and update fabric.mod.json
task.doLast(new NestJarsAction(processIncludeJarsTask.flatMap(NestableJarGenerationTask::getOutputDirectory)));
});
// Add jar task to unmapped collection
extension.getUnmappedModCollection().from(project.getTasks().getByName(JavaPlugin.JAR_TASK_NAME));
}
}

View File

@@ -67,17 +67,18 @@ public abstract class RemapTaskConfiguration implements Runnable {
SyncTaskBuildService.register(getProject());
if (extension.dontRemapOutputs()) {
extension.getUnmappedModCollection().from(getTasks().getByName(JavaPlugin.JAR_TASK_NAME));
return;
}
Configuration includeConfiguration = getProject().getConfigurations().getByName(Constants.Configurations.INCLUDE_INTERNAL);
getTasks().register(Constants.Task.PROCESS_INCLUDE_JARS, NestableJarGenerationTask.class, task -> {
TaskProvider<NestableJarGenerationTask> processIncludeJarsTask = getTasks().register(Constants.Task.PROCESS_INCLUDE_JARS, NestableJarGenerationTask.class, task -> {
task.from(includeConfiguration);
task.getOutputDirectory().set(getProject().getLayout().getBuildDirectory().dir(task.getName()));
});
if (extension.dontRemapOutputs()) {
new NonRemappedJarTaskConfiguration(getProject(), extension, processIncludeJarsTask).configure();
return;
}
// Remapping needed - use the traditional remapJar task with JIJ support (original logic)
Action<RemapJarTask> remapJarTaskAction = task -> {
final TaskProvider<AbstractArchiveTask> jarTask = getTasks().named(JavaPlugin.JAR_TASK_NAME, AbstractArchiveTask.class);

View File

@@ -36,6 +36,7 @@ import org.gradle.api.artifacts.Configuration;
import org.gradle.api.artifacts.Dependency;
import org.gradle.api.file.ConfigurableFileCollection;
import org.gradle.api.file.DirectoryProperty;
import org.gradle.api.plugins.JavaPlugin;
import org.gradle.api.plugins.JavaPluginExtension;
import org.gradle.api.provider.ListProperty;
import org.gradle.api.provider.Property;
@@ -128,7 +129,12 @@ public abstract sealed class AbstractProductionRunTask extends AbstractLoomTask
getJavaLauncher().convention(getJavaToolchainService().launcherFor(defaultToolchain));
getRunDir().convention(getProject().getLayout().getProjectDirectory().dir("run"));
if (!getExtension().dontRemapOutputs()) {
// Use the appropriate jar based on whether remapping is enabled
if (getExtension().dontRemapOutputs()) {
// No remapping - use the standard jar task
getMods().from(getProject().getTasks().named(JavaPlugin.JAR_TASK_NAME));
} else {
// Remapping enabled - use the remapJar task
getMods().from(getProject().getTasks().named(RemapTaskConfiguration.REMAP_JAR_TASK_NAME));
}

View File

@@ -0,0 +1,58 @@
/*
* This file is part of fabric-loom, licensed under the MIT License (MIT).
*
* Copyright (c) 2023 FabricMC
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package net.fabricmc.loom.test.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 IncludedJarsNoRemapTest extends Specification implements GradleProjectTestTrait {
@Unroll
def "included jars without remapping (gradle #version)"() {
setup:
def gradle = gradleProject(project: "includedJarsNoRemap", version: version)
when:
def result = gradle.run(tasks: ["jar"])
then:
result.task(":jar").outcome == SUCCESS
// Assert directly declared dependencies are present in jar (no remap)
gradle.hasOutputZipEntry("includedJars.jar", "META-INF/jars/log4j-core-2.22.0.jar")
gradle.hasOutputZipEntry("includedJars.jar", "META-INF/jars/adventure-text-serializer-gson-4.14.0.jar")
// But not transitives.
!gradle.hasOutputZipEntry("includedJars.jar", "META-INF/jars/log4j-api-2.22.0.jar")
!gradle.hasOutputZipEntry("includedJars.jar", "META-INF/jars/adventure-api-4.14.0.jar")
where:
version << STANDARD_TEST_VERSIONS
}
}

View File

@@ -44,7 +44,7 @@ class IncludedJarsTest extends Specification implements GradleProjectTestTrait {
then:
result.task(":remapJar").outcome == SUCCESS
// Assert directly declared dependencies are present
// Assert directly declared dependencies are present in remapped jar
gradle.hasOutputZipEntry("includedJars.jar", "META-INF/jars/log4j-core-2.22.0.jar")
gradle.hasOutputZipEntry("includedJars.jar", "META-INF/jars/adventure-text-serializer-gson-4.14.0.jar")

View File

@@ -0,0 +1,19 @@
plugins {
id 'net.fabricmc.fabric-loom-no-remap-experimental'
}
repositories {
mavenCentral()
}
dependencies {
minecraft 'com.mojang:minecraft:25w45a_unobfuscated'
include 'org.apache.logging.log4j:log4j-core:2.22.0'
// Test bom/platform dependencies
include platform('net.kyori:adventure-bom:4.14.0')
// bom provides version
include 'net.kyori:adventure-text-serializer-gson'
}

View File

@@ -0,0 +1 @@
rootProject.name = 'includedJars'

View File

@@ -0,0 +1,9 @@
{
"schemaVersion": 1,
"id": "modid",
"version": "0.0.0",
"name": "Example Mod",
"description": "This is an example description! Tell everyone what your mod is about!",
"environment": "*"
}