Fix the java software component not working with Loom and fix #200 (#460)

* Add modCompileOnlyApi, modRuntimeOnly; deprecate modRuntime

* begin

* continue

* Make RemapSourcesJarTask use properties

* finish

* Remove cursed version hack 😉

* Finish for real

* Add missing header

* Clarify a comment

* Fix tests

* Use Gradle's own *Elements and remove -dev jars

* Fix maven test

* Put mappingsFinal onto runtimeClasspath instead of implementation

* Make non-mod dependencies work with the legacy pom magic too

* Be a bit more clever when removing dev artifacts
This commit is contained in:
Juuxel 2021-09-05 18:08:16 +03:00 committed by GitHub
parent b1b395cedf
commit 08f055489b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
20 changed files with 134 additions and 104 deletions

View file

@ -73,7 +73,7 @@ public class LoomGradlePlugin implements BootstrappedPlugin {
}
// Apply default plugins
project.apply(ImmutableMap.of("plugin", "java"));
project.apply(ImmutableMap.of("plugin", "java-library"));
project.apply(ImmutableMap.of("plugin", "eclipse"));
project.apply(ImmutableMap.of("plugin", "idea"));

View file

@ -174,4 +174,14 @@ public interface LoomGradleExtensionAPI {
getDeprecationHelper().replaceWithInLoom0_11("customManifest", "customMinecraftManifest");
return getCustomMinecraftManifest().getOrNull();
}
/**
* If true, Loom will replace the {@code -dev} jars in the {@code *Elements} configurations
* with remapped outgoing variants.
*
* <p>Will only apply if {@link #getRemapArchives()} is also true.
*
* @return the property controlling the setup of remapped variants
*/
Property<Boolean> getSetupRemappedVariants();
}

View file

@ -25,14 +25,12 @@
package net.fabricmc.loom.configuration;
import org.gradle.api.Project;
import org.gradle.api.artifacts.ConfigurationContainer;
import org.gradle.api.plugins.JavaPlugin;
import org.gradle.api.plugins.JavaPluginConvention;
import org.gradle.api.tasks.SourceSet;
import org.gradle.api.tasks.javadoc.Javadoc;
import org.gradle.jvm.tasks.Jar;
import net.fabricmc.loom.extension.MixinApExtension;
import net.fabricmc.loom.LoomGradleExtension;
import net.fabricmc.loom.build.mixin.JavaApInvoker;
import net.fabricmc.loom.build.mixin.KaptApInvoker;
@ -41,6 +39,7 @@ import net.fabricmc.loom.configuration.ide.SetupIntelijRunConfigs;
import net.fabricmc.loom.configuration.providers.LaunchProvider;
import net.fabricmc.loom.configuration.providers.MinecraftProviderImpl;
import net.fabricmc.loom.configuration.providers.mappings.MappingsProviderImpl;
import net.fabricmc.loom.extension.MixinApExtension;
import net.fabricmc.loom.util.Constants;
public final class CompileConfiguration {
@ -48,8 +47,6 @@ public final class CompileConfiguration {
}
public static void setupConfigurations(Project project) {
final ConfigurationContainer configurations = project.getConfigurations();
LoomGradleExtension extension = LoomGradleExtension.get(project);
extension.createLazyConfiguration(Constants.Configurations.MOD_COMPILE_CLASSPATH).configure(configuration -> configuration.setTransitive(true));
@ -76,11 +73,18 @@ public final class CompileConfiguration {
extension.createLazyConfiguration(entry.getRemappedConfiguration())
.configure(configuration -> configuration.setTransitive(false));
extendsFrom(entry.getTargetConfiguration(configurations), entry.getRemappedConfiguration(), project);
if (entry.isOnModCompileClasspath()) {
if (entry.compileClasspath()) {
extendsFrom(Constants.Configurations.MOD_COMPILE_CLASSPATH, entry.sourceConfiguration(), project);
extendsFrom(Constants.Configurations.MOD_COMPILE_CLASSPATH_MAPPED, entry.getRemappedConfiguration(), project);
extendsFrom(JavaPlugin.COMPILE_CLASSPATH_CONFIGURATION_NAME, entry.getRemappedConfiguration(), project);
}
if (entry.runtimeClasspath()) {
extendsFrom(JavaPlugin.RUNTIME_CLASSPATH_CONFIGURATION_NAME, entry.getRemappedConfiguration(), project);
}
if (entry.hasConsumerConfiguration()) {
extendsFrom(entry.consumerConfiguration(), entry.sourceConfiguration(), project);
}
}
@ -92,7 +96,7 @@ public final class CompileConfiguration {
extendsFrom(Constants.Configurations.LOADER_DEPENDENCIES, Constants.Configurations.MINECRAFT_DEPENDENCIES, project);
extendsFrom(Constants.Configurations.MINECRAFT_NAMED, Constants.Configurations.LOADER_DEPENDENCIES, project);
extendsFrom(JavaPlugin.IMPLEMENTATION_CONFIGURATION_NAME, Constants.Configurations.MAPPINGS_FINAL, project);
extendsFrom(JavaPlugin.RUNTIME_CLASSPATH_CONFIGURATION_NAME, Constants.Configurations.MAPPINGS_FINAL, project);
extendsFrom(JavaPlugin.RUNTIME_CLASSPATH_CONFIGURATION_NAME, Constants.Configurations.LOOM_DEVELOPMENT_DEPENDENCIES, project);
extendsFrom(JavaPlugin.TEST_RUNTIME_CLASSPATH_CONFIGURATION_NAME, Constants.Configurations.LOOM_DEVELOPMENT_DEPENDENCIES, project);

View file

@ -24,9 +24,12 @@
package net.fabricmc.loom.configuration;
import java.lang.reflect.Method;
import java.util.HashSet;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;
import groovy.util.Node;
import org.gradle.api.Project;
@ -34,43 +37,66 @@ import org.gradle.api.artifacts.Configuration;
import org.gradle.api.artifacts.Dependency;
import org.gradle.api.artifacts.ExcludeRule;
import org.gradle.api.artifacts.ModuleDependency;
import org.gradle.api.plugins.JavaPlugin;
import org.gradle.api.publish.Publication;
import org.gradle.api.publish.PublishingExtension;
import net.fabricmc.loom.util.Constants;
import net.fabricmc.loom.LoomGradleExtension;
import net.fabricmc.loom.util.GroovyXmlUtil;
public final class MavenPublication {
private static final Map<String, String> CONFIGURATION_TO_SCOPE = Map.of(
JavaPlugin.API_ELEMENTS_CONFIGURATION_NAME, "compile",
JavaPlugin.RUNTIME_ELEMENTS_CONFIGURATION_NAME, "runtime"
);
private MavenPublication() {
}
public static void configure(Project project) {
project.afterEvaluate((p) -> {
for (RemappedConfigurationEntry entry : Constants.MOD_COMPILE_ENTRIES) {
if (!entry.hasMavenScope()) {
continue;
}
AtomicBoolean reportedDeprecation = new AtomicBoolean(false);
Configuration compileModsConfig = p.getConfigurations().getByName(entry.sourceConfiguration());
CONFIGURATION_TO_SCOPE.forEach((configurationName, scope) -> {
Configuration config = p.getConfigurations().getByName(configurationName);
// add modsCompile to maven-publish
PublishingExtension mavenPublish = p.getExtensions().findByType(PublishingExtension.class);
if (mavenPublish != null) {
processEntry(entry, compileModsConfig, mavenPublish);
processEntry(project, scope, config, mavenPublish, reportedDeprecation);
}
}
});
});
}
private static void processEntry(RemappedConfigurationEntry entry, Configuration compileModsConfig, PublishingExtension mavenPublish) {
private static boolean hasSoftwareComponent(Publication publication) {
try {
Method getComponent = publication.getClass().getMethod("getComponent");
return getComponent.invoke(publication) != null;
} catch (ReflectiveOperationException e) {
// our hacks have broken!
return false;
}
}
// TODO: Remove this in Loom 0.12
private static void processEntry(Project project, String scope, Configuration config, PublishingExtension mavenPublish, AtomicBoolean reportedDeprecation) {
mavenPublish.publications((publications) -> {
for (Publication publication : publications) {
if (!(publication instanceof org.gradle.api.publish.maven.MavenPublication)) {
if (!(publication instanceof org.gradle.api.publish.maven.MavenPublication mavenPublication)) {
continue;
}
((org.gradle.api.publish.maven.MavenPublication) publication).pom((pom) -> pom.withXml((xml) -> {
if (hasSoftwareComponent(publication)) {
continue;
} else if (!reportedDeprecation.get()) {
var deprecationHelper = LoomGradleExtension.get(project).getDeprecationHelper();
deprecationHelper.warn("Loom is applying dependency data manually to publications instead of using a software component (from(components[\"java\"])). This is deprecated and will be removed in Loom 0.12.");
reportedDeprecation.set(true);
}
mavenPublication.pom((pom) -> pom.withXml((xml) -> {
Node dependencies = GroovyXmlUtil.getOrCreateNode(xml.asNode(), "dependencies");
Set<String> foundArtifacts = new HashSet<>();
@ -83,7 +109,7 @@ public final class MavenPublication {
}
});
for (Dependency dependency : compileModsConfig.getAllDependencies()) {
for (Dependency dependency : config.getAllDependencies()) {
if (foundArtifacts.contains(dependency.getGroup() + ":" + dependency.getName())) {
continue;
}
@ -92,7 +118,7 @@ public final class MavenPublication {
depNode.appendNode("groupId", dependency.getGroup());
depNode.appendNode("artifactId", dependency.getName());
depNode.appendNode("version", dependency.getVersion());
depNode.appendNode("scope", entry.mavenScope());
depNode.appendNode("scope", scope);
if (!(dependency instanceof ModuleDependency)) {
continue;

View file

@ -31,6 +31,8 @@ import org.gradle.api.Action;
import org.gradle.api.Project;
import org.gradle.api.Task;
import org.gradle.api.UnknownTaskException;
import org.gradle.api.artifacts.Configuration;
import org.gradle.api.artifacts.dsl.ArtifactHandler;
import org.gradle.api.plugins.JavaPlugin;
import org.gradle.api.tasks.bundling.AbstractArchiveTask;
import org.jetbrains.annotations.ApiStatus;
@ -54,6 +56,35 @@ public class RemapConfiguration {
public static void setupDefaultRemap(Project project) {
setupRemap(project, true, DEFAULT_JAR_TASK_NAME, DEFAULT_SOURCES_JAR_TASK_NAME, DEFAULT_REMAP_JAR_TASK_NAME, DEFAULT_REMAP_SOURCES_JAR_TASK_NAME, DEFAULT_REMAP_ALL_JARS_TASK_NAME, DEFAULT_REMAP_ALL_SOURCES_TASK_NAME);
LoomGradleExtension extension = LoomGradleExtension.get(project);
extension.getSetupRemappedVariants().finalizeValue();
if (extension.getSetupRemappedVariants().get()) {
ArtifactHandler artifacts = project.getArtifacts();
project.getTasks().named(DEFAULT_REMAP_JAR_TASK_NAME, task -> {
artifacts.add(JavaPlugin.API_ELEMENTS_CONFIGURATION_NAME, task);
artifacts.add(JavaPlugin.RUNTIME_ELEMENTS_CONFIGURATION_NAME, task);
});
project.getTasks().named(DEFAULT_REMAP_SOURCES_JAR_TASK_NAME, RemapSourcesJarTask.class, task -> {
var artifact = artifacts.add(JavaPlugin.SOURCES_ELEMENTS_CONFIGURATION_NAME, task.getOutput());
// Remove the existing artifact that does not run remapSourcesJar.
// It doesn't seem to hurt, but I'm not sure if the file-level duplicates cause issues.
Configuration configuration = project.getConfigurations().getByName(JavaPlugin.SOURCES_ELEMENTS_CONFIGURATION_NAME);
configuration.getArtifacts().removeIf(a -> a != artifact && artifact.getFile().equals(a.getFile()));
});
// Remove -dev jars from the default jar task
for (String configurationName : new String[] { JavaPlugin.API_ELEMENTS_CONFIGURATION_NAME, JavaPlugin.RUNTIME_ELEMENTS_CONFIGURATION_NAME }) {
Configuration configuration = project.getConfigurations().getByName(configurationName);
configuration.getArtifacts().removeIf(artifact -> {
Task jarTask = project.getTasks().getByName(DEFAULT_JAR_TASK_NAME);
// if the artifact is a -dev jar and "builtBy jar"
return "dev".equals(artifact.getClassifier()) && artifact.getBuildDependencies().getDependencies(null).contains(jarTask);
});
}
}
}
@ApiStatus.Experimental // This is only an api if you squint really hard, expect it to explode every 5 mins. If you must call in afterEvaluate on all projects

View file

@ -28,13 +28,13 @@ import org.gradle.api.artifacts.ConfigurationContainer;
import org.gradle.api.plugins.JavaPlugin;
import org.jetbrains.annotations.Nullable;
public record RemappedConfigurationEntry(String sourceConfiguration, String targetConfiguration, boolean isOnModCompileClasspath, String mavenScope, @Nullable String replacedWith) {
public RemappedConfigurationEntry(String sourceConfiguration, String targetConfiguration, boolean isOnModCompileClasspath, String mavenScope) {
this(sourceConfiguration, targetConfiguration, isOnModCompileClasspath, mavenScope, null);
public record RemappedConfigurationEntry(String sourceConfiguration, String targetConfiguration, boolean compileClasspath, boolean runtimeClasspath, String consumerConfiguration, @Nullable String replacedWith) {
public RemappedConfigurationEntry(String sourceConfiguration, String targetConfiguration, boolean compileClasspath, boolean runtimeClasspath, String consumerConfiguration) {
this(sourceConfiguration, targetConfiguration, compileClasspath, runtimeClasspath, consumerConfiguration, null);
}
public boolean hasMavenScope() {
return mavenScope != null && !mavenScope.isEmpty();
public boolean hasConsumerConfiguration() {
return consumerConfiguration != null && !consumerConfiguration.isEmpty();
}
public String getRemappedConfiguration() {

View file

@ -33,9 +33,9 @@ import org.gradle.api.file.RegularFileProperty;
import org.gradle.api.provider.ListProperty;
import org.gradle.api.provider.Property;
import net.fabricmc.loom.api.LoomGradleExtensionAPI;
import net.fabricmc.loom.api.MixinApExtensionAPI;
import net.fabricmc.loom.api.decompilers.LoomDecompiler;
import net.fabricmc.loom.api.LoomGradleExtensionAPI;
import net.fabricmc.loom.configuration.ide.RunConfigSettings;
import net.fabricmc.loom.configuration.processors.JarProcessor;
import net.fabricmc.loom.configuration.providers.mappings.GradleMappingContext;
@ -56,6 +56,7 @@ public abstract class LoomGradleExtensionApiImpl implements LoomGradleExtensionA
protected final Property<Boolean> shareCaches;
protected final Property<Boolean> remapArchives;
protected final Property<String> customManifest;
protected final Property<Boolean> setupRemappedVariants;
private NamedDomainObjectContainer<RunConfigSettings> runConfigs;
@ -73,6 +74,8 @@ public abstract class LoomGradleExtensionApiImpl implements LoomGradleExtensionA
this.remapArchives = project.getObjects().property(Boolean.class)
.convention(true);
this.customManifest = project.getObjects().property(String.class);
this.setupRemappedVariants = project.getObjects().property(Boolean.class)
.convention(true);
this.deprecationHelper = new DeprecationHelper.ProjectBased(project);
}
@ -140,6 +143,11 @@ public abstract class LoomGradleExtensionApiImpl implements LoomGradleExtensionA
return customManifest;
}
@Override
public Property<Boolean> getSetupRemappedVariants() {
return setupRemappedVariants;
}
protected abstract Project getProject();
protected abstract LoomFiles getFiles();

View file

@ -131,4 +131,10 @@ public class MinecraftGradleExtension implements LoomGradleExtensionAPI {
reportDeprecation();
return parent.getCustomMinecraftManifest();
}
@Override
public Property<Boolean> getSetupRemappedVariants() {
reportDeprecation();
return parent.getSetupRemappedVariants();
}
}

View file

@ -45,6 +45,7 @@ import org.gradle.api.Project;
import org.gradle.api.artifacts.Configuration;
import org.gradle.api.file.FileCollection;
import org.gradle.api.file.RegularFileProperty;
import org.gradle.api.plugins.JavaPlugin;
import org.gradle.api.provider.Property;
import org.gradle.api.tasks.Input;
import org.gradle.api.tasks.InputFile;
@ -233,7 +234,7 @@ public class RemapJarTask extends Jar {
FileCollection files = this.classpath;
if (files == null) {
files = getProject().getConfigurations().getByName("compileClasspath");
files = getProject().getConfigurations().getByName(JavaPlugin.COMPILE_CLASSPATH_CONFIGURATION_NAME);
}
return files.getFiles().stream()

View file

@ -44,14 +44,16 @@ public class Constants {
public static final int ASM_VERSION = Opcodes.ASM9;
public static final List<RemappedConfigurationEntry> MOD_COMPILE_ENTRIES = ImmutableList.of(
new RemappedConfigurationEntry("modApi", JavaPlugin.API_CONFIGURATION_NAME, true, "compile"),
new RemappedConfigurationEntry("modImplementation", JavaPlugin.IMPLEMENTATION_CONFIGURATION_NAME, true, "runtime"),
new RemappedConfigurationEntry("modRuntime", JavaPlugin.RUNTIME_ONLY_CONFIGURATION_NAME, false, "", "modRuntimeOnly"),
new RemappedConfigurationEntry("modCompileOnly", JavaPlugin.COMPILE_ONLY_CONFIGURATION_NAME, true, ""),
new RemappedConfigurationEntry("modCompileOnlyApi", JavaPlugin.COMPILE_ONLY_CONFIGURATION_NAME, true, "compile"),
new RemappedConfigurationEntry("modRuntimeOnly", JavaPlugin.RUNTIME_ONLY_CONFIGURATION_NAME, false, "runtime")
new RemappedConfigurationEntry("modApi", JavaPlugin.API_CONFIGURATION_NAME, true, true, JavaPlugin.API_ELEMENTS_CONFIGURATION_NAME),
new RemappedConfigurationEntry("modImplementation", JavaPlugin.IMPLEMENTATION_CONFIGURATION_NAME, true, true, JavaPlugin.RUNTIME_ELEMENTS_CONFIGURATION_NAME),
new RemappedConfigurationEntry("modRuntime", JavaPlugin.RUNTIME_ONLY_CONFIGURATION_NAME, false, true, "", "modRuntimeOnly"),
new RemappedConfigurationEntry("modCompileOnly", JavaPlugin.COMPILE_ONLY_CONFIGURATION_NAME, true, false, ""),
new RemappedConfigurationEntry("modCompileOnlyApi", JavaPlugin.COMPILE_ONLY_API_CONFIGURATION_NAME, true, false, JavaPlugin.API_ELEMENTS_CONFIGURATION_NAME),
new RemappedConfigurationEntry("modRuntimeOnly", JavaPlugin.RUNTIME_ONLY_CONFIGURATION_NAME, false, true, JavaPlugin.RUNTIME_ELEMENTS_CONFIGURATION_NAME)
);
public static final String SOFTWARE_COMPONENT_NAME = "loom";
private Constants() {
}

View file

@ -76,13 +76,7 @@ jar {
publishing {
publications {
mavenJava(MavenPublication) {
// add all the jars that should be included when publishing to maven
artifact(remapJar) {
builtBy remapJar
}
artifact(sourcesJar) {
builtBy remapSourcesJar
}
from components.java
}
}

View file

@ -72,13 +72,7 @@ jar {
publishing {
publications {
mavenJava(MavenPublication) {
// add all the jars that should be included when publishing to maven
artifact(remapJar) {
builtBy remapJar
}
artifact(sourcesJar) {
builtBy remapSourcesJar
}
from components.java
}
}

View file

@ -76,13 +76,7 @@ loom {
publishing {
publications {
mavenJava(MavenPublication) {
// add all the jars that should be included when publishing to maven
artifact(remapJar) {
builtBy remapJar
}
artifact(sourcesJar) {
builtBy remapSourcesJar
}
from components.java
}
}

View file

@ -80,13 +80,7 @@ jar {
publishing {
publications {
mavenJava(MavenPublication) {
// add all the jars that should be included when publishing to maven
artifact(remapJar) {
builtBy remapJar
}
artifact(sourcesJar) {
builtBy remapSourcesJar
}
from components.java
}
}

View file

@ -30,16 +30,11 @@ java {
publishing {
publications {
mavenJava(MavenPublication) {
from components.java
artifact(remapJar) {
builtBy remapJar
}
artifact(remapJar) {
builtBy remapJar
classifier "classifier"
}
artifact(sourcesJar) {
builtBy remapSourcesJar
}
}
}

View file

@ -118,13 +118,7 @@ assemble {
publishing {
publications {
mavenJava(MavenPublication) {
// add all the jars that should be included when publishing to maven
artifact(remapJar) {
builtBy remapJar
}
artifact(sourcesJar) {
builtBy remapSourcesJar
}
from components.java
}
}

View file

@ -99,13 +99,7 @@ assemble {
publishing {
publications {
mavenJava(MavenPublication) {
// add all the jars that should be included when publishing to maven
artifact(remapJar) {
builtBy remapJar
}
artifact(sourcesJar) {
builtBy remapSourcesJar
}
from components.java
}
}

View file

@ -72,13 +72,7 @@ jar {
publishing {
publications {
mavenJava(MavenPublication) {
// add all the jars that should be included when publishing to maven
artifact(remapJar) {
builtBy remapJar
}
artifact(sourcesJar) {
builtBy remapSourcesJar
}
from components.java
}
}

View file

@ -29,16 +29,11 @@ java {
publishing {
publications {
mavenJava(MavenPublication) {
artifact(remapJar) {
builtBy remapJar
}
from components.java
artifact(remapJar) {
builtBy remapJar
classifier "classifier"
}
artifact(sourcesJar) {
builtBy remapSourcesJar
}
}
}

View file

@ -72,13 +72,7 @@ jar {
publishing {
publications {
mavenJava(MavenPublication) {
// add all the jars that should be included when publishing to maven
artifact(remapJar) {
builtBy remapJar
}
artifact(sourcesJar) {
builtBy remapSourcesJar
}
from components.java
}
}