Skip to content

Commit 8453b28

Browse files
committed
Add independently-scoped dependencies to userdev config (#1003)
Will be expanded on in ForgeGradle 7/UserDev Config 4.
1 parent 14206fa commit 8453b28

File tree

6 files changed

+231
-1
lines changed

6 files changed

+231
-1
lines changed

.github/workflows/publish.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ jobs:
1111
build:
1212
uses: MinecraftForge/SharedActions/.github/workflows/gradle.yml@main
1313
with:
14-
java: 11
14+
java: 17
1515
gradle_tasks: "publish"
1616
artifact_group: "net.minecraftforge.gradle"
1717
artifact_name: "ForgeGradle"

src/common/java/net/minecraftforge/gradle/common/config/UserdevConfigV2.java

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
import net.minecraftforge.gradle.common.config.MCPConfigV1.Function;
99
import net.minecraftforge.gradle.common.util.Utils;
10+
import org.jetbrains.annotations.ApiStatus;
1011
import org.jetbrains.annotations.Nullable;
1112

1213
import java.io.ByteArrayInputStream;
@@ -37,6 +38,10 @@ public static UserdevConfigV2 get(byte[] data) {
3738
private List<String> universalFilters;
3839
@Nullable
3940
public List<String> modules; // Modules passed to --module-path
41+
@Nullable
42+
@Deprecated
43+
@ApiStatus.ScheduledForRemoval(inVersion = "V3")
44+
public ScopedDependencies extraDependencies;
4045
private String sourceFileCharset = StandardCharsets.UTF_8.name();
4146

4247
public void setNotchObf(boolean value) {
@@ -93,4 +98,40 @@ public String setData(String name, String path) {
9398
return this.data.put(name, path);
9499
}
95100
}
101+
102+
private void addRuntimeDependency(String dependency) {
103+
if (this.extraDependencies == null)
104+
extraDependencies = new ScopedDependencies();
105+
106+
if (this.extraDependencies.runtimeOnly == null)
107+
this.extraDependencies.runtimeOnly = new ArrayList<>();
108+
109+
this.extraDependencies.runtimeOnly.add(dependency);
110+
}
111+
112+
private void addCompileDependency(String dependency) {
113+
if (this.extraDependencies == null)
114+
extraDependencies = new ScopedDependencies();
115+
116+
if (this.extraDependencies.compileOnly == null)
117+
this.extraDependencies.compileOnly = new ArrayList<>();
118+
119+
this.extraDependencies.compileOnly.add(dependency);
120+
}
121+
122+
private void addAnnotationProcessorDependency(String dependency) {
123+
if (this.extraDependencies == null)
124+
extraDependencies = new ScopedDependencies();
125+
126+
if (this.extraDependencies.annotationProcessor == null)
127+
this.extraDependencies.annotationProcessor = new ArrayList<>();
128+
129+
this.extraDependencies.annotationProcessor.add(dependency);
130+
}
131+
132+
public static class ScopedDependencies {
133+
public @Nullable List<String> runtimeOnly;
134+
public @Nullable List<String> compileOnly;
135+
public @Nullable List<String> annotationProcessor;
136+
}
96137
}

src/patcher/java/net/minecraftforge/gradle/patcher/tasks/GenerateUserdevConfig.java

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,15 @@
1919
import org.gradle.api.DefaultTask;
2020
import org.gradle.api.NamedDomainObjectContainer;
2121
import org.gradle.api.Project;
22+
import org.gradle.api.artifacts.Dependency;
2223
import org.gradle.api.file.ConfigurableFileCollection;
2324
import org.gradle.api.file.RegularFileProperty;
2425
import org.gradle.api.model.ObjectFactory;
2526
import org.gradle.api.provider.ListProperty;
2627
import org.gradle.api.provider.MapProperty;
2728
import org.gradle.api.provider.Property;
2829
import org.gradle.api.provider.Provider;
30+
import org.gradle.api.provider.ProviderConvertible;
2931
import org.gradle.api.tasks.Input;
3032
import org.gradle.api.tasks.InputFiles;
3133
import org.gradle.api.tasks.Optional;
@@ -38,6 +40,7 @@
3840
import java.io.IOException;
3941
import java.nio.charset.Charset;
4042
import java.nio.charset.StandardCharsets;
43+
import java.util.ArrayList;
4144
import java.util.Arrays;
4245
import java.util.Collection;
4346
import java.util.List;
@@ -51,6 +54,9 @@ public abstract class GenerateUserdevConfig extends DefaultTask {
5154
private DataFunction processor;
5255
private final MapProperty<String, File> processorData;
5356
private final Property<String> sourceFileEncoding;
57+
private final ListProperty<String> extraRuntimeDeps;
58+
private final ListProperty<String> extraCompileDeps;
59+
private final ListProperty<String> extraAnnotationProcessorDeps;
5460

5561
private boolean notchObf = false;
5662

@@ -68,6 +74,10 @@ public GenerateUserdevConfig(final Project project) {
6874

6975
processorData = objects.mapProperty(String.class, File.class);
7076

77+
extraRuntimeDeps = objects.listProperty(String.class);
78+
extraCompileDeps = objects.listProperty(String.class);
79+
extraAnnotationProcessorDeps = objects.listProperty(String.class);
80+
7181
getOutput().convention(getProject().getLayout().getBuildDirectory().dir(getName()).map(d -> d.file("output.json")));
7282
}
7383

@@ -103,6 +113,10 @@ public void apply() throws IOException {
103113
json.setNotchObf(notchObf);
104114
json.setSourceFileCharset(getSourceFileEncoding().get());
105115
getUniversalFilters().get().forEach(json::addUniversalFilter);
116+
json.extraDependencies = new UserdevConfigV2.ScopedDependencies();
117+
json.extraDependencies.compileOnly = new ArrayList<>(getExtraCompileDeps().get());
118+
json.extraDependencies.runtimeOnly = new ArrayList<>(getExtraRuntimeDeps().get());
119+
json.extraDependencies.annotationProcessor = new ArrayList<>(getExtraAnnotationProcessorDeps().get());
106120
}
107121

108122
Files.write(Utils.GSON.toJson(json).getBytes(StandardCharsets.UTF_8), getOutput().get().getAsFile());
@@ -177,6 +191,72 @@ private boolean isV2() {
177191
@Input
178192
@Optional
179193
public abstract ListProperty<String> getSRGLines();
194+
195+
private static String depToString(Dependency value) {
196+
String group = value.getGroup();
197+
if (group == null)
198+
throw new IllegalArgumentException("Dependency group cannot be null");
199+
200+
String version = value.getVersion();
201+
if (version == null)
202+
throw new IllegalArgumentException("Dependency version cannot be null");
203+
204+
return group + ':' + value.getName() + ':' + version;
205+
}
206+
207+
@Input
208+
@Optional
209+
public ListProperty<String> getExtraCompileDeps() {
210+
return this.extraCompileDeps;
211+
}
212+
213+
public final void addCompileDependency(Dependency value) {
214+
this.getExtraCompileDeps().add(depToString(value));
215+
}
216+
217+
public final void addCompileDependency(Provider<? extends Dependency> value) {
218+
this.addCompileDependency(value.get());
219+
}
220+
221+
public final void addCompileDependency(ProviderConvertible<? extends Dependency> value) {
222+
this.addCompileDependency(value.asProvider());
223+
}
224+
225+
@Input
226+
@Optional
227+
public ListProperty<String> getExtraRuntimeDeps() {
228+
return this.extraRuntimeDeps;
229+
}
230+
231+
public final void addRuntimeDependency(Dependency value) {
232+
this.getExtraRuntimeDeps().add(depToString(value));
233+
}
234+
235+
public final void addRuntimeDependency(Provider<? extends Dependency> value) {
236+
this.addRuntimeDependency(value.get());
237+
}
238+
239+
public final void addRuntimeDependency(ProviderConvertible<? extends Dependency> value) {
240+
this.addRuntimeDependency(value.asProvider());
241+
}
242+
243+
@Input
244+
@Optional
245+
public ListProperty<String> getExtraAnnotationProcessorDeps() {
246+
return this.extraAnnotationProcessorDeps;
247+
}
248+
249+
public final void addAnnotationProcessorDependency(Dependency value) {
250+
this.getExtraAnnotationProcessorDeps().add(depToString(value));
251+
}
252+
253+
public final void addAnnotationProcessorDependency(Provider<? extends Dependency> value) {
254+
this.addAnnotationProcessorDependency(value.get());
255+
}
256+
257+
public final void addAnnotationProcessorDependency(ProviderConvertible<? extends Dependency> value) {
258+
this.addAnnotationProcessorDependency(value.asProvider());
259+
}
180260

181261
public NamedDomainObjectContainer<RunConfig> runs(@SuppressWarnings("rawtypes") Closure closure) {
182262
return runs.configure(closure);

src/userdev/java/net/minecraftforge/gradle/userdev/DependencyManagementExtension.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ public class DependencyManagementExtension extends GroovyObjectSupport {
4343
private final DependencyRemapper remapper;
4444
private final DeobfuscatingRepo deobfuscatingRepo;
4545
private final ArtifactRepository repository;
46+
private final Property<Boolean> inheritAnnotationProcessor;
4647

4748
public DependencyManagementExtension(Project project, DependencyRemapper remapper, DeobfuscatingRepo deobfuscatingRepo) {
4849
this.project = project;
@@ -51,6 +52,7 @@ public DependencyManagementExtension(Project project, DependencyRemapper remappe
5152
this.repository = new BaseRepo.Builder()
5253
.add(deobfuscatingRepo)
5354
.attach(project, "bundled_deobf_repo");
55+
this.inheritAnnotationProcessor = project.getObjects().property(Boolean.class).convention(false);
5456
}
5557

5658
public DeobfuscatingRepo getDeobfuscatingRepo() {
@@ -61,6 +63,10 @@ public ArtifactRepository getRepository() {
6163
return repository;
6264
}
6365

66+
public Property<Boolean> getInheritAnnotationProcessor() {
67+
return inheritAnnotationProcessor;
68+
}
69+
6470
@SuppressWarnings("unused")
6571
public Dependency deobf(Object dependency) {
6672
//noinspection DataFlowIssue -- null closure is allowed here
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
/*
2+
* Copyright (c) Forge Development LLC and contributors
3+
* SPDX-License-Identifier: LGPL-2.1-only
4+
*/
5+
6+
package net.minecraftforge.gradle.userdev;
7+
8+
import org.gradle.api.Project;
9+
import org.gradle.api.artifacts.Configuration;
10+
import org.gradle.api.artifacts.Dependency;
11+
import org.gradle.api.artifacts.ExternalModuleDependency;
12+
import org.gradle.api.plugins.JavaPluginExtension;
13+
import org.gradle.api.tasks.SourceSet;
14+
import org.jetbrains.annotations.Nullable;
15+
16+
import java.util.Objects;
17+
import java.util.function.Function;
18+
19+
final class ExtraDependenciesHandler {
20+
private ExtraDependenciesHandler() { }
21+
22+
enum Scope {
23+
RUNTIME(SourceSet::getRuntimeClasspathConfigurationName, SourceSet::getRuntimeClasspathConfigurationName, SourceSet::getRuntimeOnlyConfigurationName),
24+
COMPILE(SourceSet::getCompileClasspathConfigurationName, SourceSet::getCompileClasspathConfigurationName, SourceSet::getCompileOnlyConfigurationName),
25+
ANNOTATION_PROCESSOR(SourceSet::getAnnotationProcessorConfigurationName, SourceSet::getRuntimeClasspathConfigurationName, SourceSet::getAnnotationProcessorConfigurationName);
26+
27+
private final Function<SourceSet, String> classpath;
28+
private final Function<SourceSet, String> condition;
29+
private final Function<SourceSet, String> declarable;
30+
31+
Scope(Function<SourceSet, String> classpath, Function<SourceSet, String> condition, Function<SourceSet, String> declarable) {
32+
this.classpath = classpath;
33+
this.condition = condition;
34+
this.declarable = declarable;
35+
}
36+
37+
// Check this for dependency
38+
private @Nullable Configuration getClasspathConfiguration(Project project, SourceSet sourceSet) {
39+
return project.getConfigurations().findByName(this.classpath.apply(sourceSet));
40+
}
41+
42+
// Check this for Forge
43+
private @Nullable Configuration getConditionConfiguration(Project project, SourceSet sourceSet) {
44+
return project.getConfigurations().findByName(this.condition.apply(sourceSet));
45+
}
46+
47+
// Add dependency to this
48+
private @Nullable Configuration getDeclarableConfiguration(Project project, SourceSet sourceSet) {
49+
return project.getConfigurations().findByName(this.declarable.apply(sourceSet));
50+
}
51+
}
52+
53+
static void handle(Project project, Scope scope, String group, String name, String artifact) {
54+
JavaPluginExtension java = project.getExtensions().getByType(JavaPluginExtension.class);
55+
for (SourceSet sourceSet : java.getSourceSets()) {
56+
if (isMissingDependency(scope.getConditionConfiguration(project, sourceSet), group, name))
57+
continue;
58+
59+
ExternalModuleDependency dependency = project.getDependencyFactory().create(artifact);
60+
if (isMissingDependency(scope.getClasspathConfiguration(project, sourceSet), dependency)) {
61+
Configuration configuration = scope.getDeclarableConfiguration(project, sourceSet);
62+
if (configuration == null) continue;
63+
64+
configuration.getDependencies().add(dependency);
65+
}
66+
}
67+
}
68+
69+
private static boolean isMissingDependency(@Nullable Configuration configuration, String group, String name) {
70+
return configuration != null && configuration.getAllDependencies().matching(
71+
dependency -> group.equals(dependency.getGroup()) && name.equals(dependency.getName())
72+
).isEmpty();
73+
}
74+
75+
private static boolean isMissingDependency(@Nullable Configuration configuration, Dependency dependency) {
76+
return configuration != null && configuration.getAllDependencies().matching(
77+
d -> Objects.equals(d.getGroup(), dependency.getGroup()) && Objects.equals(dependency.getName(), d.getName())
78+
).isEmpty();
79+
}
80+
}

src/userdev/java/net/minecraftforge/gradle/userdev/MinecraftUserRepo.java

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,7 @@ public void validate(Configuration cfg, Map<String, RunConfig> runs, ExtractNati
196196

197197
//Maven POMs can't self-reference apparently, so we have to add any deps that are self referential.
198198
Patcher patcher = parent;
199+
String mixinExtras = null;
199200
while (patcher != null) {
200201
patcher.getLibraries().stream().map(Artifact::from)
201202
.filter(e -> GROUP.equals(e.getGroup()) && NAME.equals(e.getName()))
@@ -217,6 +218,28 @@ public void validate(Configuration cfg, Map<String, RunConfig> runs, ExtractNati
217218
}
218219
cfg.getDependencies().add(_dep);
219220
});
221+
222+
if (patcher.configv2 != null && patcher.configv2.extraDependencies != null) {
223+
if (patcher.configv2.extraDependencies.runtimeOnly != null) {
224+
for (String artifact : patcher.configv2.extraDependencies.runtimeOnly) {
225+
ExtraDependenciesHandler.handle(project, ExtraDependenciesHandler.Scope.RUNTIME, GROUP, NAME, artifact);
226+
}
227+
}
228+
229+
if (patcher.configv2.extraDependencies.compileOnly != null) {
230+
for (String artifact : patcher.configv2.extraDependencies.compileOnly) {
231+
ExtraDependenciesHandler.handle(project, ExtraDependenciesHandler.Scope.COMPILE, GROUP, NAME, artifact);
232+
}
233+
}
234+
235+
DependencyManagementExtension fg = project.getExtensions().getByType(DependencyManagementExtension.class);
236+
if (fg.getInheritAnnotationProcessor().getOrElse(false) && patcher.configv2.extraDependencies.annotationProcessor != null) {
237+
for (String artifact : patcher.configv2.extraDependencies.annotationProcessor) {
238+
ExtraDependenciesHandler.handle(project, ExtraDependenciesHandler.Scope.ANNOTATION_PROCESSOR, GROUP, NAME, artifact);
239+
}
240+
}
241+
}
242+
220243
patcher = patcher.getParent();
221244
}
222245

0 commit comments

Comments
 (0)