Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android subprojects with Kotlin DSL

I'm working on migrating by Gradle build files to the Kotlin DSL and I encounter an issue.

On my parent build.gradle, I have the following piece of code



buildscript {
  repositories {
    google()
    mavenCentral()
  }
  dependencies {
    classpath 'com.android.tools.build:gradle:3.4.2'
    classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:${Version.kotlin}"
  }
}

allprojects {
  repositories {
    google()
    mavenCentral()
  }
}

subprojects {
  afterEvaluate { project ->

    if (project.plugins.findPlugin('com.android.application') ?:
      project.plugins.findPlugin('com.android.library')) {

      android {
        compileSdkVersion = Android.SDK_COMPILE
        defaultConfig {
          minSdkVersion Android.SDK_MIN
          targetSdkVersion Android.SDK_TARGET
          versionCode = Android.VERSION_CODE
          versionName = Android.VERSION_NAME
        }
        ...
      } 
    }
  }
}

This allows me to configure in only one place all the modules that are android applications or libraries.

However this doesn't seem to work when I migrated to kotlin:


buildscript {
  repositories {
    google()
    mavenCentral()
  }
  dependencies {
    classpath(Dependency.androidGradle)
    classpath(Dependency.kotlinGradle)
  }
}

allprojects {
  repositories {
    google()
    mavenCentral()
  }
}

subprojects {
  afterEvaluate {

    if (project.plugins.findPlugin("com.android.application") != null || 
        project.plugins.findPlugin("com.android.library") != null) {

      android { <<<<------------ Unresolved reference: android
        compileSdkVersion(Android.SDK_COMPILE)
        defaultConfig {
          minSdkVersion(Android.SDK_MIN)
          targetSdkVersion(Android.SDK_TARGET)
          versionCode = Android.VERSION_CODE
          versionName = Android.VERSION_NAME
        }
        ...
      }
    }
  }
}

The error is Unresolved reference: android and it looks like the android{} block is not recognized by the script compiler.

My theory is that the if checking for the subproject type is not enough, and I might have to cast or get a reference to some object in which I can call the android{} block, but honestly I do not know enough.

Any clues?

like image 449
Robert Estivill Avatar asked Aug 23 '19 13:08

Robert Estivill


Video Answer


1 Answers

Gradle Kotlin DSL determines the dependencies for each script from the gradle classpath plus the applied plugins. That's why its recommended to use the plugins { ... } block in the Kotlin DSL.

You need to add the android and kotlin plugins to your root without applying it.

plugins {
  id("<android-plugin>") version "<plugin-version>" apply false
  id("<kotlin-plugin>") version "<plugin-version>" apply false
}

Unfortunately, that will still not generate the static accessors for the root build script but it will give you access to the plugin classes within the script and you can reference them like:

subprojects {

  // BasePlugin is the common superclass of the AppPlugin and LibraryPlugin which are the plugin classes that "com.android.application" and "com.android.library" apply
  plugins.withType<BasePlugin> {

    // BaseExtension is the common superclass of the AppExtension and LibraryExtension which are the extension classes registered by the two plugins to the name "android"
    configure<BaseExtension> {

      // This block is typed correctly
      defaultConfig {
        // ...
      }
    }
  }
}
like image 169
efemoney Avatar answered Nov 15 '22 10:11

efemoney