Создайте смесь библиотеки Github из мультиплатформенных jvm и Kotlin

Я пытаюсь создать библиотеку Android, и у меня есть следующее:

  • Github Repo for the library
    • Library 1: Kotlin native/multiplatform code that can compile to Android and iOS
    • Библиотека 2: код Kotlin / JVM в зависимости от библиотеки 1
    • Пример приложения: приложение, использующее библиотеку 2 и библиотеку 1
  • Personal Android Project
    • Dependent on the Github Library above

В моем личном проекте у меня только:

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

Проблемы

  1. Частный проект Android загружает библиотеку Android (Библиотека 2), но мультиплатформенные модели и функции котлина (Библиотека 1) недоступны.

    Обратите внимание, что пример приложения библиотеки работает нормально. Я подозреваю, что jitpack.io неправильно публикует артефакты. Есть идеи, как это исправить? Что нужно сделать с файлами gradle, чтобы решить проблему?

  2. Я бы хотел, чтобы мультиплатформенная библиотека была опубликована отдельно. Я пытался получить к нему доступ из мультиплатформенного модуля Kotlin, но получаю сообщение «Невозможно разрешить зависимости». Вот что я пробовал:

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


Мультиплатформенность Gradle для библиотеки 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)

Gradle для библиотеки 2

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")
}

person ELKA    schedule 12.04.2020    source источник


Ответы (2)


Я предлагаю вам изменить вашу 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)

создать AndroidManifest.xml файл для библиотеки1 в src/main/AndroidManifest.xml

<manifest package="library1"/>

теперь вы можете отправить свой проект на github, создать тег и дождаться, пока jitpack сделает свое волшебство

Если вы хотите использовать его в library2, в разделе dependencies просто добавьте

implementation 'com.github.username.myrepo:library1-android:0.1' //for android
person andylamax    schedule 14.04.2020

Думаю, вам может потребоваться включить метаданные для многоплатформенной библиотеки; в 1_:

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") (которая определенно является локальной зависимостью).

person Martin Zeitler    schedule 12.04.2020
comment
Я использую jitpack.io, он использует версию выпуска GitHub для создания артефактов. Но это только создание одного из подмодулей. После того, как я применил предложенные вами изменения (кроме версии, взятой из GitHub), теперь создается мультиплатформенная платформа kotin (Библиотека 1) и ничего не связано с Библиотекой 2. Что касается последнего пункта, у меня есть другие зависимости, которые я удалил в упростить вопрос. Я должен был удалить repositories. Спасибо - person ELKA; 13.04.2020
comment
@ELKA Упаковка многоплатформенных библиотек с помощью jitpack.io еще может быть невозможна: github.com /jitpack/jitpack.io/issues/3853 - person Martin Zeitler; 17.04.2020
comment
Спасибо, перешел на maven. - person ELKA; 17.04.2020