Slackbot
05/22/2023, 2:09 PMVampire
05/22/2023, 2:30 PMbuildscript { ... }
block to the classpath of the build script
Option 2: Put it to a project also containing some plugin (could be with an empty implementation) and apply that plugin to your build script using the plugins { ... }
block
Option 3: If all those build scripts are in one build you can add your functions in buildSrc
as things built in buildSrc
are automatically added to all build script's class pathsDaniele Segato
05/22/2023, 2:38 PMbuildSrc
because of the initialization cost and deprecation
I'm not sure I understand what to do with Option 1 and 2.
Do you have an example for Option 1?
I think Option 2 is what the TiVi app is doing here with build-logic isn't it?Vampire
05/22/2023, 2:44 PMOption 3: I'd excludeShouldn't be significant more initialization cost than an included build, especially since Gradle 8because of the initialization costbuildSrc
and deprecationIt is not deprecated, it is just usually recommended to use an included build instead. But for some use-cases it is still the only way. In this case it is not the only way as you have options 1 and 2, but it would be a way without needing to add it to the buidscript classpath manually and without needing a dummy-plugin.
Do you have an example for Option 1?Not at hand, but basically the same as Option 2 just without a plugin you apply, but by adding the dependency in the
buildscript { dependencies { ... } }
block to the classpath
configuration.
I think Option 2 is what the TiVi app is doing here with build-logic isn't it?Yes and no. From a quick look, they actually have convention plugins in there. But from effect basically yes. If you apply any of the convention plugins, all classes and thus also your extension fucntions are on the classpath too and can be used. So yes, like they do just with an empty plugin implementation, that is only meant to put your extension functions on the classpath. The difference to Option 1 is just that you apply a plugin in the
plugins { ... }
block to get your classes on the classpath instead of declaring the dependency in the buildscript { ... }
block as you can save some lines that way.Daniele Segato
05/22/2023, 2:50 PMbuildscript { dependencies { ... } }
pointing to that module
and that should be enough to have those utilities available in all my other modules with autocompletion
isn't this going to create a loop where the utility module will depends on itself? (maybe I need to create it in a subfolder with it's own settings.gradle.kts?)Vampire
05/22/2023, 3:09 PMbuildSrc
ramp-up wise. I generally prefer an included build over buildSrc
, but for your use-case, especially if you need those functions in most build scripts or want to add them to all buildscripts anyway, I'd really consider using it.Daniele Segato
05/22/2023, 3:10 PMDaniele Segato
05/24/2023, 4:19 PMVampire
05/24/2023, 5:21 PMext
/ extra
is almost always the wrong way and a code smell.
It is usually just a work-around instead of doing it properly.
I'm not sure what you intend to do, but you probably will probably end up registering an extension.Daniele Segato
05/24/2023, 5:38 PMVampire
05/24/2023, 6:01 PMVampire
05/24/2023, 6:01 PMVampire
05/24/2023, 6:02 PMVampire
05/24/2023, 6:03 PMDaniele Segato
05/25/2023, 7:25 AMfun Project.doStuff() {
println "Project name is $name"
}
that I can than use in
android {
signingConfig {
doStuff() // just because
}
}
buildSrc let me do that without any problem.
But I wanted to get rid of buildSrc altogether.
I'll have to see if I can achieve the same thing with just plugins. It isn't clear to me how I would use the configuration of a plugin to setup stuff in my signingConfig inside the android plugin (will it have the settings when it run the android plugin?)
Anyway I'd like to thank you for your help Vampire. My lack of gradle understanding and knowledge is evident. I'll eventually have to fix that. I've been told the best way to build gradle understanding is to work outside of android with it / build a plugin.
I'm running out of time on this task and I'll do something that just worksβ’ for now. I'll revisit when I canVampire
05/25/2023, 8:54 AMbuildSrc
is prepended to the class path of all build scripts automatically. This has the pro that it is available anywhere, it has the con that it is available anyhwere (and thus invalidates all build scripts if a change is made, whether used or not). So with included builds instead of buildSrc
you have to make the classe from the included build part of the buildscipt classpath where you want to use it manually. You basically have two options for that. Either depend on your included build with the extension function explicitly using buildscript { dependencies { classpath(...) } }
, ot alternatively have additionally a plugin in that artifact - its implementation can be empty - and apply that plugin to the buildscript using plugins { ... }
. The sole purpose of the plugin is to bring your extension function onto the classpath of the buildscript in question.Vampire
05/25/2023, 8:56 AMDaniele Segato
05/25/2023, 9:11 AMbuildscript { dependencies { classpath(...) } }
I mean: I know classpath is supposed to give the path to a module, I guess, but since that module need to be able to use gradle / kotlin dsl and android plugin stuff how do I set that up?
(the android plugin stuff doesn't work in buildSrc either)
my build logic plugin has
plugins {
`kotlin-dsl`
}
on the top
do I just create a module with that plugin and add it in the classpath?
how about dependency to the android plugin?
this one is currently a separate project with its own settings.gradle.kts that I bring in in my main project with includeBuild
pluginManagement {
includeBuild("build-logic")
repositories {
gradlePluginPortal()
google()
mavenCentral()
}
}
Maybe there are answer to all these questions in gradle documentation but I simply cannot find it because I don't know where to look?Vampire
05/25/2023, 9:17 AMI appreciate your answer but I'm still not sure how to useYour convention plugin is in the included build
build-logic
. This build produces an artifact with a group and a name like any such project. You can also look at the build-logic:outgoingVariants
task output to see what it produces.
You declare a dependency on that artifact like you also declare other dependencies, just that you do not declare it as production dependency, but as buildscript dependency for the classpath
configuration.Vampire
05/25/2023, 9:17 AMbuildSrc
.Daniele Segato
05/25/2023, 9:19 AM> Task :build-logic:outgoingVariants
There are no outgoing variants (including legacy variants) present in project 'build-logic'.
Daniele Segato
05/25/2023, 9:20 AMDaniele Segato
05/25/2023, 9:22 AM> Task :build-logic:convention:outgoingVariants
--------------------------------------------------
Variant apiElements
--------------------------------------------------
API elements for main.
Capabilities
- mypackage.buildlogic:convention:unspecified (default capability)
Attributes
- org.gradle.category = library
- org.gradle.dependency.bundling = external
- org.gradle.jvm.environment = standard-jvm
- org.gradle.jvm.version = 17
- org.gradle.libraryelements = jar
- org.gradle.usage = java-api
- org.jetbrains.kotlin.platform.type = jvm
Artifacts
- build/libs/convention.jar (artifactType = jar)
so you are saying that if I do
buildscript { dependencies { classpath("mypackage.buildlogic:convention") } }
I can just use any public function declared inside it?
let me tryVampire
05/25/2023, 9:24 AMDaniele Segato
05/25/2023, 9:26 AMCould not resolve all files for configuration 'classpath'.
> Could not find any matches for mypackage.buildlogic:convention:+ as no versions of mypackage.buildlogic:convention are available.
Vampire
05/25/2023, 9:27 AM+
.
But it might be that you need to includeBuild
build-logic
outside pluginManagement { ... }
as it is not a plugin you are afterVampire
05/25/2023, 9:27 AMbuild-logic
just includeBuild
it inside and outside, that's fine too.Daniele Segato
05/25/2023, 9:29 AMincludeBuild("build-logic")
outside buildScripts / pluginManagement I still get the Could not find any matches for
errorDaniele Segato
05/25/2023, 9:31 AMpluginManagement {
includeBuild("build-logic")
repositories {
gradlePluginPortal()
google()
mavenCentral()
}
}
plugins {
id("com.gradle.enterprise").version ("3.11.2")
}
gradleEnterprise {
buildScan {
termsOfServiceUrl = "<https://gradle.com/terms-of-service>"
termsOfServiceAgree = "yes"
publishOnFailure()
}
}
dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories {
google()
mavenCentral()
}
}
includeBuild("build-logic")
buildscript {
dependencies {
classpath("mypackage.buildlogic:convention:+")
}
}
Vampire
05/25/2023, 11:42 AMDaniele Segato
05/25/2023, 11:57 AMVampire
05/25/2023, 12:07 PMincludeBuild
outside the pluginManagement { ... }
for it to work at least.
The buildscript
classpath
dependencies are the dependencies that you need to compile and execute the settings script (except for some special blocks like buildscript
and pluginManagement
and plugins
which are executed separately up-front). But if you need to depend on something from the includeBuild
, then it cannot work, because to evaluate the includeBuild
you first need to compile and execute the settings script. But to compile and execute the setting script you would need the result of doing it. You see the endless recursion coming? π
If you would need those extensions within the settings script, it would also work, but then only with the plugin-approach. Because the includeBuild
within the pluginManagement
is evaluated separately first, so that those included builds can contribute actual settings plugins to be used in the same settings script. So if you then apply a plugin - and be it no-op - from that included build, it (and all classes in the same artifact) is automatically added to the buildscript classpath of the settings script and you could use the extension functions, except for in some special blocks like pluginManagement
, or buildscript
, as again, those are evaluated separately first.Vampire
05/25/2023, 12:10 PMVampire
05/25/2023, 12:10 PMDaniele Segato
05/25/2023, 1:16 PM