I'm having trouble using Catalog Version in gradle, which I'm trying to apply to my project. I took an example from here https://github.com/android/nowinandroid but when I get an error like in :
Extension of type 'LibraryExtension' does not exist. Currently registered extension types: [ExtraPropertiesExtension, LibrariesForLibs, VersionCatalogsExtension, BasePluginExtension, DefaultArtifactPublicationSet, SourceSetContainer, ReportingExtension, JavaPluginExtension, JavaToolchainService, NamedDomainObjectContainer<BaseVariantOutput>, BaseAppModuleExtension, ApplicationAndroidComponentsExtension, KotlinAndroidProjectExtension, KotlinTestsRegistry]
at org.gradle.internal.extensibility.ExtensionsStorage.getHolderByType(ExtensionsStorage.java:88)
at org.gradle.internal.extensibility.ExtensionsStorage.configureExtension(ExtensionsStorage.java:70)
at org.gradle.internal.extensibility.DefaultConvention.configure(DefaultConvention.java:189)
at AndroidLibraryConventionPlugin.apply(AndroidLibraryConventionPlugin.kt:30)
at AndroidLibraryConventionPlugin.apply(AndroidLibraryConventionPlugin.kt:10)
The code I'm trying to implement is like this:
internal fun Project.configureKotlinAndroid(
commonExtension: CommonExtension<*, *, *, *>,
) {
commonExtension.apply {
compileSdk = 32
defaultConfig {
minSdk = 21
}
compileOptions {
compileOptions {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}
}
kotlinOptions {
jvmTarget = JavaVersion.VERSION_1_8.toString()
}
}
val libs = extensions.getByType<VersionCatalogsExtension>().named("libs")
dependencies {
}
}
and after that it is called here
class AndroidLibraryConventionPlugin : Plugin<Project> {
override fun apply(target: Project) {
with(target) {
with(pluginManager) {
apply("com.android.application")
apply("org.jetbrains.kotlin.android")
}
extensions.configure<LibraryExtension> {
configureKotlinAndroid(this)
defaultConfig.targetSdk = 32
}
val libs = extensions.getByType<VersionCatalogsExtension>().named("libs")
dependencies {
}
}
}
}
you need to add gradle library into your buildSrc gradle file dependencies:
compileOnly("com.android.tools.build:gradle:7.4.0")
then it will import LibraryExtension class
Related
I have separate groovy script that adds flavors to my android project. And i can apply it no problem in build.gradle files. But calling it from kotlin build.gradle.kts file im getting error.
I have flavors.gradle file
ext.configFlavors = {
flavorDimensions "brand"
productFlavors {
myBrand {
dimension "brand"
}
}
And i can easilly call this from build.gradle files
android{
...
with configFlavors
}
But in build.gradle.kts files i get:
Could not find method flavorDimensions() for arguments [brand] on project ': myModule' of type org.gradle.api.Project.
My build.gradle.kts looks like this:
import com.android.build.gradle.LibraryExtension
plugins {
id("com.android.library")
id("org.jetbrains.kotlin.android")
}
apply(from ="${rootProject.projectDir}/buildSrc/flavors.gradle" )
val configFlavors: groovy.lang.Closure<LibraryExtension> by extra
android {
compileSdk = Versions.compile_sdk_version
defaultConfig {
minSdk = Versions.min_sdk_version
targetSdk = Versions.target_sdk_version
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
consumerProguardFiles("consumer-rules.pro")
}
buildTypes {
//Dev
create("dev") {
isMinifyEnabled = false
proguardFiles(getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro")
}
//Staging
create("staging") {
isMinifyEnabled = false
proguardFiles(getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro")
}
//Production
create("production") {
isMinifyEnabled = false
proguardFiles(getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro")
}
}
// I am able to call the closure but i got the error
configFlavors()
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = "1.8"
}
buildFeatures {
viewBinding = true
}
}
dependencies {
implementation(fileTree("include" to listOf("*.jar"), "dir" to "libs"))
implementation(project(":domain"))
// list of dependencies
}
Extra properties can be accessed with the following syntax:
// get an extra property from the current project
val myProperty: String by extra
// or from the root project
val myNewProperty: String by rootProject.extra
However, configFlavours is not a simple primitive value, it's a Closure.
It's possible to access Closures in Kotlin, but without knowing what type the Closure should apply to, it's not possible to use it.
// Replace `Any` with the actual type, if known
val configFlavours: groovy.lang.Closure<Any> by extra
println(configFlavours)
// > Configure project :
// flavours_atn69ibjqzvnwf0cp7hb75l45$_run_closure1#398b577e
There are more through examples in the Gradle docs
P.S. your code has both flavour and flavor - pick a spelling please :)
I ended up adding another closure that takes libraryExtension as parameter. And using it from gradle.build.kts files. It is not optimal but it seems to work.
ext.configFlavorsWithParam = { libraryExtension ->
libraryExtension.flavorDimensions "brand"
libraryExtension.productFlavors {
brand1 {
dimension "brand"
}
}
And im calling it like this
android{
...
configFlavorsWithParam(this)
}
I'd like to Maven publish in my Android app, and I'm using kotlin-dsl for gradle files. This is how I'm trying to publish my code:
subprojects {
plugins.apply("maven-publish")
afterEvaluate {
// Common settings
if (isAndroidLibrary || isAndroidApplication) {
extensions.getByType<com.android.build.gradle.BaseExtension>().apply {
compileSdkVersion(CommonVersions.targetsdk)
buildToolsVersion = CommonVersions.buildTools
defaultConfig {
minSdkVersion(CommonVersions.minsdk)
targetSdkVersion(CommonVersions.targetsdk)
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}
buildFeatures.viewBinding = true
tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile> {
kotlinOptions {
jvmTarget = "1.8"
}
}
}
}
// Set up publishing configuration
val sourceSets: SourceSetContainer by project
print("project name: $name, ")
print("project size: ${sourceSets.size}, ")
print("project size: ${project.the<SourceSetContainer>().size}, ")
print("project size: ${the<SourceSetContainer>().size}, ")
if (!notPublishingModules.contains(name) && sourceSets.size != 0) {
configure<PublishingExtension> {
publications {
create<MavenPublication>("maven") {
groupId = "xx.yyy.zz"
artifactId = "test"
version = "0.0.0"
from(components.findByName("release"))
val sourcesJar by tasks.creating(Jar::class) {
val sourceSets: SourceSetContainer by project
from(sourceSets["main"].allJava)
classifier = "sources"
}
artifact(sourcesJar)
}
}
}
}
}
}
I always get this error: SourceSet with name 'main' not found.
As you can see I was trying to print the sourceset out, to see if it has any information or not. The size of the sourceset is always zero.
What am I doing wrong?
I use groovy with spring applications , I think you missing this in your code
sourceSets {
main {
java { srcDirs = ["src/java"] }
resources { srcDir "src/resources" }
}
}
where you define where is srcDirs are .
I am creating a Jetbrains Compose Multiplatform project. But I will only need Desktop (JVM) and Android, so two JVM targets. I want to factor out the logic which needs grpc, so both Android and Desktop can use it without me having to program it twice.
I can't seem to figure out a way of binding in my grpc/proto into the project, so that I can write the logic once and share it between android and desktop.
This is what my build.gradle.kts of the common project looks like:
plugins {
id("com.android.library")
kotlin("multiplatform")
id("org.jetbrains.compose")
}
kotlin {
android()
jvm("desktop")
sourceSets {
named("commonMain") {
dependencies {
api(compose.runtime)
api(compose.foundation)
api(compose.material)
api(compose.ui)
implementation(compose.preview)
implementation(compose.uiTooling)
}
}
}
}
android {
compileSdk = 31
defaultConfig {
minSdk = 21
targetSdk = 31
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}
sourceSets {
named("main") {
manifest.srcFile("src/androidMain/AndroidManifest.xml")
res.srcDirs("src/androidMain/res")
}
}
}
I tried binding my protos into a sourceset but couldn't get it working.
My other approach:
Next I tried creating a second submodule where the protos and the logic would be bound, but I couldn't get that working either:
Here is the build.gradle.kts for shared-logic:
import com.google.protobuf.gradle.*
import org.gradle.kotlin.dsl.proto
plugins {
kotlin("jvm")
idea
id("com.google.protobuf")
}
version = "unspecified"
repositories {
mavenCentral()
}
dependencies {
implementation(kotlin("stdlib"))
api(project(":kotlin-common")) {
exclude(group = "io.grpc", module = "grpc-protobuf")
exclude(group = "io.grpc", module = "grpc-stub")
}
implementation("io.grpc:grpc-okhttp:${Versions.GRPC}")
api("com.google.protobuf:protobuf-java-util:${Versions.PROTOBUF}")
api("io.grpc:grpc-stub:${Versions.GRPC}")
api("io.grpc:grpc-protobuf-lite:${Versions.GRPC}")
api("io.grpc:grpc-kotlin-stub:${Versions.GRPC_KOTLIN}")
api("com.google.protobuf:protobuf-kotlin-lite:${Versions.PROTOBUF}")
api("io.insert-koin:koin-core:${Versions.KOIN}")
api("org.jetbrains.kotlinx:kotlinx-coroutines-core:${Versions.COROUTINES}")
}
sourceSets {
main {
proto {
srcDirs("../protos/src/main")
}
}
}
protobuf {
protoc {
artifact = "com.google.protobuf:protoc:${Versions.PROTOBUF}"
}
plugins {
id("java") {
artifact = "io.grpc:protoc-gen-grpc-java:${Versions.GRPC}"
}
id("grpc") {
artifact = "io.grpc:protoc-gen-grpc-java:${Versions.GRPC}"
}
id("grpckt") {
artifact = "io.grpc:protoc-gen-grpc-kotlin:${Versions.GRPC_KOTLIN}:jdk7#jar"
}
}
generateProtoTasks {
all().forEach {
it.plugins {
id("grpc") {
option("lite")
}
id("grpckt") {
option("lite")
}
}
it.builtins {
id("kotlin") {
option("lite")
}
}
}
}
}
Here is the build.gradle.kts for kotlin-common:
plugins {
kotlin("jvm")
}
version = "1.0.0"
repositories {
mavenCentral()
}
dependencies {
implementation(kotlin("stdlib"))
implementation("io.grpc:grpc-stub:${Versions.GRPC}")
}
Here I get resolution error I tried fixing but couldn't figure out what to exclude:
Duplicate class com.google.protobuf.AbstractMessageLite found in modules jetified-protobuf-java-3.19.1 (com.google.protobuf:protobuf-java:3.19.1) and jetified-protobuf-javalite-3.19.1 (com.google.protobuf:protobuf-javalite:3.19.1)
Duplicate class com.google.protobuf.AbstractMessageLite$Builder found in modules jetified-protobuf-java-3.19.1 (com.google.protobuf:protobuf-java:3.19.1) and jetified-protobuf-javalite-3.19.1 (com.google.protobuf:protobuf-javalite:3.19.1)
Duplicate class com.google.protobuf.AbstractMessageLite$Builder$LimitedInputStream found in modules jetified-protobuf-java-3.19.1 (com.google.protobuf:protobuf-java:3.19.1) and jetified-protobuf-javalite-3.19.1 (com.google.protobuf:protobuf-javalite:3.19.1)
...
I wanted to configure Jetpack Compose. I did it but during running the app I get that error everytime. Jetpack is in the project and I can use it but I can't run the app.
Execution failed for task ':myModule:prepareDebugKotlinCompileTask'.
Could not resolve all files for configuration ':myModule:kotlin-extension'.
Could not find androidx.compose:compose-compiler:1.0.0-alpha05.
Searched in the following locations:
- https://dl.google.com/dl/android/maven2/androidx/compose/compose-compiler/1.0.0-alpha05/compose-compiler-1.0.0-alpha05.pom
My module's Gradle file:
plugins {
id("po-android-library")
id("kotlin-kapt")
id("de.mannodermaus.android-junit5")
}
android {
defaultConfig {
renderscriptTargetApi = AndroidSdkVersions.target
renderscriptSupportModeEnabled = true
vectorDrawables.useSupportLibrary = true
}
buildFeatures {
compose = true
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}
composeOptions {
kotlinCompilerVersion = "1.4.0"
kotlinCompilerExtensionVersion = "1.0.0-alpha05"
}
kotlinOptions {
jvmTarget = "1.8"
useIR = true
}
testOptions.unitTests.isIncludeAndroidResources = true
sourceSets {
val sharedTestDir = "src/sharedTest/java"
getByName("test") {
java.srcDir(sharedTestDir)
}
}
packagingOptions {
pickFirst("mockito-extensions/org.mockito.plugins.MockMaker")
exclude("META-INF/rxjava.properties")
exclude("META-INF/rxkotlin.properties")
}
}
dependencies {
implementation(project(":common"))
implementation(project(":android-common"))
implementation(Deps.kotlin_stdlib)
implementation("com.android.tools.build:gradle:4.1.0")
implementation("org.jetbrains.kotlin:kotlin-gradle-plugin:1.4.10")
implementation(Deps.androidx_appcompat)
implementation(Deps.koin_android_viewmodel)
implementation(Deps.koin_androidx_ext)
implementation(Deps.koin_android)
implementation(Deps.rxkotlin)
implementation("androidx.compose.runtime:runtime:1.0.0-alpha05")
implementation("androidx.compose.ui:ui:1.0.0-alpha05")
implementation("androidx.compose.foundation:foundation-layout:1.0.0-alpha05")
implementation("androidx.compose.material:material:1.0.0-alpha05")
From Compose compiler version 1.0.0-alpha04, we should use Android Studio 4.2 Canary 13 or later and com.android.tools.build:gradle version should be 4.2.0-alpha13
From the Official site reference
I have a test-utils module which contains testImplementation, androidTestImplementation and some rules and file reading extension code such as
fun getResourceAsText(path: String): String {
return object {}.javaClass.classLoader!!.getResource(path)!!.readText()
}
inline fun <reified T> convertToObjectsFromString(input: String): T? {
return Gson().fromJsonWithType<T>(input)
}
inline fun <reified T> Gson.fromJsonWithType(json: String): T? =
fromJson<T>(json, object : TypeToken<T>() {}.type)
build.gradle.kts file test-utils module
import extension.addInstrumentationTestDependencies
import extension.addUnitTestDependencies
plugins {
id(Plugins.ANDROID_LIBRARY_PLUGIN)
id(Plugins.KOTLIN_ANDROID_PLUGIN)
id(Plugins.KOTLIN_ANDROID_EXTENSIONS_PLUGIN)
id(Plugins.KOTLIN_KAPT_PLUGIN)
}
android {
compileSdkVersion(AndroidVersion.COMPILE_SDK_VERSION)
defaultConfig {
minSdkVersion(AndroidVersion.MIN_SDK_VERSION)
targetSdkVersion(AndroidVersion.TARGET_SDK_VERSION)
versionCode = AndroidVersion.VERSION_CODE
versionName = AndroidVersion.VERSION_NAME
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
}
sourceSets {
val sharedTestDir = "src/test-shared/java"
getByName("test") {
java.srcDir(sharedTestDir)
}
getByName("androidTest") {
java.srcDir(sharedTestDir)
resources.srcDir("src/test/resources")
}
}
buildTypes {
getByName("release") {
isMinifyEnabled = false
proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt"),
"proguard-rules.pro"
)
}
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = "1.8"
}
}
dependencies {
implementation(fileTree(mapOf("dir" to "libs", "include" to listOf("*.jar"))))
implementation(Deps.KOTLIN)
implementation(Deps.ANDROIDX_CORE_KTX)
addUnitTestDependencies()
addInstrumentationTestDependencies()
}
I tried adding test-utils module using implementation(project(":test-utils")) and testImplementation(project(":test-utils"))
but when i run test from another module, for instance data module i get
Unresolved reference: convertToObjectsFromString
or simple string for folder
Unresolved reference: RESPONSE_JSON_PATH
which is const val RESPONSE_JSON_PATH = "response.json"
even though imports on this test class is not red and cmd + click is pointing the exact location.