I have a large (300+ subprojects) recently migrated from maven to gradle.
Our root project contains constraints defined within the ‘allProjects’ section (could be subProjects arguably!). This keeps dependencies more in control for the subprojects.
We build lots of libraries, so some external code may use implementation platform ourtoplevelartifact:version - that’s how it was done with maven (maybe incompletely!)
As-is, with a regular java publish, the BOM does not work - consuming it throws errors. I’ve realised I need to do a little refactoring:
use the java-platform plugin
demote much of allProjects to subProjects (ie this removes application of java plugin & other changes)
move my dependency constraints from allProjects to the root project only
change constraints from implementation to api & typically runtimeOnly to runtime
add a platform declaration in subProjects so that my subprojects use the same constraints
One thing I think I’m missing though is all of the modules created by this multi module build.
I think I also want to publish a list of all of those as constraints to the BOM I am creating, as they represent a good ‘list of things that work together’. That’s important for external consumers
So How would I do that without explicitly listing? (am using groovy)? And would that cause issues with the subproject build?
For reference - these were the errors my first attempt at trying to consume my existing root project as a platform definition hit - I think fundamentally because with maven the bom kinda ‘just happened’, so the question here reflects on how to really make the bom we want (oh and I liked how the error colourised the good/warning/bad points!)
Refactoring as above will help to resolve/clarify these other points here too.
* What went wrong:
Could not determine the dependencies of task ':egeria-connector-xtdb:withDependencies'.
> Could not resolve all files for configuration ':egeria-connector-xtdb:runtimeClasspath'.
> Could not resolve org.odpi.egeria:egeria:4.0-SNAPSHOT.
Required by:
project :egeria-connector-xtdb
> No matching variant of org.odpi.egeria:egeria:4.0-SNAPSHOT:20230221.172710-30 was found. The consumer was configured to find a runtime of a platform compatible with Java 17, packaged as a jar, preferably optimized for standard JVMs, and its dependencies declared externally but:
- Variant 'apiElements' capability org.odpi.egeria:egeria:4.0-SNAPSHOT declares a component compatible with Java 17, packaged as a jar, and its dependencies declared externally:
- Incompatible because this component declares an API of a library and the consumer needed a runtime of a platform
- Other compatible attribute:
- Doesn't say anything about its target Java environment (preferred optimized for standard JVMs)
- Variant 'javadocElements' capability org.odpi.egeria:egeria:4.0-SNAPSHOT declares a runtime of a component, and its dependencies declared externally:
- Incompatible because this component declares documentation and the consumer needed a platform
- Other compatible attributes:
- Doesn't say anything about its target Java environment (preferred optimized for standard JVMs)
- Doesn't say anything about its target Java version (required compatibility with Java 17)
- Doesn't say anything about its elements (required them packaged as a jar)
- Variant 'runtimeElements' capability org.odpi.egeria:egeria:4.0-SNAPSHOT declares a runtime of a component compatible with Java 17, packaged as a jar, and its dependencies declared externally:
- Incompatible because this component declares a library and the consumer needed a platform
- Other compatible attribute:
- Doesn't say anything about its target Java environment (preferred optimized for standard JVMs)
- Variant 'sourcesElements' capability org.odpi.egeria:egeria:4.0-SNAPSHOT declares a runtime of a component, and its dependencies declared externally:
- Incompatible because this component declares documentation and the consumer needed a platform
- Other compatible attributes:
- Doesn't say anything about its target Java environment (preferred optimized for standard JVMs)
- Doesn't say anything about its target Java version (required compatibility with Java 17)
- Doesn't say anything about its elements (required them packaged as a jar)
As you found out already, the proper way to publish a BOM is by using the java-platform plugin and publishing it.
I wouldn’t do it in the root project though, but in a separate subproject.
You may ask now how that will harmonize with allprojects { ... } or subprojects { ... }.
Actually, the most appropriate answer is, that those are bad practice and should be avoided whereever possible.
Instead you should have a look at convention plugins, for example implemented as precompiled script plugins in buildSrc or an included build.