0
0
mirror of https://github.com/florisboard/florisboard.git synced 2024-09-19 11:32:18 +02:00

Add Rust build support

This commit is contained in:
Patrick Goldinger 2024-04-05 01:24:10 +02:00
parent c198e8b376
commit c5d1d3b31e
No known key found for this signature in database
GPG Key ID: 533467C3DC7B9262
13 changed files with 183 additions and 44 deletions

10
.gitignore vendored
View File

@ -47,3 +47,13 @@ crowdin.properties
# Nix stuff
.direnv/
result
# VSCode
.vscode/
# Rust
debug/
target/
Cargo.lock
**/*.rs.bk
*.pdb

View File

@ -101,12 +101,6 @@ android {
kotlinCompilerExtensionVersion = libs.versions.androidx.compose.compiler.get()
}
//externalNativeBuild {
// cmake {
// path("src/main/cpp/CMakeLists.txt")
// }
//}
buildTypes {
named("debug") {
applicationIdSuffix = ".debug"
@ -152,11 +146,6 @@ android {
initWith(getByName("release"))
signingConfig = signingConfigs.getByName("debug")
matchingFallbacks += listOf("release")
ndk {
// For running FlorisBoard on the emulator
abiFilters += listOf("x86", "x86_64")
}
}
}
@ -214,8 +203,8 @@ dependencies {
implementation(libs.patrickgold.jetpref.datastore.ui)
implementation(libs.patrickgold.jetpref.material.ui)
implementation(project(":lib:kotlin"))
implementation(project(":lib:native"))
testImplementation(libs.equalsverifier)
testImplementation(libs.kotest.assertions.core)

View File

@ -34,20 +34,17 @@ import dev.patrickgold.florisboard.ime.media.emoji.FlorisEmojiCompat
import dev.patrickgold.florisboard.ime.nlp.NlpManager
import dev.patrickgold.florisboard.ime.text.gestures.GlideTypingManager
import dev.patrickgold.florisboard.ime.theme.ThemeManager
import dev.patrickgold.florisboard.lib.NativeStr
import dev.patrickgold.florisboard.lib.cache.CacheManager
import dev.patrickgold.florisboard.lib.crashutility.CrashUtility
import dev.patrickgold.florisboard.lib.devtools.Flog
import dev.patrickgold.florisboard.lib.devtools.LogTopic
import dev.patrickgold.florisboard.lib.devtools.flogError
import dev.patrickgold.florisboard.lib.devtools.flogInfo
import dev.patrickgold.florisboard.lib.ext.ExtensionManager
import dev.patrickgold.florisboard.lib.io.AssetManager
import dev.patrickgold.florisboard.lib.io.deleteContentsRecursively
import dev.patrickgold.florisboard.lib.io.subFile
import dev.patrickgold.florisboard.lib.toNativeStr
import dev.patrickgold.jetpref.datastore.JetPref
import org.florisboard.lib.kotlin.tryOrNull
import org.florisboard.libnative.dummyAdd
import java.lang.ref.WeakReference
/**
@ -59,13 +56,9 @@ private var FlorisApplicationReference = WeakReference<FlorisApplication?>(null)
@Suppress("unused")
class FlorisApplication : Application() {
companion object {
private const val ICU_DATA_ASSET_PATH = "icu4c/icudt73l.dat"
private external fun nativeInitICUData(path: NativeStr): Int
init {
try {
System.loadLibrary("florisboard-native")
System.loadLibrary("fl_native")
} catch (_: Exception) {
}
}
@ -99,6 +92,7 @@ class FlorisApplication : Application() {
)
CrashUtility.install(this)
FlorisEmojiCompat.init(this)
flogError { "dummy result: ${dummyAdd(3,4)}" }
if (!UserManagerCompat.isUserUnlocked(this)) {
cacheDir?.deleteContentsRecursively()
@ -115,7 +109,6 @@ class FlorisApplication : Application() {
}
fun init() {
initICU(this)
cacheDir?.deleteContentsRecursively()
prefs.initializeBlocking(this)
extensionManager.value.init()
@ -123,28 +116,6 @@ class FlorisApplication : Application() {
DictionaryManager.init(this)
}
fun initICU(context: Context): Boolean {
try {
val androidAssetManager = context.assets ?: return false
val icuTmpDataFile = context.cacheDir.subFile("icudt.dat")
icuTmpDataFile.outputStream().use { os ->
androidAssetManager.open(ICU_DATA_ASSET_PATH).use { it.copyTo(os) }
}
val status = nativeInitICUData(icuTmpDataFile.absolutePath.toNativeStr())
icuTmpDataFile.delete()
return if (status != 0) {
flogError { "Native ICU data initializing failed with error code $status!" }
false
} else {
flogInfo { "Successfully loaded ICU data!" }
true
}
} catch (e: Exception) {
flogError { e.toString() }
return false
}
}
private inner class BootComplete : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
if (intent == null) return

View File

@ -0,0 +1,71 @@
plugins {
alias(libs.plugins.agp.library)
alias(libs.plugins.kotlin.android)
}
val projectMinSdk: String by project
val projectCompileSdk: String by project
val projectNdkVersion: String by project
android {
namespace = "org.florisboard.libnative"
compileSdk = projectCompileSdk.toInt()
ndkVersion = projectNdkVersion
defaultConfig {
minSdk = projectMinSdk.toInt()
externalNativeBuild {
cmake {
targets("fl_native")
arguments(
"-DCMAKE_ANDROID_API=" + minSdk.toString(),
)
}
}
ndk {
//abiFilters += listOf("armeabi-v7a", "arm64-v8a")
}
}
buildTypes {
release {
isMinifyEnabled = false
proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt"),
)
}
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = "1.8"
}
sourceSets {
maybeCreate("main").apply {
java {
srcDirs("src/main/kotlin")
}
}
}
externalNativeBuild {
cmake {
path("src/main/rust/CMakeLists.txt")
}
}
}
tasks.named("clean") {
doLast {
delete("src/main/rust/target", "src/main/rust/Cargo.lock")
}
}
dependencies {
// none
}

View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
</manifest>

View File

@ -0,0 +1,3 @@
package org.florisboard.libnative
external fun dummyAdd(a: Int, b: Int): Int

View File

@ -0,0 +1,53 @@
cmake_minimum_required(VERSION 3.22)
project(florisboard)
if(WIN32)
set(USER_HOME_DIRECTORY "$ENV{USERPROFILE}")
else()
set(USER_HOME_DIRECTORY "$ENV{HOME}")
endif()
set(RUST_TOOLCHAIN "${USER_HOME_DIRECTORY}/.cargo/bin")
### FlorisBoard ###
add_library(fl_native SHARED src/lib.c)
if(CMAKE_ANDROID_ARCH_ABI STREQUAL "armeabi-v7a")
set(ANDROID_TARGET "armv7a-linux-androideabi")
set(RUST_TARGET "armv7-linux-androideabi")
elseif(CMAKE_ANDROID_ARCH_ABI STREQUAL "arm64-v8a")
set(ANDROID_TARGET "aarch64-linux-android")
set(RUST_TARGET "aarch64-linux-android")
elseif(CMAKE_ANDROID_ARCH_ABI STREQUAL "x86")
set(ANDROID_TARGET "i686-linux-android")
set(RUST_TARGET "i686-linux-android")
elseif(CMAKE_ANDROID_ARCH_ABI STREQUAL "x86_64")
set(ANDROID_TARGET "x86_64-linux-android")
set(RUST_TARGET "x86_64-linux-android")
else()
message(FATAL_ERROR "Unsupported ABI: ${CMAKE_ANDROID_ARCH_ABI}")
endif()
get_filename_component(LLVM_TOOLCHAIN ${CMAKE_C_COMPILER} DIRECTORY)
set(FL_NATIVE_RUST_PATH "${CMAKE_CURRENT_SOURCE_DIR}/target/${RUST_TARGET}/release/libfl_native_rust.a")
add_custom_target(
setup_rust_target ALL
COMMAND ${RUST_TOOLCHAIN}/rustup target add ${RUST_TARGET}
)
add_custom_target(
fl_native_rust_build ALL
COMMAND ${RUST_TOOLCHAIN}/cargo rustc --release --target ${RUST_TARGET} --
-C linker="${LLVM_TOOLCHAIN}/${ANDROID_TARGET}${CMAKE_ANDROID_API}-clang"
DEPENDS setup_rust_target
BYPRODUCTS ${FL_NATIVE_RUST_PATH}
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
)
add_dependencies(fl_native fl_native_rust_build)
# TODO: check if there's a better way than allowing multiple symbol definitions
target_link_libraries(fl_native
android log -Wl,--whole-archive -Wl,--allow-multiple-definition ${FL_NATIVE_RUST_PATH}
)

View File

@ -0,0 +1,12 @@
[package]
name = "fl_native_rust"
version = "0.1.0"
edition = "2021"
[lib]
name = "fl_native_rust"
crate-type = ["staticlib"]
[dependencies]
dummy = { path = "../../../../../libnative/dummy" }
jni = "0.21.1"

View File

@ -0,0 +1 @@
// DO NOT DELETE ELSE CMAKE FAILS

View File

@ -0,0 +1,15 @@
use dummy;
use jni::objects::JClass;
use jni::sys::jint;
use jni::JNIEnv;
#[no_mangle]
pub extern "system" fn Java_org_florisboard_libnative_TestKt_dummyAdd(
_env: JNIEnv,
_class: JClass,
a: jint,
b: jint,
) -> jint {
dummy::addnumbers(a, b)
}

View File

@ -0,0 +1,6 @@
[package]
name = "dummy"
version = "0.1.0"
edition = "2021"
[dependencies]

View File

@ -0,0 +1,3 @@
pub fn addnumbers(left: i32, right: i32) -> i32 {
left + right
}

View File

@ -36,3 +36,4 @@ dependencyResolutionManagement {
include(":app")
include(":benchmark")
include(":lib:kotlin")
include(":lib:native")