-
-
Notifications
You must be signed in to change notification settings - Fork 66
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #142 from juanmuscaria/crucibleGradle
Move CrucibleGradle to Crucible's main repo
- Loading branch information
Showing
31 changed files
with
4,799 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
# CrucibleGradle | ||
Make ForgeGradle do more | ||
|
||
## About | ||
This is Crucible's extension over anatawa12's [ForgeGradle-1.2](https://github.com/anatawa12/ForgeGradle-1.2/). | ||
Here we keep all necessary machinery for building Crucible. | ||
|
||
This project still needs a lot of proper cleanup since it was more or less a copy/paste of old Cauldron dev plugin. | ||
A lot of tasks still does not cache properly, and we don't have much of an idea of what is going on certain parts of the | ||
FG workflow. | ||
|
||
This is basically the bare minimum to get Crucible to build on modern Gradle. | ||
|
||
## TODO | ||
* [ ] Document all tasks/add descriptions | ||
* [ ] Fix caching issues | ||
* [ ] Trim down unneeded tasks | ||
* [ ] Clean up old code and deprecated usages |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,120 @@ | ||
plugins { | ||
java | ||
`java-gradle-plugin` | ||
`maven-publish` | ||
} | ||
|
||
group = "io.github.cruciblemc" | ||
version = "1.2-SNAPSHOT" | ||
|
||
repositories { | ||
mavenCentral() | ||
maven("https://maven.minecraftforge.net/") { | ||
name = "forge" | ||
} | ||
} | ||
|
||
dependencies { | ||
// TODO? figure a way to use the runtime dependencies of FG? | ||
implementation("org.ow2.asm:asm:9.4") | ||
implementation("org.ow2.asm:asm-tree:9.4") | ||
implementation("com.google.guava:guava:31.1-jre") | ||
implementation("com.opencsv:opencsv:5.7.0") | ||
implementation("com.cloudbees:diff4j:1.3") | ||
implementation("com.github.abrarsyed.jastyle:jAstyle:1.2") | ||
implementation("net.sf.trove4j:trove4j:2.1.0") | ||
implementation("com.github.jponge:lzma-java:1.3") | ||
implementation("com.nothome:javaxdelta:2.0.1") | ||
implementation("com.google.code.gson:gson:2.10.1") | ||
implementation("com.anatawa12.forge:SpecialSource:1.11.1") | ||
implementation("org.apache.httpcomponents:httpclient:4.5.14") | ||
implementation("org.apache.httpcomponents:httpmime:4.5.14") | ||
implementation("de.oceanlabs.mcp:RetroGuard:3.6.6") | ||
implementation("de.oceanlabs.mcp:mcinjector:3.2-SNAPSHOT") | ||
implementation("net.minecraftforge:Srg2Source:4.2.7") | ||
|
||
api("com.anatawa12.forge:ForgeGradle:1.2-1.1.0") | ||
testImplementation(platform("org.junit:junit-bom:5.9.1")) | ||
testImplementation("org.junit.jupiter:junit-jupiter") | ||
|
||
implementation("com.github.tony19:named-regexp:0.2.3") | ||
|
||
// Java 9+ syntax | ||
annotationProcessor("com.github.bsideup.jabel:jabel-javac-plugin:0.4.2") | ||
compileOnly("com.github.bsideup.jabel:jabel-javac-plugin:0.4.2") | ||
|
||
// Lombok | ||
compileOnly("org.projectlombok:lombok:1.18.26") | ||
annotationProcessor("org.projectlombok:lombok:1.18.26") | ||
} | ||
|
||
tasks.test { | ||
useJUnitPlatform() | ||
} | ||
|
||
tasks.named("compileJava").configure { | ||
this as JavaCompile | ||
sourceCompatibility = "17" // for the IDE support | ||
options.release.set(8) | ||
|
||
javaCompiler.set( | ||
javaToolchains.compilerFor { | ||
languageVersion.set(JavaLanguageVersion.of(17)) | ||
} | ||
) | ||
} | ||
|
||
gradlePlugin { | ||
plugins { | ||
create("crucible") { | ||
id = "crucible" | ||
implementationClass = "io.github.cruciblemc.forgegradle.CrucibleDevPlugin" | ||
} | ||
} | ||
} | ||
|
||
publishing { | ||
publications { | ||
create<MavenPublication>("mavenJava") { | ||
from(components["java"]) | ||
artifactId = base.archivesName.get() | ||
|
||
pom { | ||
name.set(project.base.archivesName.get()) | ||
description.set("Gradle plugin for Crucible") | ||
url.set("https://github.com/CrucibleMC/CrucibleGradle") | ||
|
||
scm { | ||
url.set("https://github.com/CrucibleMC/CrucibleGradle") | ||
connection.set("scm:git:git://github.com/CrucibleMC/CrucibleGradle.git") | ||
developerConnection.set("scm:git:[email protected]:CrucibleMC/CrucibleGradle.git") | ||
} | ||
|
||
issueManagement { | ||
system.set("github") | ||
url.set("https://github.com/CrucibleMC/CrucibleGradle/issues") | ||
} | ||
|
||
licenses { | ||
license { | ||
name.set("Lesser GNU Public License, Version 2.1") | ||
url.set("https://www.gnu.org/licenses/lgpl-2.1.html") | ||
distribution.set("repo") | ||
} | ||
} | ||
|
||
developers { | ||
developer { | ||
id.set("juanmuscaria") | ||
name.set("juanmuscaria") | ||
} | ||
} | ||
} | ||
} | ||
repositories { | ||
maven(buildDir.absolutePath + "/repo") { | ||
name = "filesystem" | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
rootProject.name = "CrucibleGradle" | ||
|
88 changes: 88 additions & 0 deletions
88
buildSrc/src/main/java/com/juanmuscaria/uncode/ASMCodeRemover.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
package com.juanmuscaria.uncode; | ||
|
||
import com.google.common.io.ByteStreams; | ||
import com.juanmuscaria.uncode.cleaners.ClassCleaner; | ||
import org.objectweb.asm.ClassReader; | ||
import org.objectweb.asm.ClassWriter; | ||
import org.slf4j.Logger; | ||
import org.slf4j.LoggerFactory; | ||
|
||
import java.io.IOException; | ||
import java.nio.file.Files; | ||
import java.nio.file.Path; | ||
import java.nio.file.StandardOpenOption; | ||
import java.util.Collections; | ||
import java.util.LinkedHashMap; | ||
import java.util.Map; | ||
import java.util.zip.ZipEntry; | ||
import java.util.zip.ZipException; | ||
import java.util.zip.ZipFile; | ||
import java.util.zip.ZipOutputStream; | ||
|
||
public class ASMCodeRemover { | ||
|
||
private static final Logger logger | ||
= LoggerFactory.getLogger(ASMCodeRemover.class); | ||
|
||
/** | ||
* Removes all the code, assets, and private elements from given jar, | ||
* keeping only public classes, methods and fields with no code body. | ||
* | ||
* @param jarFile the jar file to process | ||
* @param outputFile the output file | ||
* @param overwrite if the output file should be overwritten if it already exists | ||
* @return a map with jarEntry-reason for all entries from the input jar that where removed (resources and class files) | ||
* @throws IOException if an I/O error occurs | ||
*/ | ||
public static Map<String, String> removeContent(Path jarFile, Path outputFile, boolean overwrite) throws IOException { | ||
if (!Files.exists(jarFile)) { | ||
throw new IllegalArgumentException("Input file does not exist"); | ||
} else if (!Files.isReadable(jarFile)) { | ||
throw new IllegalArgumentException("Input file is not readable"); | ||
} else if (Files.exists(outputFile) && !overwrite) { | ||
throw new IllegalArgumentException("Output file already exists"); | ||
} | ||
|
||
var failedEntries = new LinkedHashMap<String, String>(); | ||
try (var out = new ZipOutputStream(Files.newOutputStream(outputFile, StandardOpenOption.CREATE, StandardOpenOption.WRITE, StandardOpenOption.TRUNCATE_EXISTING))) { | ||
try (var zip = new ZipFile(jarFile.toFile())) { | ||
Collections.list(zip.entries()).iterator().forEachRemaining(entry -> { | ||
if (entry.getName().endsWith(".class")) { | ||
try { | ||
var classBytes = processClass(ByteStreams.toByteArray(zip.getInputStream(entry))); | ||
var newEntry = new ZipEntry(entry.getName()); | ||
out.putNextEntry(newEntry); | ||
out.write(classBytes); | ||
out.closeEntry(); | ||
} catch (Exception e) { | ||
failedEntries.put(entry.getName(), e.getMessage()); | ||
logger.debug("Failed to process class: {}", entry.getName()); | ||
logger.debug("Exception:", e); | ||
} | ||
} else if (!entry.getName().endsWith("/")) { | ||
failedEntries.put(entry.getName(), "Not a class file"); | ||
} | ||
}); | ||
} catch (ZipException e) { | ||
throw new IllegalArgumentException("Input file is corrupted or not a valid jar file: " + e.getMessage(), e); | ||
} | ||
} | ||
|
||
return failedEntries; | ||
} | ||
|
||
/** | ||
* Removes all the code from a class, keeping only its public members without any code body. | ||
* | ||
* @param classBytes input class bytes | ||
* @return the processed class bytes | ||
* @throws IllegalArgumentException if the class is not readable by the current ASM version, | ||
* if the class is synthetic or if the class is not public | ||
*/ | ||
public static byte[] processClass(byte[] classBytes) throws IllegalArgumentException { | ||
var classReader = new ClassReader(classBytes); | ||
var classWriter = new ClassWriter(classReader, ClassWriter.COMPUTE_MAXS); | ||
classReader.accept(new ClassCleaner(classWriter), 0); | ||
return classWriter.toByteArray(); | ||
} | ||
} |
117 changes: 117 additions & 0 deletions
117
buildSrc/src/main/java/com/juanmuscaria/uncode/cleaners/ClassCleaner.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,117 @@ | ||
package com.juanmuscaria.uncode.cleaners; | ||
|
||
import org.objectweb.asm.*; | ||
|
||
/** | ||
* Remove most attributes from a class, leaving only public methods without a body, public fields and inner classes. | ||
* All synthetic members are removed, classes produced by this is not intended to by loaded by the jvm. | ||
*/ | ||
public class ClassCleaner extends ClassVisitor { | ||
|
||
public ClassCleaner(ClassVisitor cv) { | ||
super(Opcodes.ASM9, cv); | ||
} | ||
|
||
@Override | ||
public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) { | ||
// We only want public classes | ||
if ((access & Opcodes.ACC_PUBLIC) == 0) { | ||
throw new IllegalArgumentException("Class is not public, skipping"); | ||
} else if ((access & Opcodes.ACC_SYNTHETIC) != 0) { | ||
throw new IllegalArgumentException("Class is synthetic (compiler generated), skipping"); | ||
} | ||
super.visit(version, access, name, signature, superName, interfaces); | ||
} | ||
|
||
@Override | ||
public void visitSource(String source, String debug) { | ||
// Warns this class was touched by the code killer | ||
super.visitSource("uncoded", null); | ||
} | ||
|
||
@Override | ||
public ModuleVisitor visitModule(String name, int access, String version) { | ||
// NO-OP - Remove element | ||
return null; | ||
} | ||
|
||
@Override | ||
public void visitNestHost(String nestHost) { | ||
// NO-OP - Remove element | ||
} | ||
|
||
@Override | ||
public void visitOuterClass(String owner, String name, String descriptor) { | ||
super.visitOuterClass(owner, name, descriptor); | ||
} | ||
|
||
@Override | ||
public AnnotationVisitor visitAnnotation(String descriptor, boolean visible) { | ||
return super.visitAnnotation(descriptor, visible); | ||
} | ||
|
||
@Override | ||
public AnnotationVisitor visitTypeAnnotation(int typeRef, TypePath typePath, String descriptor, boolean visible) { | ||
return super.visitTypeAnnotation(typeRef, typePath, descriptor, visible); | ||
} | ||
|
||
@Override | ||
public void visitAttribute(Attribute attribute) { | ||
// NO-OP - Remove element | ||
} | ||
|
||
@Override | ||
public void visitNestMember(String nestMember) { | ||
// NO-OP - Remove element | ||
} | ||
|
||
@Override | ||
public void visitPermittedSubclass(String permittedSubclass) { | ||
// NO-OP - Remove element | ||
} | ||
|
||
@Override | ||
public void visitInnerClass(String name, String outerName, String innerName, int access) { | ||
// We only want public classes | ||
if ((access & Opcodes.ACC_PUBLIC) == 0) { | ||
return; | ||
} else if ((access & Opcodes.ACC_SYNTHETIC) != 0) { | ||
return; | ||
} | ||
super.visitInnerClass(name, outerName, innerName, access); | ||
} | ||
|
||
@Override | ||
public RecordComponentVisitor visitRecordComponent(String name, String descriptor, String signature) { | ||
// NO-OP - Remove element | ||
return null; | ||
} | ||
|
||
@Override | ||
public FieldVisitor visitField(int access, String name, String descriptor, String signature, Object value) { | ||
// We only want public fields | ||
if ((access & Opcodes.ACC_PUBLIC) == 0) { | ||
return null; | ||
} else if ((access & Opcodes.ACC_SYNTHETIC) != 0) { | ||
return null; | ||
} | ||
// Keep the initial value if it's a constant | ||
return new FieldCleaner(super.visitField(access, name, descriptor, signature, (access & Opcodes.ACC_STATIC) != 0 ? value : null)); | ||
} | ||
|
||
@Override | ||
public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions) { | ||
// We only want public methods | ||
if ((access & Opcodes.ACC_PUBLIC) == 0) { | ||
return null; | ||
} else if ((access & Opcodes.ACC_SYNTHETIC) != 0) { | ||
return null; | ||
} | ||
return new MethodCleaner(super.visitMethod(access, name, descriptor, signature, exceptions), name, descriptor); | ||
} | ||
|
||
@Override | ||
public void visitEnd() { | ||
super.visitEnd(); | ||
} | ||
} |
33 changes: 33 additions & 0 deletions
33
buildSrc/src/main/java/com/juanmuscaria/uncode/cleaners/FieldCleaner.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
package com.juanmuscaria.uncode.cleaners; | ||
|
||
import org.objectweb.asm.*; | ||
|
||
/** | ||
* Cleans annotation and attributes from a field. | ||
*/ | ||
public class FieldCleaner extends FieldVisitor { | ||
|
||
public FieldCleaner(FieldVisitor fieldVisitor) { | ||
super(Opcodes.ASM9, fieldVisitor); | ||
} | ||
|
||
@Override | ||
public AnnotationVisitor visitAnnotation(String descriptor, boolean visible) { | ||
return super.visitAnnotation(descriptor, visible); | ||
} | ||
|
||
@Override | ||
public AnnotationVisitor visitTypeAnnotation(int typeRef, TypePath typePath, String descriptor, boolean visible) { | ||
return super.visitTypeAnnotation(typeRef, typePath, descriptor, visible); | ||
} | ||
|
||
@Override | ||
public void visitAttribute(Attribute attribute) { | ||
// NO-OP | ||
} | ||
|
||
@Override | ||
public void visitEnd() { | ||
super.visitEnd(); | ||
} | ||
} |
Oops, something went wrong.