Adding a java preprocessor for multi-version and multi-loader support. #39
FamroFexl
announced in
Announcements
Replies: 1 comment
-
Distant Horizons uses Manifold for multi-version management as well, so it is a good reference. |
Beta Was this translation helpful? Give feedback.
0 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
-
Selection
Manifold Preprocessor was selected as a solution for multi-version management and the MultiLoader-Template will be used in conjunction for multi-loader management. Read below for reasoning.
Synopsis
When in the first stages of creating Circumnavigate, I realized that supporting multiple Minecraft versions was a bare minimum at the least. This is because Circumnavigate fundamentally alters the "substance" of the world, making it fundamentally break throughout progressive updates without the mod. Also, supporting multiple loaders would increase Circumnavigate's user base and reputation. In order to accommodate these requirements, I started researching potential solutions.
Multi-Version Management
In the past, I created multiple versions for my mods by using completely isolated build sources. These sources were stored in different mod directories and each made up a separate git branch. In hindsight, while I could have conglomerated the sources into a single directory and stored them under a single branch, which would have been preferable, the real problem was the constant code parity between versions. Updating multiple versions simultaneously was a nightmare, because regardless of if the changes were version independent or not, they would still have to be applied to all versions.
In order to fix this problem for future, more mature mods, I started investigating java preprocessors. For those unaware, preprocessing is basically an inline compilation step which automatically selects between provided code statements based on directives. If a file exists in a Minecraft version and onwards, I can conditionally
import
it based on what Minecraft version is being used.The two most prominent java preprocessors were given below for consideration. I ultimately decided to go with the Manifold Preprocessor based on factors listed below.
JCP
The original java preprocessor.
This project was not considered because there are much more mature implementations of its idea.
Preprocessor
A JCP-inspired preprocessor used near-exclusively by ReplayMod to support its impressive Minecraft version support.
This project was not considered because it was largely made for internal use and doesn't have much external support. Besides, Stonecutter exists.
Stonecutter
Stonecutter is a Gradle plugin designed specifically for multi-version Minecraft management. It uses java's comment syntax to selectively disable preprocessor directives, and even boasts multi-loader management. It is a fork of the original Stonecutter which was largely abandoned, and is inspired by JCP and Preprocessor.
While this project was originally a definite in Circumnavigate's future, initial tests with the Circumnavigate code base showed just how janky it actually was. This disappointment immediately dealt a blow to the entire idea of multi-version support for Circumnavigate. A list of Stonecutter's deal-breaking problems is below.
gradle.properties
and thebuild.gradle
in order to manage multiple versions. While this allows it to easily switch between versions with a gradle task, it does so at the cost of a recognizable gradle build architecture. It even requires a separatestonecutter.gradle
to manage its versions.Manifold Preprocessor
Manifold is a gradle plugin which is purely designed for preprocessor directives. The advantages of this preprocessor over Stonecutter are listed below.
build.properties
file where constants for preprocessor directives are primarily stored. This prevents having to change the active version to the one specified in git every time you want to commit, because the only file that has actually been changed isbuild.properties
.Multi-Loader Management
While it is arguable that the preprocessor should be used to enable multi-loader support as well as multi-version support, when it comes to different loaders, their difference in implementation can differ substantially. Therefore, a combined approach where the preprocessor and another format is used is appropriate.
MultiLoader-Template
This is the most commonly used template for supporting multiple different mod loaders. It contains a common directory for common code and directories for each different loader implementation. The use of separate
build.gradle
files in each loader is also appropriate for supporting a more modular and less-chaotic build environment. Also, since changes between versions are often relegated to the minecraft source, and not to a particular loader, the preprocessor isn't strictly necessary for anything but thecommon
folder.Beta Was this translation helpful? Give feedback.
All reactions