From b634fb7c10cda0069bdbe3720209f58de08b29ad Mon Sep 17 00:00:00 2001 From: Diogo Matsubara Date: Wed, 17 Jul 2024 14:09:56 +0200 Subject: [PATCH] Update main release workflow (#133) * Using 'android' property to enable/disable Android configuration (#127) * Enabling snapshot publications for dev/1.0.0 * refactor(gradle): using 'android' property to enable/disable Android configuration Examples: - `gradle build -Pandroid=true` enables build with android - `gradle build` won't consider any android configuration - `gradle publishAndroidReleaseToMavenLocal -Pandroid=true` publishes to maven local, without `-Pandroid=true` it won't work. * refactor(gradle): updating publication workflows * refactor(gradle): updating readme instructions --------- Co-authored-by: zettascale-bot <161707711+zettascale-bot@users.noreply.github.com> * fix(local publication): triggering compilation of zenoh jni when publishing jvm to maven local (#128) * Update actions (#130) * chore: Update setup-java to v4 * chore: update gradle action to newer version * chore: update gradle/wrapper-validation-action@v3 --------- Co-authored-by: Darius Maitia Co-authored-by: zettascale-bot <161707711+zettascale-bot@users.noreply.github.com> --- .github/workflows/ci.yml | 11 +- .github/workflows/pre-release.yml | 4 +- .github/workflows/publish-android.yml | 8 +- .github/workflows/publish-jvm.yml | 15 +- README.md | 96 ++++++------- zenoh-kotlin/build.gradle.kts | 190 ++++++++++++++++++-------- 6 files changed, 185 insertions(+), 139 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e4810c2f..6a7933c8 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -27,18 +27,11 @@ jobs: steps: - uses: actions/checkout@v4 - - uses: actions/setup-java@v3 + - uses: actions/setup-java@v4 with: distribution: temurin java-version: 11 - - uses: nttld/setup-ndk@v1 - id: setup-ndk - with: - ndk-version: r26 - add-to-path: false - link-to-sdk: true - - name: Install Rust toolchain run: | rustup show @@ -61,7 +54,7 @@ jobs: run: cargo build - name: Setup Gradle - uses: gradle/gradle-build-action@v2 + uses: gradle/actions/setup-gradle@v3 - name: Gradle Test run: gradle jvmTest --info diff --git a/.github/workflows/pre-release.yml b/.github/workflows/pre-release.yml index 0c5b652e..a579a62e 100644 --- a/.github/workflows/pre-release.yml +++ b/.github/workflows/pre-release.yml @@ -20,7 +20,7 @@ jobs: steps: - uses: actions/checkout@v4 - - uses: actions/setup-java@v3 + - uses: actions/setup-java@v4 with: distribution: temurin java-version: 11 @@ -54,7 +54,7 @@ jobs: run: cargo build - name: Setup Gradle - uses: gradle/gradle-build-action@v2 + uses: gradle/actions/setup-gradle@v3 - name: Gradle Test run: gradle jvmTest --info diff --git a/.github/workflows/publish-android.yml b/.github/workflows/publish-android.yml index 580e6087..0ee5c265 100644 --- a/.github/workflows/publish-android.yml +++ b/.github/workflows/publish-android.yml @@ -29,7 +29,7 @@ jobs: with: ref: ${{ inputs.branch }} - - uses: actions/setup-java@v3 + - uses: actions/setup-java@v4 with: distribution: temurin java-version: 11 @@ -58,7 +58,7 @@ jobs: gradle wrapper - name: Validate Gradle wrapper - uses: gradle/wrapper-validation-action@v1 + uses: gradle/wrapper-validation-action@v3 - name: Set pub mode env var # Note: This step is intended to allow publishing snapshot packages. @@ -71,8 +71,8 @@ jobs: fi - name: Gradle Publish Android Package - uses: gradle/gradle-build-action@v2 + uses: gradle/actions/setup-gradle@v3 with: - arguments: publishAndroidReleasePublicationToGithubPackagesRepository ${{ env.PUB_MODE }} + arguments: publishAndroidReleasePublicationToGithubPackagesRepository -Pandroid=true ${{ env.PUB_MODE }} env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/publish-jvm.yml b/.github/workflows/publish-jvm.yml index 315b2558..660c5151 100644 --- a/.github/workflows/publish-jvm.yml +++ b/.github/workflows/publish-jvm.yml @@ -147,24 +147,17 @@ jobs: with: path: ${{env.JNI_LIB_PATHS}} - - uses: actions/setup-java@v3 + - uses: actions/setup-java@v4 with: distribution: temurin java-version: 11 - - uses: nttld/setup-ndk@v1 - id: setup-ndk - with: - ndk-version: r26 - add-to-path: false - link-to-sdk: true - - name: Gradle Wrapper run: | gradle wrapper - name: Validate Gradle wrapper - uses: gradle/wrapper-validation-action@v1 + uses: gradle/wrapper-validation-action@v3 - name: Set pub mode env var # Note: This step is intended to allow publishing snapshot packages. @@ -177,8 +170,8 @@ jobs: fi - name: Gradle Publish JVM Package - uses: gradle/gradle-build-action@v2 + uses: gradle/actions/setup-gradle@v3 with: - arguments: publishJvmPublicationToGithubPackagesRepository ${{ env.PUB_MODE }} + arguments: publishJvmPublicationToGithubPackagesRepository -PgithubPublish=true ${{ env.PUB_MODE }} env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/README.md b/README.md index 67c860fa..e428db95 100644 --- a/README.md +++ b/README.md @@ -67,7 +67,7 @@ This is required by Github in order to import the package, even if it's from a p After that add to the dependencies in the app's `build.gradle.kts`: ```kotlin -implementation("io.zenoh:zenoh-kotlin-android:0.10.1-rc") +implementation("io.zenoh:zenoh-kotlin-android:0.11.0") ``` ### Platforms @@ -122,7 +122,7 @@ This is required by Github in order to import the package, even if it's from a p After that add to the dependencies in the app's `build.gradle.kts`: ```kotlin -implementation("io.zenoh:zenoh-kotlin-jvm:0.10.1-rc") +implementation("io.zenoh:zenoh-kotlin-jvm:0.11.0") ``` ### Platforms @@ -146,8 +146,40 @@ Basically: * Rust ([Installation guide](https://doc.rust-lang.org/cargo/getting-started/installation.html)) * Kotlin ([Installation guide](https://kotlinlang.org/docs/getting-started.html#backend)) * Gradle ([Installation guide](https://gradle.org/install/)) + +and in case of targetting Android you'll also need: * Android SDK ([Installation guide](https://developer.android.com/about/versions/11/setup-sdk)) +## JVM JVM + +To publish a library for a JVM project into Maven local, run + +```bash +gradle -Prelease=true publishJvmPublicationToMavenLocal +``` + +This will first, trigger the compilation of Zenoh-JNI in release (if you want debug, specify `-Prelease=false`), and second publish the library into maven local, containing the native library +as a resource that will be loaded during runtime. + +:warning: The native library will be compiled against the default rustup target on your machine, so although it may work fine +for you on your desktop, the generated publication may not be working on another computer with a different operating system and/or a different cpu architecture. + +Once we have published the package, we should be able to find it under `~/.m2/repository/io/zenoh/zenoh-kotlin-jvm/0.11.0`. + +Finally, in the `build.gradle.kts` file of the project where you intend to use this library, add mavenLocal to the list of repositories and add zenoh-kotlin as a dependency: + +``` +repositories { + mavenCentral() + mavenLocal() +} + +dependencies { + testImplementation(kotlin("test")) + implementation("io.zenoh:zenoh-kotlin-jvm:0.11.0") +} +``` + ## Android Android In order to use these bindings in a native Android project, what we will do is to build them as an Android NDK Library, @@ -179,19 +211,19 @@ to install them. So, in order to publish the library onto Maven Local, run: ```bash -gradle publishAndroidReleasePublicationToMavenLocal +gradle -Pandroid=true publishAndroidReleasePublicationToMavenLocal ``` This will first trigger the compilation of the Zenoh-JNI for the previously mentioned targets, and secondly will publish the library, containing the native binaries. -You should now be able to see the package under `~/.m2/repository/io/zenoh/zenoh-kotlin-android/0.10.1-rc` +You should now be able to see the package under `~/.m2/repository/io/zenoh/zenoh-kotlin-android/0.11.0` with the following files: ``` -zenoh-kotlin-android-0.10.1-rc-sources.jar -zenoh-kotlin-android-0.10.1-rc.aar -zenoh-kotlin-android-0.10.1-rc.module -zenoh-kotlin-android-0.10.1-rc.pom +zenoh-kotlin-android-0.11.0-sources.jar +zenoh-kotlin-android-0.11.0.aar +zenoh-kotlin-android-0.11.0.module +zenoh-kotlin-android-0.11.0.pom ``` Now the library is published on maven local, let's now see how to import it into an Android project. @@ -208,7 +240,7 @@ repositories { Then in your app's `build.gradle.kts` filen add the dependency: ``` -implementation("io.zenoh:zenoh-kotlin-android:0.10.1-rc") +implementation("io.zenoh:zenoh-kotlin-android:0.11.0") ``` And finally, do not forget to add the required internet permissions on your manifest! @@ -220,38 +252,6 @@ And finally, do not forget to add the required internet permissions on your mani And that was it! You can now import the code from the `io.zenoh` package and use it at your will. -## JVM JVM - -To publish a library for a JVM project into Maven local, run - -```bash -gradle publishJvmPublicationToMavenLocal -``` - -This will first, trigger the compilation of Zenoh-JNI, and second publish the library into maven local, containing the native library -as a resource that will be loaded during runtime. - -:warning: The native library will be compiled against the default rustup target on your machine, so although it may work fine -for you on your desktop, the generated publication may not be working on another computer with a different operating system and/or a different cpu architecture. -This is different from Android in the fact that Android provides an in build mechanism to dynamically load native libraries depending on the CPU's architecture, while -for JVM it's not the case and that logic must be implemented. Building against multiple targets and loading them dynamically is one of our short term goals. - -Once we have published the package, we should be able to find it under `~/.m2/repository/io/zenoh/zenoh-kotlin-jvm/0.10.1-rc`. - -Finally, in the `build.gradle.kts` file of the project where you intend to use this library, add mavenLocal to the list of repositories and add zenoh-kotlin as a dependency: - -``` -repositories { - mavenCentral() - mavenLocal() -} - -dependencies { - testImplementation(kotlin("test")) - implementation("io.zenoh:zenoh-kotlin-jvm:0.10.1-rc") -} -``` - ## Building the documentation Because it's a Kotlin project, we use [Dokka](https://kotlinlang.org/docs/dokka-introduction.html) to generate the documentation. @@ -263,13 +263,7 @@ gradle zenoh-kotlin:dokkaHtml ## Running the tests -To run the tests, we must first build the native library -```bash -cd zenoh-jni -cargo build -``` - -and then run: +To run the tests, run: ```bash gradle jvmTest @@ -323,12 +317,8 @@ add some extra functionalities and test this library a bit further, we will only ### Potential API changes -When using this library, keep in mind changes may occur, especially since this is the first version of the library. We have, however, -aimed to make the design as stable as possible from the very beginning, so changes on the code probably won't be substantial. - -### Missing features +When using this library, keep in mind the api is not fully stable. Changes are to be expected, especially for version 1.0.0. -There are some missing features we will implement soon. The most notorious is the Pull Subscriber feature. ### Performance diff --git a/zenoh-kotlin/build.gradle.kts b/zenoh-kotlin/build.gradle.kts index 594e0b41..86b5fff8 100644 --- a/zenoh-kotlin/build.gradle.kts +++ b/zenoh-kotlin/build.gradle.kts @@ -12,65 +12,28 @@ // ZettaScale Zenoh Team, // +import com.nishtahir.CargoExtension + plugins { - id("com.android.library") kotlin("multiplatform") kotlin("plugin.serialization") id("com.adarshr.test-logger") id("org.jetbrains.dokka") - id("org.mozilla.rust-android-gradle.rust-android") `maven-publish` } -android { - namespace = "io.zenoh" - compileSdk = 30 - - ndkVersion = "26.0.10792818" - - defaultConfig { - minSdk = 30 - } +val androidEnabled = project.findProperty("android")?.toString()?.toBoolean() == true +val release = project.findProperty("release")?.toString()?.toBoolean() == true +val githubPublish = project.findProperty("githubPublish")?.toString()?.toBoolean() == true - compileOptions { - sourceCompatibility = JavaVersion.VERSION_11 - targetCompatibility = JavaVersion.VERSION_11 - } +var buildMode = if (release) BuildMode.RELEASE else BuildMode.DEBUG - buildTypes { - getByName("release") { - isMinifyEnabled = false - } - getByName("debug") { - isMinifyEnabled = false - } - } - sourceSets { - getByName("main") { - manifest.srcFile("src/androidMain/AndroidManifest.xml") - } - } - publishing { - singleVariant("release") { - withSourcesJar() - withJavadocJar() - } - } -} +if (androidEnabled) { + apply(plugin = "com.android.library") + apply(plugin = "org.mozilla.rust-android-gradle.rust-android") -cargo { - pythonCommand = "python3" - module = "../zenoh-jni" - libname = "zenoh-jni" - targetIncludes = arrayOf("libzenoh_jni.so") - targetDirectory = "../zenoh-jni/target/" - profile = "release" - targets = arrayListOf( - "arm", - "arm64", - "x86", - "x86_64", - ) + configureCargo() + configureAndroid() } kotlin { @@ -80,12 +43,14 @@ kotlin { kotlinOptions.jvmTarget = "11" } testRuns["test"].executionTask.configure { - val zenohPaths = "../zenoh-jni/target/debug" + val zenohPaths = "../zenoh-jni/target/$buildMode" jvmArgs("-Djava.library.path=$zenohPaths") } } - androidTarget { - publishLibraryVariants("release") + if (androidEnabled) { + androidTarget { + publishLibraryVariants("release") + } } @Suppress("Unused") @@ -102,19 +67,24 @@ kotlin { implementation(kotlin("test")) } } - val androidUnitTest by getting { - dependencies { - implementation(kotlin("test-junit")) + if (androidEnabled) { + val androidUnitTest by getting { + dependencies { + implementation(kotlin("test-junit")) + } } } val jvmMain by getting { - resources.srcDir("../zenoh-jni/target/release").include(arrayListOf("*.dylib", "*.so", "*.dll")) - - // The line below is intended to load the native libraries that are crosscompiled on GitHub actions when publishing a JVM package. - resources.srcDir("../jni-libs").include("*/**") + if (githubPublish) { + // The line below is intended to load the native libraries that are crosscompiled on GitHub actions when publishing a JVM package. + resources.srcDir("../jni-libs").include("*/**") + } else { + resources.srcDir("../zenoh-jni/target/$buildMode").include(arrayListOf("*.dylib", "*.so", "*.dll")) + } } + val jvmTest by getting { - resources.srcDir("../zenoh-jni/target/debug").include(arrayListOf("*.dylib", "*.so", "*.dll")) + resources.srcDir("../zenoh-jni/target/$buildMode").include(arrayListOf("*.dylib", "*.so", "*.dll")) } } @@ -140,7 +110,7 @@ tasks.withType { doFirst { // The line below is added for the Android Unit tests which are equivalent to the JVM tests. // For them to work we need to specify the path to the native library as a system property and not as a jvmArg. - systemProperty("java.library.path", "../zenoh-jni/target/debug") + systemProperty("java.library.path", "../zenoh-jni/target/$buildMode") } } @@ -150,3 +120,103 @@ tasks.whenObjectAdded { this.inputs.dir(buildDir.resolve("rustJniLibs/android")) } } + +tasks.named("compileKotlinJvm") { + dependsOn("buildZenohJni") +} + +tasks.register("buildZenohJni") { + doLast { + if (!githubPublish) { + // This is intended for local publications. For publications done through GitHub workflows, + // the zenoh-jni build is achieved and loaded differently from the CI + buildZenohJNI(buildMode) + } + } +} + +fun buildZenohJNI(mode: BuildMode = BuildMode.DEBUG) { + val cargoCommand = mutableListOf("cargo", "build") + + if (mode == BuildMode.RELEASE) { + cargoCommand.add("--release") + } + + val result = project.exec { + commandLine(*(cargoCommand.toTypedArray()), "--manifest-path", "../zenoh-jni/Cargo.toml") + } + + if (result.exitValue != 0) { + throw GradleException("Failed to build Zenoh-JNI.") + } + + Thread.sleep(1000) +} + +enum class BuildMode { + DEBUG { + override fun toString(): String { + return "debug" + } + }, + RELEASE { + override fun toString(): String { + return "release" + } + } +} + +fun Project.configureAndroid() { + extensions.configure("android") { + namespace = "io.zenoh" + compileSdk = 30 + + ndkVersion = "26.0.10792818" + + defaultConfig { + minSdk = 30 + } + + compileOptions { + sourceCompatibility = JavaVersion.VERSION_11 + targetCompatibility = JavaVersion.VERSION_11 + } + + buildTypes { + getByName("release") { + isMinifyEnabled = false + } + getByName("debug") { + isMinifyEnabled = false + } + } + sourceSets { + getByName("main") { + manifest.srcFile("src/androidMain/AndroidManifest.xml") + } + } + publishing { + singleVariant("release") { + withSourcesJar() + withJavadocJar() + } + } + } +} + +fun Project.configureCargo() { + extensions.configure("cargo") { + pythonCommand = "python3" + module = "../zenoh-jni" + libname = "zenoh-jni" + targetIncludes = arrayOf("libzenoh_jni.so") + targetDirectory = "../zenoh-jni/target/" + profile = "release" + targets = arrayListOf( + "arm", + "arm64", + "x86", + "x86_64", + ) + } +}