What do you all here think of this? <https://twitt...
# gradle
p
f
If it wouldn't still be stringly typed it would be brilliant (consider it a feature request πŸ˜‰ ).
Something similar for other dependencies would be nice too.
api("org.openjdk.jmh", "1.23") { api("jmh-core"); api("jmh-generator-annprocess") }
(just using JMH here because I have a build file with it directly in front of me).
p
yeah, someone mentioned that, looking into it now πŸ™‚
Aaarg! Can’t share code between settings and modules 😭 And settings.gradle is compiles before buildSrc πŸ™ƒ
o
f
The
buildSrc
approach is a well known one but it comes with major drawbacks and makes the overall handling actually more complicated than it has to be.
o
for me,
buildSrc
is really very usable, so I can very easy configure every module similar and configurable So, it's project related I think
f
Drawbacks include: you always need to search for an appropriate name and cross your fingers that it never collides with anything else; backticks won't help because dependencies contain tons of chars that are illegal and if we verbatim repeat the name of the dependency we can anyways directly use a string. Gradle will be slower but much worse IntelliJ will be as it has big troubles with Kotlin Script (this is a general known issue). Versions are hardcoded for dependencies, this might be fine for a simple multi-module library where everything is anyways always the same (although it probably could use capabilities) but is a deal breaker for a monorepo with multiple microservices. I went through many iterations with Gradle and declaring dependencies with small to big teams. I never found the right strategy that is understood by everyone and easy to use.
j
@Oleg Yukhnevich when you update your gradle to 6.0 your settings.gradle.kts will stop working
p
Yeah, I was about to mention that, you’re in for a suprise πŸ˜…
o
hm, no, it's gradle 6, and it's work πŸ™‚
we can anyways directly use a string
But, if to think, we don't always now string exactly, rly
IntelliJ will be as it has big troubles with Kotlin Script
with 1.3.70 kotlin and 6.x gradle - it's really now much faster, then before
Versions are hardcoded for dependencies
in my lib versions can be easily overridden, if it needed just take any dependency, and use
.version("1.5.0")
or `.version(project.properties["some_version"])
I never found the right strategy that is understood by everyone and easy to use.
Can you also share you tries and drawbacks of them?
j
@Oleg Yukhnevich I checked your repo and you are using gradle 5.6.4 in your develop branch https://github.com/whyoleg/kamp/blob/develop/gradle/wrapper/gradle-wrapper.properties
o
I sent second repository, where that
plugin
is used πŸ™‚ here: https://github.com/whyoleg/ktd/blob/clients-rework/gradle/wrapper/gradle-wrapper.properties and it's 6.1
j
Not the same we are talking about I think. BTW feels free to update this https://github.com/whyoleg/kamp/blob/develop/gradle/wrapper/gradle-wrapper.properties I don't know how settings.gradle.kts can use Plugins.rootModule if when it compiles that object is not ready.
o
Ah, about that Okay, It will not work with gradle 6, I know, I just need to inline classpaths But, it just a
plugin
configuration, and it's gradle version not so needed So, if u look at second repository, which I sent, there this plugin is used as build script classpath dependency in settings.gradle.kts and in buildSrc, and it works really well with gradle 6
p
I've got something that works on 6 and actually it's easier to use. I'll try to post it later πŸ˜…
f
The first thing we tried was dependency locks, but it was to complicated to update only parts. The Java ecosystem with its wild versioning is unbelievable and the major reason why something like this cannot work. PHP might be shit but their dependency management tool Composer got that right from the start. So does cargo from Rust. The next thing was the typed
buildSrc
approach. At that time many people came to this solution and everyone was posting about it everywhere. The issues mentioned above and the fact that many people were extremely confused by
buildSrc
made it a failure as well. The next thing I did was also in conjunction with
buildSrc
but without types, I kept the strings. I find it hard to explain but can post it later. It's actually pretty neat. What I mostly use today is https://plugins.gradle.org/plugin/nebula.resolution-rules combined with
platform
. Not many things require any versions anymore with this approach beause I'm mostly working with Spring. Of course there are still many projects that have no BOM (😠) but in those cases Nebula RR can mitigate it. It has its limitations too https://github.com/nebula-plugins/gradle-resolution-rules-plugin/issues/97 … so at the end of the day one always ends up with complicated Gradle scripts to get those wild Java dependencies nicely aligned.
o
@pablisco
I'll try to post it later
Will wait to try it πŸ™‚ Any git repo exists to track?
@Fleshgrinder Thx for explanation It's really interesting, how people are fighting with dependencies resolution For me, my approach really work good, but Now, I don't use it in really BIG projects, may be smth will change in future And one more thing, that my plugin is really rescue now for me, because it supports declaring MPP dependencies, which now, for many dependencies is really hard to use When you need to apply it in different sourceSets, with same everything except
common/jvm/js/native
suffix With my approach it one line, which, really, decrease amount of code needed for simple dependency management
f
πŸ‘ It's really great if it works for you. I think what we can learn from this thread is that it's really hard to find a common solution that works for everything. This also explains why the Gradle team hasn't found it yet. πŸ˜›
o
I think,
Gradle metadata
is the first step, to create such solution, so in future, I believe smth will be
f
I sure hope so! But the various Java projects out there also have to settle on a versioning strategy that works and allows tools to build on top. SemVer is perfect for libraries and its time projects adopt it.
p
Ok, here is a first prototype: https://gist.github.com/pablisco/e50c792f1febb77af0fbc2d4f8f2810e It works, but I'm gonna try to make it into a grade plugin so it's reusable. I'll update here when ready. For now if anyone wants to try it on their own projects I'll welcome any feedback. The script generates a graph for the modules into
_modules.kt
inside
buildSrc
. This file is determined by the project's file structure. So it should be less friction when adding or extracting modules.
o
I see, what you do, but, what if I need to ignore module for some time? or on some condition, for CI f.e.?
I do similar here https://github.com/whyoleg/kamp/blob/develop/lib/src/main/kotlin/dev/whyoleg/kamp/project/Module.kt (it also generate file in buildSrc, which can be used for modules dependencies) but with explicit modules: https://github.com/whyoleg/ktd/blob/master/settings.gradle.kts
p
I'm planning to add an ignore option once I create is as a plugin 😁
Forgot to mention, this adds type safety as we can use the generated modules like this:
Copy code
api(local.core)
I'm also considering adding a separate plugin to add groovy support for projects that may have a mix of both languages (with large projects and teams it's not trivial to migrate them all at once)
o
the same here: https://github.com/whyoleg/ktd/blob/clients-rework/ktd-client/build.gradle.kts
Copy code
metadata {
        dependenciesMain {
            api(ProjectModules.core)
        }
    }
metadata is MPP target from kotlin plugin
ProjectModules
is auto generated file in buildSrc
p
Here is my implementation: https://github.com/pablisco/auto-module Let me know what you think.
o
Interesting But what more interesting, is what it generate for one of my projects πŸ™‚ I will try it later today!
πŸ‘ 1
f
Very nice work, you should propose inclusion in Gradle. πŸ™‚ The root module could also use the name of the root project instead of local, no?
p
It can be customised to any name 😁