2
votes

I uploaded a shared module from a Kotlin Multiplatform to JFrogs Artifactory. The goal is to use this shared module in another android app project and share business logic across projects.

I tried to only upload the android variant of the shared module - for the current purpose the iOS variant are not needed to be uploaded to artifactory.

I wrote this code in the build.gradle.kts of the shared module in the Kotlin Multiplatform project:

plugins {
    kotlin("multiplatform")
    id("com.android.library")
    id("kotlin-android-extensions")
    kotlin("plugin.serialization")

    // plugins required for uploading to artifactory
    id("maven-publish")
    id("com.jfrog.artifactory") version "4.13.0"
}

.
.
.

artifactory {
    setContextUrl("https://rbartifactory.jfrog.io/artifactory/")
    publish(delegateClosureOf<PublisherConfig> {
        repository(delegateClosureOf<DoubleDelegateWrapper> {
            setProperty("repoKey", "App-Shared-Test-KMP")
            setProperty("username", "<MY-USERNAME>")
            setProperty("password", "<MY-USER-API-KEY>")
            setProperty("maven", true)
        })
        defaults(delegateClosureOf<groovy.lang.GroovyObject> {
            invokeMethod("publications", arrayOf(
                    "androidDebug", "androidRelease", "kotlinMultiplatform", "metadata"
            ))
        })
    })
}

In the settings.gradle I also added enableFeaturePreview("GRADLE_METADATA").

To implement that gradle I read this article here: https://medium.com/vmware-end-user-computing/publishing-kotlin-multiplatform-artifacts-to-artifactory-maven-a283ae5912d6

Because I want this shared module to be used in other Android App projects I skip all steps regarding the maven publications of the iOS part.

The upload to artifactory is successful with ./gradlew artifactoryPublish:

Artifactory-browser

I try to consume it in the android app and for this I added the connection to artifactory and to this repo in the android app build.gradle file like suggested in artifactory when using "Set Me Up" button. And I also link finally the framework in the dependencies block of the build.gradle of the Android App:

dependencies {
    .
    .
    .

    implementation(group: 'com.rb.kmp_test_shared_lib', name: 'shared', version: '1.0.4', ext: 'jar')
}

In the android app I run in this error here:

Could not determine the dependencies of task ':app:lintVitalRelease'.
> Could not resolve all artifacts for configuration ':app:debugCompileClasspath'.
   > Could not resolve com.rb.kmp_test_shared_lib:shared:1.0.4.
     Required by:
         project :app
      > No matching variant of com.rb.kmp_test_shared_lib:shared:1.0.4 was found. The consumer was configured to find an API of a component, as well as attribute 'com.android.build.api.attributes.BuildTypeAttr' with value 'debug', attribute 'org.jetbrains.kotlin.platform.type' with value 'androidJvm' but:
          - Variant 'commonMainMetadataElements-published' capability com.rb.kmp_test_shared_lib:shared:1.0.4:
              - Incompatible because this component declares a usage of 'kotlin-api' of a component, as well as attribute 'org.jetbrains.kotlin.platform.type' with value 'common' and the consumer needed an API of a component, as well as attribute 'org.jetbrains.kotlin.platform.type' with value 'androidJvm'
              - Other compatible attribute:
                  - Doesn't say anything about com.android.build.api.attributes.BuildTypeAttr (required 'debug')
          - Variant 'iosArm64ApiElements-published' capability com.rb.kmp_test_shared_lib:shared:1.0.4:
              - Incompatible because this component declares a usage of 'kotlin-api' of a component, as well as attribute 'org.jetbrains.kotlin.platform.type' with value 'native' and the consumer needed an API of a component, as well as attribute 'org.jetbrains.kotlin.platform.type' with value 'androidJvm'
              - Other compatible attribute:
                  - Doesn't say anything about com.android.build.api.attributes.BuildTypeAttr (required 'debug')
          - Variant 'iosArm64MetadataElements-published' capability com.rb.kmp_test_shared_lib:shared:1.0.4:
              - Incompatible because this component declares a usage of 'kotlin-metadata' of a component, as well as attribute 'org.jetbrains.kotlin.platform.type' with value 'native' and the consumer needed an API of a component, as well as attribute 'org.jetbrains.kotlin.platform.type' with value 'androidJvm'
              - Other compatible attribute:
                  - Doesn't say anything about com.android.build.api.attributes.BuildTypeAttr (required 'debug')
          - Variant 'iosX64ApiElements-published' capability com.rb.kmp_test_shared_lib:shared:1.0.4:
              - Incompatible because this component declares a usage of 'kotlin-api' of a component, as well as attribute 'org.jetbrains.kotlin.platform.type' with value 'native' and the consumer needed an API of a component, as well as attribute 'org.jetbrains.kotlin.platform.type' with value 'androidJvm'
              - Other compatible attribute:
                  - Doesn't say anything about com.android.build.api.attributes.BuildTypeAttr (required 'debug')
          - Variant 'iosX64MetadataElements-published' capability com.rb.kmp_test_shared_lib:shared:1.0.4:
              - Incompatible because this component declares a usage of 'kotlin-metadata' of a component, as well as attribute 'org.jetbrains.kotlin.platform.type' with value 'native' and the consumer needed an API of a component, as well as attribute 'org.jetbrains.kotlin.platform.type' with value 'androidJvm'
              - Other compatible attribute:
                  - Doesn't say anything about com.android.build.api.attributes.BuildTypeAttr (required 'debug')
          - Variant 'metadataApiElements-published' capability com.rb.kmp_test_shared_lib:shared:1.0.4:
              - Incompatible because this component declares a usage of 'kotlin-metadata' of a component, as well as attribute 'org.jetbrains.kotlin.platform.type' with value 'common' and the consumer needed an API of a component, as well as attribute 'org.jetbrains.kotlin.platform.type' with value 'androidJvm'
              - Other compatible attribute:
                  - Doesn't say anything about com.android.build.api.attributes.BuildTypeAttr (required 'debug')
* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.

Why did I get this error when trying to use that library? How can I exactly consume Kotlin Multiplatform libraries from jfrogs artifactory in other android apps?

It is maybe because of the jars which get uploaded by running ./gradlew artifactoryPublish? There should be aar files uploaded in artifactory?

Maybe this lines here did not work anymore? The article I read to implement that was written in May 2020 and since then there were some major Kotlin Multiplatform releases:

defaults(delegateClosureOf<groovy.lang.GroovyObject> {
            invokeMethod("publications", arrayOf(
                    "androidDebug", "androidRelease", "kotlinMultiplatform", "metadata"
            ))
        })

I guess instead of androidDebug and androidRelease I need to put there some other attributes in.

I am really grateful for every help with this - I am looking for hours for an solution.

1
Thanks for the answer. Another thing I noticed - this version of the plugin works well: classpath("org.jfrog.buildinfo:build-info-extractor-gradle:4.13.0") I tried with latest version 4.15.2, and it was working only intermittently.user2880827

1 Answers

3
votes

For android apps aar libraries are necessary - so I need to upload air files to artifactory.

To upload aar files I add a publishing block to the build.gradle.kts of my shared module in the KMP project:

publishing {
    publications {
        create<MavenPublication>("aar") {
            artifact("$buildDir/outputs/aar/${project.name}-release.aar")
        }
    }
}

I also changed the artifactory block and replace the defaults part to this:

defaults(delegateClosureOf<groovy.lang.GroovyObject> {
    invokeMethod("publications", "aar")
    setProperty("publishArtifacts", true)
})

After this changes I clean the project and build all artifacts:

./gradlew clean
./gradlew :shared:build

When all assets build successful (and aar files are in the outputs folder of the KMP project) I upload the aar's successful with ./gradlew artifactoryPublish and then I can simply use them in another android app.

The answer from Vadim of the question Convert to gradle-kotlin-dsl Jfrog.Artifactory config helped me with writing the code to upload aar's to artifactory.