From 5d989522ec46443d6cc26bad4299b0bc1b5b56c0 Mon Sep 17 00:00:00 2001 From: "Kenneth J. Shackleton" Date: Thu, 7 Dec 2023 10:05:58 +0000 Subject: [PATCH 1/7] Android Gradle Plugin 8.2.0. Signed-off-by: Kenneth J. Shackleton --- buildSrc/build.gradle.kts | 2 +- buildSrc/src/main/kotlin/Versions.kt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts index 73b475e83d..6001dc121f 100644 --- a/buildSrc/build.gradle.kts +++ b/buildSrc/build.gradle.kts @@ -38,5 +38,5 @@ gradlePlugin { dependencies { implementation(kotlin("gradle-plugin", version = kotlinVersion)) - implementation("com.android.tools.build:gradle:8.0.2") + implementation("com.android.tools.build:gradle:8.2.0") } diff --git a/buildSrc/src/main/kotlin/Versions.kt b/buildSrc/src/main/kotlin/Versions.kt index c81b57066c..66390965ce 100644 --- a/buildSrc/src/main/kotlin/Versions.kt +++ b/buildSrc/src/main/kotlin/Versions.kt @@ -22,7 +22,7 @@ enum class Versions( ) { ANDROID_BENCHMARK("1.2.0-alpha13", URL("https://developer.android.com/studio/profile/benchmark")), ANDROID_BUILD_TOOLS("34.0.0", URL("https://developer.android.com/studio/releases/build-tools")), - ANDROID_GRADLE_PLUGIN("8.0.2", URL("https://developer.android.com/tools/revisions/gradle-plugin.html")), + ANDROID_GRADLE_PLUGIN("8.2.0", URL("https://developer.android.com/tools/revisions/gradle-plugin.html")), ANDROID_LINT("30.0.2", URL("https://github.com/googlesamples/android-custom-lint-rules")), ANDROID_NDK("26.1.10909125", URL("https://developer.android.com/ndk")), ANDROID_SDK("34", URL("https://developer.android.com/sdk")), From ba2ba745387aafe20387129736f04b8f5f1be39a Mon Sep 17 00:00:00 2001 From: "Kenneth J. Shackleton" Date: Sun, 4 Feb 2024 18:17:05 +0000 Subject: [PATCH 2/7] Target at least API 34 in AndroidLibBenchmark. Signed-off-by: Kenneth J. Shackleton --- AndroidLibBenchmark/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AndroidLibBenchmark/build.gradle.kts b/AndroidLibBenchmark/build.gradle.kts index 035a70b43d..9cb7c253ad 100644 --- a/AndroidLibBenchmark/build.gradle.kts +++ b/AndroidLibBenchmark/build.gradle.kts @@ -33,7 +33,7 @@ android { namespace = "com.bloomberg.selekt.android.benchmark" defaultConfig { minSdkVersion(21) - targetSdkVersion(32) + targetSdkVersion(34) testInstrumentationRunner = "androidx.benchmark.junit4.AndroidBenchmarkRunner" testInstrumentationRunnerArguments.putAll(arrayOf( "androidx.benchmark.suppressErrors" to "EMULATOR,LOW_BATTERY,UNLOCKED" From 851daae75c3f5bbbefd5db7eeb0a3e784e32990a Mon Sep 17 00:00:00 2001 From: "Kenneth J. Shackleton" Date: Sun, 4 Feb 2024 18:20:25 +0000 Subject: [PATCH 3/7] Android Gradle Plugin 8.2.2. Signed-off-by: Kenneth J. Shackleton --- buildSrc/build.gradle.kts | 2 +- buildSrc/src/main/kotlin/Versions.kt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts index 6001dc121f..9c268c99d4 100644 --- a/buildSrc/build.gradle.kts +++ b/buildSrc/build.gradle.kts @@ -38,5 +38,5 @@ gradlePlugin { dependencies { implementation(kotlin("gradle-plugin", version = kotlinVersion)) - implementation("com.android.tools.build:gradle:8.2.0") + implementation("com.android.tools.build:gradle:8.2.2") } diff --git a/buildSrc/src/main/kotlin/Versions.kt b/buildSrc/src/main/kotlin/Versions.kt index 66390965ce..b6c59440b4 100644 --- a/buildSrc/src/main/kotlin/Versions.kt +++ b/buildSrc/src/main/kotlin/Versions.kt @@ -22,7 +22,7 @@ enum class Versions( ) { ANDROID_BENCHMARK("1.2.0-alpha13", URL("https://developer.android.com/studio/profile/benchmark")), ANDROID_BUILD_TOOLS("34.0.0", URL("https://developer.android.com/studio/releases/build-tools")), - ANDROID_GRADLE_PLUGIN("8.2.0", URL("https://developer.android.com/tools/revisions/gradle-plugin.html")), + ANDROID_GRADLE_PLUGIN("8.2.2", URL("https://developer.android.com/tools/revisions/gradle-plugin.html")), ANDROID_LINT("30.0.2", URL("https://github.com/googlesamples/android-custom-lint-rules")), ANDROID_NDK("26.1.10909125", URL("https://developer.android.com/ndk")), ANDROID_SDK("34", URL("https://developer.android.com/sdk")), From 11fe8e79644667c6ee5516859fafe5b3d2b77992 Mon Sep 17 00:00:00 2001 From: "Kenneth J. Shackleton" Date: Sat, 10 Feb 2024 12:51:09 +0000 Subject: [PATCH 4/7] Log parent directory. Signed-off-by: Kenneth J. Shackleton --- .../main/kotlin/com/bloomberg/selekt/commons/NativeResources.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/selekt-java/src/main/kotlin/com/bloomberg/selekt/commons/NativeResources.kt b/selekt-java/src/main/kotlin/com/bloomberg/selekt/commons/NativeResources.kt index 2845eb8aaa..bfe0251089 100644 --- a/selekt-java/src/main/kotlin/com/bloomberg/selekt/commons/NativeResources.kt +++ b/selekt-java/src/main/kotlin/com/bloomberg/selekt/commons/NativeResources.kt @@ -61,7 +61,7 @@ internal fun libraryResourceNames( fun loadEmbeddedLibrary(loader: ClassLoader, parentDirectory: String, name: String) { val url = checkNotNull(libraryResourceNames(parentDirectory, name).firstNotNullOfOrNull { loader.getResource(it) - }) { "Failed to find resource with name: $name" } + }) { "Failed to find resource with name: $name in directory: $parentDirectory" } @Suppress("NewApi") // Not used by Android. val file = createTempFile("lib$name", "lib").toFile().apply { deleteOnExit() } try { From 965e8607a0a2f5b2f30b39ce7ddf1762d902204e Mon Sep 17 00:00:00 2001 From: "Kenneth J. Shackleton" Date: Sat, 10 Feb 2024 12:57:40 +0000 Subject: [PATCH 5/7] Log resolved platform identifier in Gradle script. Signed-off-by: Kenneth J. Shackleton --- SQLite3/build.gradle.kts | 1 + 1 file changed, 1 insertion(+) diff --git a/SQLite3/build.gradle.kts b/SQLite3/build.gradle.kts index bb041719af..4baaa7097d 100644 --- a/SQLite3/build.gradle.kts +++ b/SQLite3/build.gradle.kts @@ -125,6 +125,7 @@ fun osName() = System.getProperty("os.name").lowercase(Locale.US).run { } fun platformIdentifier() = "${osName()}-${System.getProperty("os.arch")}" +logger.quiet("Resolved platform identifier: {}", platformIdentifier()) tasks.register("buildHost") { dependsOn("makeSQLite") From 4c1d0c96d6556e5af5abed214b1fb3b8398a5687 Mon Sep 17 00:00:00 2001 From: "Kenneth J. Shackleton" Date: Sun, 11 Feb 2024 15:07:55 +0000 Subject: [PATCH 6/7] Load native libraries from assets location during test. Signed-off-by: Kenneth J. Shackleton --- build.gradle.kts | 6 +++- .../com/bloomberg/selekt/android/Loader.kt | 8 ++--- selekt-android/build.gradle.kts | 5 +-- .../selekt/android/NativeFixtures.kt | 4 +-- .../selekt/commons/NativeResources.kt | 35 +++++++++++++++++-- .../selekt/commons/NativeResourcesKtTest.kt | 2 +- 6 files changed, 48 insertions(+), 12 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index 7923effef3..a64b621796 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -126,7 +126,11 @@ subprojects { } } tasks.withType().configureEach { - systemProperty("com.bloomberg.selekt.lib.can_use_embedded", true) + systemProperty("com.bloomberg.selekt.can_use_load", true) + systemProperty( + "com.bloomberg.selekt.library_path", + layout.buildDirectory.dir("intermediates/assets/debugUnitTest").get().asFile.toString() + ) } tasks.withType().configureEach { kotlinOptions { diff --git a/selekt-android-sqlcipher/src/debug/kotlin/com/bloomberg/selekt/android/Loader.kt b/selekt-android-sqlcipher/src/debug/kotlin/com/bloomberg/selekt/android/Loader.kt index 22c784fb16..a44014a74f 100644 --- a/selekt-android-sqlcipher/src/debug/kotlin/com/bloomberg/selekt/android/Loader.kt +++ b/selekt-android-sqlcipher/src/debug/kotlin/com/bloomberg/selekt/android/Loader.kt @@ -18,18 +18,18 @@ package com.bloomberg.selekt.android import com.bloomberg.selekt.ExternalSQLite import com.bloomberg.selekt.SQLite -import com.bloomberg.selekt.commons.loadEmbeddedLibrary +import com.bloomberg.selekt.commons.loadLibrary import com.bloomberg.selekt.externalSQLiteSingleton -private const val CAN_USE_EMBEDDED_PROPERTY_KEY = "com.bloomberg.selekt.lib.can_use_embedded" +private const val CAN_USE_LOAD_PROPERTY_KEY = "com.bloomberg.selekt.can_use_load" fun loadSQLite(): ExternalSQLite = externalSQLiteSingleton { "selekt".let { try { System.loadLibrary(it) } catch (e: UnsatisfiedLinkError) { - if (System.getProperty(CAN_USE_EMBEDDED_PROPERTY_KEY, null) == "true") { - loadEmbeddedLibrary(checkNotNull(SQLite::class.java.classLoader), "jni", it) + if (System.getProperty(CAN_USE_LOAD_PROPERTY_KEY, null) == "true") { + loadLibrary(checkNotNull(SQLite::class.java.classLoader), "jni", it) } else { throw e } diff --git a/selekt-android/build.gradle.kts b/selekt-android/build.gradle.kts index bc16fba857..e4e8565ae4 100644 --- a/selekt-android/build.gradle.kts +++ b/selekt-android/build.gradle.kts @@ -47,7 +47,7 @@ android { buildConfigField("String", "gitCommitSha1", "\"${gitCommit()}\"") } } - sourceSets["test"].resources.srcDir(layout.buildDirectory.dir("intermediates/libs")) + sourceSets["test"].assets.srcDir(layout.buildDirectory.dir("intermediates/libs")) publishing { singleVariant("release") { withJavadocJar() @@ -92,6 +92,7 @@ tasks.register("copyJniLibs") { fileTree(project(":Selektric").layout.buildDirectory.dir("intermediates/libs")) ) into(layout.buildDirectory.dir("intermediates/libs/jni")) + mustRunAfter("buildNativeHost") } tasks.register("buildNativeHost") { @@ -107,7 +108,7 @@ arrayOf("Debug", "Release").map { "pre${it}UnitTestBuild" }.forEach { } } -arrayOf("Debug", "Release").map { "process${it}UnitTestJavaRes" }.forEach { +arrayOf("Debug", "Release").map { "merge${it}UnitTestAssets" }.forEach { tasks.whenTaskAdded { if (it == name) { dependsOn("copyJniLibs") diff --git a/selekt-android/src/test/kotlin/com/bloomberg/selekt/android/NativeFixtures.kt b/selekt-android/src/test/kotlin/com/bloomberg/selekt/android/NativeFixtures.kt index ae4628708c..15e170555e 100644 --- a/selekt-android/src/test/kotlin/com/bloomberg/selekt/android/NativeFixtures.kt +++ b/selekt-android/src/test/kotlin/com/bloomberg/selekt/android/NativeFixtures.kt @@ -1,10 +1,10 @@ package com.bloomberg.selekt.android -import com.bloomberg.selekt.commons.loadEmbeddedLibrary +import com.bloomberg.selekt.commons.loadLibrary internal object NativeFixtures { init { - loadEmbeddedLibrary(NativeFixtures::class.java.classLoader!!, "jni", "selektric") + loadLibrary(checkNotNull(NativeFixtures::class.java.classLoader), "jni", "selektric") check(nativeInit() == 0) } diff --git a/selekt-java/src/main/kotlin/com/bloomberg/selekt/commons/NativeResources.kt b/selekt-java/src/main/kotlin/com/bloomberg/selekt/commons/NativeResources.kt index bfe0251089..6f1200c08d 100644 --- a/selekt-java/src/main/kotlin/com/bloomberg/selekt/commons/NativeResources.kt +++ b/selekt-java/src/main/kotlin/com/bloomberg/selekt/commons/NativeResources.kt @@ -20,10 +20,14 @@ import java.io.BufferedOutputStream import java.io.File import java.io.FileOutputStream import java.io.IOException +import java.nio.file.Files import java.util.Locale +import kotlin.io.path.Path import kotlin.io.path.createTempFile import kotlin.jvm.Throws +private const val LIBRARY_PATH_KEY = "com.bloomberg.selekt.library_path" + @Suppress("Detekt.StringLiteralDuplication") @JvmSynthetic internal fun osNames(systemOsName: String = System.getProperty("os.name")) = systemOsName.lowercase(Locale.US).run { @@ -50,7 +54,7 @@ internal fun libraryExtensions() = osNames().map { }.toSet() @JvmSynthetic -internal fun libraryResourceNames( +internal fun libraryNames( parentDirectory: String, name: String ) = (platformIdentifiers() * libraryExtensions()).map { @@ -59,7 +63,7 @@ internal fun libraryResourceNames( @Throws(IOException::class) fun loadEmbeddedLibrary(loader: ClassLoader, parentDirectory: String, name: String) { - val url = checkNotNull(libraryResourceNames(parentDirectory, name).firstNotNullOfOrNull { + val url = checkNotNull(libraryNames(parentDirectory, name).firstNotNullOfOrNull { loader.getResource(it) }) { "Failed to find resource with name: $name in directory: $parentDirectory" } @Suppress("NewApi") // Not used by Android. @@ -74,3 +78,30 @@ fun loadEmbeddedLibrary(loader: ClassLoader, parentDirectory: String, name: Stri file.delete() } } + +@Suppress("NewApi") +private fun loadLibrary( + libraryPath: String, + parentDirectory: String, + name: String +) { + val path = libraryNames(parentDirectory, name).map { + Path(libraryPath, it) + }.first { + Files.exists(it) + }.toAbsolutePath() + @Suppress("UnsafeDynamicallyLoadedCode") + System.load(path.toString()) +} + +@Throws(IOException::class) +fun loadLibrary( + loader: ClassLoader, + parentDirectory: String, + name: String +) { + when (val libraryPath = System.getProperty(LIBRARY_PATH_KEY)) { + null -> loadEmbeddedLibrary(loader, parentDirectory, name) + else -> loadLibrary(libraryPath, parentDirectory, name) + } +} diff --git a/selekt-java/src/test/kotlin/com/bloomberg/selekt/commons/NativeResourcesKtTest.kt b/selekt-java/src/test/kotlin/com/bloomberg/selekt/commons/NativeResourcesKtTest.kt index 40d61284a8..401ac20a11 100644 --- a/selekt-java/src/test/kotlin/com/bloomberg/selekt/commons/NativeResourcesKtTest.kt +++ b/selekt-java/src/test/kotlin/com/bloomberg/selekt/commons/NativeResourcesKtTest.kt @@ -54,7 +54,7 @@ internal class NativeResourcesKtTest { @Test fun commonLibraryResourceName() { - libraryResourceNames("jni", "selekt").forEach { + libraryNames("jni", "selekt").forEach { assertTrue(it.startsWith("jni")) } } From f8cacc824be37a940051804f1dd8e3f80349e9ec Mon Sep 17 00:00:00 2001 From: "Kenneth J. Shackleton" Date: Sun, 11 Feb 2024 15:44:11 +0000 Subject: [PATCH 7/7] While here, simplify loading embedded library. Signed-off-by: Kenneth J. Shackleton --- .../kotlin/com/bloomberg/selekt/commons/NativeResources.kt | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/selekt-java/src/main/kotlin/com/bloomberg/selekt/commons/NativeResources.kt b/selekt-java/src/main/kotlin/com/bloomberg/selekt/commons/NativeResources.kt index 6f1200c08d..a93ef145e4 100644 --- a/selekt-java/src/main/kotlin/com/bloomberg/selekt/commons/NativeResources.kt +++ b/selekt-java/src/main/kotlin/com/bloomberg/selekt/commons/NativeResources.kt @@ -16,7 +16,6 @@ package com.bloomberg.selekt.commons -import java.io.BufferedOutputStream import java.io.File import java.io.FileOutputStream import java.io.IOException @@ -67,10 +66,12 @@ fun loadEmbeddedLibrary(loader: ClassLoader, parentDirectory: String, name: Stri loader.getResource(it) }) { "Failed to find resource with name: $name in directory: $parentDirectory" } @Suppress("NewApi") // Not used by Android. - val file = createTempFile("lib$name", "lib").toFile().apply { deleteOnExit() } + val file = createTempFile("lib$name", "lib").toFile() try { url.openStream().use { inputStream -> - BufferedOutputStream(FileOutputStream(file)).use { outputStream -> inputStream.copyTo(outputStream) } + FileOutputStream(file).use { + inputStream.copyTo(it) + } } @Suppress("UnsafeDynamicallyLoadedCode") System.load(file.absolutePath)