From 026d7fed974f6ab5afdd399b8536d52eb7005ffb Mon Sep 17 00:00:00 2001 From: Technici4n <13494793+Technici4n@users.noreply.github.com> Date: Thu, 14 Nov 2024 21:32:21 +0100 Subject: [PATCH] Allow duplicate libraries in the installer profile to make sure they always match specified tool versions --- .../neodev/NeoDevConfigurations.java | 27 ++++++++++--------- .../net/neoforged/neodev/NeoDevPlugin.java | 13 ++++++--- .../installer/CreateInstallerProfile.java | 22 ++++++++++++--- 3 files changed, 42 insertions(+), 20 deletions(-) diff --git a/buildSrc/src/main/java/net/neoforged/neodev/NeoDevConfigurations.java b/buildSrc/src/main/java/net/neoforged/neodev/NeoDevConfigurations.java index 602265f4fe..ba048dd121 100644 --- a/buildSrc/src/main/java/net/neoforged/neodev/NeoDevConfigurations.java +++ b/buildSrc/src/main/java/net/neoforged/neodev/NeoDevConfigurations.java @@ -56,6 +56,12 @@ static NeoDevConfigurations createAndSetup(Project project) { // Resolvable configurations. // + /** + * Resolved {@link #neoFormDataOnly}. + * This is used to add NeoForm to the installer libraries. + * Only the zip is used (for the mappings), not the NeoForm tools, so it's not transitive. + */ + final Configuration neoFormDataOnly; /** * Resolvable {@link #neoFormDependencies}. */ @@ -84,12 +90,6 @@ static NeoDevConfigurations createAndSetup(Project project) { * This is also used to produce the legacy classpath file for server installs. */ final Configuration launcherProfileClasspath; - /** - * Libraries that need to be downloaded and installed by the installer. - * This includes all dependencies added by NeoForge, the NeoForm archive, - * and all dependencies needed by the various tools that the installer runs. - */ - final Configuration installerProfileLibraries; // // The configurations for resolution only are declared in the build.gradle file. @@ -117,22 +117,27 @@ private NeoDevConfigurations(ConfigurationContainer configurations) { userdevCompileOnly = dependencyScope(configurations, "userdevCompileOnly"); userdevTestFixtures = dependencyScope(configurations, "userdevTestFixtures"); + neoFormDataOnly = resolvable(configurations, "neoFormDataOnly"); neoFormClasspath = resolvable(configurations, "neoFormClasspath"); modulePath = resolvable(configurations, "modulePath"); userdevClasspath = resolvable(configurations, "userdevClasspath"); userdevCompileOnlyClasspath = resolvable(configurations, "userdevCompileOnlyClasspath"); userdevTestClasspath = resolvable(configurations, "userdevTestClasspath"); launcherProfileClasspath = resolvable(configurations, "launcherProfileClasspath"); - installerProfileLibraries = resolvable(configurations, "installerProfileLibraries"); // Libraries & module libraries & MC dependencies need to be available when compiling in NeoDev, // and on the runtime classpath too for IDE debugging support. configurations.getByName("implementation").extendsFrom(libraries, moduleLibraries, neoFormDependencies); - // runtimeClasspath is our reference for all dependency versions. - // Make sure that any configuration we resolve are consistent with it. + // runtimeClasspath is our reference for all MC dependency versions. + // Make sure that any classpath we resolve is consistent with it. var runtimeClasspath = configurations.getByName(JavaPlugin.RUNTIME_CLASSPATH_CONFIGURATION_NAME); + neoFormDataOnly.setTransitive(false); + neoFormDataOnly.extendsFrom(neoFormData); + + neoFormClasspath.extendsFrom(neoFormDependencies); + modulePath.extendsFrom(moduleLibraries); modulePath.shouldResolveConsistentlyWith(runtimeClasspath); @@ -147,9 +152,5 @@ private NeoDevConfigurations(ConfigurationContainer configurations) { launcherProfileClasspath.extendsFrom(libraries, moduleLibraries); launcherProfileClasspath.shouldResolveConsistentlyWith(runtimeClasspath); - - installerProfileLibraries.extendsFrom(libraries, moduleLibraries, neoFormData); - installerProfileLibraries.shouldResolveConsistentlyWith(runtimeClasspath); - // Installer tools are also added to `installerProfileLibraries`, from NeoDevPlugin. } } diff --git a/buildSrc/src/main/java/net/neoforged/neodev/NeoDevPlugin.java b/buildSrc/src/main/java/net/neoforged/neodev/NeoDevPlugin.java index 14908ca745..0a075bbab6 100644 --- a/buildSrc/src/main/java/net/neoforged/neodev/NeoDevPlugin.java +++ b/buildSrc/src/main/java/net/neoforged/neodev/NeoDevPlugin.java @@ -245,7 +245,11 @@ public void apply(Project project) { task.getNeoForgeVersion().set(neoForgeVersion); task.getMcAndNeoFormVersion().set(mcAndNeoFormVersion); task.getIcon().set(project.getRootProject().file("docs/assets/neoforged.ico")); - task.setLibraries(configurations.installerProfileLibraries); + // Anything that is on the launcher classpath should be downloaded by the installer. + // (At least on the server side). + task.addLibraries(configurations.launcherProfileClasspath); + // We need the NeoForm zip for the SRG mappings. + task.addLibraries(configurations.neoFormDataOnly); task.getRepositoryURLs().set(project.provider(() -> { List repos = new ArrayList<>(); for (var repo : project.getRepositories().withType(MavenArtifactRepository.class)) { @@ -267,10 +271,11 @@ public void apply(Project project) { files.setCanBeResolved(true); files.getDependencies().add(installerProcessor.tool.asDependency(project)); }); - configurations.installerProfileLibraries.extendsFrom(configuration); - // Each tool should resolve consistently with the full set of installed libraries. - configuration.shouldResolveConsistentlyWith(configurations.installerProfileLibraries); createInstallerProfile.configure(task -> { + // Add installer processor. + // Different processors might use different versions of the same library, + // but that is fine because each processor gets its own classpath. + task.addLibraries(configuration); task.getProcessorClasspaths().put(installerProcessor, DependencyUtils.configurationToGavList(configuration)); task.getProcessorGavs().put(installerProcessor, installerProcessor.tool.asGav(project)); }); diff --git a/buildSrc/src/main/java/net/neoforged/neodev/installer/CreateInstallerProfile.java b/buildSrc/src/main/java/net/neoforged/neodev/installer/CreateInstallerProfile.java index 5170acf524..171ed2b1d1 100644 --- a/buildSrc/src/main/java/net/neoforged/neodev/installer/CreateInstallerProfile.java +++ b/buildSrc/src/main/java/net/neoforged/neodev/installer/CreateInstallerProfile.java @@ -2,6 +2,7 @@ import com.google.gson.GsonBuilder; import net.neoforged.neodev.utils.FileUtils; +import net.neoforged.neodev.utils.MavenIdentifier; import org.gradle.api.DefaultTask; import org.gradle.api.artifacts.Configuration; import org.gradle.api.file.RegularFileProperty; @@ -46,8 +47,8 @@ public CreateInstallerProfile() {} @Nested protected abstract ListProperty getLibraryFiles(); - public void setLibraries(Configuration libraries) { - getLibraryFiles().set(IdentifiedFile.listFromConfiguration(getProject(), libraries)); + public void addLibraries(Configuration libraries) { + getLibraryFiles().addAll(IdentifiedFile.listFromConfiguration(getProject(), libraries)); } @Input @@ -134,8 +135,23 @@ public void createInstallerProfile() throws IOException { ); getLogger().info("Collecting libraries for Installer Profile"); + // Remove potential duplicates. + var libraryFilesToResolve = new LinkedHashMap(getLibraryFiles().get().size()); + for (var libraryFile : getLibraryFiles().get()) { + var existingFile = libraryFilesToResolve.putIfAbsent(libraryFile.getIdentifier().get(), libraryFile); + if (existingFile != null) { + var existing = existingFile.getFile().getAsFile().get(); + var duplicate = libraryFile.getFile().getAsFile().get(); + if (!existing.equals(duplicate)) { + throw new IllegalArgumentException("Cannot resolve installer profile! Library %s has different files: %s and %s.".formatted( + libraryFile.getIdentifier().get(), + existing, + duplicate)); + } + } + } var libraries = new ArrayList<>( - LibraryCollector.resolveLibraries(getRepositoryURLs().get(), getLibraryFiles().get())); + LibraryCollector.resolveLibraries(getRepositoryURLs().get(), libraryFilesToResolve.values())); var universalJar = getUniversalJar().getAsFile().get().toPath(); libraries.add(new Library(