How can I convert this from groovy to kotlin?

I have a multi module project and have the below in the root project build.gradle. How can I convert it to a Kotlin version?:

plugins {
   id 'org.sonarqube' version "2.8"
   id "jacoco"
}

allprojects {
   repositories {
       mavenLocal()
       maven { url = "<some-url>" }
   }
  
   // Specific for the case where the project is a Java project....
   if(project.plugin.findPlugin("java") {
       // All Java projects must be aligned to this single Java toolchain.
       java { 
           toolchain { 
               languageVersion = JavaLanguageVersion.of(17)
           }
       }
      test { useJUnitPlatform() }

       jacocoTestReport {
          reports {
              xml.required.set(true)
              xml.destination file("${buildDir}/reports/jacoco.xml")
          }
       }

      check.dependsOn jacocoTestReport

      plugins.withType(JacocoPlugin) {
          tasks["tests"].finalizedBy 'jacocoTestReport'
      }
     
      tasks.sonarqube { dependsOn 'jacocoTestReport' }

      task copyDeps(type: Copy, dependsOn: build) {
          from configurations.runtimeClasspath
          into "${buildDir}/my-deps"
      }
    
   }
}

I have tried to convert it but get stuck with no type safe accessors available. The primer says they are not available for Plugins applied via cross-project configuration - is that in this case (since I am using allProjects)?

To start with, you indeed should not use allprojects { ... } or similar, this is not only about missing accessors in Kotlin.

You should also strongly reconsider whether you use mavenLocal(), as it is broken by design in Maven and makes your builds slow and flaky.

Also if you want to react to plugins being applied, you should not things like findPlugin or plugins.withType or plugins. at all (look at its documentation), but for example pluginManager.withPlugin("...") { ... }.

Regarding the missing accessors, it is not that you apply the plugins via cross-project configuration. That would be the case if you would apply plugins within allprojects { ... } for example. But you don’t apply the plugins at all. But the effect is the same, you do not get the accessors. The accessors are only there for things Gradle knows will be present which it only know for things you applied within the same build script within its plugins { ... } block. Due to that, you can not use things like java { ... } for example.

You can of course use the type-unsafe more verbose API like configure<JavaExtension> { ... }, but you better stop following bad-practice, so stop using any allprojects { ... }, subprojects { ... }, project("...") { ... }, or similar. Instead consider using convention plugins, for example in buildSrc or an included build, for example implemented as precompiled script plugins.

1 Like

Thank you - do you have an example github repo which shows a simple way of using convention plugins?

And do you reccomend implemeting these plugins in Java?

In which language you implement them is pretty much up to you.

For local convention plugins I personally prefer using Kotlin, either in .kt files, or as precompiled script plugins which look almost like normal build scripts.

Just for public plugins, or better said for plugins that should be compatible with as many Gradle versions as possible without much hassle, I prefer using Java and there the lowest version supported by the lowest supported Gradle version, so Java 8 currently. That way you do not get into trouble with incompatibilities of Groovy or Kotlin versions and so on.

For an example, you can just have a look at the samples also linked in the docs I linked you to, or you can just use gw init to generate a new project, those also contain convention plugin usage.