diff --git a/AndroidLibBenchmark/build.gradle.kts b/AndroidLibBenchmark/build.gradle.kts index 15ac86dd34..bceeeea131 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" 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") 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/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts index e6873a4482..74fcd282ac 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.2") } diff --git a/buildSrc/src/main/kotlin/Versions.kt b/buildSrc/src/main/kotlin/Versions.kt index f71ea7ccb0..0ec0211335 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.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")), 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 2845eb8aaa..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,14 +16,17 @@ package com.bloomberg.selekt.commons -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 +53,7 @@ internal fun libraryExtensions() = osNames().map { }.toSet() @JvmSynthetic -internal fun libraryResourceNames( +internal fun libraryNames( parentDirectory: String, name: String ) = (platformIdentifiers() * libraryExtensions()).map { @@ -59,14 +62,16 @@ 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" } + }) { "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) @@ -74,3 +79,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")) } }