https://gradle.com/ logo
Join Slack
Powered by
# plugin-development
  • k

    Kelvin Chung

    02/17/2025, 5:43 AM
    Question: is there something that has the “container” semantics from
    NamedDomainObjectContainer
    , but applied to a
    NamedDomainObjectList
    ?
    v
    • 2
    • 2
  • j

    jonathan gafner

    02/18/2025, 11:33 AM
    Hi I tried to publish a plugin to the portal - and got an email that the a TXT record is missing to validate that the repository corrisponde to the web url, so I added it and re-published the plugin. I tryoed to get news but since the 5th of February I got no answer, can somebody from the Gradle team please check and update me? Thanks
    👀 1
    v
    • 2
    • 1
  • f

    Felix de Souza

    02/18/2025, 3:35 PM
    is
    Project#getVersion
    going to be changed in Gradle 9 to be property aware? I thought it would, but I’m not seeing the annotation in the
    master
    branch, unless there is another branch tracking 9.x ?
    a
    t
    +2
    • 5
    • 15
  • k

    Kelvin Chung

    02/18/2025, 5:44 PM
    Question: is there a public API where I can do some introspection on registered bindings in an
    ExtensiblePolymorphicDomainObjectContainer
    ? I have a
    BuildService
    that contains an instance of it, and thus there are possible use cases for which duplicate registrations could happen.
  • k

    Kelvin Chung

    02/18/2025, 6:24 PM
    Question: Suppose I have this:
    Copy code
    abstract class MyExtension @Inject constructor(val service: Provider<MyService>) {
      // ...
    }
    
    class MyPlugin : Plugin<PluginAware> {
      override fun apply(target: PluginAware) {
        val gradle = when (target) {
          // ...
        }
        val service = gradle.sharedServices.registerIfAbsent(...)
      }
    }
    The intent is that if the plugin was applied to a
    Project
    , then I would create a
    MyExtension
    object in the project's extension container, but if the plugin was applied to a
    Settings
    , then the plugin would create a
    MyExtension
    project in both the settings and every project (and similarly if the plugin was applied to a
    Gradle
    . The question is: is that a good idea, and if so, how would I go about that?
  • n

    no

    02/20/2025, 11:13 AM
    So I just discovered by accident that my project had both junit 4 and junit 5 dependencies but was actually running using junit5 and the junit platform. I discovered this as I was confused why the
    @Before
    annotation had no effect (it's part of junit4). Is there a systematic way of preventing junit4 classes from creeping in to my junit5 project? And also vice versa?
    v
    t
    a
    • 4
    • 10
  • d

    Daniele Segato

    02/28/2025, 8:43 AM
    I had a convention plugin to extend in feature the Android plugin
    Copy code
    interface EnvironmentPluginExtension : Named {
        val applicationId: Property<String?>
        val applicationIdSuffix: Property<String?>
        val versionNameSuffix: Property<String?>
        val disableDebugBuild: Property<Boolean>
        val disableReleaseBuild: Property<Boolean>
    }
    Than I in the plugin I had
    Copy code
    pluginManager.apply("com.android.application")
    val extension = extensions.getByType<ApplicationExtension>()
    val envContainer = objects.domainObjectContainer(EnvironmentPluginExtension::class.java)
    (extension as ExtensionAware).extensions.add("environments", envContainer)
    envContainer.whenObjectAdded {
      val customSuffix = applicationIdSuffix.orNull // always null
      // ...
    }
    and used it to configure environments in the android application from the build.gradle.kts file I could do stuff like this
    Copy code
    android {
      
        environments {
            create("dev")
            create("stage") {
              applicationIdSuffix = ".staging"
            }
        }
    }
    I remember it used to work - but I used defaults values since I set this up. now that I needed it - several gradle versions laters - I noticed it doesn’t work anymore apparently
    whenObjectAdded
    is now running BEFORE the domain object is configured (which is absurd imho). I cannot use
    afterEvaluate
    can anyone give me some way of achieving what I need?
    v
    e
    • 3
    • 8
  • v

    Vampire

    02/28/2025, 11:55 AM
    Does anyone have a good idea how to model a task input property that can either be a file or directory? In pre-
    Property
    times I had an
    @Internal
    property that was set to either, and then a derived
    @Optional @InputFile
    read-only property and a derived
    @Optional @InputDirectory
    read-only property which checked whether the internal property is a file or directory and at execution time checked that exactly one of them is set. I'm thinking about cleaner ways to rewrite this, without splitting the task into multiple tasks.
    e
    m
    • 3
    • 4
  • c

    Charlie Hubbard

    02/28/2025, 6:40 PM
    Hi, I have a simple plugin I’ve written. It works great when used in my automated test and when used in single-project builds. Things get weird when it’s used in a subproject of a multi-project build. My plugin’s
    apply
    method looks like this:
    Copy code
    class SslCertGenPlugin implements Plugin<Project> {
    
        void apply(Project project) {
            Security.addProvider(new BouncyCastleProvider())
            CertificateExtension certificate = project.extensions.create( "certificate", CertificateExtension )
            project.tasks.register("generateCert", X509Certificate, project, certificate )
        }
    }
    However, in a multi-project build where the plugin could be applied to a subproject this doesn’t work. It assumes the plugin is defined at the root project even when it’s not. So how does a plugin know the difference? When it was applied at the root vs a subproject?
    t
    e
    v
    • 4
    • 24
  • c

    Clayton Walker

    03/05/2025, 9:12 PM
    Is it possible to get SourceSets without dependencies? For example, we're writing a code formatter/validator. We don't want sources that were registered with i.e. a code-generation framework (grpc/graphql/jooq/openapi) to be included as an input, nor do we want these task to be run if we're just checking format. Most formatting plugins I've seen end up depending on code-generation tasks, and I'm wondering if there's ways to avoid that
    v
    • 2
    • 3
  • s

    solonovamax

    03/08/2025, 10:35 PM
    Hi, I am trying to make a gradle plugin which configures the kotlin compiler options for a project. in my plugin's code, I have something which looks roughly like this:
    Copy code
    fun configureProject() {
        project.configure<KotlinProjectExtension> {
            if (this is HasConfigurableKotlinCompilerOptions<*>)
                configureCommonCompilerOptions()
    
            when (this) {
                is KotlinJvmProjectExtension    -> {
                    configureJvmCompilerOptions()
                }
    
                is KotlinMultiplatformExtension -> {
                    targets.withType<KotlinJvmTarget>().configureEach {
                        configureJvmCompilerOptions()
                    }
    
                    targets.withType<KotlinJsIrTarget>().configureEach {
                        configureJsCompilerOptions()
                    }
                }
            }
        }
    }
    
    private fun HasConfigurableKotlinCompilerOptions<*>.configureCommonCompilerOptions() {
        val nyx = this@NyxKotlinExtension
        compilerOptions {
            // ...
        }
    }
    however, the problem I'm facing is that when I add this plugin to another project and this code gets executed, then the following exception will be thrown:
    Copy code
    Caused by: java.lang.ClassCastException: class org.jetbrains.kotlin.gradle.dsl.KotlinJvmProjectExtension_Decorated cannot be cast to class org.jetbrains.kotlin.gradle.dsl.HasConfigurableKotlinCompilerOptions (org.jetbrains.kotlin.gradle.dsl.KotlinJvmProjectExtension_Decorated and org.jetbrains.kotlin.gradle.dsl.HasConfigurableKotlinCompilerOptions are in unnamed module of loader org.gradle.internal.classloader.VisitableURLClassLoader$InstrumentingVisitableURLClassLoader @47f6e669)
    this makes absolutely no sense as to why it's occurring, as
    KotlinJvmProjectExtension
    definitely inherits from
    HasConfigurableKotlinCompilerOptions
    . if you would like to see exactly what I'm doing, then that can be found here: https://github.com/solo-studios/nyx/blob/ae325df6221244572757ff661767621c8de01262/src/main/kotlin/ca/solostudios/nyx/plugin/compile/NyxKotlinExtension.kt#L370-L439 you can test this behaviour by doing the following in any gradle project: first, add the following to your `settings.gradle.kts`:
    Copy code
    pluginManagement {
        repositories {
            maven("<https://maven.solo-studios.ca/snapshots/>")
            mavenCentral()
            gradlePluginPortal()
        }
        resolutionStrategy {
            eachPlugin {
                if (requested.id.id == "ca.solo-studios.nyx") {
                    useModule("ca.solo-studios:nyx:0.3.0-20250308.223428-37")
                }
            }
        }
    }
    then, add the following to your `build.gradle.kts`:
    Copy code
    plugins {
        id("ca.solo-studios.nyx") version "0.3.0-SNAPSHOT"
    }
    re-import the project, and it will fail. the source code for the entire project can be found on github. edit: I have published a workaround, so you need to do funny resolution stuff to get the broken version.
    a
    v
    • 3
    • 3
  • g

    gmazzo

    03/10/2025, 10:24 AM
    Hello peeps, I got a request of adding GPG-signature to one of my plugins to support Dependencies Verification. After a bit of research/discussion (and after adding
    singing
    plugin to the project), we end up concluding the
    Plugin Portal
    is somehow ignoring
    .asc
    files, they are not there when requested by URL. Which is not the case for Maven Central's URL. Does anyone knows if this an intentional behavior of Plugins Portal, or a bug?
    👀 1
    m
    v
    • 3
    • 12
  • b

    Benoît Liessens

    03/11/2025, 6:25 PM
    Hi everyone, I’m centralising common gradle plugins (and config) in team specific gradle plugin. Now I hit problem with merging plugin extensions. So my QualityPlugin applies Detekt and configures detekt to run all rules:
    Copy code
    class QualityPlugin : Plugin<Project> {
        override fun apply(target: Project) {
            target.pluginManager.apply(DetektPlugin::class.java)
    
            target.extensions.configure(DetektExtension::class.java) {
                allRules = true
            }
        }
    }
    Now I have a project where I want to apply my QualityPlugin and, additionally, set a Detekt base line:
    Copy code
    plugins {
     id("my quality plugin name")
    }
     
    detekt {
        baseline = file("config/detekt-baseline-test.xml")
    }
    I was expecting Gradle to graciously merge the
    allRules
    and
    baseline
    settings in the DetektExtension but alas. The baseline is ignored. What am I doing wrong? Thanks
    t
    • 2
    • 2
  • h

    Harshjeet Patil

    03/14/2025, 4:58 PM
    Could not find method pluginName() for arguments on extension 'intellij' of type org.jetbrains.intellij.IntelliJPluginExtension. Does any one know what is this about? everytime I try to build it pops up
    v
    • 2
    • 2
  • d

    Denis Berestinsky

    03/15/2025, 12:46 PM
    Hi. I'm a developer of a Gradle plugin that uses
    TransformAction
    . There is a case when
    inputArtifact
    for
    TransformAction
    doesn't exist (But it has to be an output artifact of an another subproject). What's the proper way to handle this case? And what are the possible causes of it?
    v
    • 2
    • 1
  • v

    Vampire

    03/17/2025, 5:09 PM
    Does anyone know a good way how to find the reason for a
    CircularReferenceException
    in task ordering besides "just seeing the problem"? I have a cycle and I have no idea where it comes from right now.
  • k

    Kelvin Chung

    03/17/2025, 5:56 PM
    Question: when designing a
    ValueSource
    , is there a serializability requirement on the parameters? eg.
    Copy code
    abstract class MyValueSource : ValueSource<String, MyValueSource.Parameters> {
      interface Parameters : ValueSourceParameters {
        val myClient: Property<MyClient>
      }
    }
    vs.
    Copy code
    abstract class MyValueSource : ValueSource<String, MyValueSource.Parameters> {
      interface Parameters : ValueSourceParameters {
        val myService: Property<MyService> // from a BuildService provider
        val clientName: Property<String>
      }
      
      private val myClient = parameters.myService.zip(parameters.myClient) { ... }
    }
    I seem to recall that there being a case, but I want to make sure, since you can certainly design without.
    ➕ 3
    r
    m
    • 3
    • 6
  • b

    Ben Madore

    03/18/2025, 1:34 PM
    We have two types of repos, single-project, and multiple-sub-project. We have a conventions plugin that we apply to all projects and sub-projects. It has an extension that accepts the artifact name to be emitted by a given project, and reacts to the presents of the
    maven-publish
    plugin, configuring publication. e.g.
    val artifactName: Property<String> = project.objects.property(String::class.java)
    used as
    Copy code
    fooConventions {
        artifactName = "my-artifact-name"
    }
    a few times we’ve run into issues where someone copy-pastes some code and duplicates the artifact name, this unfortunately isn’t caught until the jar file is attempted to be published to artifactory, and user gets an unclear message that the artifact has already been published, and they tend to think it’s a CI problem instead of a project problem. What would be the most ideal way to validate that the configuration across all sub-projects does not contain any duplicates between each project’s
    conventions.artifactName
    property? Is this a valid use of a Shared Build Service? I could do it simply at the top level project and reach down into the subprojects, but i think then it’d have to be in an
    afterEvaluate
    which, as i understand it, is detrimental to config caching.
    v
    • 2
    • 3
  • n

    no

    03/21/2025, 8:02 AM
    Hey there 👋 I'm developing a Gradle plugin and I want to download a jar (r8 jar) from
    <https://storage.googleapis.com/r8-releases/>
    . I would normally add an ivy repository from my Gradle plugin to do this but this doesn't work if the consuming project has
    Copy code
    dependencyResolutionManagement {
      repositoriesMode.set(RepositoriesMode.PREFER_SETTINGS)
    }
    I could use a Gradle task to download the jar but then it wouldn't be cached like a dependency download is. Are there other alternatives here?
    t
    v
    +2
    • 5
    • 6
  • b

    Ben Bader

    03/21/2025, 3:25 PM
    Hi folks! I'm probably missing something obvious but - is there a simple way (in a Task action) to convert an arbitrary
    java.nio.file.Path
    into a
    FileTreeElement
    ? The paths are not guaranteed to point to files within the Gradle project; my interest here is in using a
    PatternSet
    to filter them, but the spec it creates only operates on
    FileTreeElement
    instances. Is such a thing even possible with the public API?
    v
    • 2
    • 3
  • s

    Slackbot

    03/23/2025, 7:59 AM
    This message was deleted.
    configuration-cache-report.htmloutput.logs
    f
    • 2
    • 2
  • k

    Karunakara NH

    03/25/2025, 7:37 AM
    👋 Hello, team! We are getting the below error while running the command on windows, unable to download the plugin, Could you please help here?
    p
    v
    • 3
    • 2
  • l

    Lebomodiko

    03/25/2025, 9:01 AM
    hey guys, it's my first time using android studio and i keep on getting this error when i run my code, how can i fix this?
    v
    • 2
    • 1
  • c

    Clayton Walker

    03/26/2025, 4:18 PM
    Strange request, is it possible to get a platform’s dependency version? Say there’s a tool that takes a lazy string, how would I go about something like
    Copy code
    extension {
        version = configuraitons.oneOfThem.incoming.platforms.matching("spring-boot-dependencies").versionOf("some-sub-dep")
    }
    That way I lazily retrieve a sub-version of a bom
    v
    • 2
    • 3
  • s

    Sergey Morgunov

    03/26/2025, 5:36 PM
    Hi, @Oleg Nenashev! 👋 Please tell me if there is any officially recommended guideline for naming of plugin IDs. For example, in my case, I want to separate our plugin into two separate ones (for Java and for Scala). So, I’m thinking of naming them 🤔 Was:
    com.example.myplugin
    Working version so far:
    com.example.myplugin-java
    com.example.myplugin-scala
    But I don’t really like this mixing of separators 🙃
    gradle fellow 1
    👀 1
    o
    e
    +3
    • 6
    • 9
  • r

    RTAkland

    04/03/2025, 5:20 AM
    Hi, im developing a gradle plugin compat for kotlin multiplatform project, i want to set the generated/kotlin/commonMain for commonMain sourceSet, set generated/kotlin/nativeMain for nativeMain sourceSet, my code is here
    Copy code
    target.extensions.getByType(KotlinMultiplatformExtension::class.java)
                            .sourceSets.findByName(it.value.targetName)?.kotlin
                            ?.srcDir("build/generated/kotlin/${it.value.targetName}")
    but it not work, only commonMain sourceSet are be set
    v
    • 2
    • 1
  • s

    Suhas Sharma

    04/07/2025, 5:22 PM
    hello i needed some help with publishing gradle plugin i am writing gradle plugin for kotlin foundation gsoc i had issues publishing it can anyone help me with it
    c
    c
    v
    • 4
    • 7
  • k

    Kevin Brightwell

    04/10/2025, 8:06 PM
    I have a gradle plugin that needs to find the transitive project dependencies for a project. As of Gradle 8, we do this. However, I was upgrading Gradle and got a deprecation warning we can't access the
    dependencyProject
    property anymore. What is the Gradle 9 way to do this?
    v
    • 2
    • 4
  • a

    Adam

    04/11/2025, 10:12 AM
    So we distribute our convention plugins via an internal artifactory, but keep them in the same repository for quick iteration, so that when we want to modify them, we just
    includeBuild
    the directory in our settings script This works fine, however, I want to add all these plugins to the project classpath as such by adding them to the root project build script
    Copy code
    plugins {
      alias(libs.plugins.internal.company.plugin) apply false
      alias(libs.plugins.internal.company.otherPlugin) apply false
      // etc
    }
    When I do this, it works fine until I include the build for local iteration. I basically can’t sync because of the following error
    Error resolving plugin [id: 'plugin.name', version: '1.0.43'] > The request for this plugin could not be satisfied because the plugin is already on the classpath with an unknown version, so compatibility cannot be checked.
    I’m guessing this happens because when I include the build, gradle seems to add the plugins in it to the classpath with an
    unknown
    version, but then also tries to grab the latest published versions since I’m also trying to add them to the classpath, thus creating a conflict. Is there any way to work around this or will I have to resort to just commenting out my plugins from the
    plugins
    block whenever I want to work on them locally?
    v
    p
    n
    • 4
    • 9
  • c

    Callum Rogers

    04/14/2025, 2:12 PM
    For Isolated Projects (which we are far, far away from using, but I’m trying to write new plugin code “correctly”) - is the idea that since you can’t access the extensions/properties/other state of other projects, every exchange of information between two project should happen through resolving a
    Configuration
    with custom attributes a la https://docs.gradle.org/current/userguide/cross_project_publications.html#sec:variant-aware-sharing? Or is there some other way to safely read data from other projects?
    a
    m
    +3
    • 6
    • 54
1...3233343536Latest