Lars Ködderitzsch
03/12/2024, 6:58 AMlib/plugins
directory of the distribution were unsuccessful.
Is there a way to do this?Marek
03/12/2024, 7:57 PMonVariants
together with tasks.named
to make my task dependent on tasks assemble(CapitalizedVariantName)
and bundle(CapitalizedVariantName)
to make sure it gets executed whenever I build either apk or app bundle. But apparently the aforementioned tasks are not yet in the task graph at this point.
I want to make sure its done right following the configuration avoidance principles and want to ensure tasks are not created when not needed.
I thought that maybe artifacts API can be used. In the end I want to produce a file, but the file I want to generate shouldn't be a part of the apk, just a file that should eventually be committed to the repository.Dylan Bolger
03/13/2024, 4:33 PMproject.version
using a plugin I've written. Ideally, I'd like the plugin to support loading the project.version
from the project.rootProject.version
if one was not provided in the `project`'s build.gradle. Is there a method I can use to configure this at the correct time without using project.afterEvaluate
? I'm unsure if the project needs to be evaluated before the version can be determined, or if there's a different way I should be looking to evaluate the version. I tried using project.configure(project.version, { //... }
but this seems to be too early, considering the property I'd like to evaluate is still the default convention
value.StefMa
03/14/2024, 3:32 PMHttpClient
) and then calls some function of this HttpClient
. Right now I put the ApiToken
(String) into the task and created the HttpClient in the TaskAction
function.
Now I want test this with TestKit.
Obviously, I don't want to test the real HttpClient
call and want to fake it.
For this I thought I can add the HttpClient
as a Property<HttpClient>
to the task and use it as @Internal
.
But with that approach the configuration cache fails.
cannot serialize object of type 'kotlinx.coroutines.scheduling.DefaultIoScheduler', a subtype of 'java.util.concurrent.Executor', as these are not supported with the configuration cache.
.. And moreI also once created a custom
BuildService
to @Inject
the HttpClient
.
But this also didn't worked as expected because in test I couldn't apply my plugin because this would create a real instance of the HttpClient
. Not applying the plugin failed because for some reasons my source code was not added to the test classpath if I don't apply the plugin (sounds weird, but this was the case 🤷 ). Therefore I couldn't use any classes of my plugin...
Reading about this a bit more I came to the conclusion that my question might be way more general:
How to add a custom object to a Task that works with the configuration cache 🙈
Seems that right now the best solution is to create an BuildService for these cases..? But this sounds a bit wrong to me... 🤔 🤷
Appreciate any help here!Kelvin Chung
03/15/2024, 4:50 PMabstract class MyTask : DefaultTask() {
init {
val task = project.tasks.register("myTask-$name-derived") {
}
finalizedBy(task)
}
}
What would be a sane redesign so that you don't have this?Wesley Hartford
03/15/2024, 11:36 PMGiuseppe Barbieri
03/16/2024, 9:35 AMmaven-publish
) from within another ::apply
plugin?James
03/18/2024, 4:43 PMsolonovamax
03/19/2024, 2:23 AMArtifactRepository
, similar to a MavenArtifactRepository
, however it
• only accepts uploads (not downloads) of artifacts
• will pack all the artifacts into a zip before uploading
• otherwise acts identically to DefaultMavenArtifactRepository
(ie. will generate .sha1
, .sha256
, and .sha512
files, .md5
files, will build the pom, etc.)
the problem is, looking at how ArtifactRepository
are implemented, it seems like I'd need to use a lot of internal apis, as I'd most likely need to have my own instance of MavenPublisher
, among other things, in order to be able to properly bundle the files into a zip.
does anyone happen to know of any custom implementations of `ArtifactRepository`s I could look at, or some pointers on what things I should look into?Kelvin Chung
03/20/2024, 6:08 PMval taskA = tasks.named("A")
tasks.register("B") {
onlyIf { taskA.get().onlyIf.isSatisfiedBy(this) }
}
I think the intent is that B has the same onlyIf
conditions as A, whatever they they may be, but the issue is that onlyIf
appears to be internal API even though the compiler doesn't flag it. Any advice on a redesign?JohnBuhanan
03/20/2024, 8:39 PMval composeAllowList = Providers.of(
setOf(
":foo:ui",
":bar:ui",
":etc:ui", // 40 such entries in here
)
)
fun Project.composeAllowList() {
val modulePath = path
tasks.withType(KotlinCompile::class.java).configureEach {
inputs.property("composeAllowList", composeAllowList)
doFirst {
// We check to see if the Compose Compiler plugin has been added to the compiler args.
val usingComposeCompiler =
kotlinOptions.freeCompilerArgs.any { it.contains("androidx.compose.compiler") }
if (usingComposeCompiler) {
val composeAllowlist = inputs.properties["composeAllowList"] as Set<String>
val moduleInComposeAllowlist = composeAllowlist.contains(modulePath)
// If the module is using Jetpack Compose but isn"t in the allowlist...💥
if (!moduleInComposeAllowlist && !modulePath.endsWith("twig")) {
throw GradleException("Module $modulePath is not in the allowlist for Compose!")
}
}
}
}
}
Marcin Robaczyński
03/22/2024, 1:02 PM@Option
but unless I invoke each task with their own option provided it won't work. Calling group task will fail as that Option
is not registered for it. I know on alternative would be to use a project property but that would enforce project getting reconfigured which I'd rather avoid.
Running ./gradlew taskToRunThemAll
invokes all of child tasks (myTaskMain
, myTaskTest
etc).
This will work fine:
./gradlew myTaskMain --my-input=foo myTaskTest --my-input=foo
This will fail as there is no option with the same name declared for the group task:
./gradlew taskToRunThemAll --my-input=foo
If I do create another task type and add my-input
option to it, it will consume it and the parameter won't be shared anyway.
class MyPlugin : Plugin<Project> {
override fun apply(target: Project) {
val extension = target.extensions.getByType(KotlinProjectExtension::class.java)
val perSourceTask = extension.sourceSets.all { set ->
val dirs = set.kotlin.sourceDirectories.toList()
val taskName = "myTask${set.name.capitalized()}"
target.tasks.register(taskName, SomeSourceTask::class.java) {
it.setSource(dirs)
}
}
val topLevelTask = target.tasks.register("taskToRunThemAll")
topLevelTask.configure { it.dependsOn(perSourceTask)
}
}
abstract class SomeSourceTask : SourceTask() {
@get:Option(
option = "my-input",
description = "..."
)
@get:Input
abstract val myInput: Property<String>
}
efemoney
03/22/2024, 1:59 PMAnthony Johnson
03/27/2024, 6:03 AMsolonovamax
03/28/2024, 7:02 PMAbstractMavenPublisher
, isn't accessible when using implementation(gradleApi())
(even though other internal classes are..?) for some reasonKelvin Chung
03/28/2024, 8:45 PMabstract class MyValueSource : ValueSource<String, MyValueSource.Parameters> {
interface Parameters : ValueSourceParameters {
abstract val client: Property<MyClient>
// other stuff
}
}
Just to clarify, then, that it's generally better to have a client constructed internally rather than have it passed in...?Nicklas Ansman
03/29/2024, 8:00 PMProjectDependencyInternal
) to emulate what typesafe project accessors. I understand this is risky but feel the risk is worth it in this case, but of course I'd prefer to not use the internal API. Is there any other way around this with today's API that doesn't require extra syntax?Andreas Wenger
03/31/2024, 1:14 PMArjan van Wieringen (avwie)
03/31/2024, 4:08 PMKelvin Chung
04/01/2024, 12:43 AMabstract class MyTask @Inject constructor(private val layout: ProjectLayout) : DefaultTask()
and this:
abstract class MyTask : DefaultTask() {
private val layout = project.layout
}
It seems like the first is preferred over the second - any insights as to why that is?Tapchicoma
04/03/2024, 9:09 PMListProperty
ignoring non-configured `Provider`s? So far ListProperty
complains that provider does not have value configured. Example of what I want to do:
val listOfString = objects.listProperty<String>()
val firstProvider = objects.property<String>()
val secondProvider = objects.property<String>().convention("two")
listOfString.add(firstProvider)
listOfString.add(secondProvider)
logger.warn("ZZZ: ${listOfString.get()}")
Marc Hermans
04/08/2024, 9:08 AMMarc Hermans
04/08/2024, 9:10 AMLennart Jörelid
04/11/2024, 3:13 PMJan Celada
04/12/2024, 3:26 AMapply() { }
i register tasks called "deploy" deploy task executes some code checking. Executing it will be: ./gradlew myappname:deploy
I have no issue so far everything it working.
When i look at the terminal I wonder why it is calling other projects. Let's say i have other project name app1
, app2
, app3
calling ./gradlew myappname:deploy
results to:
> Configure project: app1
> Configure project: app2
> Configure project: app3
> Configure project: myappname
Well I just want to understand what is happening to make a informed decision if I want to pursue this
1. If I have 100 projects, so it will be called right?
2. Is this secure?
3. Am I doing the right thing?
4. Can this be improve?Alex Kopp
04/16/2024, 11:02 AMKelvin Chung
04/18/2024, 7:58 PMplugins {
groovy
`kotlin-dsl`
}
In my plugin entry point (myPlugin.gradle.kts
), I have this:
import my.groovy.sources.ThisClass
(ie. ThisClass
is part of the Groovy source set)
Right now, my IDE is not reporting any issues, but it looks like the compileKotlin
task is barfing because it can't find ThisClass
. Is there something that needs to be wired specifically, possibly to ensure that the Groovy and Kotlin code is interoperable?Kelvin Chung
04/19/2024, 11:17 PMabstract class AbstractMyTask : DefaultTask() {
abstract val base: Provider<String>
private val derived = base.map { ... }
}
abstract class MyTask : AbstractMyTask {
override val base = ...
}
It seems Gradle is unable to create MyTask
instances due to a NullPointerException
on derived
in AbstractMyTask
. Is this a known thing?Simon Mavi Stewart
04/21/2024, 6:59 AMProjectConnection.model
to return custom `ProgressEvent`s to the caller? I think that if my ToolingModelBuilder
can get hold of a ProgressListener
, I should be able to call statusChanged
, but it’s not clear how to get hold of the instance.Jendrik Johannes
04/25/2024, 8:44 AMbuild.gradle(.kts)
file, we end up with a file of several 100 lines for some projects. Which is not practical. Therefore, we want to split up the configuration. In our build system, we have concept called "*process*" which corresponds to one or more Gradle tasks. A project can have several 100 of these processes. We want to have one configuration file per process. How do we achieve this best? Here is what we tried/do now:
• Using pre-compiled script plugins is not an option. The files are something developers work with regularly. Changing a configuration cannot invalidate the whole build. Which pre-compiled script plugins do, as changing them changes the plugin classpath.
• We started using Kotlin DSL for good IDE support in IntelliJ for our custom DSL/extension.
• But for the split-up, the only option we found is "traditional" script plugins in Groovy DSL. Now we have a mix of build.gradle.kts
(Kotlin) and .gradle
(Groovy) script files.
◦ (Is there a way to use the Kotlin DSL here with a custom extension? I think there isn't right?)
• Many developers will probably use VS Code as they use it for the actual development as well. And the Kotlin DSL support is not good here, which weakens the argument for Kotlin DSL in general.
I am not happy with the mixed DSL situation we have right now. The only "acceptable" solution I see right now is moving completely to Groovy DSL. But also there the IDE support is bad even in IDEA. Our custom extension is not recognized in the script plugins (.gradle
files). I am not very satisfied with the solution because of that. And I wonder if there is any other alternative I am missing.