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..20d073a991 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,25 @@ package com.bloomberg.selekt.android import com.bloomberg.selekt.ExternalSQLite import com.bloomberg.selekt.SQLite +import com.bloomberg.selekt.commons.loadLibrary import com.bloomberg.selekt.commons.loadEmbeddedLibrary import com.bloomberg.selekt.externalSQLiteSingleton +import java.lang.IllegalStateException -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") { + val loader = checkNotNull(SQLite::class.java.classLoader) + try { + loadEmbeddedLibrary(loader, "jni", it) + } catch (e: IllegalStateException) { + loadLibrary("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..017cbac2ce 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("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..0c2be19107 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,18 @@ fun loadEmbeddedLibrary(loader: ClassLoader, parentDirectory: String, name: Stri file.delete() } } + +@Suppress("NewApi") +@Throws(IOException::class) +fun loadLibrary(parentDirectory: String, name: String) { + val assetsPath = checkNotNull(System.getProperty(LIBRARY_PATH_KEY)) { + "System property $LIBRARY_PATH_KEY was not set" + } + val path = libraryNames(parentDirectory, name).map { + Path(assetsPath, it) + }.first { + Files.exists(it) + }.toAbsolutePath() + @Suppress("UnsafeDynamicallyLoadedCode") + System.load(path.toString()) +} 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")) } }