Hi - A quick question regarding the version catalo...
# community-support
d
Hi - A quick question regarding the version catalog I have
libs.versions.toml
under
rootProject/gradle/
. Can I use
libs.*
in my
build.gradle.kts
under
rootProject/buildSrc
?
v
If you include it in
buildSrc/settings.gradle.kts
, yes, otherwise not
buildSrc
is a standalone build that just happens to be built before your main build
d
Okay. so each subproject/build with has to have its own libs.versions.toml ? Is there a way to share this among different subprojects ?
v
No, all subprojects share the same. But
buildSrc
is not a subproject, it is a standalone build. And as I said, you can easily share it by just defining to use it in its settings script.
d
One more question 🙂. I have a class defined in
DemoTask.Kt
I want to register a task of this type in my
build.gradle.kts
. Should I use
buildSrc
or Precompiled script plugins. Which one is better/ recommended ? Currently I am having to define the task classes in a separate build and include this build to register tasks in different one and set the buildscript/dependencies/classpath.
s
buildSrc vs precompiled script plugins is a wrong question. Your options are 1) buildSrc vs an explicitly included build, and 2) precompiled script plugins vs classic plugins (a class extending Plugin<Something>).
d
I believe
2) explicitly included
build is what I am currently using. I was thinking If I can create a pre-compiled plugin that provides the task (demo-task) , I can apply this to the build file. Can I not do that ?
s
I thought you were using buildSrc, at least from your question above, but anyway, it doesn’t really matter. You can define new task types in both kinds of plugins. and you can also register new task instances in both kinds of plugins.
As to what is recommended, in my projects I start with buildSrc because it’s simpler and less boilerplate. Once it grows a bit, I extract it into a separate build. And I like precompiled script plugins but I’m not sure how they interact e.g. with publishing to Gradle’s plugin portal so if I’m writing a public plugin, I use the classic style. I also had a case where I wanted to write a plugin that could be applied to both Settings and Project and in that case I couldn’t use precompiled script plugins.
v
I personally prefer to use an included build over
buildSrc
whenever possible and only use
buildSrc
if I really need to, like for example to monkey-patch 3rd-party plugin classes.
Whether you use precompiled script plugins or normal plugin classes is mainly a question of preference, in the end you get the same result
I start with buildSrc because it’s simpler and less boilerplate
technically, yes, 1 line less boilerplate 🙂
s
well I think you also don’t have to include settings.gradle.kts for buildSrc but you might be right 🙂
v
Even if you don't have to, it is bad practice to not have. Every build should always have a settings script 🙂
s
right, that’s exactly what makes it boilerplate 🙂
okay maybe not boilerplate but overhead would be a better term
v
But boilerplate you should even have in
buildSrc
🙂
d
Okay. I am not using
buildSrc
yet but just exploring my options. I am starting with a simple use case of creating a module and registering a custom task. I can define the CustomTask class in the
build.gradle.kts
but it will become difficult to maintain in the future. If the CustomTask is defined out of the build file then I can either use an included build or buildSrc. And I understand now that included builds are the recommended way. And then I came across the pre compiled script plugins which might also help me what I trying to do. Thanks for the inputs and suggestions. 🙏
v
Yeah, having the task class directly in the build script works but definitely is discouraged. build scripts are optimally as declarative as possible and have no imperative logic. What the recommended way between
buildSrc
and an included build is, depends on whom you ask. Even Gradle is not really consistent imho, as the docs in most places still show
buildSrc
, while the
init
task generates an included build for build logic. But by tendency, I would trust code more than documentation. 🙂 If you ask me, I recommend using an included build. But for small projects the subtle differences between the two are most often neglectible. precompiled script plugins are really just syntactic sugar to creating a binary plugin, the end result should be the same, and you could as well publish plugins written as precompiled script plugins.
d
I still haven't found my way around 😐 So any help or pointer is appreciated. This is my structure. I want the subproject to be compiled before the root project's build script so that I can import MyCustomTask in the build file and register a task. How can I achieve this. It works when I use
buildSrc
but don't know how to do it with a subproject. root-project ├── build.gradle.kts ├── gradle ├── gradlew ├── gradlew.bat ├── settings.gradle.kts └── sub-project ├── build.gradle.kts ├── settings.gradle.kts └── src ├── main │ ├── kotlin │ │ └── com.example │ │ └── MyCustomTask.kt │ └── resources └── test ├── kotlin │ └── com.example │ └── MyCustomTaskTest.kt └── resources
v
buildSrc
is built and put via a parent class loader to the classpath of all build scripts. That's also the reason why for example all tasks in all projects are out-of-date when you change anything in
buildSrc
. With an included build, it is only built and added to the classpath - including version conflict resolution of dependencies - when it is actually used. If you use a plugin that is built there, this happens automatically. If you just want to use that custom task, you need to add the buildscript classpath dependency in some way. On is to depend on it in
buildscript { dependencies { classpath(...) } }
, another would be to add a plugin with no actions that you apply to your project, just to get the code onto the classpath that way.
🫡 1
s
In root-project/settings.gradle.kts add this:
Copy code
pluginManagement {
  includeBuild("sub-project")
}
It has to be added to the beginning of the file, before the
plugins
block.
v
It was a bold assumption, but I pretty much guess he already has that. But that does not change anything as long as you do not add a buildscript dependency on it or apply a plugin from it as I described. Included builds behave saner than
buildSrc
and only build what is used and necessary and only includes it where it is used.
🙌 1
d
This is where I was having trouble.
buildscript { dependencies { classpath(...) } }
I tried
classpath(":sub-project")
and
classpath(files("sub-project/src/main/com/example"))
If I build the compile the subproject independently and point to its
build/libs/sub-project.jar
it works fine. So was wondering how to build the subproject and make it available to the
buildScript {}
s
Can you use
plugins
block instead? It would make your life easier. If you have to use
buildscript
then you can give your project a group and name and use that group and name in
classpath
, e.g.
classpath("mygroup:myplugin")
and Gradle should automatically replace it with a dependency on the project from the included build.
☝️ 1
d
I did try with the group and name as well and I got this error.
Copy code
A problem occurred configuring root project 'root-project'.
> Could not resolve all files for configuration ':classpath'.
   > Could not find org.example:sub-project:.
     Required by:
         project :
I have
include(":sub-project")
in my
root-project/settings.gradle.kts
And for the
plugins{}
is it same as what mentioned by Bjorn ? to register a plugin with no tasks and apply to the root project's build.gradle.kts ?
s
do you set
group = "org.example"
in your subproject’s build.gradle.kts? yes, that’s the same as Björn suggested.
d
do you set
group = "org.example"
in your subproject’s build.gradle.kts?
Yes I did.
This is my
sub-project/build.gradle.kts
where GreetingsPlugin Class is defined in
src/main/com/example/MyCustomTask.kt
Copy code
plugins {
    kotlin("jvm") version "2.0.0"
    `java-gradle-plugin`

}

dependencies {
    implementation(libs.bundles.jackson)
    implementation(libs.bundles.http4k)
    testImplementation(libs.bundles.test)
}

gradlePlugin{
    plugins{
        create("greetingsPlugin"){
            id = "com.example.greetingsPlugin"
            implementationClass = "com.example.GreetingsPlugin"
        }
    }
}
I apply the plugin in my
root-project/build.gradle.kts
like this
Copy code
import com.example.MyCustomTask

plugins {
    id("com.example.greetingsPlugin")
}

tasks.register("customTask", MyCustomTask::class.java) {
    println("do something")
}
Subproject is included in th rootproject's settings But Still I get this error.
Copy code
Plugin [id: 'com.example.greetingsPlugin'] was not found in any of the following sources:
I am not sure If I am missing something 😐
s
What’s in settings.gradle.kts of the root project?
d
just the
rootProject.name
and
include("sub-project)
s
can you post it?
d
Copy code
rootProject.name = "root-project"

include(":sub-project")
include is not the same as includeBuild btw
(and adding it at the end of the file is not the same as adding it in pluginManagement block in the beginning)
👀 1
🙌 1
d
Thanks Sergej. That helped. guessing by their names include - is to tell gradle that the root project has a sub-project with specified name ( inside the root project's directory) includeBuild - builds includes a project (can be outside the root project directory as well) ?
s
yes, “included builds” are different from subprojects, they can be built completely separate from the including build.
d
so when specifying a project using the includeBuild, gradle runs the build task on the module and then includes it. is that right ?
s
I can’t really give a simple explanation of what it does… it basically treats that project as a separate thing but modifies the including (“parent”) project to use the artifacts built by the included build in place of its own dependencies. So it can be used for build logic or to combine two related independent projects for a sort of integration testing (provided they use compatible Gradle versions).
AFAIU the Gradle team also recommends using included builds instead of subprojects in some scenarios but I’m a bit fuzzy on the guidelines here.
d
okay. Thank you so much for your time and help 🙏
👍 1