vigna / fastutil

fastutil extends the Java™ Collections Framework by providing type-specific maps, sets, lists and queues.
Apache License 2.0
1.74k stars 194 forks source link

Document build system workarounds for the class def conflict of fastutil-core.jar and fastutil.jar #309

Open techsy730 opened 7 months ago

techsy730 commented 7 months ago

Due to interdependence between the different packages and Java's module system being very particular, splitting fastutil into separate disjoint jars is impractical. Thus, the two jars of fastutil-core.jar and fastutil.jar both currently contain some of the same classes.

Many build systems or static analysis tools will complain in this case unless the duplicate .class file definitions are bit-for-bit identical. Which may not be the case in situations of transitive dependencies pulling in different versions of the two jars.

While there is currently a warning in the documentation to this effect, it doesn't directly help the developer solve the problem.

We should have documentation and code samples somewhere about workarounds for such conflicts for the most popular build systems.

techsy730 commented 7 months ago

For example Gradle (in addition to the usual Maven mechanism of excluding a transitive dependency of a direct dependency by name) supports substituting dependencies programmatically. For example, with a bit of build.gradle code, Gradle can transitively replace all dependencies onto fastutil-core into fastutil (or vice versa) transparently to the dependency graph. This has the advantage of preserving minimum version number requirements, which plain transitive exclusion does not.

For example, a project with transitive dependencies onto fastutil-core:8.5.5 and fastutil-8.0.0. Under simple exclusion of fastutil-core:8.5.5, then fastutil-8.0.0 would still be chosen. Possibly breaking the dependency that uses fastutil-core APIs introduced in 8.5.0.

With substitution, that dependency onto fastutil-core:8.5.5 will be replaced with fastutil:8.5.5 in the dependency graph. So the correct solution of using fastutil:8.5.5 (unless the top level build.gradle explicitly specified otherwise) for the final selection would be taken.

However, the API for this isn't exactly among most discoverable parts of the Gradle documentation, and implementing it can run into some Gradle quirks. A pre-made code snippet for this would both raise awareness of this possible solution, as well as an easy copy-pastable snippet of code already tested to work properly in Gradle, could be very useful for developers.

vigna commented 7 months ago

Mmmhhh... I'm totally ignorant of build systems outside of ant, but maybe we can add something to the README that at least points to the right resurces.