Skip to content

Commit c3400bf

Browse files
committed
feat(android): enable ggml-hexagon backend
1 parent 8f6418e commit c3400bf

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

46 files changed

+14036
-232
lines changed

.gitignore

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,3 +85,9 @@ ios/rnwhisper.xcframework/**/*.framework
8585

8686
local-plan/
8787
local-plan-done/
88+
89+
# Hexagon HTP build artifacts
90+
build-hexagon-htp/
91+
bin/arm64-v8a/libggml-htp-*.so
92+
cpp/ggml-hexagon/htp/v73/htp_iface_stub.c
93+
cpp/ggml-hexagon/htp/v73/htp_iface.h

android/build.gradle

Lines changed: 64 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,64 @@ def isNewArchitectureEnabled() {
1515

1616
apply plugin: "com.android.library"
1717

18+
def repoRootDir = project.projectDir.parentFile
19+
def htpLibSourceDir = new File(repoRootDir, "bin/arm64-v8a")
1820

1921
def appProject = rootProject.allprojects.find { it.plugins.hasPlugin('com.android.application') }
2022

23+
if (appProject != null) {
24+
def configureHtpSyncTask = { Project applicationProject ->
25+
def assetsRootDir = new File(applicationProject.projectDir, "src/main/assets")
26+
def ggmlHexagonDir = new File(assetsRootDir, "ggml-hexagon")
27+
28+
def syncTask = applicationProject.tasks.register("syncRNWhisperHtpAssets", Copy) {
29+
group = "whisper.rn"
30+
description = "Copies whisper.rn Hexagon HTP libraries into the host application's assets directory."
31+
32+
onlyIf {
33+
if (!htpLibSourceDir.exists()) {
34+
logger.info("whisper.rn: No HTP libraries found at ${htpLibSourceDir.absolutePath}, skipping asset sync")
35+
return false
36+
}
37+
true
38+
}
39+
40+
doFirst {
41+
if (!assetsRootDir.exists()) {
42+
assetsRootDir.mkdirs()
43+
}
44+
if (!ggmlHexagonDir.exists()) {
45+
ggmlHexagonDir.mkdirs()
46+
return
47+
}
48+
ggmlHexagonDir.listFiles({ File dir, String name ->
49+
name.startsWith("libggml-htp-") && name.endsWith(".so")
50+
} as FilenameFilter)?.each { File lib ->
51+
lib.delete()
52+
}
53+
}
54+
55+
into(assetsRootDir)
56+
from(htpLibSourceDir) {
57+
include "libggml-htp-*.so"
58+
into "ggml-hexagon"
59+
}
60+
}
61+
62+
applicationProject.tasks.matching { it.name == "preBuild" }.configureEach {
63+
dependsOn(syncTask)
64+
}
65+
}
66+
67+
if (appProject.state.executed) {
68+
configureHtpSyncTask(appProject)
69+
} else {
70+
appProject.afterEvaluate {
71+
configureHtpSyncTask(appProject)
72+
}
73+
}
74+
}
75+
2176
if (isNewArchitectureEnabled()) {
2277
apply plugin: "com.facebook.react"
2378
}
@@ -74,13 +129,18 @@ android {
74129
minSdkVersion getExtOrIntegerDefault("minSdkVersion")
75130
targetSdkVersion getExtOrIntegerDefault("targetSdkVersion")
76131
buildConfigField "boolean", "IS_NEW_ARCHITECTURE_ENABLED", isNewArchitectureEnabled().toString()
132+
def homeDir = System.getProperty("user.home")
133+
def hexagonSdkRoot = System.getenv('HEXAGON_SDK_ROOT') ?: "${homeDir}/.hexagon-sdk/6.4.0.2"
134+
def hexagonToolsRoot = System.getenv('HEXAGON_TOOLS_ROOT') ?: "${homeDir}/.hexagon-sdk/6.4.0.2/tools/HEXAGON_Tools/19.0.04"
77135
externalNativeBuild {
78136
cmake {
79137
abiFilters (*reactNativeArchitectures())
80138
// Configure STL to be compatible with ReactAndroid JSI libraries
81139
arguments "-DANDROID_STL=c++_shared",
82140
"-DREACT_NATIVE_MINOR_VERSION=${REACT_NATIVE_MINOR_VERSION}",
83-
"-DANDROID_SUPPORT_FLEXIBLE_PAGE_SIZES=ON"
141+
"-DANDROID_SUPPORT_FLEXIBLE_PAGE_SIZES=ON",
142+
"-DHEXAGON_SDK_ROOT=${hexagonSdkRoot}",
143+
"-DHEXAGON_TOOLS_ROOT=${hexagonToolsRoot}"
84144
}
85145
}
86146
ndk {
@@ -105,6 +165,9 @@ android {
105165
"**/libturbomodulejsijni.so",
106166
"**/libreact_nativemodule_core.so",
107167
]
168+
jniLibs {
169+
excludes += ["**/libcdsprpc.so"]
170+
}
108171
}
109172

110173
buildFeatures {

android/src/main/CMakeLists.txt

Lines changed: 36 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -18,105 +18,82 @@ include_directories(
1818
${RNWHISPER_LIB_DIR}/jsi
1919
)
2020

21+
# Include core library builds
22+
add_subdirectory(rnwhisper)
23+
24+
# JNI source files
2125
set(
22-
SOURCE_FILES
23-
${RNWHISPER_LIB_DIR}/ggml.c
24-
${RNWHISPER_LIB_DIR}/ggml-alloc.c
25-
${RNWHISPER_LIB_DIR}/ggml-backend.cpp
26-
${RNWHISPER_LIB_DIR}/ggml-backend-reg.cpp
27-
${RNWHISPER_LIB_DIR}/ggml-cpu/amx/amx.cpp
28-
${RNWHISPER_LIB_DIR}/ggml-cpu/amx/mmq.cpp
29-
${RNWHISPER_LIB_DIR}/ggml-cpu/ggml-cpu.c
30-
${RNWHISPER_LIB_DIR}/ggml-cpu/ggml-cpu.cpp
31-
${RNWHISPER_LIB_DIR}/ggml-cpu/quants.c
32-
${RNWHISPER_LIB_DIR}/ggml-cpu/traits.cpp
33-
${RNWHISPER_LIB_DIR}/ggml-cpu/repack.cpp
34-
${RNWHISPER_LIB_DIR}/ggml-cpu/unary-ops.cpp
35-
${RNWHISPER_LIB_DIR}/ggml-cpu/binary-ops.cpp
36-
${RNWHISPER_LIB_DIR}/ggml-cpu/vec.cpp
37-
${RNWHISPER_LIB_DIR}/ggml-cpu/ops.cpp
38-
${RNWHISPER_LIB_DIR}/ggml-opt.cpp
39-
${RNWHISPER_LIB_DIR}/ggml-threading.cpp
40-
${RNWHISPER_LIB_DIR}/ggml-quants.c
41-
${RNWHISPER_LIB_DIR}/gguf.cpp
42-
${RNWHISPER_LIB_DIR}/whisper.cpp
43-
${RNWHISPER_LIB_DIR}/rn-audioutils.cpp
44-
${RNWHISPER_LIB_DIR}/rn-whisper.cpp
26+
JNI_SOURCE_FILES
4527
${RNWHISPER_LIB_DIR}/jsi/RNWhisperJSI.cpp
4628
${CMAKE_SOURCE_DIR}/jni.cpp
4729
)
4830

4931
find_library(LOG_LIB log)
5032

51-
function(build_library target_name arch cpu_flags)
52-
if (NOT ${arch} STREQUAL "generic")
53-
set(SOURCE_FILES_ARCH
54-
${RNWHISPER_LIB_DIR}/ggml-cpu/arch/${arch}/quants.c
55-
${RNWHISPER_LIB_DIR}/ggml-cpu/arch/${arch}/repack.cpp
56-
)
57-
endif ()
33+
# Build JNI wrapper library function
34+
function(build_rnwhisper_jni jni_name rnwhisper_name cpu_flags)
35+
# Check if Hexagon is enabled (name contains "_hexagon")
36+
string(REGEX MATCH ".*_hexagon.*" ENABLE_HEXAGON ${rnwhisper_name})
5837

5938
add_library(
60-
${target_name}
39+
${jni_name}
6140
SHARED
62-
${SOURCE_FILES}
63-
${SOURCE_FILES_ARCH}
41+
${JNI_SOURCE_FILES}
6442
)
6543

66-
# Link JSI libraries
44+
# JNI wrapper links to core library and ReactAndroid
6745
if(${REACT_NATIVE_MINOR_VERSION} GREATER_EQUAL 76)
68-
target_link_libraries(${target_name}
46+
target_link_libraries(${jni_name}
6947
${LOG_LIB}
7048
android
49+
${rnwhisper_name}
7150
fbjni::fbjni
7251
ReactAndroid::jsi
7352
ReactAndroid::reactnative
7453
)
7554
else ()
76-
target_link_libraries(${target_name}
55+
target_link_libraries(${jni_name}
7756
${LOG_LIB}
7857
android
58+
${rnwhisper_name}
7959
fbjni::fbjni
8060
ReactAndroid::jsi
8161
ReactAndroid::turbomodulejsijni
8262
ReactAndroid::react_nativemodule_core
8363
)
8464
endif ()
8565

86-
if (${arch} STREQUAL "generic")
87-
target_compile_options(${target_name} PRIVATE -DWSP_GGML_CPU_GENERIC)
88-
endif ()
66+
target_compile_options(${jni_name} PRIVATE -pthread ${cpu_flags})
8967

90-
target_compile_options(${target_name} PRIVATE -DWSP_GGML_USE_CPU -DWSP_GGML_USE_CPU_REPACK -pthread ${cpu_flags})
68+
if (ENABLE_HEXAGON)
69+
target_compile_options(${jni_name} PRIVATE -DWSP_GGML_USE_HEXAGON)
70+
endif ()
9171

9272
if (${CMAKE_BUILD_TYPE} STREQUAL "Debug")
93-
target_compile_options(${target_name} PRIVATE -DRNWHISPER_ANDROID_ENABLE_LOGGING)
73+
target_compile_options(${jni_name} PRIVATE -DRNWHISPER_ANDROID_ENABLE_LOGGING)
9474
endif ()
9575

96-
# NOTE: If you want to debug the native code, you can uncomment if and endif
97-
# Note that it will be extremely slow
98-
# if (NOT ${CMAKE_BUILD_TYPE} STREQUAL "Debug")
99-
target_compile_options(${target_name} PRIVATE -O3 -DNDEBUG)
100-
target_compile_options(${target_name} PRIVATE -fvisibility=hidden -fvisibility-inlines-hidden)
101-
target_compile_options(${target_name} PRIVATE -ffunction-sections -fdata-sections)
102-
103-
target_link_options(${target_name} PRIVATE -Wl,--gc-sections)
104-
target_link_options(${target_name} PRIVATE -Wl,--exclude-libs,ALL)
105-
target_link_options(${target_name} PRIVATE -flto)
106-
# endif ()
76+
target_compile_options(${jni_name} PRIVATE -O3 -DNDEBUG)
77+
target_compile_options(${jni_name} PRIVATE -fvisibility=hidden -fvisibility-inlines-hidden)
78+
target_compile_options(${jni_name} PRIVATE -ffunction-sections -fdata-sections)
79+
80+
target_link_options(${jni_name} PRIVATE -Wl,--gc-sections)
81+
target_link_options(${jni_name} PRIVATE -Wl,--exclude-libs,ALL)
82+
target_link_options(${jni_name} PRIVATE -flto)
10783
endfunction()
10884

109-
build_library("rnwhisper" "generic" "")
85+
# Build JNI wrapper variants
86+
build_rnwhisper_jni("rnwhisper_jni" "rnwhisper" "")
11087

11188
if (${ANDROID_ABI} STREQUAL "arm64-v8a")
112-
build_library("rnwhisper_v8fp16_va_2" "arm" "-march=armv8.2-a+fp16")
113-
build_library("rnwhisper_v8" "arm" "-march=armv8-a")
89+
build_rnwhisper_jni("rnwhisper_jni_v8fp16_va_2" "rnwhisper_v8fp16_va_2" "-march=armv8.2-a+fp16")
90+
build_rnwhisper_jni("rnwhisper_jni_v8" "rnwhisper_v8" "-march=armv8-a")
91+
# Hexagon HTP variant (experimental)
92+
build_rnwhisper_jni("rnwhisper_jni_v8_2_hexagon" "rnwhisper_v8_2_hexagon" "-march=armv8.2-a+fp16+dotprod")
11493
elseif (${ANDROID_ABI} STREQUAL "armeabi-v7a")
115-
build_library("rnwhisper_vfpv4" "arm" "-mfpu=neon-vfpv4")
94+
build_rnwhisper_jni("rnwhisper_jni_vfpv4" "rnwhisper_vfpv4" "-mfpu=neon-vfpv4")
11695
elseif (${ANDROID_ABI} STREQUAL "x86_64")
117-
# x86_64 target
118-
build_library("rnwhisper_x86_64" "x86" "-march=x86-64" "-mtune=intel" "-msse4.2" "-mpopcnt")
96+
build_rnwhisper_jni("rnwhisper_jni_x86_64" "rnwhisper_x86_64" "-march=x86-64" "-mtune=intel" "-msse4.2" "-mpopcnt")
11997
endif ()
12098

121-
12299
include_directories(${RNWHISPER_LIB_DIR})

0 commit comments

Comments
 (0)