【问题标题】:Create a Github library mix of jvm and Kotlin multiplatform创建 jvm 和 Kotlin 多平台的 Github 库组合
【发布时间】:2020-04-12 18:37:17
【问题描述】:

我正在尝试构建一个 Android 库,我有以下内容:

  • 库的 Github 存储库
    • 库 1:可编译为 Android 和 iOS 的 Kotlin 原生/多平台代码
    • 库 2:Kotlin/JVM 代码依赖于库 1
    • 示例应用:使用库 2 和库 1 的应用
  • 个人安卓项目
    • 依赖上面的 Github 库

在我的个人项目中,我只有:

implementation 'com.github.username:myrepo:0.5'

问题

  1. 私有 Android 项目正在加载 android 库(库 2),但无法访问多平台 kotlin 模型和函数(库 1)。

    请注意,该库的示例应用程序运行良好。我怀疑 jitpack.io 没有正确发布工件。关于如何解决这个问题的任何想法?是否应该对 gradle 文件做些什么来解决问题?

  2. 我想单独发布多平台库。我试图从多平台 Kotlin 模块访问它,但我得到“无法解决依赖关系”。这就是我正在尝试的:

    implementation 'com.github.username.myrepo:library1_moduleName:0.1'


Gradle for Library 1 多平台:

plugins {
    kotlin("multiplatform")
}

kotlin {
    //select iOS target platform depending on the Xcode environment variables
    val iOSTarget: (String, KotlinNativeTarget.() -> Unit) -> KotlinNativeTarget =
        if (System.getenv("SDK_NAME")?.startsWith("iphoneos") == true)
            ::iosArm64
        else
            ::iosX64

    iOSTarget("ios") {
        binaries {
            framework {
                baseName = "library1"
                freeCompilerArgs.add("-Xobjc-generics")

            }
        }
    }

    jvm("android")

    sourceSets["commonMain"].dependencies {
        implementation("org.jetbrains.kotlin:kotlin-stdlib-common")
    }

    sourceSets["androidMain"].dependencies {
        implementation("org.jetbrains.kotlin:kotlin-stdlib")
    }
}

val packForXcode by tasks.creating(Sync::class) {
    val targetDir = File(buildDir, "xcode-frameworks")

    /// selecting the right configuration for the iOS
    /// framework depending on the environment
    /// variables set by Xcode build
    val mode = System.getenv("CONFIGURATION") ?: "DEBUG"
    val framework = kotlin.targets
        .getByName<KotlinNativeTarget>("ios")
        .binaries.getFramework(mode)
    inputs.property("mode", mode)
    dependsOn(framework.linkTask)

    from({ framework.outputDirectory })
    into(targetDir)

    /// generate a helpful ./gradlew wrapper with embedded Java path
    doLast {
        val gradlew = File(targetDir, "gradlew")
        gradlew.writeText(
            "#!/bin/bash\n"
                    + "export 'JAVA_HOME=${System.getProperty("java.home")}'\n"
                    + "cd '${rootProject.rootDir}'\n"
                    + "./gradlew \$@\n"
        )
        gradlew.setExecutable(true)
    }
}

tasks.getByName("build").dependsOn(packForXcode)

库 2 的 Gradle

apply plugin: 'com.android.library'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'

android {

    repositories {
        google()
        jcenter()
        maven { url 'https://jitpack.io' }
    }

    compileSdkVersion 29
    buildToolsVersion "29.0.0"


    defaultConfig {
        minSdkVersion 19
        targetSdkVersion 29

        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
        consumerProguardFiles 'consumer-rules.pro'
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }

}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
    api project(":library1")
}

【问题讨论】:

    标签: kotlin gradle gradle-kotlin-dsl kotlin-multiplatform


    【解决方案1】:

    我建议你更改你的build.gradle 配置以定位android/ 将其更改为

    plugins {
        kotlin("multiplatform")
        id("com.android.library")
        id("maven-publish")
    }
    
    android {
        compileSdkVersion 29
        buildToolsVersion "29.0.0"
    
        defaultConfig {
            minSdkVersion 19
            targetSdkVersion 29
        }
    
        buildTypes {
            release {
                minifyEnabled false
                proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
            }
        }
    }
    
    kotlin {
        //select iOS target platform depending on the Xcode environment variables
        val iOSTarget: (String, KotlinNativeTarget.() -> Unit) -> KotlinNativeTarget =
            if (System.getenv("SDK_NAME")?.startsWith("iphoneos") == true)
                ::iosArm64
            else
                ::iosX64
    
        iOSTarget("ios") {
            binaries {
                framework {
                    baseName = "library1"
                    freeCompilerArgs.add("-Xobjc-generics")
    
                }
            }
        }
    
        // jvm("android")
        android {
            publishLibraryVariants("release")
        }
    
        sourceSets["commonMain"].dependencies {
            implementation("org.jetbrains.kotlin:kotlin-stdlib-common")
        }
    
        sourceSets["androidMain"].dependencies {
            implementation("org.jetbrains.kotlin:kotlin-stdlib")
        }
    }
    
    val packForXcode by tasks.creating(Sync::class) {
        val targetDir = File(buildDir, "xcode-frameworks")
    
        /// selecting the right configuration for the iOS
        /// framework depending on the environment
        /// variables set by Xcode build
        val mode = System.getenv("CONFIGURATION") ?: "DEBUG"
        val framework = kotlin.targets
            .getByName<KotlinNativeTarget>("ios")
            .binaries.getFramework(mode)
        inputs.property("mode", mode)
        dependsOn(framework.linkTask)
    
        from({ framework.outputDirectory })
        into(targetDir)
    
        /// generate a helpful ./gradlew wrapper with embedded Java path
        doLast {
            val gradlew = File(targetDir, "gradlew")
            gradlew.writeText(
                "#!/bin/bash\n"
                        + "export 'JAVA_HOME=${System.getProperty("java.home")}'\n"
                        + "cd '${rootProject.rootDir}'\n"
                        + "./gradlew \$@\n"
            )
            gradlew.setExecutable(true)
        }
    }
    
    tasks.getByName("build").dependsOn(packForXcode)
    

    src/main/AndroidManifest.xml下的library1创建一个AndroidManifest.xml文件

    <manifest package="library1"/>
    

    您现在可以将您的项目推送到 github,创建一个标签并等待 jitpack 发挥作用

    当你想在 library2 中使用它时,在 dependencies 部分下,只需添加

    implementation 'com.github.username.myrepo:library1-android:0.1' //for android
    

    【讨论】:

      【解决方案2】:

      认为您可能需要为multi-platform library 启用元数据;在settings.gradle:

      enableFeaturePreview('GRADLE_METADATA')
      

      以及为 Maven 配置库(不清楚如何将其发布到 GitHub,因为 build.gradle 没有任何自动化功能)。即使将其发布到 GitHub 而不是 mavenLocal(),它也可能需要提供某种元数据......因为“无法解决依赖关系”可能会暗示,假设它存在于引用的包名称下。

      apply plugin: 'maven-publish'
      group 'com.github.username'
      version '1.0.0'
      

      配置api 仅适用于被多个模块引用的依赖项;其他所有内容(任何一次出现)都应为implementation。我的意思是,我发现库 2 build.gradle 令人困惑,因为在顶部它读取 maven { url 'https://jitpack.io' }(实际上没有引用远程依赖项),然后它读取 api project(":library1")(这绝对是本地依赖项)。

      【讨论】:

      • 我正在使用jitpack.io,它依赖于 GitHub 发布版本来构建工件。但它只是构建子模块之一。在我应用了您建议的更改之后(除了从 GitHub 获取的版本),它现在正在构建 kotin 多平台(库 1)并且与库 2 没有任何关系。对于最后一点,我有其他依赖项已删除简化问题。我应该删除repositories。谢谢
      • @ELKA 使用 jitpack.io 打包多平台库可能尚无法实现:github.com/jitpack/jitpack.io/issues/3853
      • 谢谢,我切换到 maven。
      猜你喜欢
      • 1970-01-01
      • 2021-07-03
      • 2018-06-12
      • 1970-01-01
      • 2019-12-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-05-04
      相关资源
      最近更新 更多