From 8440af8235d7cc886f8d69473a880185ea24e0af Mon Sep 17 00:00:00 2001 From: Christian Melchior Date: Fri, 15 Dec 2023 14:19:44 +0100 Subject: [PATCH 01/12] Add improved Gradle setup for building on CI --- packages/build.gradle.kts | 126 +++++++++++++++++++++++++ packages/cinterop/build.gradle.kts | 106 +++++++++++++-------- packages/gradle.properties | 25 +++++ packages/library-base/build.gradle.kts | 6 +- packages/library-sync/build.gradle.kts | 21 ++--- 5 files changed, 232 insertions(+), 52 deletions(-) diff --git a/packages/build.gradle.kts b/packages/build.gradle.kts index 296bf17b24..3177eac4a7 100644 --- a/packages/build.gradle.kts +++ b/packages/build.gradle.kts @@ -33,6 +33,132 @@ allprojects { } } +/** + * Task that will build and publish the defined packages to /packages/build/m2-buildrepo`. + * This is mostly suited for CI jobs that wants to build select publications on specific runners. + * + * + * See `gradle.properties` for specific configuration options available to this task. + * + * For local development, using: + * + * ``` + * > ./gradlew publishAllPublicationsToTestRepository + * ``` + * + * will build and publish all targets available to the builder platform. + */ +tasks.register("publishCIPackages") { + group = "Publishing" + description = "Publish packages that has been configured for this CI node. See `gradle.properties`." + + // Figure out which targets are configured. This will impact which sub modules will be published + val availableTargets = setOf( + "iosArm64", + "iosX64", + "jvm", + "macosX64", + "macosArm64", + "android", + "metadata", + "compilerPlugin", + "gradlePlugin" + ) + val mainHostTarget: Set = setOf("metadata") // "kotlinMultiplatform" + + val isMainHost: Boolean? = if (project.properties.containsKey("realm.kotlin.mainHost")) { + project.properties["realm.kotlin.mainHost"] == "true" + } else { + null + } + // Find user configured platforms (if any) + val userTargets: Set? = (project.properties["realm.kotlin.targets"] as String?)?.split(",")?.toSet() + userTargets?.forEach { + if (!availableTargets.contains(it)) { + project.logger.error("Unknown publication: $it") + throw IllegalArgumentException("Unknown publication: $it") + } + } + // Configure which platforms publications we do want to publish + val wantedTargets: Collection = when (isMainHost) { + true -> mainHostTarget + (userTargets ?: availableTargets) + false -> userTargets ?: (availableTargets - mainHostTarget) + null -> availableTargets + } + + if (wantedTargets.contains("jvm") || wantedTargets.contains("android")) { + dependsOn(":jni-swig-stub:publishAllPublicationsToTestRepository") + } + wantedTargets.forEach { target: String -> + when(target) { + "iosArm64" -> { + dependsOn( + ":cinterop:publishIosArm64PublicationToTestRepository", + ":cinterop:publishIosSimulatorArm64PublicationToTestRepository", + ":library-base:publishIosArm64PublicationToTestRepository", + ":library-base:publishIosSimulatorArm64PublicationToTestRepository", + ":library-sync:publishIosArm64PublicationToTestRepository", + ":library-sync:publishIosSimulatorArm64PublicationToTestRepository", + ) + } + "iosX64" -> { + dependsOn( + ":cinterop:publishIosX64PublicationToTestRepository", + ":library-base:publishIosX64PublicationToTestRepository", + ":library-sync:publishIosX64PublicationToTestRepository", + ) + } + "jvm" -> { + dependsOn( + ":cinterop:publishJvmPublicationToTestRepository", + ":library-base:publishJvmPublicationToTestRepository", + ":library-sync:publishJvmPublicationToTestRepository", + ) + } + "macosX64" -> { + dependsOn( + ":cinterop:publishMacosX64PublicationToTestRepository", + ":library-base:publishMacosX64PublicationToTestRepository", + ":library-sync:publishMacosX64PublicationToTestRepository", + ) + } + "macosArm64" -> { + dependsOn( + ":cinterop:publishMacosArm64PublicationToTestRepository", + ":library-base:publishMacosArm64PublicationToTestRepository", + ":library-sync:publishMacosArm64PublicationToTestRepository", + ) + } + "android" -> { + dependsOn( + ":cinterop:publishAndroidReleasePublicationToTestRepository", + ":library-base:publishAndroidReleasePublicationToTestRepository", + ":library-sync:publishAndroidReleasePublicationToTestRepository", + ) + } + "metadata" -> { + dependsOn( + ":cinterop:publishKotlinMultiplatformPublicationToTestRepository", + ":library-base:publishKotlinMultiplatformPublicationToTestRepository", + ":library-sync:publishKotlinMultiplatformPublicationToTestRepository", + ) + } + "compilerPlugin" -> { + dependsOn( + ":plugin-compiler:publishAllPublicationsToTestRepository", + ":plugin-compiler-shaded:publishAllPublicationsToTestRepository" + ) + } + "gradlePlugin" -> { + dependsOn(":gradle-plugin:publishAllPublicationsToTestRepository") + } + else -> { + throw IllegalArgumentException("Unsupported target: $target") + } + } + } +} + tasks.register("uploadDokka") { dependsOn("dokkaHtmlMultiModule") group = "Release" diff --git a/packages/cinterop/build.gradle.kts b/packages/cinterop/build.gradle.kts index 93cdb46e9e..c5aabf428b 100644 --- a/packages/cinterop/build.gradle.kts +++ b/packages/cinterop/build.gradle.kts @@ -60,6 +60,17 @@ val buildType: BuildType = if ((System.getenv("CONFIGURATION") ?: "RELEASE").equ BuildType.DEBUG } + +fun checkIfBuildingNativeLibs(task: Task, action: Task.() -> Unit) { + // Whether or not to build the underlying native Realm Libs. Generally these are only + // needed at runtime and thus can be ignored when only building the layers on top + if (project.extra.properties["ignoreNativeLibs"] != "true") { + action(task) + } else { + logger.warn("Ignore building native libs") + } +} + val corePath = "external/core" val absoluteCorePath = "$rootDir/$corePath" val jvmJniPath = "src/jvmMain/resources/jni" @@ -115,6 +126,8 @@ val nativeLibraryIncludesIosSimulatorArm64Release = kotlin { jvm() android("android") { + // Changing this will also requires an update to the publishCIPackages task + // in /packages/build.gradle.kts publishLibraryVariants("release") } // Cinterops seems sharable across architectures (x86_64/arm) with option of differentiation in @@ -275,25 +288,6 @@ kotlin { } } } - - // See https://kotlinlang.org/docs/reference/mpp-publish-lib.html#publish-a-multiplatform-library - // FIXME MPP-BUILD We need to revisit this when we enable building on multiple hosts. Right now it doesn't do the right thing. - /*** - * Uncommenting below will cause the aritifact to not be published for cinterop-jvm coordinate: - * > Task :cinterop:publishJvmPublicationToMavenLocal SKIPPED - Task :cinterop:publishJvmPublicationToMavenLocal in cinterop Starting - Skipping task ':cinterop:publishJvmPublicationToMavenLocal' as task onlyIf is false. - Task :cinterop:publishJvmPublicationToMavenLocal in cinterop Finished - :cinterop:publishJvmPublicationToMavenLocal (Thread[Execution worker for ':',5,main]) completed. Took 0.0 secs. - */ -// configure(listOf(targets["metadata"], jvm())) { -// mavenPublication { -// val targetPublication = this@mavenPublication -// tasks.withType() -// .matching { it.publication == targetPublication } -// .all { onlyIf { findProperty("isMainHost") == "true" } } -// } -// } } android { @@ -353,28 +347,51 @@ if (HOST_OS.isMacOs()) { val capiMacosUniversal by tasks.registering { build_C_API_Macos_Universal(buildVariant = buildType) } + // Building Simulator binaries for iosX64 (x86_64) and iosSimulatorArm64 (i.e Apple silicon arm64) - val capiSimulator by tasks.registering { + val capiSimulatorX64 by tasks.registering { build_C_API_Simulator("x86_64", buildType) + } + + // Building Simulator binaries for iosSimulatorArm64 (i.e Apple silicon arm64) + val capiSimulatorArm64 by tasks.registering { build_C_API_Simulator("arm64", buildType) } + // Building for ios device (arm64 only) val capiIosArm64 by tasks.registering { build_C_API_iOS_Arm64(buildType) } tasks.named("cinteropRealm_wrapperIosArm64") { - dependsOn(capiIosArm64) + checkIfBuildingNativeLibs(this) { + dependsOn(capiIosArm64) + } + } + + tasks.named("cinteropRealm_wrapperIosX64") { + checkIfBuildingNativeLibs(this) { + dependsOn(capiSimulatorX64) + } + } + tasks.named("cinteropRealm_wrapperIosSimulatorArm64") { - dependsOn(capiSimulator) + checkIfBuildingNativeLibs(this) { + dependsOn(capiSimulatorArm64) + } } tasks.named("cinteropRealm_wrapperMacosX64") { - dependsOn(capiMacosUniversal) + checkIfBuildingNativeLibs(this) { + dependsOn(capiMacosUniversal) + } } + tasks.named("cinteropRealm_wrapperMacosArm64") { - dependsOn(capiMacosUniversal) + checkIfBuildingNativeLibs(this) { + dependsOn(capiMacosUniversal) + } } } @@ -382,30 +399,40 @@ val buildJVMSharedLibs: TaskProvider by tasks.registering { if (HOST_OS.isMacOs()) { buildSharedLibrariesForJVMMacOs() } else if (HOST_OS.isWindows()) { - buildSharedLibrariesForJVMWindows() + buildSharedLibrariesForJVMWindows() } else { throw IllegalStateException("Building JVM libraries on this platform is not supported: $HOST_OS") } +} - // Only on CI for Snapshots and Releases which will run on MacOS. +/** + * Task responsible for copying native files for all architectures into the correct location, + * making the library ready for distribution. + * + * The task assumes that some other task already pre-built the binaries, making this task + * mostly useful on CI. + */ +val copyJVMSharedLibs: TaskProvider by tasks.registering { val copyJvmABIs = project.hasProperty("copyJvmABIs") && project.property("copyJvmABIs") == "true" if (copyJvmABIs) { - if (!HOST_OS.isMacOs()) { - throw IllegalStateException("Creating a full JVM bundle with all architectures is " + - "currently only supported on MacOs. This was: $HOST_OS") - } + // copy MacOS pre-built binaries + project.file("$buildDir/realmMacOsBuild/librealmc.dylib") + .copyTo(project.file("$jvmJniPath/macos/librealmc.dylib"), overwrite = true) + genHashFile(platform = "macos", prefix = "lib", suffix = ".dylib") // copy Linux pre-built binaries - project.file("src/jvmMain/linux-build-dir/librealmc.so") + project.file("$buildDir/realmLinuxBuild/librealmc.so") .copyTo(project.file("$jvmJniPath/linux/librealmc.so"), overwrite = true) genHashFile(platform = "linux", prefix = "lib", suffix = ".so") // copy Window pre-built binaries - project.file("src/jvmMain/windows-build-dir/Release/realmc.dll") + project.file("$buildDir/realmWindowsBuild/Release/realmc.dll") .copyTo(project.file("$jvmJniPath/windows/realmc.dll"), overwrite = true) genHashFile(platform = "windows", prefix = "", suffix = ".dll") // Register copied libraries as output + outputs.file(project.file("$jvmJniPath/macos/librealmc.dylib")) + outputs.file(project.file("$jvmJniPath/macos/dynamic_libraries.properties")) outputs.file(project.file("$jvmJniPath/linux/librealmc.so")) outputs.file(project.file("$jvmJniPath/linux/dynamic_libraries.properties")) outputs.file(project.file("$jvmJniPath/windows/realmc.dll")) @@ -433,7 +460,7 @@ fun getSharedCMakeFlags(buildType: BuildType, ccache: Boolean = true): Array + # See https://kotlinlang.org/docs/mpp-publish-lib.html#publish-an-android-library # Allow the default dependency name to match the client debug build type. Otherwise the client project has to # explicitly specify the debug variant (ex: implementation("io.realm.kotlin:library-base-debug:0.8.0")) diff --git a/packages/library-base/build.gradle.kts b/packages/library-base/build.gradle.kts index 1a75c1b893..c2edd01dff 100644 --- a/packages/library-base/build.gradle.kts +++ b/packages/library-base/build.gradle.kts @@ -36,7 +36,9 @@ project.extensions.configure(kotlinx.atomicfu.plugin.gradle.AtomicFUPluginExtens // Common Kotlin configuration kotlin { jvm() - android("android") { + androidTarget("android") { + // Changing this will also requires an update to the publishCIPackages task + // in /packages/build.gradle.kts publishLibraryVariants("release") } ios() @@ -225,6 +227,8 @@ val javadocJar by tasks.registering(Jar::class) { archiveClassifier.set("javadoc") } +// Make sure that docs are published for the Metadata publication as well. This is required +// by Maven Central publishing { // See https://dev.to/kotlin/how-to-build-and-publish-a-kotlin-multiplatform-library-going-public-4a8k publications.withType { diff --git a/packages/library-sync/build.gradle.kts b/packages/library-sync/build.gradle.kts index d2f3afe90e..3860ab158a 100644 --- a/packages/library-sync/build.gradle.kts +++ b/packages/library-sync/build.gradle.kts @@ -35,7 +35,9 @@ project.extensions.configure(kotlinx.atomicfu.plugin.gradle.AtomicFUPluginExtens // Common Kotlin configuration kotlin { jvm() - android("android") { + androidTarget("android") { + // Changing this will also requires an update to the publishCIPackages task + // in /packages/build.gradle.kts publishLibraryVariants("release") } iosX64() @@ -110,17 +112,6 @@ kotlin { // visibility modifier and will be stripped from Dokka, but will unfortunately still // leak into auto-complete in the IDE. explicitApi = org.jetbrains.kotlin.gradle.dsl.ExplicitApiMode.Strict - - // See https://kotlinlang.org/docs/reference/mpp-publish-lib.html#publish-a-multiplatform-library - // FIXME MPP-BUILD We need to revisit this when we enable building on multiple hosts. Right now it doesn't do the right thing. -// configure(listOf(targets["metadata"], jvm())) { -// mavenPublication { -// val targetPublication = this@mavenPublication -// tasks.withType() -// .matching { it.publication == targetPublication } -// .all { onlyIf { findProperty("isMainHost") == "true" } } -// } -// } } // Using a custom name module for internal methods to avoid default name mangling in Kotlin compiler which uses the module @@ -205,6 +196,8 @@ val javadocJar by tasks.registering(Jar::class) { archiveClassifier.set("javadoc") } +// Make sure that docs are published for the Metadata publication as well. This is required +// by Maven Central publishing { // See https://dev.to/kotlin/how-to-build-and-publish-a-kotlin-multiplatform-library-going-public-4a8k publications.withType { @@ -214,7 +207,7 @@ publishing { // TODO: configure DOKKA so that it's only published for sync and not base val common = publications.getByName("kotlinMultiplatform") as MavenPublication -// // Configuration through examples/kmm-sample does not work if we do not resolve the tasks -// // completely, hence the .get() below. + // Configuration through examples/kmm-sample does not work if we do not resolve the tasks + // completely, hence the .get() below. common.artifact(tasks.named("dokkaJar").get()) } From 60e02558863e911264298621cd54e5abd44d835d Mon Sep 17 00:00:00 2001 From: Christian Melchior Date: Fri, 15 Dec 2023 14:30:03 +0100 Subject: [PATCH 02/12] Update JenkinsFile + cleanup --- Jenkinsfile | 2 +- packages/build.gradle.kts | 12 ++++++++---- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index e39f7d87b0..1dfbf8a9ba 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -385,7 +385,7 @@ def runBuild() { } sh """ cd packages - chmod +x gradlew && ./gradlew publishAllPublicationsToTestRepository ${buildJvmAbiFlag} ${signingFlags} --info --stacktrace --no-daemon + chmod +x gradlew && ./gradlew publishCIPackages ${buildJvmAbiFlag} ${signingFlags} --info --stacktrace --no-daemon """ } } diff --git a/packages/build.gradle.kts b/packages/build.gradle.kts index 3177eac4a7..6d59009483 100644 --- a/packages/build.gradle.kts +++ b/packages/build.gradle.kts @@ -64,6 +64,7 @@ tasks.register("publishCIPackages") { "compilerPlugin", "gradlePlugin" ) + val mainHostTarget: Set = setOf("metadata") // "kotlinMultiplatform" val isMainHost: Boolean? = if (project.properties.containsKey("realm.kotlin.mainHost")) { @@ -72,7 +73,11 @@ tasks.register("publishCIPackages") { null } // Find user configured platforms (if any) - val userTargets: Set? = (project.properties["realm.kotlin.targets"] as String?)?.split(",")?.toSet() + val userTargets: Set? = (project.properties["realm.kotlin.targets"] as String?) + ?.split(",") + ?.map { it.trim() } + ?.filter { it.isNotEmpty() } + ?.toSet() userTargets?.forEach { if (!availableTargets.contains(it)) { project.logger.error("Unknown publication: $it") @@ -86,9 +91,6 @@ tasks.register("publishCIPackages") { null -> availableTargets } - if (wantedTargets.contains("jvm") || wantedTargets.contains("android")) { - dependsOn(":jni-swig-stub:publishAllPublicationsToTestRepository") - } wantedTargets.forEach { target: String -> when(target) { "iosArm64" -> { @@ -110,6 +112,7 @@ tasks.register("publishCIPackages") { } "jvm" -> { dependsOn( + ":jni-swig-stub:publishAllPublicationsToTestRepository", ":cinterop:publishJvmPublicationToTestRepository", ":library-base:publishJvmPublicationToTestRepository", ":library-sync:publishJvmPublicationToTestRepository", @@ -131,6 +134,7 @@ tasks.register("publishCIPackages") { } "android" -> { dependsOn( + ":jni-swig-stub:publishAllPublicationsToTestRepository", ":cinterop:publishAndroidReleasePublicationToTestRepository", ":library-base:publishAndroidReleasePublicationToTestRepository", ":library-sync:publishAndroidReleasePublicationToTestRepository", From 218c34c1baeb260d2f82bca89d84885d4692198f Mon Sep 17 00:00:00 2001 From: Christian Melchior Date: Fri, 15 Dec 2023 14:41:33 +0100 Subject: [PATCH 03/12] Fix new build paths on Jenkins --- Jenkinsfile | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index 1dfbf8a9ba..0b4b89f847 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -724,9 +724,11 @@ def build_jvm_linux(String buildType) { unstash name: 'swig_jni' docker.build('jvm_linux', '-f packages/cinterop/src/jvmMain/generic.Dockerfile .').inside { sh """ - cd packages/cinterop/src/jvmMain/ - rm -rf linux-build-dir - mkdir linux-build-dir + cd packages/cinterop + mkdir build + cd build + rm -rf realmLinuxBuild + mkdir realmLinuxBuild cd linux-build-dir cmake -DCMAKE_BUILD_TYPE=${buildType} \ -DREALM_ENABLE_SYNC=1 \ @@ -736,7 +738,7 @@ def build_jvm_linux(String buildType) { make -j8 """ - stash includes:'packages/cinterop/src/jvmMain/linux-build-dir/librealmc.so', name: 'linux_so_file' + stash includes:'packages/cinterop/build/realmLinuxBuild/librealmc.so', name: 'linux_so_file' } } @@ -757,9 +759,9 @@ def build_jvm_windows(String buildType) { def cmakeDefinitions = cmakeOptions.collect { k,v -> "-D$k=$v" }.join(' ') dir('packages') { - bat "cd cinterop\\src\\jvmMain && rmdir /s /q windows-build-dir & mkdir windows-build-dir && cd windows-build-dir && \"${tool 'cmake'}\" ${cmakeDefinitions} ..\\..\\jvm && \"${tool 'cmake'}\" --build . --config Release" + bat "cd cinterop\\build && mkdir build && cd build && && rmdir /s /q realmWindowsBuild & mkdir realmWindowsBuild && cd realmWindowsBuild && \"${tool 'cmake'}\" ${cmakeDefinitions} ..\\..\\jvm && \"${tool 'cmake'}\" --build . --config Release" } - stash includes: 'packages/cinterop/src/jvmMain/windows-build-dir/Release/realmc.dll', name: 'win_dll' + stash includes: 'packages/cinterop/build/realmWindowsBuild/Release/realmc.dll', name: 'win_dll' } def trackBuildMetrics(version) { From 0097f70f52d49b88605e1f0f5cb8b737248f51af Mon Sep 17 00:00:00 2001 From: Christian Melchior Date: Fri, 15 Dec 2023 14:47:13 +0100 Subject: [PATCH 04/12] Make sure we build on Linux/Windows --- Jenkinsfile | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index 0b4b89f847..b5e7a5f5b8 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -19,7 +19,7 @@ import groovy.json.JsonOutput @Library('realm-ci') _ // Branches from which we release SNAPSHOT's. Only release branches need to run on actual hardware. -releaseBranches = [ 'main', 'releases', 'next-major' ] +releaseBranches = [ 'main', 'releases', 'next-major', 'cm/gradle-setup-for-ci' ] // Branches that are "important", so if they do not compile they will generate a Slack notification slackNotificationBranches = [ 'main', 'releases', 'next-major' ] // Shortcut to current branch name that is being tested @@ -281,24 +281,24 @@ pipeline { testAndCollect("examples/realm-java-compatibility", "-Pkotlin.experimental.tryK2=true connectedAndroidTest") } } - stage('Track build metrics') { - when { expression { currentBranch == "main" } } - steps { - trackBuildMetrics(version) - } - } - stage('Publish SNAPSHOT to Maven Central') { - when { expression { shouldPublishSnapshot(version) } } - steps { - runPublishSnapshotToMavenCentral() - } - } - stage('Publish Release to Maven Central') { - when { expression { publishBuild } } - steps { - runPublishReleaseOnMavenCentral() - } - } + // stage('Track build metrics') { + // when { expression { currentBranch == "main" } } + // steps { + // trackBuildMetrics(version) + // } + // } + // // stage('Publish SNAPSHOT to Maven Central') { + // when { expression { shouldPublishSnapshot(version) } } + // steps { + // runPublishSnapshotToMavenCentral() + // } + // } + // stage('Publish Release to Maven Central') { + // when { expression { publishBuild } } + // steps { + // runPublishReleaseOnMavenCentral() + // } + // } } } } From 4eb9e58768ae12969adaabdfb95854eef1e67499 Mon Sep 17 00:00:00 2001 From: Christian Melchior Date: Fri, 15 Dec 2023 15:05:16 +0100 Subject: [PATCH 05/12] Improve Gradle properties --- Jenkinsfile | 4 ++-- packages/cinterop/build.gradle.kts | 2 +- packages/gradle.properties | 16 ++++++++++++++++ 3 files changed, 19 insertions(+), 3 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index b5e7a5f5b8..12f0a3a165 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -366,11 +366,11 @@ def genAndStashSwigJNI() { stash includes: 'packages/jni-swig-stub/build/generated/sources/jni/realmc.cpp,packages/jni-swig-stub/build/generated/sources/jni/realmc.h', name: 'swig_jni' } def runBuild() { - def buildJvmAbiFlag = "-PcopyJvmABIs=false" + def buildJvmAbiFlag = "-Prealm.kotlin.copyNativeJvmLibs=false" if (shouldBuildJvmABIs()) { unstash name: 'linux_so_file' unstash name: 'win_dll' - buildJvmAbiFlag = "-PcopyJvmABIs=true" + buildJvmAbiFlag = "-Prealm.kotlin.copyNativeJvmLibs=true" } withCredentials([ diff --git a/packages/cinterop/build.gradle.kts b/packages/cinterop/build.gradle.kts index c5aabf428b..429fcf8619 100644 --- a/packages/cinterop/build.gradle.kts +++ b/packages/cinterop/build.gradle.kts @@ -64,7 +64,7 @@ val buildType: BuildType = if ((System.getenv("CONFIGURATION") ?: "RELEASE").equ fun checkIfBuildingNativeLibs(task: Task, action: Task.() -> Unit) { // Whether or not to build the underlying native Realm Libs. Generally these are only // needed at runtime and thus can be ignored when only building the layers on top - if (project.extra.properties["ignoreNativeLibs"] != "true") { + if (project.extra.properties["realm.kotlin.buildRealmCore"] == "true") { action(task) } else { logger.warn("Ignore building native libs") diff --git a/packages/gradle.properties b/packages/gradle.properties index 527e4852ab..4ba41d1156 100644 --- a/packages/gradle.properties +++ b/packages/gradle.properties @@ -25,6 +25,7 @@ android.useAndroidX=true kotlin.mpp.androidSourceSetLayoutVersion=2 # Realm Kotlin build options +# # See https://kotlinlang.org/docs/multiplatform-publish-lib.html # The main host is responsible for publishing the KMP metadata needed to lookup platform specific # artifacts. During a publishing process, one host is _required_ to be the main host. @@ -49,6 +50,21 @@ realm.kotlin.mainHost=true # # realm.kotlin.targets= +# Whether or not to build Realm Core on the platform running the build. +# This can be used to prevent certain targets transentively starting a +# native build, which can easily take 30+ minutes. This is e.g. relevant +# when only building docs or compiler/gradle plugins. +realm.kotlin.buildRealmCore=true + +# Whether or not to copy pre-built JVM native files into place, making them +# ready to run or package the final JVM JARs. +# +# The prebuilt files must be placed in this location for this to work: +# - MacOS: /packages/cinterop/build/realmMacOsBuild/librealmc.dylib +# - Linux: /packages/cinterop/build/realmWindowsBuild/librealmc.so +# - Windows: /packages/cinterop/build/realmWindowsBuild/Release/realmc.dll +realm.kotlin.copyNativeJvmLibs=false + # See https://kotlinlang.org/docs/mpp-publish-lib.html#publish-an-android-library # Allow the default dependency name to match the client debug build type. Otherwise the client project has to # explicitly specify the debug variant (ex: implementation("io.realm.kotlin:library-base-debug:0.8.0")) From fde4940b808c3e94c771cee42d06cbca6821ed3d Mon Sep 17 00:00:00 2001 From: Christian Melchior Date: Fri, 15 Dec 2023 15:58:48 +0100 Subject: [PATCH 06/12] Fix JVM builds --- Jenkinsfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index 12f0a3a165..490ffab0d1 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -729,7 +729,7 @@ def build_jvm_linux(String buildType) { cd build rm -rf realmLinuxBuild mkdir realmLinuxBuild - cd linux-build-dir + cd realmLinuxBuild cmake -DCMAKE_BUILD_TYPE=${buildType} \ -DREALM_ENABLE_SYNC=1 \ -DREALM_NO_TESTS=1 \ @@ -759,7 +759,7 @@ def build_jvm_windows(String buildType) { def cmakeDefinitions = cmakeOptions.collect { k,v -> "-D$k=$v" }.join(' ') dir('packages') { - bat "cd cinterop\\build && mkdir build && cd build && && rmdir /s /q realmWindowsBuild & mkdir realmWindowsBuild && cd realmWindowsBuild && \"${tool 'cmake'}\" ${cmakeDefinitions} ..\\..\\jvm && \"${tool 'cmake'}\" --build . --config Release" + bat "cd cinterop\\build && mkdir build && cd build && && rmdir /s /q realmWindowsBuild && mkdir realmWindowsBuild && cd realmWindowsBuild && \"${tool 'cmake'}\" ${cmakeDefinitions} ..\\..\\jvm && \"${tool 'cmake'}\" --build . --config Release" } stash includes: 'packages/cinterop/build/realmWindowsBuild/Release/realmc.dll', name: 'win_dll' } From d7acab7d43806363d13cff695f9c7014241c62e7 Mon Sep 17 00:00:00 2001 From: Christian Melchior Date: Fri, 15 Dec 2023 16:07:15 +0100 Subject: [PATCH 07/12] More fixes --- Jenkinsfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index 490ffab0d1..72a98b955d 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -734,7 +734,7 @@ def build_jvm_linux(String buildType) { -DREALM_ENABLE_SYNC=1 \ -DREALM_NO_TESTS=1 \ -DREALM_BUILD_LIB_ONLY=true \ - ../../jvm + ../../src/jvm make -j8 """ @@ -759,7 +759,7 @@ def build_jvm_windows(String buildType) { def cmakeDefinitions = cmakeOptions.collect { k,v -> "-D$k=$v" }.join(' ') dir('packages') { - bat "cd cinterop\\build && mkdir build && cd build && && rmdir /s /q realmWindowsBuild && mkdir realmWindowsBuild && cd realmWindowsBuild && \"${tool 'cmake'}\" ${cmakeDefinitions} ..\\..\\jvm && \"${tool 'cmake'}\" --build . --config Release" + bat "cd cinterop && mkdir build && cd build && rmdir /s /q realmWindowsBuild && mkdir realmWindowsBuild && cd realmWindowsBuild && \"${tool 'cmake'}\" ${cmakeDefinitions} ..\\..\\jvm && \"${tool 'cmake'}\" --build . --config Release" } stash includes: 'packages/cinterop/build/realmWindowsBuild/Release/realmc.dll', name: 'win_dll' } From 08cf1fbc4dc77c3f93717825da33febcac6f11e3 Mon Sep 17 00:00:00 2001 From: Christian Melchior Date: Fri, 15 Dec 2023 16:38:07 +0100 Subject: [PATCH 08/12] Fix Windows path --- Jenkinsfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Jenkinsfile b/Jenkinsfile index 72a98b955d..b5895d4ad8 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -759,7 +759,7 @@ def build_jvm_windows(String buildType) { def cmakeDefinitions = cmakeOptions.collect { k,v -> "-D$k=$v" }.join(' ') dir('packages') { - bat "cd cinterop && mkdir build && cd build && rmdir /s /q realmWindowsBuild && mkdir realmWindowsBuild && cd realmWindowsBuild && \"${tool 'cmake'}\" ${cmakeDefinitions} ..\\..\\jvm && \"${tool 'cmake'}\" --build . --config Release" + bat "cd cinterop && mkdir build && cd build && rmdir /s /q realmWindowsBuild && mkdir realmWindowsBuild && cd realmWindowsBuild && \"${tool 'cmake'}\" ${cmakeDefinitions} ..\\..\\src\\jvm && \"${tool 'cmake'}\" --build . --config Release" } stash includes: 'packages/cinterop/build/realmWindowsBuild/Release/realmc.dll', name: 'win_dll' } From 2d3db6abb74b37f4bca34559c1a7b01b8982944c Mon Sep 17 00:00:00 2001 From: Christian Melchior Date: Fri, 15 Dec 2023 17:06:22 +0100 Subject: [PATCH 09/12] Fix Windows syntax --- Jenkinsfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Jenkinsfile b/Jenkinsfile index b5895d4ad8..592f3540dc 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -759,7 +759,7 @@ def build_jvm_windows(String buildType) { def cmakeDefinitions = cmakeOptions.collect { k,v -> "-D$k=$v" }.join(' ') dir('packages') { - bat "cd cinterop && mkdir build && cd build && rmdir /s /q realmWindowsBuild && mkdir realmWindowsBuild && cd realmWindowsBuild && \"${tool 'cmake'}\" ${cmakeDefinitions} ..\\..\\src\\jvm && \"${tool 'cmake'}\" --build . --config Release" + bat "cd cinterop && rmdir /s /q build & mkdir build & cd build && rmdir /s /q realmWindowsBuild & mkdir realmWindowsBuild && cd realmWindowsBuild && \"${tool 'cmake'}\" ${cmakeDefinitions} ..\\..\\src\\jvm && \"${tool 'cmake'}\" --build . --config Release" } stash includes: 'packages/cinterop/build/realmWindowsBuild/Release/realmc.dll', name: 'win_dll' } From 47d0d86c5a741fd80ff4f7ca9235fd15bbfd855d Mon Sep 17 00:00:00 2001 From: Christian Melchior Date: Fri, 15 Dec 2023 19:21:55 +0100 Subject: [PATCH 10/12] Cleanup --- Jenkinsfile | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index 592f3540dc..7125882966 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -19,7 +19,7 @@ import groovy.json.JsonOutput @Library('realm-ci') _ // Branches from which we release SNAPSHOT's. Only release branches need to run on actual hardware. -releaseBranches = [ 'main', 'releases', 'next-major', 'cm/gradle-setup-for-ci' ] +releaseBranches = [ 'main', 'releases', 'next-major' ] // Branches that are "important", so if they do not compile they will generate a Slack notification slackNotificationBranches = [ 'main', 'releases', 'next-major' ] // Shortcut to current branch name that is being tested @@ -281,24 +281,24 @@ pipeline { testAndCollect("examples/realm-java-compatibility", "-Pkotlin.experimental.tryK2=true connectedAndroidTest") } } - // stage('Track build metrics') { - // when { expression { currentBranch == "main" } } - // steps { - // trackBuildMetrics(version) - // } - // } - // // stage('Publish SNAPSHOT to Maven Central') { - // when { expression { shouldPublishSnapshot(version) } } - // steps { - // runPublishSnapshotToMavenCentral() - // } - // } - // stage('Publish Release to Maven Central') { - // when { expression { publishBuild } } - // steps { - // runPublishReleaseOnMavenCentral() - // } - // } + stage('Track build metrics') { + when { expression { currentBranch == "main" } } + steps { + trackBuildMetrics(version) + } + } + // stage('Publish SNAPSHOT to Maven Central') { + when { expression { shouldPublishSnapshot(version) } } + steps { + runPublishSnapshotToMavenCentral() + } + } + stage('Publish Release to Maven Central') { + when { expression { publishBuild } } + steps { + runPublishReleaseOnMavenCentral() + } + } } } } From 95d3de5bbe4d2fe0eaadd9b1325742ec4fd4014f Mon Sep 17 00:00:00 2001 From: Christian Melchior Date: Fri, 15 Dec 2023 19:25:49 +0100 Subject: [PATCH 11/12] Cleanup --- Jenkinsfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Jenkinsfile b/Jenkinsfile index 7125882966..bc9bd22167 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -287,7 +287,7 @@ pipeline { trackBuildMetrics(version) } } - // stage('Publish SNAPSHOT to Maven Central') { + stage('Publish SNAPSHOT to Maven Central') { when { expression { shouldPublishSnapshot(version) } } steps { runPublishSnapshotToMavenCentral() From 4c245841a8437d2925b2ae9180a9a17731ed625f Mon Sep 17 00:00:00 2001 From: Christian Melchior Date: Tue, 19 Dec 2023 12:42:06 +0100 Subject: [PATCH 12/12] PR feedback --- packages/build.gradle.kts | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/packages/build.gradle.kts b/packages/build.gradle.kts index 6d59009483..fcc0536eda 100644 --- a/packages/build.gradle.kts +++ b/packages/build.gradle.kts @@ -67,31 +67,31 @@ tasks.register("publishCIPackages") { val mainHostTarget: Set = setOf("metadata") // "kotlinMultiplatform" - val isMainHost: Boolean? = if (project.properties.containsKey("realm.kotlin.mainHost")) { - project.properties["realm.kotlin.mainHost"] == "true" - } else { - null - } + val isMainHost: Boolean = project.properties["realm.kotlin.mainHost"]?.let { it == "true" } ?: false + // Find user configured platforms (if any) val userTargets: Set? = (project.properties["realm.kotlin.targets"] as String?) ?.split(",") ?.map { it.trim() } ?.filter { it.isNotEmpty() } ?.toSet() + userTargets?.forEach { if (!availableTargets.contains(it)) { project.logger.error("Unknown publication: $it") throw IllegalArgumentException("Unknown publication: $it") } } + // Configure which platforms publications we do want to publish - val wantedTargets: Collection = when (isMainHost) { - true -> mainHostTarget + (userTargets ?: availableTargets) - false -> userTargets ?: (availableTargets - mainHostTarget) - null -> availableTargets + val publicationTargets = (userTargets ?: availableTargets).let { + when (isMainHost) { + true -> it + mainHostTarget + false -> it - mainHostTarget + } } - wantedTargets.forEach { target: String -> + publicationTargets.forEach { target: String -> when(target) { "iosArm64" -> { dependsOn(