Main file, which use apply from
build.gradle.kts
plugins {
id("com.android.library")
kotlin("android")
kotlin("android.extensions")
kotlin("kapt")
}
apply {
from("$rootDir/config/include.gradle.kts")
}
android {
...
}
second file which includes single files for apply
include.gradle.kts
apply {
from("$rootDir/config/exclude.gradle.kts")
from("$rootDir/config/default.gradle.kts")
from("$rootDir/config/testing/testing.gradle")
}
and in exclude.gradle.kts I have:
android {
packagingOptions {
exclude ("META-INF/DEPENDENCIES.TXT")
exclude ("META-INF/LICENSE.TXT")
}}
But it failed on:
Script compilation errors:
Line 01: android {
^ Unresolved reference: android
Line 02: packagingOptions {
^ Unresolved reference: packagingOptions
Line 03: exclude ("META-INF/DEPENDENCIES.TXT")
^ Unresolved reference. None of the following candidates is applicable because of receiver type mismatch:
public fun Configuration.exclude(group: String? = ..., module: String? = ...): Configuration defined in org.gradle.kotlin.dsl
When I didn't use KTS file, but .gradle and Groovy and proper syntax, it works as expected. All excludes from the file are "included" into main build.gradle.kts into android and work as expected without any error.
Work same as when use Groovy
Failed on: Unresolved reference: android
Gradle 5.0
------------------------------------------------------------
Build time: 2018-11-26 11:48:43 UTC
Revision: 7fc6e5abf2fc5fe0824aec8a0f5462664dbcd987
Kotlin DSL: 1.0.4
Kotlin: 1.3.10
Groovy: 2.5.4
Ant: Apache Ant(TM) version 1.9.13 compiled on July 10 2018
JVM: 1.8.0_181 (Oracle Corporation 25.181-b13)
OS: Windows 10 10.0 amd64
Android Studio 3.4 Canary 7
Build #AI-183.4284.148.34.5159543, built on December 3, 2018
JRE: 1.8.0_152-release-1248-b01 amd64
JVM: OpenJDK 64-Bit Server VM by JetBrains s.r.o
Windows 10 10.0
kotlin: 1.3.11
using buildSrc
The accessors aren't generated for script files that aren't the project script file.
Yes, I have the same experience with a multi-module project. I have put some common android {} declarations into a common-android.gradle file and apply it from each module's build.gradle.kts file. Its contents are:
android {
compileSdkVersion 28
buildToolsVersion "28.0.3"
defaultConfig {
minSdkVersion 15
targetSdkVersion 28
multiDexEnabled true
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}
Unfortunately, I cannot convert this common file to Kotlin or I get the same Unresolved reference: android error as @mtrakal. On the other hand, if I keep the file to Groovy and apply it as such, it works correctly.
You can declare the extension manually in your exclude.gradle.kts.
Full disclosure, I'm not an android developer.
However, if you put this logic in your build.gradle.kts file:
android {
packagingOptions {
exclude ("META-INF/DEPENDENCIES.TXT")
exclude ("META-INF/LICENSE.TXT")
}}
From there, you should be able to jump to the declaration of the android variable.
It should look something like this:
/**
* Configures the [android][[some long import here].AndroidExtension] project extension.
*/
fun Project.android(configure: [some long import here].AndroidExtension.() -> Unit) =
extensions.configure("checkstyle", configure)
You can copy and paste that logic into the bottom of your exclude.gradle.kts and everything should work from there.
When we put everything from exclude.gradle.kts / common-android.gradle.kts to build.gradle.kts we don't need these files (exclude.gradle.kts / common-android.gradle.kts).
The reason, why we move some common parts to a single file is, that we use the same code in all modules...
like:
/mobile/build.gradle.kts contains apply(from("exclude.gradle.kts"))
/wear/build.gradle.kts contains apply(from("exclude.gradle.kts"))
/common/build.gradle.kts contains apply(from("exclude.gradle.kts"))
/sub-mobule1/build.gradle.kts contains apply(from("exclude.gradle.kts"))
/sub-mobule2/build.gradle.kts contains apply(from("exclude.gradle.kts"))
etc...
All modules use the same code and we don't want to edit on all submodules, so we use one file, which is (shared) applied in all modules.
In this files are just part of android code, every build.gradle.kts contains different parts inside and shared part from exclude.gradle.kts / common-android.gradle.kts
@mtrakal - please check out this documentation. When you are working in an applied script (aka a script plugin), type-safe accessors are not yet available (for standard built-ins and for applied plugins).
The way kotlin-dsl makes these available (android { }, etc) is by generating them and including them on the main build script's classpath automatically. For plugins applied through the plugins block, it also generates accessors so that they can be used just-in-time (I'm probably over-simplifying).
So when you are not in a main build script (settings, init, applied) or when you apply a plugin outside of the plugins block (i.e. apply()), you will not have access to type-safe accessors of the DSL.
What @JLLeitschuh is suggesting is a way to manually pull in the code for the accessors you want.
You do this by putting some sample code of what you want in the main build file (or the target code itself, temporarily), use your IDE to go to where the accessors are written/generated, and then manually paste the accessor code into the script where type-safe accessors are not automatically on the classpath.
After doing this, you will be able to run the configuration code using those accessors (aka, using the the DSL, android { }).
Note that just because you pull in an accessor for android { }, it will not automatically give you access to all the parts configurable in android. In the case of the exclude.gradle.kts script, you would need to pull in the accessors for both android { } and android.packingOptions { } (using the same method).
One problem I see with this is that when iterating through all subprojects, top script has no way of statically knowing of what type of project is each project in extensions. There is different extension class for library projects and app projects for example, but both are named android.
Also related to https://github.com/gradle/kotlin-dsl/issues/427
I've tried what @JLLeitschuh suggest but didn't work
val Project.`android`: AppExtension
get() =
(this as ExtensionAware).extensions.getByName("android") as AppExtension
fun Project.`android`(configure: AppExtension.() -> Unit): Unit =
(this as ExtensionAware).extensions.configure("android", configure)
@kiratheone A bit more information would be useful.
Hellow!
Use Gradle 5.2.1 and simple scripts:
build.gradle.kts
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
plugins {
kotlin("jvm") version "1.3.11"
}
group = "com.smouking"
version = "1.0-SNAPSHOT"
repositories {
jcenter()
}
dependencies {
compile(kotlin("stdlib-jdk8"))
}
tasks.withType<KotlinCompile> {
kotlinOptions.jvmTarget = "1.8"
}
apply(from ="ktlint.gradle.kts")
ktlint.gradle.kts
import org.jlleitschuh.gradle.ktlint.KtlintPlugin
buildscript {
repositories {
gradlePluginPortal()
}
dependencies {
//classpath(kotlin("gradle-plugin", version = "1.3.21"))
classpath("org.jlleitschuh.gradle:ktlint-gradle:7.1.0")
}
}
//The plugins {} block must not be used here
apply<KtlintPlugin>()
It failed on:
* Exception is:
java.lang.NoClassDefFoundError: org/jetbrains/kotlin/gradle/plugin/KotlinSourceSet
If uncomment classpath(kotlin("gradle-plugin", version = "1.3.21"))
It failed on:
* Exception is:
Caused by: java.lang.IllegalStateException: Could not find any convention object of type KotlinSourceSet.
because KotlinSourceSet. loaded diferent Classloader.
How to fix it?
This has nothing to do with the issue at hand...
Why not? I can not use apply(from=) for configure my project.
Should I do another issue?
@JLLeitschuh my external gradle.kts file
apply(plugin = "com.android.application")
/**
* Configures the [android][com.android.build.gradle.internal.dsl.BaseAppModuleExtension] extension.
*/
fun org.gradle.api.Project.`android`(configure: com.android.build.gradle.internal.dsl.BaseAppModuleExtension.() -> Unit): Unit =
(this as org.gradle.api.plugins.ExtensionAware).extensions.configure("android", configure)
I get an error
Script compilation errors:
Line 11: fun org.gradle.api.Project.`android`(configure: com.android.build.gradle.internal.dsl.BaseAppModuleExtension.() -> Unit): Unit =
^ Unresolved reference: android
Line 12: (this as org.gradle.api.plugins.ExtensionAware).extensions.configure("android", configure)
^ None of the following functions can be called with the arguments supplied:
public abstract fun <T : Any!> configure(p0: Class<TypeVariable(T)!>!, p1: Action<in TypeVariable(T)!>!): Unit defined in org.gradle.api.plugins.ExtensionContainer
@Incubating public abstract fun <T : Any!> configure(p0: String!, p1: Action<in TypeVariable(T)!>!): Unit defined in org.gradle.api.plugins.ExtensionContainer
public abstract fun <T : Any!> configure(p0: TypeOf<TypeVariable(T)!>!, p1: Action<in TypeVariable(T)!>!): Unit defined in org.gradle.api.plugins.ExtensionContainer
2 errors
any update on this? when can we expect a proper fix for the accessors?
As @JLLeitschuh, @fuzzyweapon mentioned, android {} isn't available in the applied script because limitations documented at https://docs.gradle.org/current/userguide/kotlin_dsl.html#type-safe-accessors
The issue pointed by @BulatMukhutdinov above is due to applied script plugins being evaluated in an isolated classloader. In other words they don't share the classpath of the plugins applied to the project build script, hence they cannot see com.android.* in the example. This is also a current limitation. FWIW, Groovy scripts are subject to the same limitation, but Groovy then rely on dynamic reflection for the better or worse.
If you'd use Kotlin DSL precompiled script plugins in buildSrc instead, then you'll get the type safe accessors and no classpath issues, see https://docs.gradle.org/current/userguide/kotlin_dsl.html#kotdsl:precompiled_plugins
Thanks for the answer @eskatos
Tried to use precompiled script, but with no luck
_buildSrc/src/main/kotlin/common-feature-android-library.gradle.kts:_
plugins {
id("com.android.library")
kotlin("android")
kotlin("kapt")
kotlin("android.extensions")
}
android {
compileSdkVersion(Versions.compileSdk)
defaultConfig {
minSdkVersion(Versions.minSdk)
targetSdkVersion(Versions.targetSdk)
versionCode = Releases.versionCode
versionName = Releases.versionName
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
getByName("release") {
isMinifyEnabled = false
proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro")
}
}
compileOptions {
sourceCompatibility = Versions.sourceCompat
targetCompatibility = Versions.targetCompat
}
}
dependencies {
implementation(project(":core"))
kapt(Google.daggerCompiler)
testImplementation("junit:junit:4.12")
androidTestImplementation("androidx.test.ext:junit:1.1.0")
androidTestImplementation("androidx.test.espresso:espresso-core:3.1.1")
}
Am i doing something wrong? Got the same error Unresolved reference: android, compileVersionSdk, defaultConfig, etc
According to documentation (https://docs.gradle.org/current/userguide/kotlin_dsl.html#kotdsl:precompiled_plugins) it got to work
What version of Gradle are you using?
I forgot to mention that type-safe accessors were added to precompiled script plugins in Gradle 5.3 https://docs.gradle.org/5.3/release-notes.html#kotlin-dsl
Gradle version 5.3.1
@BOMBeR369, I can't see anything obvious in the snippet above, maybe you miss the kotlin-dsl plugin applied in buildSrc/build.gradle.kts? Please use the forums for support questions https://discuss.gradle.org/
@eskatos it still doesn't work for me either, same unresolved reference errors
Same for me, unresolved reference errors
I have the same, can't make it work. Annoying that there's so little documentation about it.
Same.
Same
Same
The solution described above works for me.
If you can't make it work, please open another issue with details and a reproducer project so we can help you.
@eskatos can you publish a demo with Android? I can't solve this problem too...
Ok, the same problem here. Is there any demo how to resolve this problem?
Found the solution that worked for me. The only thing I need to do is to add android-gradle-plugin into buildSrc/build.gradle.kts. My buildSrc/build.gradle.kts (for example):
buildscript {
repositories {
jcenter()
google()
}
dependencies {
classpath("com.android.tools.build:gradle:3.5.0")
}
}
plugins {
`kotlin-dsl`
}
allprojects {
repositories {
jcenter()
google()
}
}
gradlePlugin {
plugins {
register("symbols-plugin") {
id = "symbols"
implementationClass = "com.don11995.build.Symbols"
}
}
}
kotlinDslPluginOptions {
experimentalWarning.set(false)
}
dependencies {
implementation("com.android.tools.build:gradle:3.5.0")
}
@personshelldon @eskatos This isn't working in the same scenario..
I changed my build script of buildSrc to the one @personshelldon suggested and tried moving the file with the android config closure into the buildSrc folder.. It still doesn't work..
Can you please give more instructions? A lot of us have trouble converting our groovy gradle scripts to kotlin
I want to have a common file for com.android.application and com.android.library, so I can't have either plugin in the plugins declaration closure. Things work and build as a plugin if I have any id in the plugins closure while keeping the common gradle.kts file in the buildSrc module though.
Is it possible to have kotlin in such a case?
@Sai-Teja usually the app module is the application, so you can do an if else to check the name, if it is app, you use application, if not, library.
@JavierSegoviaCordoba That is true. But I wanted to have something generic so that apps with multiple targets such as ones that have the same code base but different app modules for wear OS and store app can use.
After spending about two days on this, I feel that it is better to stick with groovy for gradle scripting. It is just more flexible in allowing to split the code among files and better support online.
I have 3 files right now.
android-app.gradle, android-lib.gradle, android-common.gradle
With kotlin scripting, I need to package these into a plugin.. which needs to have the android plugin compulsorily in the file for getting the android object. @eskatos correct me if I am wrong.
Apart from these I have some protobuf and grpc gradle files as well.. Groovy just looks simpler as of today.
@Sai-Teja I have multiple kts files: for Android modules, for Kotlin only modules, etc. You should can get the same behavior with kts. Have you tried to create your own plugin?
Same issue here. Please add sample project on how to solve this problem. Also could you reopen this issue? It's actually not solved. @eskatos
My solution: https://stackoverflow.com/a/60482635/5279996
We want to apply specific android block using pre-compiled scripts with Kotlin DSL in order to favor re-usability and modularization.
1 - We have to compile the com.android.tools.build:gradle:x.x.x by adding the dependency in the build.gradle.kts:
plugins {
`kotlin-dsl`
`kotlin-dsl-precompiled-script-plugins`
}
repositories {
jcenter()
google()
}
dependencies {
implementation("com.android.tools.build:gradle:4.0.0")
}
2 - In our script file, add the plugin com.android.application or com.android.library and do not apply it: apply false. Here is an example, in my case called variants.gradle.kts.
package scripts
plugins { id("com.android.application") apply false }
android {
buildTypes {
getByName("debug") {
isMinifyEnabled = false
applicationIdSuffix = ".debug"
isDebuggable = true
}
getByName("release") {
isMinifyEnabled = true
proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"),
"proguard-rules.pro")
}
}
flavorDimensions("version")
productFlavors {
create("dev") {
dimension = "version"
applicationIdSuffix = ".dev"
versionNameSuffix = "-dev"
}
create("internal") {
dimension = "version"
applicationIdSuffix = ".internal"
versionNameSuffix = "-internal"
}
create("public") {
dimension = "version"
}
}
}
3 - Apply the pre-compiled script plugin in your android application/module:
plugins {
// Application Specific plugins
id(BuildPlugins.androidApplication)
id(BuildPlugins.kotlinAndroid)
id(BuildPlugins.kotlinAndroidExtensions)
// Internal Script plugins
id(ScriptPlugins.variants)
}
I hope that helps.
Cheers!
@android10 Is the first script inside buildSrc?
And I am assuming BuildPlugins.androidApplication is not auto-generated so, I am using strings like "com.android.application" instead.
I am still getting a "Unresolved reference: android" inside my "android-common.gradle.kts"
Most helpful comment
@eskatos can you publish a demo with Android? I can't solve this problem too...