MinecraftForge / ForgeGradle

Minecraft mod development framework used by Forge and FML for the gradle build system
GNU Lesser General Public License v2.1
509 stars 437 forks source link

Fix eclipse run configurations for multi-projects #828

Closed sciwhiz12 closed 2 years ago

sciwhiz12 commented 2 years ago

This PR fixes an issue where referencing the source set of another project from a mod's sources in a run configuration causes the output folder to be referenced for that mod in the generated Eclipse runs to be incorrect.

See the commit message for more details:

Originally, the Eclipse runs generator uses the eclipse model of the current project to retrieve the classpath, in order to make a mapping of source set names to their corresponding output folders. This is important so the mod code loaded by FML is the classes compiled by Eclipse, not by Gradle.

However, there's a problem when a run config uses multiple source sets with the same name from different projects

First, because only the current project's eclipse model is queried, the run generator has no information on the output folders for source sets outside the current project. Second, there is no way to retrieve the project for a source set in order to get the eclipse model for those projects because source sets do not carry with them their owning project's information. Third, because the map keys are only source set names, there is no way to retrieve the proper output folder for source sets which share the same name but come from different projects.

To solve this, there are now two maps: one is the allOutputs map which is the original map of source set names to output folders, and the new one is sourceSetsToOutputs, which tracks SourceSet instances (using an IdentityHashMap) to a corresponding project-specific map of source set names to output folders. For each SourceSet that belongs to a project, they all share the same project-specific outputs map. This allows looking up first by source set for the project-specific outputs map (falling back to the original shared outputs map if not present), then by source set name.

To create the sourceSetsToOutputs map, all projects within the Gradle build are iterated over and retrieved for the eclipse plugin if it is present (which is usually the case when running from Eclipse), and then retrieving the eclipse model object and classpath from there.


Post-merge note: The allOutputs map was removed because of the revelation that it will never normally be queried.

LexManos commented 2 years ago

Please provide a example zip/git of the setup so we can reproduce and test.

CreativeMD commented 2 years ago

Here is an example setup for testing: 1.18_multi_mod.zip

About the setup It uses McJty's MultiWorkspace. The workspace folder should "connect" all mods together and generate a launch command to start all of them at the same time. This test setup only contains the mod CreativeCore. In the root directory there is a gradle project which should links all subprojects together.

Executing the gradlew genEclipseRuns command in the root directory generates launch files in workspace, which unfortunately contains a wrong reference to the bin folder of the CreativeCore project: CreativeCore%%...PATH...\1.18_multi_mod\workspace\bin\main;...

Here is the same setup with the fixed ForgeGradle version (newest + this pr): 1.18_multi_mod_fixed.zip

Using the same command the generated launch files have now the correct path: CreativeCore%%...PATH...\1.18_multi_mod\CreativeCore\bin\main...