Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Inject interfaces to vanilla classes using JST #1765

Merged
merged 15 commits into from
Dec 15, 2024

This file was deleted.

This file was deleted.

59 changes: 20 additions & 39 deletions buildSrc/src/main/java/net/neoforged/neodev/NeoDevPlugin.java
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,6 @@ public void apply(Project project) {
);
var applyAt = configureAccessTransformer(
project,
configurations,
createSourceArtifacts,
neoDevBuildDir,
atFiles);
Expand All @@ -109,18 +108,26 @@ public void apply(Project project) {

// 3. Apply interface injections after the ATs
// this jar is only used for the patches in the repo
var applyInterfaceInjection = configureInterfaceInjection(
project, configurations,
applyAt.flatMap(ApplyAccessTransformer::getOutputJar),
neoDevBuildDir,
List.of(project.getRootProject().file("src/main/resources/META-INF/interfaces.json"))
);
var applyInterfaceInjection = project.getTasks().register("applyInterfaceInjection", TransformSources.class, task -> {
task.getInputJar().set(applyAt.flatMap(TransformSources::getOutputJar));
task.getInterfaceInjectionData().from(project.getRootProject().file("src/main/resources/META-INF/interfaces.json"));
task.getOutputJar().set(neoDevBuildDir.map(dir -> dir.file("artifacts/interface-injected-sources.jar")));
task.getInterfaceStubsJar().set(neoDevBuildDir.map(dir -> dir.file("artifacts/interface-injection-stubs.jar")));
Matyrobbrt marked this conversation as resolved.
Show resolved Hide resolved
});

tasks.withType(TransformSources.class, task -> {
task.setGroup(INTERNAL_GROUP);
task.classpath(configurations.getExecutableTool(Tools.JST));

task.getLibraries().from(configurations.neoFormClasspath);
task.getLibrariesFile().set(neoDevBuildDir.map(dir -> dir.file("minecraft-libraries-for-" + task.getName() + ".txt")));
});

// 4. Apply patches to the source jar from 3.
var patchesFolder = project.getRootProject().file("patches");
var applyPatches = tasks.register("applyPatches", ApplyPatches.class, task -> {
task.setGroup(INTERNAL_GROUP);
task.getOriginalJar().set(applyInterfaceInjection.flatMap(ApplyJSTTransformer::getOutputJar));
task.getOriginalJar().set(applyInterfaceInjection.flatMap(TransformSources::getOutputJar));
task.getPatchesFolder().set(patchesFolder);
task.getPatchedJar().set(neoDevBuildDir.map(dir -> dir.file("artifacts/patched-sources.jar")));
task.getRejectsFolder().set(project.getRootProject().file("rejects"));
Expand Down Expand Up @@ -197,15 +204,15 @@ public void apply(Project project) {
// Generate source patches into a patch archive, based on the jar with injected interfaces.
var genSourcePatches = tasks.register("generateSourcePatches", GenerateSourcePatches.class, task -> {
task.setGroup(INTERNAL_GROUP);
task.getOriginalJar().set(applyInterfaceInjection.flatMap(ApplyJSTTransformer::getOutputJar));
task.getOriginalJar().set(applyInterfaceInjection.flatMap(TransformSources::getOutputJar));
task.getModifiedSources().set(project.file("src/main/java"));
task.getPatchesJar().set(neoDevBuildDir.map(dir -> dir.file("source-patches.zip")));
});

// Generate source patches that are based on the production environment (without separate interface injection)
var genProductionPatches = tasks.register("generateProductionSourcePatches", GenerateSourcePatches.class, task -> {
task.setGroup(INTERNAL_GROUP);
task.getOriginalJar().set(applyAt.flatMap(ApplyJSTTransformer::getOutputJar));
task.getOriginalJar().set(applyAt.flatMap(TransformSources::getOutputJar));
task.getModifiedSources().set(project.file("src/main/java"));
task.getPatchesFolder().set(neoDevBuildDir.map(dir -> dir.dir("production-source-patches")));
});
Expand Down Expand Up @@ -461,48 +468,22 @@ public void apply(Project project) {
setupProductionServerTest(project, installerJar);
}

private static TaskProvider<ApplyAccessTransformer> configureAccessTransformer(
private static TaskProvider<TransformSources> configureAccessTransformer(
Project project,
NeoDevConfigurations configurations,
TaskProvider<CreateMinecraftArtifacts> createSourceArtifacts,
Provider<Directory> neoDevBuildDir,
List<File> atFiles) {

// Pass -PvalidateAccessTransformers to validate ATs.
var validateAts = project.getProviders().gradleProperty("validateAccessTransformers").map(p -> true).orElse(false);
return project.getTasks().register("applyAccessTransformer", ApplyAccessTransformer.class, task -> {
configureJSTTask(task, configurations, neoDevBuildDir);
return project.getTasks().register("applyAccessTransformer", TransformSources.class, task -> {
task.getInputJar().set(createSourceArtifacts.flatMap(CreateMinecraftArtifacts::getSourcesArtifact));
task.getAccessTransformers().from(atFiles);
task.getValidate().set(validateAts);
task.getValidateAccessTransformers().set(validateAts);
task.getOutputJar().set(neoDevBuildDir.map(dir -> dir.file("artifacts/access-transformed-sources.jar")));
});
}

private static TaskProvider<ApplyInterfaceInjectionTransformer> configureInterfaceInjection(
Project project,
NeoDevConfigurations configurations,
Provider<RegularFile> input,
Provider<Directory> neoDevBuildDir,
List<File> dataFiles) {

return project.getTasks().register("applyInterfaceInjection", ApplyInterfaceInjectionTransformer.class, task -> {
configureJSTTask(task, configurations, neoDevBuildDir);
task.getInputJar().set(input);
task.getInterfaceInjectionData().from(dataFiles);
task.getOutputJar().set(neoDevBuildDir.map(dir -> dir.file("artifacts/interface-injected-transformed-sources.jar")));
task.getStubsJar().set(neoDevBuildDir.map(dir -> dir.file("artifacts/interface-injection-stubs.jar")));
});
}

private static void configureJSTTask(ApplyJSTTransformer task, NeoDevConfigurations configurations, Provider<Directory> neoDevBuildDir) {
task.setGroup(INTERNAL_GROUP);
task.classpath(configurations.getExecutableTool(Tools.JST));

task.getLibraries().from(configurations.neoFormClasspath);
task.getLibrariesFile().set(neoDevBuildDir.map(dir -> dir.file("minecraft-libraries-for-" + task.getName() + ".txt")));
}

private static BinaryPatchOutputs configureBinaryPatchCreation(Project project,
NeoDevConfigurations configurations,
TaskProvider<CreateCleanArtifacts> createCleanArtifacts,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,14 @@
import net.neoforged.neodev.utils.FileUtils;
import org.gradle.api.file.ConfigurableFileCollection;
import org.gradle.api.file.RegularFileProperty;
import org.gradle.api.provider.Property;
import org.gradle.api.tasks.Classpath;
import org.gradle.api.tasks.Input;
import org.gradle.api.tasks.InputFile;
import org.gradle.api.tasks.InputFiles;
import org.gradle.api.tasks.Internal;
import org.gradle.api.tasks.JavaExec;
import org.gradle.api.tasks.Optional;
import org.gradle.api.tasks.OutputFile;
import org.gradle.api.tasks.TaskAction;

Expand All @@ -17,12 +21,27 @@
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
* Runs <a href="https://github.com/neoforged/JavaSourceTransformer">JavaSourceTransformer</a> over the Minecraft source code.
*/
abstract class ApplyJSTTransformer extends JavaExec {
abstract class TransformSources extends JavaExec {
@Optional
@InputFiles
public abstract ConfigurableFileCollection getAccessTransformers();

@Input
@Optional
public abstract Property<Boolean> getValidateAccessTransformers();

@Optional
@InputFiles
public abstract ConfigurableFileCollection getInterfaceInjectionData();

@Optional
@OutputFile
public abstract RegularFileProperty getInterfaceStubsJar();

@InputFile
public abstract RegularFileProperty getInputJar();

Expand All @@ -37,9 +56,7 @@ abstract class ApplyJSTTransformer extends JavaExec {
public abstract RegularFileProperty getLibrariesFile();

@Inject
public ApplyJSTTransformer() {}

abstract void addArgs(List<String> arguments);
public TransformSources() {}

@Override
@TaskAction
Expand All @@ -57,7 +74,30 @@ public void exec() {
"--libraries-list", getLibrariesFile().getAsFile().get().getAbsolutePath()
));

addArgs(args);
if (!getAccessTransformers().isEmpty()) {
args.addAll(Arrays.asList(
"--enable-accesstransformers",
"--access-transformer-validation", getValidateAccessTransformers().get() ? "error" : "log"
));
for (var file : getAccessTransformers().getFiles()) {
args.addAll(Arrays.asList(
"--access-transformer", file.getAbsolutePath()
));
}
}

if (!getInterfaceInjectionData().isEmpty()) {
args.addAll(Arrays.asList(
"--enable-interface-injection",
"--interface-injection-stubs", getInterfaceStubsJar().get().getAsFile().getAbsolutePath()
));

for (var file : getInterfaceInjectionData().getFiles()) {
args.addAll(Arrays.asList(
"--interface-injection-data", file.getAbsolutePath()
));
}
}

args.addAll(Arrays.asList(
getInputJar().getAsFile().get().getAbsolutePath(),
Expand Down
Loading