jjohannes / gradle-project-setup-howto

How to structure a growing Gradle project with smart dependency management?

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Use TOML version catalogs

yogurtearl opened this issue · comments

It would be helpful to have examples that use TOML version catalogs.

Maybe the platform plugins can read coordinate info from the version catalog?

Thanks for the suggestion @yogurtearl. I think you are right. I'll look into adding another variation of the setup that uses the version catalog.

I just did something similar over here: https://github.com/jjohannes/idiomatic-gradle#summer-2022-update-gradle-751

There are essentially two good options I think:

  1. Add the catalog only for coordinates and use it as addition to the platform. Then use the aliases from the catalog in the platform and the build files. That's what you suggest if I understand correctly. That would be this change in the idiomatic-gradle project jjohannes/idiomatic-gradle@version_catalog_with_platform
  2. Remove the platform completely and only use the catalog. And do the versions management in the catalog then. That would be this change (on top of the previous one) in the idiomatic-gradle project: jjohannes/idiomatic-gradle@version_catalog_without_platform

In this project setup, these changes would influence how the custom dependency analysis (checking for newer versions) works. (1) is probably easy to adjust, (2) might be more involved. I'll take a look when I find some time.

Is there a way to have the group, artifact AND version in TOML, but pull that all into the platform?

My preference would be to have ALL versions across everything in a TOML version catalog file, but read info form the TOML file and use it wherever needed including in platforms.

You can also put the versions in the TOML file and keep the platform. I think you are flexible there. Whatever fits best for your.

Then versions are in the platform, but also all the places where you define dependencies.

E.g. if you have this in the catalog:

guava = { module = "com.google.guava:guava", version = "29.0-jre" }

You can put this into a build file

dependencies {
    implementation(libs.guava)
}

And this into the platform:

dependencies.constraints {
    implementation(libs.guava)
}

Practically, this works. But you also don't need the platform anymore, because the versions are already in all places. That's why I removed the platform in the example linked above, once the versions were in the TOML file.

But you also don't need the platform anymore, because the versions are already in all places.

if you are using enforcedPlatform , is that still true?

What if we put all group/artifact/versions in TOML, use them in a platform project, use enforcedPlatform to apply each platform as needed.

This will make sure the version in the TOML file are the versions actually used.
It could be confusing/misleading, if the version in the TOML file aren't actually the versions used because a transitive dep causes gradle to pick a different version.

These are a lot of different topics in my opinion. :)

  • enforcePlatform - I won't recommend using that. It think it was introduced as a compromise to get some Maven-like behaviour into Gradle. It still uses the "old" force concept in Gradle dependencies that blindly replaces all versions with the one defined in a platform. Rather, I would use reject inside the platform (or strictly if necessary).
  • IMO, the idea that you, no matter what, get the version you defined is not a good way to do this for large dependency graphs. It sounds intuitive, but replacing (especially downgrading) transitive dependencies can break things. That's why this example setup proposes to use reject to avoid unwanted updates and use dependency analysis to keep an eye on the versions used.
  • Both reject and strictly can also be used when defining versions in the Catalog. Although it get's a bit ugly IMO, because then you write more complex versions in the TOML file without good IDE support. That's a reason why I prefer to put them in a build.gradle file of a platform project.

But if you are comfortable with the "hammer" of just replacing all versions with what you define, you can use strictly (short notation !!) on all the versions that you define in the Catalog and then you do not need a Platform to use enforcePlatform for having the same effect in your project. But that's not an approach I would recommend (or use) in general.

This repo has been updated. It now:

From the experience in a few projects I looked at over the past months, this is the best compromise to combine all features.