Search code examples
androidkotlingradlegradle-kotlin-dslandroid-multi-module

Android App module's build.gradle.kts Unresolved reference error when importing a Kotlin class from an included (composite) module


In the #NowInAndroid sample app a Kotlin file NiaBuildType from an included module is being imported in the app modules build.gradle.kts file.

###build.gradle.kts (:app)

import com.google.samples.apps.nowinandroid.NiaBuildType

I have tried achieving almost the same result but every time I get Unresolved reference: au error.

My package structure in the included build is the same as my app module to enable transitive dependency. unlike the NIA app I don't have convention plugins in a submodule (convention module is included in the build-logic module which itself is included in the project using pluginmanager{}) and only have one included buildplugin module. Here is my file in my included module buildplugin :

package au.com.myproject
object AppVersion {
    const val versionCode = 1
    const val versionName = "1.0"
}

here is the project's settings.gradle.kts file:

pluginManagement {
    includeBuild("buildplugin")
    repositories {
        google()
        mavenCentral()
        gradlePluginPortal()
    }
}

This is my buildplugin module build.gradle.kts file:

plugins {
    `kotlin-dsl`
}

group = "au.com.myproject.buildplugin"

repositories {
    google()
    mavenCentral()
}

dependencies {
    compileOnly(gradleApi())

    implementation("com.android.tools.build:gradle:8.1.0")
    implementation(kotlin("gradle-plugin"))
}

and this is my usage in the app modules build.gradle.kts:

import au.com.myproject.AppVersion

plugins {
    ...
}

android {
    namespace = "au.com.myproject"
    compileSdk = 34

    defaultConfig {
        applicationId = "au.com.myproject.pai"
        minSdk = 24
        //noinspection OldTargetApi
        targetSdk = 33
        versionCode = AppVersion.versionCode
        versionName = AppVersion.versionName

        testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
    }
...

If I use buildSrcinstead of composite build, the object can be imported without any issue.

I am not sure what I am missing and have been smashing my head against the wall for a couple of days now trying different approaches.


Solution

  • I think the trick here is that you need to define and reference the plugin explicitly if it's not in buildSrc. buildSrc acts like an auto-included plugin.

    (Looking at the app/build.gradle.kts in Now-In-Android, you'll see the plugins registered by the build-logic module being pulled in in the plugins block.)

    To go without buildSrc, I think the following should work. (They're similar to an included plugin I've defined in a build)

    1. In your buildplugin/build.gradle.kts, add

      // Copyright 2023 Google LLC.
      // SPDX-License-Identifier: Apache-2.0
      
      // at top
      plugins {
          `java-gradle-plugin`
      }
      
      ...
      
      gradlePlugin {
          plugins.register("buildplugin") {
              id = "buildplugin"
              implementationClass = "au.com.myproject.buildplugin.BuildPlugin"
          }
      }
      
    2. Create a BuildPlugin if you don't already have one. Something like

      // Copyright 2023 Google LLC.
      // SPDX-License-Identifier: Apache-2.0
      class BuildPlugin: Plugin<Project> {
          override fun apply(project: Project) {
              // register tasks, create extensions if needed
          }
      }
      

      (I'm not positive you need implementationClass and the plugin class if you don't need to register tasks or create extension...)

    3. Your settings.gradle.kts looks good; it includes buildplugin during the build and makes it visible to other modules.

    4. Explicitly use the plugin in your app/build.gradle.kts

      // Copyright 2023 Google LLC.
      // SPDX-License-Identifier: Apache-2.0
      plugins {
          ...
          id("buildplugin")
      }