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 .
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'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
Hey I am publish library in kotlin multiplatform. I used this command ./gradlew clean assemble publish my three package is generated. I given the name var libraryArtifactId = "kmm-module" but I don't understand why other name is coming from.
1st package name is com.vivek.kmm-module
2nd package name is com.vivek.kotlinproject-android-debug
3rd package name is com.vivek.kotlinproject-android
I understand 1st package name, but I am not understanding where the 2nd and 3rd artificatId coming from?
build.gradle.kts
plugins {
kotlin("multiplatform") version "1.6.21"
id("com.android.library")
id("maven-publish")
}
val libraryVersion = "0.0.1"
var libraryGroup = "com.vivek"
var libraryArtifactId = "kmm-module"
repositories {
google()
mavenCentral()
}
kotlin {
android {
publishLibraryVariants("release", "debug")
}
sourceSets {
val commonMain by getting
val androidMain by getting
}
}
android {
compileSdk = 21
sourceSets["main"].manifest.srcFile("src/androidMain/AndroidManifest.xml")
defaultConfig {
minSdk = 21
targetSdk = 31
}
#Suppress("UnstableApiUsage") compileOptions {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}
}
publishing {
publications {
group = libraryGroup
publications.withType<MavenPublication> {
groupId = libraryGroup
artifactId = libraryArtifactId
version = libraryVersion
}
repositories {
maven {
url = uri("https://maven.pkg.github.com/vivek-modi/kotlinmultiplatfromproject")
credentials {
username = (System.getenv("GITHUB_USER") ?: project.properties["GITHUB_USER"]).toString()
password = (System.getenv("GITHUB_PERSONAL_ACCESS_TOKEN") ?: project.properties["GITHUB_PERSONAL_ACCESS_TOKEN"]).toString()
}
}
}
}
}
I am adding my github repository. I used github packages for publishing library. Thanks
you can remove this line to avoid the android artifact.
android {
publishLibraryVariants("release", "debug")
}
I have a project with the standard java library and this creates several .jar files, one being a docset and another the source set. Now I have successfully created an android-library using the maven-publish plugin, but when I add the .aar files to another project, they don't contain neither source nor comments as the .jar version did, so I don't get help inside the IDE or look into the implementation of methods.
What do I need to add to my build.gradle.kts to include docstrings and sources in the debug version of the .aar I'm publishing locally as a file? The linked gradle documentation from that Android developer page does not mention anything about docstrings or sources at all.
import org.jetbrains.kotlin.config.KotlinCompilerVersion
plugins {
id("com.android.library")
kotlin("android")
`maven-publish`
}
group = "com.wavelt.libs"
version = "1.0.0"
android {
compileSdkVersion(30)
buildToolsVersion = "30.0.2"
defaultConfig {
minSdkVersion(16)
targetSdkVersion(30)
versionCode = 1
versionName = "1.0.0"
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
consumerProguardFiles("consumer-rules.pro")
}
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"
freeCompilerArgs = listOf("-Xinline-classes")
}
}
dependencies {
implementation(kotlin("stdlib-jdk7", KotlinCompilerVersion.VERSION))
implementation("androidx.core:core-ktx:1.3.2")
implementation("androidx.appcompat:appcompat:1.2.0")
implementation("com.google.android.material:material:1.3.0")
testImplementation("junit:junit:4.13.2")
androidTestImplementation("androidx.test.ext:junit:1.1.2")
androidTestImplementation("androidx.test.espresso:espresso-core:3.3.0")
androidTestImplementation("com.android.support.test:runner:1.0.2")
androidTestImplementation("com.android.support.test:rules:1.0.2")
}
// https://developer.android.com/studio/build/maven-publish-plugin
afterEvaluate {
publishing {
repositories {
maven {
// https://docs.gradle.org/current/userguide/publishing_maven.html#publishing_maven:repositories
url = uri("$buildDir/repository")
}
}
publications {
create<MavenPublication>("debug") {
// Applies the component for the release build variant.
from(components["debug"])
artifactId = "wavelt-android-debug"
artifact("androidJavadocsJar") // Doesn't seem to work
}
create<MavenPublication>("release") {
// Applies the component for the release build variant.
from(components["release"])
artifactId = "wavelt-android"
}
}
}
}
While I've read about other devs being able to cram the javadocs into the .aar file, this is not explicitly necessary at all to gain documentation and source code inspection from inside IDEs like Android Studio. In fact, looking at the way a typical java library works, it creates files like:
foo-ver.jar
foo-ver-sources.jar
foo-ver-javadoc.jar
The only difference with an Android library would be having these files:
foo-ver.aar
foo-ver-sources.jar
foo-ver-javadoc.jar
Which means that the sources and javadoc jars can still be copied along the .aar and the IDE will load them. Having said that, the publish example code only creates the .aar file, looking at other questions like this one I was able to modify the script to create the .aar plus the two other .jar packages:
import org.jetbrains.kotlin.config.KotlinCompilerVersion
plugins {
id("com.android.library")
kotlin("android")
`maven-publish`
id("org.jetbrains.dokka") version "0.9.17"
}
group = "com.wavelt.libs"
version = "1.0.0"
android {
compileSdkVersion(30)
buildToolsVersion = "30.0.2"
defaultConfig {
minSdkVersion(16)
targetSdkVersion(30)
versionCode = 1
versionName = "1.0.0"
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
consumerProguardFiles("consumer-rules.pro")
}
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"
freeCompilerArgs = listOf("-Xinline-classes")
}
}
dependencies {
//implementation(fileTree(mapOf("dir" to "libs", "include" to listOf("*.jar"))))
implementation(kotlin("stdlib-jdk7", KotlinCompilerVersion.VERSION))
implementation("androidx.core:core-ktx:1.3.2")
implementation("androidx.appcompat:appcompat:1.2.0")
implementation("com.google.android.material:material:1.3.0")
testImplementation("junit:junit:4.13.2")
androidTestImplementation("androidx.test.ext:junit:1.1.2")
androidTestImplementation("androidx.test.espresso:espresso-core:3.3.0")
androidTestImplementation("com.android.support.test:runner:1.0.2")
androidTestImplementation("com.android.support.test:rules:1.0.2")
}
tasks.dokka {
outputFormat = "html"
outputDirectory = "$buildDir/javadoc"
moduleName = rootProject.name
}
val dokkaJar by tasks.creating(Jar::class) {
group = JavaBasePlugin.DOCUMENTATION_GROUP
description = "Assembles Kotlin docs with Dokka"
archiveClassifier.set("javadoc")
from(tasks.dokka)
dependsOn(tasks.dokka)
}
val sourcesJar by tasks.creating(Jar::class) {
group = JavaBasePlugin.DOCUMENTATION_GROUP
description = "Assembles sources JAR"
archiveClassifier.set("sources")
from(android.sourceSets.getByName("main").java.srcDirs)
}
artifacts {
archives(sourcesJar)
archives(dokkaJar)
}
// https://developer.android.com/studio/build/maven-publish-plugin
afterEvaluate {
publishing {
repositories {
maven {
// https://docs.gradle.org/current/userguide/publishing_maven.html#publishing_maven:repositories
url = uri("$buildDir/repository")
}
}
publications {
create<MavenPublication>("debug") {
// Applies the component for the release build variant.
from(components["debug"])
artifactId = "wavelt-android-debug"
artifact(sourcesJar)
artifact(dokkaJar)
}
create<MavenPublication>("release") {
// Applies the component for the release build variant.
from(components["release"])
artifactId = "wavelt-android"
}
}
}
}
With these modifications the ./gradlew publish task will generate all files, and despite one of them having .aar they work the same as .jar when copied together into another project.
I am creating a Kotlin Multiplatform library with Android support.
When I try to build with gradle I get an error (./gradlew build --warning-mode all).
Either this:
Could not determine the dependencies of task ':lib:compileDebugAidl'.
> Failed to find target with hash string '29' in: /home/user/Android/Sdk
Or that:
Could not determine the dependencies of task ':lib:verifyReleaseResources'.
> Failed to find target with hash string '29' in: /home/user/Android/Sdk
The first right after indexing and the second when I do ./gradlew clean
However, there is this dependency in any case since I have already created Android apps based on that.
I have also tried Target 28 and an RC version of 30 (since 30 has not yet been officially released, but I have still created apps)
My structure of the gradle files is like this:
root
|-build.gradle.kts
|-settings.gradle.kts
|-gradlew
|-gradlew.bat
|-gradle
|-wrapper
|-gradle-wrapper.jar
|-gradle-wrapper.properties
|-lib
|-build.gradle.kts
settings.gradle.kts:
rootProject.name = "Library"
include(":lib")
root build.gradle.kts:
buildscript {
repositories {
addRepos()
maven(uri("https://dl.bintray.com/kotlin/kotlin-eap")) {
metadataSources {
gradleMetadata()
mavenPom()
}
}
}
dependencies {
classpath("com.android.tools.build:gradle:4.1.0-beta04")
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.3.72")
}
}
allprojects {
repositories {
addRepos()
maven(uri("https://dl.bintray.com/kotlin/kotlin-eap")) {
metadataSources {
gradleMetadata()
mavenPom()
}
}
}
}
lib build.gradle.kts:
plugins {
id("com.android.library")
kotlin("multiplatform")
id("maven-publish")
}
group = "de.datlag"
version = "1.0"
android {
compileSdkVersion = 29.toString()
buildToolsVersion = "29.0.3"
defaultConfig {
targetSdkVersion(29)
versionCode = 1
versionName = "1.0"
}
buildTypes {
val debug by getting {
isMinifyEnabled = false
isDebuggable = true
isShrinkResources = false
}
val release by getting {
isMinifyEnabled = false
isDebuggable = false
isShrinkResources = false
}
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}
}
repositories {
addRepos()
}
kotlin {
jvm {
compilations.all {
kotlinOptions.jvmTarget = JavaVersion.VERSION_1_8.toString()
}
}
js {
browser()
nodejs()
}
android {
publishAllLibraryVariants()
}
val hostOs = System.getProperty("os.name")
val isMingwX64 = hostOs.startsWith("Windows")
val nativeTarget = when {
hostOs == "Mac OS X" -> macosX64("native")
hostOs == "Linux" -> linuxX64("native")
isMingwX64 -> mingwX64("native")
else -> throw GradleException("Host OS is not supported in Kotlin/Native.")
}
sourceSets {
val commonMain by getting {
dependencies {
implementation(kotlin("stdlib-common"))
}
}
val commonTest by getting {
dependencies {
implementation(kotlin("test-common"))
implementation(kotlin("test-annotations-common"))
}
}
val jvmMain by getting {
dependencies {
implementation(kotlin("stdlib-jdk8"))
}
}
val jvmTest by getting {
dependencies {
implementation(kotlin("test"))
implementation(kotlin("test-junit"))
}
}
val androidMain by getting {
dependsOn(jvmMain)
}
val androidTest by getting {
dependsOn(jvmTest)
}
val jsMain by getting {
dependencies {
implementation(kotlin("stdlib-js"))
}
}
val jsTest by getting {
dependencies {
implementation(kotlin("test-js"))
}
}
val nativeMain by getting { }
val nativeTest by getting { }
}
}
addRepos method:
fun RepositoryHandler.addRepos() {
mavenLocal {
metadataSources {
gradleMetadata()
mavenPom()
}
}
mavenCentral {
metadataSources {
gradleMetadata()
mavenPom()
}
}
jcenter {
metadataSources {
gradleMetadata()
mavenPom()
}
}
google {
metadataSources {
gradleMetadata()
mavenPom()
}
}
gradlePluginPortal()
}
In lib.build.gradle.kts you should use the compileSdkVersion(29) syntax rather than setting a string. You can see in the source for these extensions that the behavior is different if you call the string version.
/** #see #getCompileSdkVersion() */
public void compileSdkVersion(String version) {
checkWritability();
this.target = version;
}
/** #see #getCompileSdkVersion() */
public void compileSdkVersion(int apiLevel) {
compileSdkVersion("android-" + apiLevel);
}
The when passing an int it will append "android-" for you. So you could do compileSdkVersion = "android-29" if you wanted, but just passing the int is easier