jjohannes / gradle-project-setup-howto

How to structure a growing Gradle project with smart dependency management?
Apache License 2.0
155 stars 18 forks source link

How to create platform rules? #21

Closed mqware closed 4 months ago

mqware commented 5 months ago

(This post is copied over from here: How to create a platform rule for BouncyCastle? as it is related to this project.)

Hi @jjohannes,

Thanks for your quick response!

What I did for other libraries in the example, is to use the "parent POM" of the corresponding library (which sometimes already is a kind of platform). Unfortunately, in this case there is no parent you can use. This is a limitation of the pattern. What you can do is use something for BOUNCY_CASTLE_PLATFORM that you do not use at all - maybe BOUNCY_CASTLE_PLATFORM = "org.bouncycastle:bcprov-ext-jdk18on"

Unfortunately this didn't work, apparently because it provides the same capability. I got a similar error as above:

Could not determine the dependencies of task ':app:compileJava'.
> Could not resolve all task dependencies for configuration ':app:compileClasspath'.
   > Could not resolve org.bouncycastle:bcprov-ext-jdk18on:1.78.1.
     Required by:
         project :app > project :platform
      > Module 'org.bouncycastle:bcprov-ext-jdk18on' has been rejected:
           Cannot select module with conflict on capability 'org.gradlex:bouncycastle-bcprov:1.78.1' also provided by [org.bouncycastle:bcprov-ext-jdk18on:1.78.1(compile), org.bouncycastle:bcprov-ext-jdk18on:1.78.1(platform-compile)]
   > Could not resolve org.bouncycastle:bcprov-jdk15to18:1.78.1.
     Required by:
         project :app > org.bouncycastle:bcpkix-jdk15to18:1.78.1
         project :app > org.bouncycastle:bcutil-jdk15to18:1.78.1
      > Module 'org.bouncycastle:bcprov-ext-jdk18on' has been rejected:
           Cannot select module with conflict on capability 'org.gradlex:bouncycastle-bcprov:1.78.1' also provided by [org.bouncycastle:bcprov-ext-jdk18on:1.78.1(compile), org.bouncycastle:bcprov-ext-jdk18on:1.78.1(platform-compile)]

Nevertheless, this was helpful, because next I tried BOUNCY_CASTLE_PLATFORM = "org.bouncycastle:bcmail-jdk18on" and that worked fine. So, thanks for pointing me in the right direction. :smile:

Looking at the example, I see that I also did that with org.apache.poi:poi. I have to revisit that. I will probably run into the same problem if I update the example to use org.gradlex.jvm-dependency-conflict-resolution.

Actually I wanted to ask about this, (although this would be more suited for the gradle-project-setup-howto project), but the poi rule doesn't seem to be doing anything, because the dependency graph (under the platform) looks like this:

|    +--- org.apache.poi:poi:5.2.3
|    |    +--- commons-codec:commons-codec:1.15
|    |    +--- org.apache.commons:commons-collections4:4.4
|    |    +--- org.apache.commons:commons-math3:3.6.1
|    |    +--- commons-io:commons-io:2.11.0 -> 2.13.0
|    |    +--- com.zaxxer:SparseBitSet:1.2
|    |    \--- org.apache.logging.log4j:log4j-api:2.18.0 -> 2.20.0
|    |         \--- org.apache.logging.log4j:log4j-bom:2.20.0
|    |              +--- org.apache.logging.log4j:log4j-api:2.20.0 (c)
|    |              +--- org.apache.logging.log4j:log4j-core:2.20.0 (c)
|    |              \--- org.apache.logging.log4j:log4j-jcl:2.20.0 -> org.slf4j:jcl-over-slf4j:2.0.7 (c)

This is just what's in the pom with nothing added or removed. Unlike org.apache.httpcomponents:httpcomponents-client for example, where I only see a list of constraints that were added by the rule.

Note: I am happy to see that you successfully use this setup. Thanks for the feedback. 😄

It is not a complete success yet, but I am getting there. :smile: First I had to build the whole project from scratch, one file at a time, so I can try and (at least somewhat) understand the structure, because it is way over my head. Then I moved in the actual source code and now I am trying to put all the dependencies into the platform project, migrate my existing rules, etc. But thanks for providing this framework, I think it will be great, once I complete it. :laughing:

This pattern with the platform rules however, is one thing I am not so sure about anymore. I stopped using it in real™️ projects. I plan to update the gradle-project-setup-howto repo and I am not sure if I will keep it in there. But I have to look at it in more detail again.

Great, and I was thinking that I was modernizing my project. Now you're telling me that I am using outdated, "legacy" technology. :joy::joy::joy:

Hope this solves your issue for now. I'll comment here again once I found the time to update the gradle-project-setup-howto example.

Looking forward to the updates. Until then I'll continue working with this dinosaur. 😂

jjohannes commented 4 months ago

In the updated setup, I now integrated the version catalog (#5) and no longer use alignment BOMs directly. Instead I define the version for one (or more, if necessary) of the components. And then I used the "alignment" feature of the jvm-dependency-conflict-resolution plugin to define alignment where needed. The approach used there does not require a "fake" BOM anymore and thus can't run into the problem you initially ran into.

Alignment in updated setup: https://github.com/jjohannes/gradle-project-setup-howto/blob/main/gradle/plugins/src/main/kotlin/org.example.gradle.base.dependency-rules.gradle.kts#L29-L49 Docs for jvm-dependency-conflict-resolution: https://gradlex.org/jvm-dependency-conflict-resolution/#patch-dsl-block

Hope this helps. Let me know if you have follow up questions.