Skip to content

Commit

Permalink
Initial work on a bunch of improvements with respects to handling of …
Browse files Browse the repository at this point in the history
…Definition, Specification, and NeoForm
  • Loading branch information
marchermans committed Jun 21, 2024
1 parent 66ba46e commit 1776129
Show file tree
Hide file tree
Showing 111 changed files with 1,095 additions and 771 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import net.neoforged.gradle.common.runs.run.RunImpl;
import net.neoforged.gradle.common.runs.tasks.RunsReport;
import net.neoforged.gradle.common.runtime.definition.CommonRuntimeDefinition;
import net.neoforged.gradle.common.runtime.extensions.DefaultRuntimesContainer;
import net.neoforged.gradle.common.runtime.extensions.RuntimesExtension;
import net.neoforged.gradle.common.runtime.naming.OfficialNamingChannelConfigurator;
import net.neoforged.gradle.common.tasks.CleanCache;
Expand All @@ -35,6 +36,7 @@
import net.neoforged.gradle.dsl.common.runs.run.Run;
import net.neoforged.gradle.dsl.common.runs.run.RunDevLogin;
import net.neoforged.gradle.dsl.common.runs.type.RunType;
import net.neoforged.gradle.dsl.common.runtime.extensions.RuntimesContainer;
import net.neoforged.gradle.dsl.common.util.ConfigurationUtils;
import net.neoforged.gradle.dsl.common.util.NamingConstants;
import net.neoforged.gradle.util.UrlConstants;
Expand Down Expand Up @@ -70,8 +72,6 @@ public class CommonProjectPlugin implements Plugin<Project> {

@Override
public void apply(Project project) {
project.getObjects().

//Apply the evaluation extension to monitor immediate execution of indirect tasks when evaluation already happened.
project.getExtensions().create(NamingConstants.Extension.EVALUATION, ProjectEvaluationExtension.class, project);

Expand All @@ -92,6 +92,7 @@ public void apply(Project project) {

final ExtensionManager extensionManager = project.getExtensions().getByType(ExtensionManager.class);
extensionManager.registerExtension("subsystems", Subsystems.class, (p) -> p.getObjects().newInstance(SubsystemsExtension.class, p));
extensionManager.registerExtension("runtimes", RuntimesContainer.class, (p) -> p.getObjects().newInstance(DefaultRuntimesContainer.class, p));

project.getExtensions().create(IdeManagementExtension.class, "ideManager", IdeManagementExtension.class, project);
project.getExtensions().create("allRuntimes", RuntimesExtension.class);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ public AccessTransformersExtension(Project project) {
this.projectDependencies = project.getDependencies();
this.projectArtifacts = project.getArtifacts();

// We have to add these after project evaluation because of dependency replacement making configurations non-lazy; adding them earlier would prevent further addition of dependencies
// We have to add these after project evaluation because of dependency replacement making configurations non-lazy; adding them earlier would prevent further addition of compileDependencies
project.afterEvaluate(p -> {
p.getConfigurations().maybeCreate(CommonProjectPlugin.ACCESS_TRANSFORMER_CONFIGURATION).fromDependencyCollector(getConsume());
p.getConfigurations().maybeCreate(CommonProjectPlugin.ACCESS_TRANSFORMER_API_CONFIGURATION).fromDependencyCollector(getConsumeApi());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ public void createTaskAndConfiguration() {
// Unfortunately, while we can hopefully rely on disambiguation rules to get us some of these, others run
// into issues. The target JVM version is the most worrying - we don't want to pull in a variant for a newer
// jvm version. We could copy DefaultJvmFeature, and search for the target version of the compile task,
// but this is difficult - we only have a feature name, not the linked source set. For this reason, we use
// but this is difficult - we only have a feature identifier, not the linked source set. For this reason, we use
// the toolchain version, which is the most likely to be correct.
attributes.attributeProvider(TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE, javaPlugin.getToolchain().getLanguageVersion().map(JavaLanguageVersion::asInt));
attributes.attribute(Usage.USAGE_ATTRIBUTE, project.getObjects().named(Usage.class, Usage.JAVA_RUNTIME));
Expand All @@ -141,7 +141,7 @@ public void createTaskAndConfiguration() {

TaskProvider<JarJar> jarJarTask = project.getTasks().register(withPrefix(JAR_JAR_TASK_NAME), net.neoforged.gradle.common.tasks.JarJar.class, jarJar -> {
jarJar.setGroup(JAR_JAR_GROUP);
jarJar.setDescription("Create a combined JAR of project and selected dependencies");
jarJar.setDescription("Create a combined JAR of project and selected compileDependencies");
jarJar.getArchiveClassifier().convention(prefix.isEmpty() ? "all" : prefix + "-all");

if (!this.getDefaultSourcesDisabled()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ public <T> void registerExtension(String name, Class<T> publicFacingType, IExten
}
}

throw new IllegalArgumentException("Property '" + String.format(EXTENSION_CHECK_PROPERTY_NAME, name) + "' is not a valid extension creator. It must be either a string of a class name implementing IExtensionCreator, or an instance of IExtensionCreator.");
throw new IllegalArgumentException("Property '" + String.format(EXTENSION_CHECK_PROPERTY_NAME, name) + "' is not a valid extension creator. It must be either a string of a class identifier implementing IExtensionCreator, or an instance of IExtensionCreator.");
}

public static void registerOverride(final Project project, final String name, final IExtensionCreator<?> creator) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import com.google.gson.JsonObject;
import net.minecraftforge.gdi.ConfigurableDSLElement;
import net.neoforged.gradle.common.tasks.MinecraftArtifactFileCacheProvider;
import net.neoforged.gradle.common.tasks.MinecraftGameArtifactProvidingTask;
import net.neoforged.gradle.common.tasks.MinecraftVersionManifestFileCacheProvider;
import net.neoforged.gradle.common.util.FileCacheUtils;
import net.neoforged.gradle.common.util.FileDownloadingUtils;
Expand All @@ -31,6 +32,7 @@
import java.util.EnumMap;
import java.util.Map;
import java.util.Objects;
import java.util.SortedSet;
import java.util.concurrent.ConcurrentHashMap;

public abstract class MinecraftArtifactCacheExtension implements ConfigurableDSLElement<MinecraftArtifactCache>, MinecraftArtifactCache {
Expand Down Expand Up @@ -127,20 +129,18 @@ public final Map<GameArtifact, TaskProvider<? extends WithOutput>> cacheGameVers

@NotNull
@Override
public NamedDomainObjectProvider<? extends WithOutput> gameArtifactTask(@NotNull NamedDomainObjectCollection<WithOutput> tasks, @NotNull GameArtifact artifact, @NotNull final String minecraftVersion) {
final MinecraftVersionAndUrl resolvedVersion = resolveVersion(minecraftVersion);

if (artifact == GameArtifact.VERSION_MANIFEST) {
return tasks.named(NamingConstants.Task.CACHE_VERSION_MANIFEST + resolvedVersion.getVersion(), MinecraftVersionManifestFileCacheProvider.class);
public NamedDomainObjectProvider<? extends WithOutput> gameArtifactTask(@NotNull NamedDomainObjectCollection<WithOutput> tasks, @NotNull GameArtifact artifact) {
final NamedDomainObjectCollection<? extends MinecraftGameArtifactProvidingTask> matchingTasks = tasks.withType(MinecraftGameArtifactProvidingTask.class)
.matching(task -> task.gameArtifact().equals(artifact));

final SortedSet<String> matchingTaskNames = matchingTasks.getNames();
if (matchingTaskNames.size() == 1) {
return matchingTasks.named(matchingTaskNames.first());
} else if (matchingTaskNames.size() > 1) {
throw new IllegalStateException("Found multiple tasks for game artifact: " + artifact);
} else {
throw new IllegalStateException("Could not find task for game artifact: " + artifact);
}

final String taskName = "%s%s%s%s".formatted(
NamingConstants.Task.CACHE_VERSION_PREFIX,
StringUtils.capitalize(artifact.getType().orElseThrow().name().toLowerCase()),
StringUtils.capitalize(artifact.getDistributionType().orElseThrow().getName().toLowerCase()),
resolvedVersion.getVersion());

return tasks.named(taskName, MinecraftArtifactFileCacheProvider.class);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ public ReplacementLogic(Project project) {
@Override
public void handleConfiguration(Configuration configuration) {
//TODO: Figure out if there is any way to do this lazily.
//TODO: Configure each runs in an immutable context, so we can't add a listener to the dependencies.
//TODO: Configure each runs in an immutable context, so we can't add a listener to the compileDependencies.
configuration.getDependencies().whenObjectAdded(dependency -> {
//We need to check if our configuration is unhandled, we can only do this here and not in the register because of way we register unhandled configurations after their creation:
//TODO: Find a better way to handle this.
Expand All @@ -68,7 +68,7 @@ public void handleConfiguration(Configuration configuration) {
return;
}

//We only support module based dependencies.
//We only support module based compileDependencies.
if (dependency instanceof ModuleDependency) {
final ModuleDependency moduleDependency = (ModuleDependency) dependency;
//Try replacing the dependency.
Expand Down Expand Up @@ -232,7 +232,7 @@ void handleDependencyReplacement(Configuration configuration, Dependency depende
}
}

//For each configuration that we target we now need to add the new dependencies to.
//For each configuration that we target we now need to add the new compileDependencies to.
for (Configuration targetConfiguration : targetConfigurations) {
//Create a dependency from the tasks that copies the raw jar to the repository.
//The sources jar is not needed here.
Expand All @@ -254,7 +254,7 @@ void handleDependencyReplacement(Configuration configuration, Dependency depende
*
* @param dependency The dependency that is being replaced.
* @param result The replacement result from one of the handlers.
* @param sourceArtifactSelectorName The name of the task that selects the source artifact.
* @param sourceArtifactSelectorName The identifier of the task that selects the source artifact.
* @param newRepoEntry The new repository entry that the dependency is being replaced with.
* @return The task that selects the source artifact from the dependency and puts it in the Ivy repository.
*/
Expand All @@ -268,7 +268,7 @@ private TaskProvider<? extends WithOutput> createOrLookupSourcesTask(Dependency
//Create a new task, using the repository to create the output.
final Repository repository = project.getExtensions().getByType(Repository.class);
return project.getTasks().register(sourceArtifactSelectorName, ArtifactFromOutput.class, artifactFromOutput -> {
artifactFromOutput.setGroup("neogradle/dependencies");
artifactFromOutput.setGroup("neogradle/compileDependencies");
artifactFromOutput.setDescription(String.format("Selects the source artifact from the %s dependency and puts it in the Ivy repository", dependency));

artifactFromOutput.getInput().set(result.getSourcesJar().flatMap(WithOutput::getOutput));
Expand All @@ -282,7 +282,7 @@ private TaskProvider<? extends WithOutput> createOrLookupSourcesTask(Dependency
*
* @param dependency The dependency that is being replaced.
* @param result The replacement result from one of the handlers.
* @param rawArtifactSelectorName The name of the task that selects the raw artifact.
* @param rawArtifactSelectorName The identifier of the task that selects the raw artifact.
* @param newRepoEntry The new repository entry that the dependency is being replaced with.
* @return The task that selects the raw artifact from the dependency and puts it in the Ivy repository.
*/
Expand All @@ -296,7 +296,7 @@ private TaskProvider<? extends WithOutput> createOrLookupRawTask(Dependency depe
// Create a new task, using the repository to create the output.
final Repository repository = project.getExtensions().getByType(Repository.class);
return project.getTasks().register(rawArtifactSelectorName, ArtifactFromOutput.class, artifactFromOutput -> {
artifactFromOutput.setGroup("neogradle/dependencies");
artifactFromOutput.setGroup("neogradle/compileDependencies");
artifactFromOutput.setDescription(String.format("Selects the raw artifact from the %s dependency and puts it in the Ivy repository", dependency));

artifactFromOutput.getInput().set(result.getRawJar().flatMap(WithOutput::getOutput));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,15 +92,15 @@ private void writeInfo(final Dependency entry) throws XMLStreamException {
// License
// TODO: deal with custom projects?
this.writer.writeEmptyElement("license");
this.writer.writeAttribute("name", "Minecraft EULA");
this.writer.writeAttribute("identifier", "Minecraft EULA");
this.writer.writeAttribute("url", "https://www.minecraft.net/en-us/eula");

// End
this.writer.writeEndElement();
}

private void writeDependencies(final Configuration dependencies) throws XMLStreamException {
this.writer.writeStartElement("dependencies");
this.writer.writeStartElement("compileDependencies");

for (final ResolvedArtifact extra : dependencies.getResolvedConfiguration().getResolvedArtifacts()) {
this.writeDependency(extra);
Expand All @@ -120,13 +120,13 @@ private void writeDependency(final ResolvedArtifact dep) throws XMLStreamExcepti
}

this.writer.writeAttribute("org", dep.getModuleVersion().getId().getGroup());
this.writer.writeAttribute("name", dep.getModuleVersion().getId().getName());
this.writer.writeAttribute("identifier", dep.getModuleVersion().getId().getName());
this.writer.writeAttribute("rev", dep.getModuleVersion().getId().getVersion());
this.writer.writeAttribute("transitive", "false");

if (hasClassifier) {
this.writer.writeEmptyElement("artifact");
this.writer.writeAttribute("name", dep.getModuleVersion().getId().getName());
this.writer.writeAttribute("identifier", dep.getModuleVersion().getId().getName());
this.writer.writeAttribute("classifier", classifier);
this.writer.writeAttribute("ext", "jar");
this.writer.writeEndElement();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@ private void writeDummyDataIfNeeded(
final Configuration dependencies,
final boolean hasSource
) throws IOException, XMLStreamException {
//Construct all paths, ensuring that the metadata file name matches the pattern we configured above in the repo metadata.
//Construct all paths, ensuring that the metadata file identifier matches the pattern we configured above in the repo metadata.
final Path jarFile = buildArtifactPath(entry);
final Path baseDir = jarFile.getParent();
final Path metaFile = baseDir.resolve(String.format("ivy-%s-ng%d.xml", entry.getVersion(), METADATA_VERSION));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ public void configureIdeaConventions(Project project, IDEA ideaConventions) {

final File DotIdeaDirectory = new File(project.getProjectDir(), ".idea");
final File GradleXml = new File(DotIdeaDirectory, "gradle.xml");
return FileUtils.contains(GradleXml, "<option name=\"delegatedBuild\" value=\"false\" />");
return FileUtils.contains(GradleXml, "<option identifier=\"delegatedBuild\" value=\"false\" />");
})
);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ protected CommonRuntimeDefinition(
public final TaskProvider<? extends WithOutput> getTask(String name) {
final String taskName = CommonRuntimeUtils.buildTaskName(this, name);
if (!taskOutputs.containsKey(taskName)) {
throw new IllegalArgumentException("No task with name " + name + " found in runtime " + specification.getVersionedName());
throw new IllegalArgumentException("No task with identifier " + name + " found in runtime " + specification.getVersionedName());
}

return taskOutputs.get(taskName);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ protected CommonRuntimeExtension(Project project) {

public static void configureCommonRuntimeTaskParameters(Runtime runtimeTask, Map<String, String> symbolicDataSources, String step, LegacySpecification spec, File runtimeDirectory) {
runtimeTask.getSymbolicDataSources().set(symbolicDataSources);
runtimeTask.getStepName().set(step);
runtimeTask.getStep().set(step);
runtimeTask.getDistribution().set(spec.getDistribution());
runtimeTask.getMinecraftVersion().set(CacheableMinecraftVersion.from(spec.getMinecraftVersion(), spec.getProject()).getFull());
runtimeTask.getRuntimeDirectory().set(runtimeDirectory);
Expand Down Expand Up @@ -140,7 +140,7 @@ private S createSpec(Action<B> configurator) {
@NotNull
public final D getByName(final String name) {
return this.definitions.computeIfAbsent(name, (n) -> {
throw new RuntimeException(String.format("Failed to find runtime with name: %s", n));
throw new RuntimeException(String.format("Failed to find runtime with identifier: %s", n));
});
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,21 @@

import net.neoforged.gradle.common.util.DelegatingDomainObjectContainer;
import net.neoforged.gradle.dsl.common.runtime.definition.Definition;
import net.neoforged.gradle.dsl.common.runtime.definition.DependencyHandler;
import net.neoforged.gradle.dsl.common.runtime.definition.Outputs;
import net.neoforged.gradle.dsl.common.runtime.extensions.RuntimesContainer;
import net.neoforged.gradle.dsl.common.runtime.spec.Specification;
import net.neoforged.gradle.dsl.common.runtime.spec.TaskTreeBuilder;
import net.neoforged.gradle.dsl.common.tasks.WithOutput;
import org.gradle.api.InvalidUserDataException;
import org.gradle.api.Project;
import org.gradle.api.tasks.TaskProvider;

public class DefaultRuntimesContainer extends DelegatingDomainObjectContainer<Definition> implements RuntimesContainer {
import javax.inject.Inject;

public abstract class DefaultRuntimesContainer extends DelegatingDomainObjectContainer<Definition> implements RuntimesContainer {

@Inject
public DefaultRuntimesContainer(Project project) {
super(project, Definition.class, name -> {
throw new InvalidUserDataException("Cannot create a runtime definition without a specification. Use register(Specification, TaskTreeBuilder) instead.");
Expand All @@ -19,7 +26,11 @@ public DefaultRuntimesContainer(Project project) {
@Override
public Definition register(Specification specification, TaskTreeBuilder builder) throws InvalidUserDataException {
final TaskTreeBuilder.BuildResult buildResult = builder.build(specification);
final Definition definition = new Definition(specification, buildResult.dependencies(), buildResult.handler());
final Definition definition = new Definition(
specification,
new DependencyHandler(buildResult.compileDependencies(), buildResult.runtimeDependencies()),
buildResult.handler(),
buildResult.outputs());

add(definition);

Expand Down
Loading

0 comments on commit 1776129

Please sign in to comment.