Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
553784a
[js/rn] Support JSI
hans00 Aug 16, 2025
6ae0ebf
Reorganize and format code
hans00 Aug 16, 2025
a9aafee
Fix build and format code
hans00 Aug 16, 2025
c7bf670
Support React Native >= 0.71
hans00 Aug 16, 2025
7cd890b
Correct pointer type
hans00 Aug 18, 2025
3386c7f
Fix session lifetime management
hans00 Aug 24, 2025
b50195f
Merge branch 'microsoft:main' into rn-jsi
hans00 Oct 22, 2025
2c1da00
Fix lint error
hans00 Oct 22, 2025
0f7c1a5
Fix bob build error
hans00 Oct 22, 2025
85ad855
Fix build error
hans00 Oct 25, 2025
5e3854a
Fix iOS build fail
hans00 Oct 26, 2025
dd9cf01
Support load model from Android URI format `file:/path/to/something`
hans00 Oct 26, 2025
f7ccfd3
Merge branch 'main' into rn-jsi
hans00 Oct 30, 2025
f941697
Correct podspec var name
hans00 Oct 30, 2025
80846c4
Remove module test codes, because JSI API is hard test without integrate
hans00 Oct 31, 2025
476bca2
Move basic test into E2E test
hans00 Oct 31, 2025
6ccc33b
Correct import path
hans00 Oct 31, 2025
2a88693
Remove iOS unit test and correct podspec file
hans00 Nov 4, 2025
fd23835
Try fix build error
hans00 Nov 4, 2025
842a8f8
Remove Android unit test and fix local build lib linking
hans00 Nov 4, 2025
8173d06
Correct AAR copy path
hans00 Nov 5, 2025
2311f2e
Upload CI test results
hans00 Nov 5, 2025
d3361fe
Fix iOS test fail
hans00 Nov 5, 2025
4611c81
Fix iOS read assets
hans00 Nov 5, 2025
d02120e
Correct text
hans00 Nov 5, 2025
9b44561
Add assets into iOS bundle resource
hans00 Nov 5, 2025
aa59984
Regenerate test assets
hans00 Nov 5, 2025
31caf7e
Correct file
hans00 Nov 5, 2025
0e24a79
Merge branch 'microsoft:main' into rn-jsi
hans00 Nov 5, 2025
3badbf5
Add missing files
hans00 Nov 11, 2025
9a7db51
Format code
hans00 Nov 12, 2025
0917c0e
Fix Android button selector
hans00 Nov 13, 2025
891fb63
Add missing files for Android E2E
hans00 Nov 15, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
93 changes: 23 additions & 70 deletions .github/workflows/react_native.yml
Original file line number Diff line number Diff line change
Expand Up @@ -53,14 +53,11 @@ jobs:
cp tools/ci_build/github/js/react_native_e2e_full_aar_build_settings.json ${{ runner.temp }}/.build_settings/build_settings.json

python3 -m pip install --user -r ${{ github.workspace }}/tools/ci_build/requirements/pybind/requirements.txt
python3 ${{ github.workspace }}/tools/ci_build/github/android/build_aar_package.py --build_dir ${{ runner.temp }} --config Release --android_sdk_path $ANDROID_SDK_ROOT --android_ndk_path $ANDROID_NDK_ROOT ${{ runner.temp }}/.build_settings/build_settings.json

python3 ${{ github.workspace }}/tools/ci_build/github/android/build_aar_package.py --build_dir ${{ runner.temp }} --config Release --android_sdk_path $ANDROID_SDK_ROOT --android_ndk_path $ANDROID_NDK_ROOT ${{ runner.temp }}/.build_settings/build_settings.json

# Copy the built artifacts to give folder for publishing
BASE_PATH=${{ runner.temp }}/aar_out/Release/com/microsoft/onnxruntime/onnxruntime-android/${OnnxRuntimeVersion}
cp ${BASE_PATH}/*.jar ${{ runner.temp }}/artifacts
cp ${BASE_PATH}/*.aar ${{ runner.temp }}/artifacts
cp ${BASE_PATH}/*.pom ${{ runner.temp }}/artifacts
cp -r ${{ runner.temp }}/aar_out/Release/com ${{ runner.temp }}/artifacts

- name: Upload Android AAR Artifact
uses: actions/upload-artifact@v5
Expand Down Expand Up @@ -109,10 +106,8 @@ jobs:

- name: Copy AAR to React Native and E2E directories
run: |
mkdir -p ${{ github.workspace }}/js/react_native/android/libs
cp ${{ runner.temp }}/android-full-aar/*.aar ${{ github.workspace }}/js/react_native/android/libs
mkdir -p ${{ github.workspace }}/js/react_native/e2e/android/app/libs
cp ${{ runner.temp }}/android-full-aar/*.aar ${{ github.workspace }}/js/react_native/e2e/android/app/libs
cp -r ${{ runner.temp }}/android-full-aar/com ${{ github.workspace }}/js/react_native/e2e/android/app/libs

- name: Install dependencies and bootstrap
run: |
Expand Down Expand Up @@ -141,10 +136,6 @@ jobs:
with:
ndk-version: 28.0.13004108

- name: Run React Native Android Instrumented Tests
run: ./gradlew connectedDebugAndroidTest --stacktrace
working-directory: ${{ github.workspace }}/js/react_native/android

- name: Run React Native Detox Android e2e Tests
run: |
JEST_JUNIT_OUTPUT_FILE=${{ github.workspace }}/js/react_native/e2e/android-test-results.xml \
Expand All @@ -169,6 +160,15 @@ jobs:
echo "Emulator PID file was expected to exist but does not."
fi

- name: Upload Android Test Results
if: always()
uses: actions/upload-artifact@v5
with:
name: android-test-results
path: |
${{ github.workspace }}/js/react_native/e2e/android-test-results.xml
${{ github.workspace }}/js/react_native/e2e/artifacts

react_native_ci_ios_build:
name: React Native CI iOS Build
runs-on: macos-14
Expand Down Expand Up @@ -211,62 +211,6 @@ jobs:
name: ios_pod
path: ${{ runner.temp }}/ios_pod

react_native_ci_ios_unit_tests:
name: React Native CI iOS Unit Tests
needs: react_native_ci_ios_build
runs-on: macos-14
timeout-minutes: 90
steps:
- name: Checkout repository
uses: actions/checkout@v5

- name: Download iOS pod artifact
uses: actions/download-artifact@v6
with:
name: ios_pod
path: ${{ runner.temp }}/ios_pod

- name: Use Xcode 15.3.0
run: sudo xcode-select --switch /Applications/Xcode_15.3.0.app/Contents/Developer

- name: Use Node.js 22.x
uses: actions/setup-node@v6
with:
node-version: '22.x'

- uses: microsoft/onnxruntime-github-actions/setup-build-tools@v0.0.9
with:
vcpkg-version: '2025.06.13'
vcpkg-hash: 735923258c5187966698f98ce0f1393b8adc6f84d44fd8829dda7db52828639331764ecf41f50c8e881e497b569f463dbd02dcb027ee9d9ede0711102de256cc
cmake-version: '3.31.8'
cmake-hash: 99cc9c63ae49f21253efb5921de2ba84ce136018abf08632c92c060ba91d552e0f6acc214e9ba8123dee0cf6d1cf089ca389e321879fd9d719a60d975bcffcc8
add-cmake-to-path: 'true'
disable-terrapin: 'true'

- name: Install dependencies and bootstrap
run: |
npm ci
working-directory: ${{ github.workspace }}/js
- run: npm ci
working-directory: ${{ github.workspace }}/js/common
- run: |
set -e -x
npm ci
npm run bootstrap-no-pods
working-directory: ${{ github.workspace }}/js/react_native

- name: Pod install
run: |
set -e -x
ls ${{ runner.temp }}/ios_pod/onnxruntime-c
ORT_C_LOCAL_POD_PATH=${{ runner.temp }}/ios_pod/onnxruntime-c pod install --verbose
working-directory: ${{ github.workspace }}/js/react_native/ios

- name: Run React Native iOS Instrumented Tests
run: |
/usr/bin/xcodebuild -sdk iphonesimulator -configuration Debug -workspace ${{ github.workspace }}/js/react_native/ios/OnnxruntimeModule.xcworkspace -scheme OnnxruntimeModuleTest -destination 'platform=iOS Simulator,name=iPhone 15,OS=17.4' test CODE_SIGNING_ALLOWED=NO
working-directory: ${{ github.workspace }}/js/react_native/ios

react_native_ci_ios_e2e_tests:
name: React Native CI iOS E2E Tests
needs: react_native_ci_ios_build
Expand Down Expand Up @@ -314,7 +258,7 @@ jobs:
npm ci
npm run bootstrap-no-pods
working-directory: ${{ github.workspace }}/js/react_native

- name: Pod install for e2e tests
run: |
set -e -x
Expand All @@ -331,3 +275,12 @@ jobs:
--loglevel verbose \
--take-screenshots failing
working-directory: ${{ github.workspace }}/js/react_native/e2e

- name: Upload iOS Test Results
if: always()
uses: actions/upload-artifact@v5
with:
name: ios-test-results
path: |
${{ github.workspace }}/js/react_native/e2e/ios-test-results.xml
${{ github.workspace }}/js/react_native/e2e/artifacts
104 changes: 83 additions & 21 deletions js/react_native/android/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,37 +1,99 @@
project(OnnxruntimeJSIHelper)
project(OnnxruntimeJSI)
cmake_minimum_required(VERSION 3.9.0)

set (PACKAGE_NAME "onnxruntime-react-native")
set (BUILD_DIR ${CMAKE_SOURCE_DIR}/build)
set(PACKAGE_NAME "onnxruntime-react-native")
set(BUILD_DIR ${CMAKE_SOURCE_DIR}/build)
set(CMAKE_VERBOSE_MAKEFILE ON)
set(CMAKE_CXX_STANDARD 17)

file(TO_CMAKE_PATH "${NODE_MODULES_DIR}/react-native/ReactCommon/jsi/jsi/jsi.cpp" libPath)
option(ORT_EXTENSIONS_ENABLED "Enable Ort Extensions" NO)
option(USE_NNAPI "Use NNAPI" YES)
option(USE_QNN "Use QNN" NO)

file(GLOB libfbjni_link_DIRS "${BUILD_DIR}/fbjni-*.aar/jni/${ANDROID_ABI}")
file(GLOB libfbjni_include_DIRS "${BUILD_DIR}/fbjni-*-headers.jar/")

file(GLOB onnxruntime_include_DIRS
"${BUILD_DIR}/onnxruntime-android-*.aar/headers")
file(GLOB onnxruntime_link_DIRS
"${BUILD_DIR}/onnxruntime-android-*.aar/jni/${ANDROID_ABI}/")

if(ORT_EXTENSIONS_ENABLED)
add_definitions(-DORT_ENABLE_EXTENSIONS)
endif()

if(USE_QNN)
add_definitions(-DUSE_QNN)
endif()

if(USE_NNAPI)
add_definitions(-DUSE_NNAPI)
endif()

file(TO_CMAKE_PATH
"${NODE_MODULES_DIR}/react-native/ReactCommon/jsi/jsi/jsi.cpp" libPath)

find_package(fbjni REQUIRED CONFIG)
find_package(ReactAndroid REQUIRED CONFIG)

find_library(
onnxruntime-lib onnxruntime
PATHS ${onnxruntime_link_DIRS}
NO_CMAKE_FIND_ROOT_PATH)

set(RN_INCLUDES
"${NODE_MODULES_DIR}/react-native/React"
"${NODE_MODULES_DIR}/react-native/React/Base"
"${NODE_MODULES_DIR}/react-native/ReactCommon"
"${NODE_MODULES_DIR}/react-native/ReactCommon/jsi"
"${NODE_MODULES_DIR}/react-native/ReactCommon/callinvoker")

if(${REACT_NATIVE_VERSION} VERSION_GREATER_EQUAL "0.76")
set(RN_LIBS
ReactAndroid::reactnative
ReactAndroid::jsi)
else()
list(
APPEND
RN_INCLUDES
"${NODE_MODULES_DIR}/react-native/ReactAndroid/src/main/java/com/facebook/react/turbomodule/core/jni"
)
set(RN_LIBS
ReactAndroid::jsi
ReactAndroid::react_nativemodule_core
ReactAndroid::turbomodulejsijni)
endif()

include_directories(
"${NODE_MODULES_DIR}/react-native/React"
"${NODE_MODULES_DIR}/react-native/React/Base"
"${NODE_MODULES_DIR}/react-native/ReactCommon/jsi"
)
../cpp
${RN_INCLUDES}
${onnxruntime_include_DIRS}
${libfbjni_include_DIRS})

add_library(onnxruntimejsihelper
SHARED
${libPath}
src/main/cpp/cpp-adapter.cpp
)
add_library(
onnxruntimejsi SHARED
${libPath}
src/main/cpp/cpp-adapter.cpp
../cpp/JsiMain.cpp
../cpp/InferenceSessionHostObject.cpp
../cpp/JsiUtils.cpp
../cpp/SessionUtils.cpp
../cpp/TensorUtils.cpp)

# Configure C++ 17
set_target_properties(
onnxruntimejsihelper PROPERTIES
CXX_STANDARD 17
CXX_EXTENSIONS OFF
POSITION_INDEPENDENT_CODE ON
)
onnxruntimejsi
PROPERTIES CXX_STANDARD 17
CXX_EXTENSIONS OFF
POSITION_INDEPENDENT_CODE ON)

find_library(log-lib log)

target_link_libraries(
onnxruntimejsihelper
${log-lib} # <-- Logcat logger
android # <-- Android JNI core
onnxruntimejsi
${onnxruntime-lib}
fbjni::fbjni
${RN_LIBS}
${log-lib} # <-- Logcat logger
android # <-- Android JNI core
)
76 changes: 59 additions & 17 deletions js/react_native/android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -48,23 +48,22 @@ static def findNodeModules(baseDir) {

def nodeModules = findNodeModules(projectDir);

def checkIfOrtExtensionsEnabled() {
def readPackageJsonField(field) {
// locate user's project dir
def reactnativeRootDir = project.rootDir.parentFile
// get package.json file in root directory
def packageJsonFile = new File(reactnativeRootDir, 'package.json')
// read field 'onnxruntimeExtensionsEnabled'
if (packageJsonFile.exists()) {
def packageJsonContents = packageJsonFile.getText()
def packageJson = new groovy.json.JsonSlurper().parseText(packageJsonContents)
return packageJson.onnxruntimeExtensionsEnabled == "true"
return packageJson.get(field)
} else {
logger.warn("Could not find package.json file in the expected directory: ${reactnativeRootDir}. ONNX Runtime Extensions will not be enabled.")
logger.warn("Could not find package.json file in the expected directory: ${reactnativeRootDir}. ${field} will not be enabled.")
}
return false
}

boolean ortExtensionsEnabled = checkIfOrtExtensionsEnabled()
boolean ortExtensionsEnabled = readPackageJsonField('onnxruntimeExtensionsEnabled') == "true"
boolean useQnn = readPackageJsonField('onnxruntimeUseQnn') == "true"

def REACT_NATIVE_VERSION = ['node', '--print', "JSON.parse(require('fs').readFileSync(require.resolve('react-native/package.json'), 'utf-8')).version"].execute(null, rootDir).text.trim()
def REACT_NATIVE_MINOR_VERSION = REACT_NATIVE_VERSION.split("\\.")[1].toInteger()
Expand All @@ -85,9 +84,18 @@ android {
cppFlags "-O2 -frtti -fexceptions -Wall -Wno-unused-variable -fstack-protector-all"
if (REACT_NATIVE_MINOR_VERSION >= 71) {
// fabricjni required c++_shared
arguments "-DANDROID_STL=c++_shared", "-DNODE_MODULES_DIR=${nodeModules}", "-DORT_EXTENSIONS_ENABLED=${ortExtensionsEnabled}"
arguments "-DANDROID_STL=c++_shared",
"-DNODE_MODULES_DIR=${nodeModules}",
"-DORT_EXTENSIONS_ENABLED=${ortExtensionsEnabled}",
"-DREACT_NATIVE_VERSION=${REACT_NATIVE_VERSION}",
"-DUSE_QNN=${useQnn}",
"-DUSE_NNAPI=${!useQnn}"
} else {
arguments "-DNODE_MODULES_DIR=${nodeModules}", "-DORT_EXTENSIONS_ENABLED=${ortExtensionsEnabled}"
arguments "-DNODE_MODULES_DIR=${nodeModules}",
"-DORT_EXTENSIONS_ENABLED=${ortExtensionsEnabled}",
"-DREACT_NATIVE_VERSION=${REACT_NATIVE_VERSION}",
"-DUSE_QNN=${useQnn}",
"-DUSE_NNAPI=${!useQnn}"
}
abiFilters (*reactNativeArchitectures())
}
Expand Down Expand Up @@ -119,6 +127,9 @@ android {
"META-INF",
"META-INF/**",
"**/libjsi.so",
"**/libfbjni.so",
"**/libreact_nativemodule_core.so",
"**/libturbomodulejsijni.so"
]
}

Expand Down Expand Up @@ -147,6 +158,10 @@ android {
}
}
}

configurations {
extractLibs
}
}

repositories {
Expand Down Expand Up @@ -217,27 +232,54 @@ repositories {
"Ensure you have you installed React Native as a dependency in your project and try again."
)
}

flatDir {
dir 'libs'
}
}

dependencies {
//noinspection GradleDynamicVersion
implementation "com.facebook.react:react-android:"+ REACT_NATIVE_VERSION
api "org.mockito:mockito-core:2.28.2"

androidTestImplementation "androidx.test:runner:1.5.2"
androidTestImplementation "androidx.test:rules:1.5.0"
implementation "junit:junit:4.12"

androidTestImplementation "com.linkedin.dexmaker:dexmaker-mockito-inline-extended:2.28.1"
if (useQnn) {
extractLibs "com.microsoft.onnxruntime:onnxruntime-android-qnn:latest.integration@aar"
} else {
extractLibs "com.microsoft.onnxruntime:onnxruntime-android:latest.integration@aar"
}

implementation "com.microsoft.onnxruntime:onnxruntime-android:latest.integration@aar"
if (VersionNumber.parse(REACT_NATIVE_VERSION) < VersionNumber.parse("0.71")) {
extractLibs "com.facebook.fbjni:fbjni:+:headers"
extractLibs "com.facebook.fbjni:fbjni:+"
}

// By default it will just include onnxruntime full aar package
if (ortExtensionsEnabled) {
implementation "com.microsoft.onnxruntime:onnxruntime-extensions-android:latest.integration@aar"
}
}
}

task extractLibs {
doLast {
configurations.extractLibs.files.each {
def file = it.absoluteFile
copy {
from zipTree(file)
into "$buildDir/$file.name"
include "**/*.h", "**/*.so"
}
}
}
}

def nativeBuildDependsOn(dependsOnTask, variant) {
def buildTasks = tasks.findAll({ task ->
!task.name.contains("Clean") && (task.name.contains("externalNative") || task.name.contains("CMake")) })
if (variant != null) {
buildTasks = buildTasks.findAll({ task -> task.name.contains(variant) })
}
buildTasks.forEach { task -> task.dependsOn(dependsOnTask) }
}

afterEvaluate {
nativeBuildDependsOn(extractLibs, null)
}
Loading
Loading