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:
parent
c198e8b376
commit
c5d1d3b31e
10
.gitignore
vendored
10
.gitignore
vendored
@ -47,3 +47,13 @@ crowdin.properties
|
||||
# Nix stuff
|
||||
.direnv/
|
||||
result
|
||||
|
||||
# VSCode
|
||||
.vscode/
|
||||
|
||||
# Rust
|
||||
debug/
|
||||
target/
|
||||
Cargo.lock
|
||||
**/*.rs.bk
|
||||
*.pdb
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
71
lib/native/build.gradle.kts
Normal file
71
lib/native/build.gradle.kts
Normal 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
|
||||
}
|
4
lib/native/src/main/AndroidManifest.xml
Normal file
4
lib/native/src/main/AndroidManifest.xml
Normal file
@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
</manifest>
|
@ -0,0 +1,3 @@
|
||||
package org.florisboard.libnative
|
||||
|
||||
external fun dummyAdd(a: Int, b: Int): Int
|
53
lib/native/src/main/rust/CMakeLists.txt
Normal file
53
lib/native/src/main/rust/CMakeLists.txt
Normal 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}
|
||||
)
|
12
lib/native/src/main/rust/Cargo.toml
Normal file
12
lib/native/src/main/rust/Cargo.toml
Normal 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"
|
1
lib/native/src/main/rust/src/lib.c
Normal file
1
lib/native/src/main/rust/src/lib.c
Normal file
@ -0,0 +1 @@
|
||||
// DO NOT DELETE ELSE CMAKE FAILS
|
15
lib/native/src/main/rust/src/lib.rs
Normal file
15
lib/native/src/main/rust/src/lib.rs
Normal 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)
|
||||
}
|
6
libnative/dummy/Cargo.toml
Normal file
6
libnative/dummy/Cargo.toml
Normal file
@ -0,0 +1,6 @@
|
||||
[package]
|
||||
name = "dummy"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
3
libnative/dummy/src/lib.rs
Normal file
3
libnative/dummy/src/lib.rs
Normal file
@ -0,0 +1,3 @@
|
||||
pub fn addnumbers(left: i32, right: i32) -> i32 {
|
||||
left + right
|
||||
}
|
@ -36,3 +36,4 @@ dependencyResolutionManagement {
|
||||
include(":app")
|
||||
include(":benchmark")
|
||||
include(":lib:kotlin")
|
||||
include(":lib:native")
|
||||
|
Loading…
Reference in New Issue
Block a user