diff --git a/.github/workflows/compilation-check.yml b/.github/workflows/compilation-check.yml index 14df0c6..135768e 100644 --- a/.github/workflows/compilation-check.yml +++ b/.github/workflows/compilation-check.yml @@ -12,17 +12,15 @@ jobs: steps: - uses: actions/checkout@v1 - - name: Set up JDK 1.8 + - name: Set up JDK 11 uses: actions/setup-java@v1 with: - java-version: 1.8 + java-version: 11 - name: Cocoapods install run: (cd sample/ios-app && pod install) - - name: Build K/N cache - run: ./gradlew :tensorflow:runCommonizer - name: Check library run: ./gradlew build publishToMavenLocal syncMultiPlatformLibraryDebugFrameworkIosX64 - name: Install pods with kotlin run: cd sample/ios-app && pod install - name: build ios sample - run: cd sample/ios-app && xcodebuild -scheme tensorflow-test -workspace tensorflow-test.xcworkspace -configuration Debug build CODE_SIGNING_REQUIRED=NO CODE_SIGNING_ALLOWED=NO \ No newline at end of file + run: cd sample/ios-app && set -o pipefail && xcodebuild -scheme tensorflow-test -workspace tensorflow-test.xcworkspace -configuration Debug -sdk iphonesimulator -arch x86_64 build CODE_SIGNING_REQUIRED=NO CODE_SIGNING_ALLOWED=NO | xcpretty diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 8f7847f..28e15bb 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -21,14 +21,12 @@ jobs: steps: - uses: actions/checkout@v1 - - name: Set up JDK 1.8 + - name: Set up JDK 11 uses: actions/setup-java@v1 with: - java-version: 1.8 + java-version: 11 - name: Cocoapods install run: (cd sample/ios-app && pod install) - - name: Build K/N cache - run: ./gradlew :tensorflow:runCommonizer - name: Publish library run: ./gradlew publish release: @@ -44,6 +42,6 @@ jobs: with: commitish: ${{ github.ref }} tag_name: release/${{ github.event.inputs.version }} - release_name: Release ${{ github.event.inputs.version }} + release_name: ${{ github.event.inputs.version }} body: "Will be filled later" draft: true \ No newline at end of file diff --git a/build.gradle.kts b/build.gradle.kts index b119e73..594bd0b 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -2,12 +2,6 @@ * Copyright 2020 IceRock MAG Inc. Use of this source code is governed by the Apache 2.0 license. */ -import java.util.Base64 - -plugins { - plugin(Deps.Plugins.detekt) apply false -} - buildscript { repositories { mavenCentral() @@ -21,110 +15,16 @@ buildscript { } } dependencies { - with(Deps.Plugins) { - listOf( - androidApplication, - androidLibrary, - kotlinMultiplatform, - kotlinKapt, - kotlinAndroid, - mokoResources - ).forEach { plugin(it) } - } + classpath(":tensorflow-build-logic") + classpath("dev.icerock.moko:resources-generator:0.16.1") } } -allprojects { - repositories { - mavenCentral() - google() - - maven { url = uri("https://jitpack.io") } - maven { url = uri("http://dl.bintray.com/lukaville/maven") } - - jcenter { - content { - includeGroup("org.jetbrains.trove4j") - includeGroup("org.jetbrains.kotlinx") - includeGroup("org.tensorflow") - } - } - } - - apply(plugin = Deps.Plugins.detekt.id) - - configure { - toolVersion = Versions.detekt - input.setFrom("src/commonMain/kotlin", "src/androidMain/kotlin", "src/iosMain/kotlin") - } - dependencies { - "detektPlugins"(Deps.Libs.Jvm.detektFormatting) - } - - plugins.withId(Deps.Plugins.mavenPublish.id) { +allprojects { + plugins.withId("org.gradle.maven-publish") { group = "dev.icerock.moko" - version = Versions.Libs.MultiPlatform.mokoTensorflow - - val javadocJar by tasks.registering(Jar::class) { - archiveClassifier.set("javadoc") - } - - configure { - repositories.maven("https://s01.oss.sonatype.org/service/local/staging/deploy/maven2/") { - name = "OSSRH" - - credentials { - username = System.getenv("OSSRH_USER") - password = System.getenv("OSSRH_KEY") - } - } - - publications.withType { - // Stub javadoc.jar artifact - artifact(javadocJar.get()) - - // Provide artifacts information requited by Maven Central - pom { - name.set("MOKO tensorflow") - description.set("Tensorflow Lite bindings for mobile (android & ios) Kotlin Multiplatform development") - url.set("https://github.com/icerockdev/moko-tensorflow") - licenses { - license { - url.set("https://github.com/icerockdev/moko-tensorflow/blob/master/LICENSE.md") - } - } - - developers { - developer { - id.set("Tetraquark") - name.set("Vladislav Areshkin") - email.set("vareshkin@icerockdev.com") - } - } - - scm { - connection.set("scm:git:ssh://github.com/icerockdev/moko-tensorflow.git") - developerConnection.set("scm:git:ssh://github.com/icerockdev/moko-tensorflow.git") - url.set("https://github.com/icerockdev/moko-tensorflow") - } - } - } - - apply(plugin = Deps.Plugins.signing.id) - - configure { - val signingKeyId: String? = System.getenv("SIGNING_KEY_ID") - val signingPassword: String? = System.getenv("SIGNING_PASSWORD") - val signingKey: String? = System.getenv("SIGNING_KEY")?.let { base64Key -> - String(Base64.getDecoder().decode(base64Key)) - } - if (signingKeyId != null) { - useInMemoryPgpKeys(signingKeyId, signingKey, signingPassword) - sign(publications) - } - } - } + version = libs.versions.mokoTensorflowVersion.get() } } diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts deleted file mode 100644 index e856d25..0000000 --- a/buildSrc/build.gradle.kts +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright 2019 IceRock MAG Inc. Use of this source code is governed by the Apache 2.0 license. - */ - -plugins { - id("org.jetbrains.kotlin.jvm") version("1.4.31") -} - -repositories { - mavenCentral() - google() - - jcenter { - content { - includeGroup("org.jetbrains.trove4j") - } - } -} - -dependencies { - implementation("dev.icerock:mobile-multiplatform:0.9.1") - implementation("org.jetbrains.kotlin:kotlin-gradle-plugin:1.4.31") - implementation("com.android.tools.build:gradle:4.1.1") -} diff --git a/buildSrc/src/main/kotlin/Deps.kt b/buildSrc/src/main/kotlin/Deps.kt deleted file mode 100755 index 1ca6610..0000000 --- a/buildSrc/src/main/kotlin/Deps.kt +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright 2020 IceRock MAG Inc. Use of this source code is governed by the Apache 2.0 license. - */ - -object Deps { - object Plugins { - val androidApplication = GradlePlugin(id = "com.android.application") - val androidLibrary = GradlePlugin(id = "com.android.library") - - val kotlinMultiplatform = GradlePlugin(id = "org.jetbrains.kotlin.multiplatform") - val kotlinKapt = GradlePlugin(id = "kotlin-kapt") - val kotlinAndroid = GradlePlugin(id = "kotlin-android") - val kotlinAndroidExtensions = GradlePlugin(id = "kotlin-parcelize") - val mavenPublish = GradlePlugin(id = "maven-publish") - val signing = GradlePlugin(id = "signing") - - val mobileMultiplatform = GradlePlugin(id = "dev.icerock.mobile.multiplatform") - val mokoResources = GradlePlugin( - id = "dev.icerock.mobile.multiplatform-resources", - module = "dev.icerock.moko:resources-generator:${Versions.Plugins.mokoResources}" - ) - - val detekt = GradlePlugin(id = "io.gitlab.arturbosch.detekt", version = Versions.detekt) - } - - object Libs { - object Android { - val kotlinStdLib = AndroidLibrary( - name = "org.jetbrains.kotlin:kotlin-stdlib:${Versions.kotlin}" - ) - val appCompat = AndroidLibrary( - name = "androidx.appcompat:appcompat:${Versions.Libs.Android.appCompat}" - ) - val constraintLayout = AndroidLibrary( - name = "androidx.constraintlayout:constraintlayout:1.1.3" - ) - val coreKtx = AndroidLibrary( - name = "androidx.core:core-ktx:1.1.0" - ) - val playServices = AndroidLibrary( - name = "com.google.android.gms:play-services-tasks:17.0.0" - ) - val androidDraw = AndroidLibrary( - name = "com.github.divyanshub024:AndroidDraw:v0.1" - ) - - val tensorflowLite = AndroidLibrary( - name = "org.tensorflow:tensorflow-lite:${Versions.Libs.Android.tensorflowLite}" - ) - } - - object MultiPlatform { - val kotlinStdLib = MultiPlatformLibrary( - android = Android.kotlinStdLib.name, - common = "org.jetbrains.kotlin:kotlin-stdlib-common:${Versions.kotlin}" - ) - val mokoTensorflow = MultiPlatformLibrary( - common = "dev.icerock.moko:tensorflow:${Versions.Libs.MultiPlatform.mokoTensorflow}", - iosX64 = "dev.icerock.moko:tensorflow-iosx64:${Versions.Libs.MultiPlatform.mokoTensorflow}", - iosArm64 = "dev.icerock.moko:tensorflow-iosarm64:${Versions.Libs.MultiPlatform.mokoTensorflow}" - ) - val mokoResources = MultiPlatformLibrary( - common = "dev.icerock.moko:resources:${Versions.Libs.MultiPlatform.mokoResources}", - iosX64 = "dev.icerock.moko:resources-iosx64:${Versions.Libs.MultiPlatform.mokoResources}", - iosArm64 = "dev.icerock.moko:resources-iosarm64:${Versions.Libs.MultiPlatform.mokoResources}" - ) - val mokoMedia = MultiPlatformLibrary( - common = "dev.icerock.moko:media:${Versions.Libs.MultiPlatform.mokoMedia}", - iosX64 = "dev.icerock.moko:media-iosx64:${Versions.Libs.MultiPlatform.mokoMedia}", - iosArm64 = "dev.icerock.moko:media-iosarm64:${Versions.Libs.MultiPlatform.mokoMedia}" - ) - - val coroutineWorker = MultiPlatformLibrary( - common = "com.autodesk:coroutineworker:${Versions.Libs.MultiPlatform.coroutineWorker}" - ) - } - - object Jvm { - const val detektFormatting = "io.gitlab.arturbosch.detekt:detekt-formatting:${Versions.detekt}" - } - } -} diff --git a/buildSrc/src/main/kotlin/Versions.kt b/buildSrc/src/main/kotlin/Versions.kt deleted file mode 100755 index ffbd1a1..0000000 --- a/buildSrc/src/main/kotlin/Versions.kt +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright 2020 IceRock MAG Inc. Use of this source code is governed by the Apache 2.0 license. - */ - -object Versions { - object Android { - const val compileSdk = 28 - const val targetSdk = 28 - const val minSdk = 19 - } - - const val kotlin = "1.4.31" - const val detekt = "1.15.0" - - private const val mokoResources = "0.15.1" - - object Plugins { - const val android = "4.1.1" - - const val kotlin = Versions.kotlin - const val mokoResources = Versions.mokoResources - } - - object Libs { - object Android { - const val appCompat = "1.1.0" - const val tensorflowLite = "2.2.0" - } - - object MultiPlatform { - const val mokoTensorflow = "0.1.1" - const val mokoResources = Versions.mokoResources - const val mokoMedia = "0.6.2" - - const val coroutineWorker = "0.6.3" - } - } -} diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml new file mode 100644 index 0000000..032ccf6 --- /dev/null +++ b/gradle/libs.versions.toml @@ -0,0 +1,28 @@ +[versions] +kotlinVersion = "1.5.20" +mokoResourcesVersion = "0.16.1" +androidVersion = "4.1.1" +appCompatVersion = "1.1.0" +tensorflowLiteVersion = "2.2.0" +mokoTensorflowVersion = "0.2.0" +mokoMediaVersion = "0.9.0" +coroutinesVersion = "1.5.0-native-mt" +constraintLayoutVersion = "1.1.3" +coreKtxVersion = "1.1.0" +playServicesVersion = "17.0.0" +androidDrawVersion = "v0.1" +lifecycleRuntimeVersion = "2.2.0" + +[libraries] +appCompat = { module = "androidx.appcompat:appcompat", version.ref = "appCompatVersion" } +kotlinStdLib = { module = "org.jetbrains.kotlin:kotlin-stdlib", version.ref = "kotlinVersion" } +constraintLayout = { module = "androidx.constraintlayout:constraintlayout", version.ref = "constraintLayoutVersion" } +coreKtx = { module = "androidx.core:core-ktx", version.ref = "coreKtxVersion" } +playServices = { module = "com.google.android.gms:play-services-tasks", version.ref = "playServicesVersion" } +androidDraw = { module = "com.github.divyanshub024:AndroidDraw", version.ref = "androidDrawVersion" } +tensorflowLite = { module = "org.tensorflow:tensorflow-lite", version.ref = "tensorflowLiteVersion" } +mokoTensorflow = { module = "dev.icerock.moko:tensorflow", version.ref = "mokoTensorflowVersion" } +mokoResources = { module = "dev.icerock.moko:resources", version.ref = "mokoResourcesVersion" } +mokoMedia = { module = "dev.icerock.moko:media", version.ref = "mokoMediaVersion" } +coroutines = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version.ref = "coroutinesVersion" } +lifecycleRuntime = { module = "androidx.lifecycle:lifecycle-runtime-ktx", version.ref = "lifecycleRuntimeVersion" } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 8998263..f3c52d3 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.8.3-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.2-all.zip diff --git a/sample/android-app/build.gradle.kts b/sample/android-app/build.gradle.kts index d45bed8..3d5a3e9 100644 --- a/sample/android-app/build.gradle.kts +++ b/sample/android-app/build.gradle.kts @@ -3,54 +3,29 @@ */ plugins { - id("com.android.application") + id("android-app-convention") id("kotlin-android") } android { - compileSdkVersion(Versions.Android.compileSdk) - - dexOptions { - javaMaxHeapSize = "2g" - } - defaultConfig { - minSdkVersion(Versions.Android.minSdk) - targetSdkVersion(Versions.Android.targetSdk) - applicationId = "dev.icerock.moko.samples.tensorflow" versionCode = 1 versionName = "0.1.0" - - vectorDrawables.useSupportLibrary = true - testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" - } - - buildTypes { - getByName("release") { - isMinifyEnabled = false - proguardFiles(getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro") - } - getByName("debug") { - isDebuggable = true - applicationIdSuffix = ".debug" - } - } - - packagingOptions { - exclude("META-INF/*.kotlin_module") } } dependencies { - implementation(Deps.Libs.Android.kotlinStdLib.name) - - implementation(Deps.Libs.Android.coreKtx.name) - implementation(Deps.Libs.Android.appCompat.name) - implementation(Deps.Libs.Android.constraintLayout.name) - implementation(Deps.Libs.Android.androidDraw.name) - implementation(Deps.Libs.Android.playServices.name) - - implementation(project("${parent!!.path}:mpp-library")) + implementation(libs.coroutines) + implementation(libs.kotlinStdLib) + implementation(libs.coreKtx) + implementation(libs.appCompat) + implementation(libs.constraintLayout) + implementation(libs.androidDraw) + implementation(libs.playServices) + implementation(libs.mokoResources) + implementation(libs.lifecycleRuntime) + + implementation(projects.sample.mppLibrary) } diff --git a/sample/android-app/src/main/java/com/icerockdev/MainActivity.kt b/sample/android-app/src/main/java/com/icerockdev/MainActivity.kt index 37aca02..6baf5fe 100644 --- a/sample/android-app/src/main/java/com/icerockdev/MainActivity.kt +++ b/sample/android-app/src/main/java/com/icerockdev/MainActivity.kt @@ -11,6 +11,7 @@ import android.os.Bundle import android.view.MotionEvent import android.widget.Button import android.widget.TextView +import androidx.lifecycle.lifecycleScope import com.divyanshu.draw.widget.DrawView import com.icerockdev.library.ResHolder import com.icerockdev.library.TFDigitClassifier @@ -58,7 +59,7 @@ class MainActivity : AppCompatActivity() { } interpreter = Interpreter(ResHolder.getDigitsClassifierModel(), InterpreterOptions(2, useNNAPI = true), this) - digitClassifier = TFDigitClassifier(interpreter) + digitClassifier = TFDigitClassifier(interpreter, this.lifecycleScope) digitClassifier.initialize() isInterpreterInited.set(true) diff --git a/sample/ios-app/Podfile.lock b/sample/ios-app/Podfile.lock index 29169f6..2895be2 100644 --- a/sample/ios-app/Podfile.lock +++ b/sample/ios-app/Podfile.lock @@ -28,4 +28,4 @@ SPEC CHECKSUMS: PODFILE CHECKSUM: 0bd758d123d6d6a658976b260fce011651596789 -COCOAPODS: 1.10.0 +COCOAPODS: 1.10.1 diff --git a/sample/ios-app/tensorflow-test.xcodeproj/project.pbxproj b/sample/ios-app/tensorflow-test.xcodeproj/project.pbxproj index c658d6b..521a528 100644 --- a/sample/ios-app/tensorflow-test.xcodeproj/project.pbxproj +++ b/sample/ios-app/tensorflow-test.xcodeproj/project.pbxproj @@ -357,6 +357,7 @@ "$(inherited)", "@executable_path/Frameworks", ); + ONLY_ACTIVE_ARCH = YES; PRODUCT_BUNDLE_IDENTIFIER = dev.icerock.moko.sample.tensorflowtest; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_VERSION = 5.0; @@ -375,6 +376,7 @@ "$(inherited)", "@executable_path/Frameworks", ); + ONLY_ACTIVE_ARCH = YES; PRODUCT_BUNDLE_IDENTIFIER = dev.icerock.moko.sample.tensorflowtest; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_VERSION = 5.0; diff --git a/sample/ios-app/tensorflow-test/ViewController.swift b/sample/ios-app/tensorflow-test/ViewController.swift index 3462b12..8c10eb7 100644 --- a/sample/ios-app/tensorflow-test/ViewController.swift +++ b/sample/ios-app/tensorflow-test/ViewController.swift @@ -15,10 +15,10 @@ class ViewController: UIViewController, SketchViewDelegate { private var tfDigitClassifier: TFDigitClassifier? private var isInterpreterInited: Bool = false - + private var scope: MainCoroutineScope? override func viewDidLoad() { super.viewDidLoad() - + scope = MainCoroutineScope() sketchView.lineWidth = 30 sketchView.backgroundColor = UIColor.black sketchView.lineColor = UIColor.white @@ -28,13 +28,15 @@ class ViewController: UIViewController, SketchViewDelegate { let modelFileRes: ResourcesFileResource = ResHolder().getDigitsClassifierModel() interpreter = TensorflowInterpreter(fileResource: modelFileRes, options: options) - tfDigitClassifier = TFDigitClassifier(interpreter: interpreter!) + tfDigitClassifier = TFDigitClassifier(interpreter: interpreter!, scope: scope!) tfDigitClassifier?.initialize() self.isInterpreterInited = true } + deinit { + scope?.close() interpreter?.close() } diff --git a/sample/mpp-library/build.gradle.kts b/sample/mpp-library/build.gradle.kts index 7233d17..f0ea22b 100644 --- a/sample/mpp-library/build.gradle.kts +++ b/sample/mpp-library/build.gradle.kts @@ -4,34 +4,30 @@ plugins { id("com.android.library") + id("android-base-convention") + id("detekt-convention") id("org.jetbrains.kotlin.multiplatform") - id("dev.icerock.mobile.multiplatform") - id("dev.icerock.mobile.multiplatform-resources") + id("dev.icerock.mobile.multiplatform.android-manifest") id("dev.icerock.mobile.multiplatform.ios-framework") + id("dev.icerock.mobile.multiplatform.cocoapods") + id("dev.icerock.mobile.multiplatform-resources") } -android { - compileSdkVersion(Versions.Android.compileSdk) - - defaultConfig { - minSdkVersion(Versions.Android.minSdk) - targetSdkVersion(Versions.Android.targetSdk) - } +kotlin { + android() + ios() } dependencies { - mppLibrary(Deps.Libs.MultiPlatform.kotlinStdLib) - - mppLibrary(Deps.Libs.MultiPlatform.mokoResources) - mppLibrary(Deps.Libs.MultiPlatform.mokoMedia) - - commonMainApi(project(":tensorflow")) - - mppLibrary(Deps.Libs.MultiPlatform.coroutineWorker) + commonMainImplementation(libs.kotlinStdLib) + commonMainImplementation(libs.mokoResources) + commonMainImplementation(libs.mokoMedia) + commonMainApi(projects.tensorflow) + commonMainImplementation(libs.coroutines) } multiplatformResources { - multiplatformResourcesPackage = "dev.icerock.moko.sample.tensorflowtest" + multiplatformResourcesPackage = "dev.icerock.moko.sample.tensorflowtest" } cocoaPods { @@ -52,4 +48,4 @@ kotlin { "TensorFlowLiteC" ) } -} +} \ No newline at end of file diff --git a/sample/mpp-library/src/commonMain/kotlin/com/icerockdev/library/TFDigitClassifier.kt b/sample/mpp-library/src/commonMain/kotlin/com/icerockdev/library/TFDigitClassifier.kt index 3af5edf..0b2c00c 100644 --- a/sample/mpp-library/src/commonMain/kotlin/com/icerockdev/library/TFDigitClassifier.kt +++ b/sample/mpp-library/src/commonMain/kotlin/com/icerockdev/library/TFDigitClassifier.kt @@ -4,11 +4,14 @@ package com.icerockdev.library -import com.autodesk.coroutineworker.CoroutineWorker import dev.icerock.moko.tensorflow.Interpreter +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch class TFDigitClassifier( - private val interpreter: Interpreter + private val interpreter: Interpreter, + private val scope: CoroutineScope ) { var inputImageWidth: Int = 0 // will be inferred from TF Lite model @@ -26,12 +29,12 @@ class TFDigitClassifier( } fun classifyAsync(inputData: Any, onResult: (String) -> Unit) { - CoroutineWorker.execute { + scope.launch(Dispatchers.Default) { val result = Array(1) { FloatArray(OUTPUT_CLASSES_COUNT) } interpreter.run(listOf(inputData), mapOf(Pair(0, result))) - val maxIndex = result[0].indices.maxBy { result[0][it] } ?: -1 + val maxIndex = result[0].indices.maxByOrNull { result[0][it] } ?: -1 val strResult = "Prediction Result: $maxIndex\nConfidence: ${result[0][maxIndex]}" onResult(strResult) diff --git a/sample/mpp-library/src/iosMain/kotlin/com/icerockdev/library/MainCoroutineScope.kt b/sample/mpp-library/src/iosMain/kotlin/com/icerockdev/library/MainCoroutineScope.kt new file mode 100644 index 0000000..a1d0a1f --- /dev/null +++ b/sample/mpp-library/src/iosMain/kotlin/com/icerockdev/library/MainCoroutineScope.kt @@ -0,0 +1,12 @@ +package com.icerockdev.library + +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.SupervisorJob +import kotlinx.coroutines.cancel + +class MainCoroutineScope : CoroutineScope by CoroutineScope(Dispatchers.Main + SupervisorJob()) { + fun close() { + this.cancel() + } +} diff --git a/settings.gradle.kts b/settings.gradle.kts index 106c223..f7f6592 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -2,6 +2,27 @@ * Copyright 2020 IceRock MAG Inc. Use of this source code is governed by the Apache 2.0 license. */ + +enableFeaturePreview("VERSION_CATALOGS") +enableFeaturePreview("TYPESAFE_PROJECT_ACCESSORS") + +dependencyResolutionManagement { + repositories { + mavenCentral() + google() + + jcenter { + content { + includeGroup("org.jetbrains.kotlinx") + includeGroup("org.tensorflow") + } + } + maven { url = uri("https://jitpack.io") } + } +} + +includeBuild("tensorflow-build-logic") + include(":tensorflow") include(":sample:android-app") include(":sample:mpp-library") diff --git a/tensorflow-build-logic/build.gradle.kts b/tensorflow-build-logic/build.gradle.kts new file mode 100644 index 0000000..84cbae3 --- /dev/null +++ b/tensorflow-build-logic/build.gradle.kts @@ -0,0 +1,17 @@ +plugins { + `kotlin-dsl` +} + +repositories { + mavenCentral() + google() + + gradlePluginPortal() +} + +dependencies { + api("dev.icerock:mobile-multiplatform:0.12.0") + api("org.jetbrains.kotlin:kotlin-gradle-plugin:1.5.20") + api("com.android.tools.build:gradle:4.2.1") + api("io.gitlab.arturbosch.detekt:detekt-gradle-plugin:1.15.0") +} diff --git a/tensorflow-build-logic/src/main/kotlin/android-app-convention.gradle.kts b/tensorflow-build-logic/src/main/kotlin/android-app-convention.gradle.kts new file mode 100644 index 0000000..2859874 --- /dev/null +++ b/tensorflow-build-logic/src/main/kotlin/android-app-convention.gradle.kts @@ -0,0 +1,32 @@ +/* + * Copyright 2021 IceRock MAG Inc. Use of this source code is governed by the Apache 2.0 license. + */ + +plugins { + id("com.android.application") + id("android-base-convention") + id("kotlin-android") +} + +android { + dexOptions { + javaMaxHeapSize = "2g" + } + + buildTypes { + getByName("release") { + isMinifyEnabled = true + proguardFiles(getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro") + } + getByName("debug") { + isDebuggable = true + applicationIdSuffix = ".debug" + } + } + + packagingOptions { + exclude("META-INF/*.kotlin_module") + exclude("META-INF/AL2.0") + exclude("META-INF/LGPL2.1") + } +} diff --git a/tensorflow-build-logic/src/main/kotlin/android-base-convention.gradle.kts b/tensorflow-build-logic/src/main/kotlin/android-base-convention.gradle.kts new file mode 100644 index 0000000..51c8312 --- /dev/null +++ b/tensorflow-build-logic/src/main/kotlin/android-base-convention.gradle.kts @@ -0,0 +1,14 @@ +/* + * Copyright 2021 IceRock MAG Inc. Use of this source code is governed by the Apache 2.0 license. + */ + +import com.android.build.gradle.BaseExtension + +configure { + compileSdkVersion(30) + + defaultConfig { + minSdkVersion(19) + targetSdkVersion(30) + } +} diff --git a/tensorflow-build-logic/src/main/kotlin/android-library-convention.gradle.kts b/tensorflow-build-logic/src/main/kotlin/android-library-convention.gradle.kts new file mode 100644 index 0000000..c435401 --- /dev/null +++ b/tensorflow-build-logic/src/main/kotlin/android-library-convention.gradle.kts @@ -0,0 +1,13 @@ +/* + * Copyright 2021 IceRock MAG Inc. Use of this source code is governed by the Apache 2.0 license. + */ + +plugins { + id("com.android.library") + id("kotlin-android") + id("android-base-convention") +} + +android { + sourceSets.all { java.srcDir("src/$name/kotlin") } +} diff --git a/tensorflow-build-logic/src/main/kotlin/android-publication-convention.gradle.kts b/tensorflow-build-logic/src/main/kotlin/android-publication-convention.gradle.kts new file mode 100644 index 0000000..b4dae9e --- /dev/null +++ b/tensorflow-build-logic/src/main/kotlin/android-publication-convention.gradle.kts @@ -0,0 +1,15 @@ +/* + * Copyright 2021 IceRock MAG Inc. Use of this source code is governed by the Apache 2.0 license. + */ + +plugins { + id("publication-convention") +} + +afterEvaluate { + publishing.publications { + create("release", MavenPublication::class.java) { + from(components.getByName("release")) + } + } +} diff --git a/tensorflow-build-logic/src/main/kotlin/detekt-convention.gradle.kts b/tensorflow-build-logic/src/main/kotlin/detekt-convention.gradle.kts new file mode 100644 index 0000000..68343a8 --- /dev/null +++ b/tensorflow-build-logic/src/main/kotlin/detekt-convention.gradle.kts @@ -0,0 +1,15 @@ +/* + * Copyright 2021 IceRock MAG Inc. Use of this source code is governed by the Apache 2.0 license. + */ + +plugins { + id("io.gitlab.arturbosch.detekt") +} + +detekt { + input.setFrom("src/commonMain/kotlin", "src/androidMain/kotlin", "src/iosMain/kotlin", "src/main/kotlin") +} + +dependencies { + "detektPlugins"("io.gitlab.arturbosch.detekt:detekt-formatting:1.15.0") +} diff --git a/tensorflow-build-logic/src/main/kotlin/javadoc-stub-convention.gradle.kts b/tensorflow-build-logic/src/main/kotlin/javadoc-stub-convention.gradle.kts new file mode 100644 index 0000000..a1a2691 --- /dev/null +++ b/tensorflow-build-logic/src/main/kotlin/javadoc-stub-convention.gradle.kts @@ -0,0 +1,16 @@ +/* + * Copyright 2021 IceRock MAG Inc. Use of this source code is governed by the Apache 2.0 license. + */ + +plugins { + id("org.gradle.maven-publish") +} + +val javadocJar by tasks.registering(Jar::class) { + archiveClassifier.set("javadoc") +} + +publishing.publications.withType { + // Stub javadoc.jar artifact + artifact(javadocJar.get()) +} diff --git a/tensorflow-build-logic/src/main/kotlin/multiplatform-library-convention.gradle.kts b/tensorflow-build-logic/src/main/kotlin/multiplatform-library-convention.gradle.kts new file mode 100644 index 0000000..347106b --- /dev/null +++ b/tensorflow-build-logic/src/main/kotlin/multiplatform-library-convention.gradle.kts @@ -0,0 +1,18 @@ +/* + * Copyright 2021 IceRock MAG Inc. Use of this source code is governed by the Apache 2.0 license. + */ + +plugins { + id("com.android.library") + id("org.jetbrains.kotlin.multiplatform") + id("android-base-convention") + id("dev.icerock.mobile.multiplatform.android-manifest") +} + +kotlin { + ios() + android { + publishLibraryVariants("release", "debug") + } +} + diff --git a/tensorflow-build-logic/src/main/kotlin/publication-convention.gradle.kts b/tensorflow-build-logic/src/main/kotlin/publication-convention.gradle.kts new file mode 100644 index 0000000..f0d2810 --- /dev/null +++ b/tensorflow-build-logic/src/main/kotlin/publication-convention.gradle.kts @@ -0,0 +1,65 @@ +/* + * Copyright 2021 IceRock MAG Inc. Use of this source code is governed by the Apache 2.0 license. + */ + +import java.util.Base64 + +plugins { + id("javadoc-stub-convention") + id("org.gradle.maven-publish") + id("signing") +} + +publishing { + repositories.maven("https://s01.oss.sonatype.org/service/local/staging/deploy/maven2/") { + name = "OSSRH" + + credentials { + username = System.getenv("OSSRH_USER") + password = System.getenv("OSSRH_KEY") + } + } + + publications.withType { + // Provide artifacts information requited by Maven Central + pom { + name.set("MOKO tensorflow") + description.set("Tensorflow Lite bindings for mobile (android & ios) Kotlin Multiplatform development") + url.set("https://github.com/icerockdev/moko-tensorflow") + licenses { + license { + name.set("Apache-2.0") + distribution.set("repo") + url.set("https://github.com/icerockdev/moko-tensorflow/blob/master/LICENSE.md") + } + } + + developers { + developer { + id.set("Tetraquark") + name.set("Vladislav Areshkin") + email.set("vareshkin@icerockdev.com") + } + } + + scm { + connection.set("scm:git:ssh://github.com/icerockdev/moko-tensorflow.git") + developerConnection.set("scm:git:ssh://github.com/icerockdev/moko-tensorflow.git") + url.set("https://github.com/icerockdev/moko-tensorflow") + } + } + } +} + + +signing { + val signingKeyId: String? = System.getenv("SIGNING_KEY_ID") + val signingPassword: String? = System.getenv("SIGNING_PASSWORD") + val signingKey: String? = System.getenv("SIGNING_KEY")?.let { base64Key -> + String(Base64.getDecoder().decode(base64Key)) + } + if (signingKeyId != null) { + useInMemoryPgpKeys(signingKeyId, signingKey, signingPassword) + sign(publishing.publications) + } +} diff --git a/tensorflow/build.gradle.kts b/tensorflow/build.gradle.kts index 2447d6c..019650c 100644 --- a/tensorflow/build.gradle.kts +++ b/tensorflow/build.gradle.kts @@ -3,29 +3,18 @@ */ plugins { - plugin(Deps.Plugins.androidLibrary) - plugin(Deps.Plugins.kotlinMultiplatform) - plugin(Deps.Plugins.kotlinAndroidExtensions) - plugin(Deps.Plugins.mobileMultiplatform) - plugin(Deps.Plugins.mavenPublish) -} - -android { - compileSdkVersion(Versions.Android.compileSdk) - - defaultConfig { - minSdkVersion(Versions.Android.minSdk) - targetSdkVersion(Versions.Android.targetSdk) - } + id("multiplatform-library-convention") + id("dev.icerock.mobile.multiplatform.android-manifest") + id("publication-convention") + id("dev.icerock.mobile.multiplatform.cocoapods") } dependencies { - mppLibrary(Deps.Libs.MultiPlatform.kotlinStdLib) + commonMainImplementation(libs.kotlinStdLib) + commonMainImplementation(libs.mokoResources) - mppLibrary(Deps.Libs.MultiPlatform.mokoResources) - - androidLibrary(Deps.Libs.Android.appCompat) - androidLibrary(Deps.Libs.Android.tensorflowLite) + androidMainImplementation(libs.appCompat) + androidMainImplementation(libs.tensorflowLite) } cocoaPods { @@ -33,3 +22,4 @@ cocoaPods { pod("TensorFlowLiteObjC", module = "TFLTensorFlowLite") } + diff --git a/tensorflow/src/iosArm64Main b/tensorflow/src/iosArm64Main index 93d7d74..46be4b8 120000 --- a/tensorflow/src/iosArm64Main +++ b/tensorflow/src/iosArm64Main @@ -1 +1 @@ -iosMain \ No newline at end of file +iosX64Main \ No newline at end of file diff --git a/tensorflow/src/iosX64Main b/tensorflow/src/iosX64Main deleted file mode 120000 index 93d7d74..0000000 --- a/tensorflow/src/iosX64Main +++ /dev/null @@ -1 +0,0 @@ -iosMain \ No newline at end of file diff --git a/tensorflow/src/iosMain/kotlin/dev/icerock/moko/tensorflow/InterpreterOptions.kt b/tensorflow/src/iosX64Main/kotlin/dev.icerock.moko.tensorflow/InterpreterOptions.kt similarity index 100% rename from tensorflow/src/iosMain/kotlin/dev/icerock/moko/tensorflow/InterpreterOptions.kt rename to tensorflow/src/iosX64Main/kotlin/dev.icerock.moko.tensorflow/InterpreterOptions.kt diff --git a/tensorflow/src/iosMain/kotlin/dev/icerock/moko/tensorflow/Tensor.kt b/tensorflow/src/iosX64Main/kotlin/dev.icerock.moko.tensorflow/Tensor.kt similarity index 100% rename from tensorflow/src/iosMain/kotlin/dev/icerock/moko/tensorflow/Tensor.kt rename to tensorflow/src/iosX64Main/kotlin/dev.icerock.moko.tensorflow/Tensor.kt diff --git a/tensorflow/src/iosMain/kotlin/dev/icerock/moko/tensorflow/TensorExt.kt b/tensorflow/src/iosX64Main/kotlin/dev.icerock.moko.tensorflow/TensorExt.kt similarity index 100% rename from tensorflow/src/iosMain/kotlin/dev/icerock/moko/tensorflow/TensorExt.kt rename to tensorflow/src/iosX64Main/kotlin/dev.icerock.moko.tensorflow/TensorExt.kt diff --git a/tensorflow/src/iosMain/kotlin/dev/icerock/moko/tensorflow/TensorflowAliases.kt b/tensorflow/src/iosX64Main/kotlin/dev.icerock.moko.tensorflow/TensorflowAliases.kt similarity index 100% rename from tensorflow/src/iosMain/kotlin/dev/icerock/moko/tensorflow/TensorflowAliases.kt rename to tensorflow/src/iosX64Main/kotlin/dev.icerock.moko.tensorflow/TensorflowAliases.kt