Skip to content

Commit

Permalink
Subproject Helper Methods, Add an Idiot-Proof Pom Stuffing Fix (#10)
Browse files Browse the repository at this point in the history
  • Loading branch information
calmilamsy authored Jan 21, 2025
1 parent 735d409 commit 08351fa
Show file tree
Hide file tree
Showing 4 changed files with 117 additions and 3 deletions.
3 changes: 3 additions & 0 deletions src/main/java/babric/BabricExtension.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@
public class BabricExtension {
public final Property<Boolean> disableM1Fixes;

public final Property<Boolean> disablePomOverride;

public BabricExtension(Project project) {
disableM1Fixes = project.getObjects().property(Boolean.class).convention(false);
disablePomOverride = project.getObjects().property(Boolean.class).convention(false);
}
}
40 changes: 38 additions & 2 deletions src/main/java/babric/BabricLoomPlugin.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,18 @@
import babric.processor.GambacLibraryProcessor;
import babric.processor.LWJGL2LibraryProcessor;
import babric.processor.NestFixingJarProcessor;
import groovy.util.Node;
import groovy.util.NodeList;
import net.fabricmc.loom.LoomGradleExtension;
import net.fabricmc.loom.api.LoomGradleExtensionAPI;
import net.fabricmc.loom.configuration.providers.minecraft.library.LibraryProcessorManager;
import org.gradle.api.Plugin;
import org.gradle.api.Project;
import org.gradle.api.artifacts.Configuration;
import org.gradle.api.plugins.PluginAware;
import org.gradle.api.provider.ListProperty;
import org.gradle.api.publish.PublishingExtension;
import org.gradle.api.publish.maven.MavenPublication;
import org.gradle.internal.os.OperatingSystem;

import java.util.Map;
Expand All @@ -27,16 +32,21 @@ public void apply(PluginAware target) {
if (target instanceof Project project) applyProject(project);
}

@SuppressWarnings("UnstableApiUsage")
private void applyProject(Project project) {
project.getLogger().lifecycle("Babric loom: " + VERSION);

BabricExtension babricExtension = project.getExtensions().create("babric", BabricExtension.class, project);

// Add a transitiveImplementation configuration because gradle has no built-in way to say "don't add this to the pom"
Configuration transitiveImplementation = project.getConfigurations().create("transitiveImplementation");
project.getConfigurations().getByName("implementation").extendsFrom(transitiveImplementation);

ListProperty<LibraryProcessorManager.LibraryProcessorFactory> libraryProcessors = LoomGradleExtension.get(project).getLibraryProcessors();
libraryProcessors.add(LWJGL2LibraryProcessor::new);

LoomGradleExtensionAPI extension = (LoomGradleExtensionAPI) project.getExtensions().getByName("loom");

BabricExtension babricExtension = project.getExtensions().create("babric", BabricExtension.class, project);

libraryProcessors.add((platform, libraryContext) -> new GambacLibraryProcessor(platform, libraryContext, extension, project, babricExtension));

extension.getVersionsManifests().add("babric-manifest", "https://babric.github.io/manifest-polyfill/version_manifest_v2.json", -10);
Expand All @@ -57,5 +67,31 @@ private void applyProject(Project project) {
});
}
});

// Wipes the normal pom's dependency block and substitutes in the transitiveImplementation configuration contents.
PublishingExtension publishing = project.getExtensions().getByType(PublishingExtension.class);
project.afterEvaluate(p -> {
if (!babricExtension.disablePomOverride.get()) {
publishing.getPublications().forEach(publication -> {
if (publication instanceof MavenPublication mavenPublication) {
mavenPublication.pom(mavenPom -> mavenPom.withXml(xmlProvider -> {
Node depsNode = new Node(null, "dependencies");

// Jank solution to an annoying issue
project.getConfigurations().getByName("transitiveImplementation").getDependencies().forEach(dependency -> {
Node depNode = depsNode.appendNode("dependency");
depNode.appendNode("groupId", dependency.getGroup());
depNode.appendNode("artifactId", dependency.getName());
depNode.appendNode("version", dependency.getVersion());
depNode.appendNode("scope", "runtime");
});

// Replace the dependency block, because it's just hopelessly wrong and includes floader+asm for some reason
((Node) ((NodeList) xmlProvider.asNode().get("dependencies")).get(0)).replaceNode(depsNode);
}));
}
});
}
});
}
}
69 changes: 69 additions & 0 deletions src/main/java/babric/SubprojectHelpers.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package babric;

import groovy.util.Node;
import net.fabricmc.loom.util.GroovyXmlUtil;
import org.gradle.api.Project;
import org.gradle.api.artifacts.Dependency;
import org.gradle.api.publish.PublishingExtension;
import org.gradle.api.publish.maven.MavenPublication;

import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
* A utility class which can be used in multi-module builds to neatly tie multi-mod structures together.
*/
public class SubprojectHelpers {

/**
* Adds the provided subprojects to the parent project as dependencies. A must-have for multi-module projects.
* @param project The root project to add the subprojects to.
* @param projectNames The names of the subprojects to be added.
*/
public static void addModuleDependencies(Project project, String... projectNames) {
List<Dependency> modules = Arrays.stream(projectNames).map((it) -> project.getDependencies().project(Map.of("path", ":" + it, "configuration", "dev"))).collect(Collectors.toList());

modules.forEach(dependency -> project.getDependencies().add("implementation", dependency));

MavenPublication publishing = (MavenPublication) project.getExtensions().getByType(PublishingExtension.class).getPublications().getByName("mavenJava");
publishing.pom((e) -> e.withXml((f) -> {
addDependencyXMLs(f.asNode(), "implementation", modules);
}));
}

/**
* Adds a project to the provided maven pom. Used for fixing maven poms elsewhere, and is safe to be used by multi-module projects.
* @param xml The maven pom XML root node.
* @param scope The scope of the dependency. Usually "implementation".
* @param dependency The project to add as a dependency.
*/
public static void addDependencyXML(Node xml, String scope, Project dependency) {
Node depsNode = GroovyXmlUtil.getOrCreateNode(xml, "dependencies");

Node appNode = depsNode.appendNode("dependency");
appNode.appendNode("groupId", dependency.getGroup());
appNode.appendNode("artifactId", dependency.getName());
appNode.appendNode("version", dependency.getVersion());
appNode.appendNode("scope", scope);
}

/**
* Adds a list of projects to the maven pom. Used for fixing maven poms elsewhere, and is safe to be used by multi-module projects.
* @param xml The maven pom XML root node.
* @param scope The scope of the dependency. Usually "implementation".
* @param dependencies The projects to add as a dependency.
*/
public static void addDependencyXMLs(Node xml, String scope, List<Dependency> dependencies) {
Node depsNode = GroovyXmlUtil.getOrCreateNode(xml, "dependencies");

for (Dependency dep : dependencies) {
Node appNode = depsNode.appendNode("dependency");
appNode.appendNode("groupId", dep.getGroup());
appNode.appendNode("artifactId", dep.getName());
appNode.appendNode("version", dep.getVersion());
appNode.appendNode("scope", scope);
}
}
}
8 changes: 7 additions & 1 deletion test-mod/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ base {

babric {
// disableM1Fixes.set(true) // Uncomment this to disable gambac (M1 colours fix.)
// disablePomOverride.set(true) // Uncomment this to disable the pom override that helps simplify dependency management.
}

repositories {
Expand All @@ -32,7 +33,12 @@ dependencies {
modImplementation "net.fabricmc:fabric-loader:${project.loader_version}"

implementation "org.slf4j:slf4j-api:1.8.0-beta4"
implementation "org.apache.logging.log4j:log4j-slf4j18-impl:2.17.2"
transitiveImplementation "org.apache.logging.log4j:log4j-slf4j18-impl:2.17.2"

// This is an example on how to include a mod transitively.
// transitiveImplementation(modImplementation("net.glasslauncher.mods:glass-networking:1.0.3") {
// transitive = false // Disables trying to resolve this mod's dependencies.
// })
}

processResources {
Expand Down

0 comments on commit 08351fa

Please sign in to comment.