Skip to content

Commit 44a8f22

Browse files
authored
Added Java Bindings for Adapters API (#1030)
* Added Java Bindings for Adapters API and test cases. * Enable Java CI tests on win-x64, win-arm64, linux-x64 and osx-arm64. * Fix existing Java test cases. * Fix some style issues reported by spotless. Internal work item: https://task.ms/aii/52363
1 parent c5745fd commit 44a8f22

34 files changed

+675
-222
lines changed

.github/workflows/linux-cpu-x64-build.yml

+17
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,18 @@ jobs:
2727
with:
2828
dotnet-version: '8.0.x'
2929

30+
- name: Setup Java 17
31+
uses: actions/setup-java@v4
32+
with:
33+
java-version: '17'
34+
distribution: 'temurin'
35+
cache: 'gradle'
36+
37+
- name: Setup Gradle
38+
uses: gradle/actions/setup-gradle@v3
39+
with:
40+
gradle-version: '8.6'
41+
3042
- name: Get the Latest OnnxRuntime Nightly Version
3143
shell: pwsh
3244
run: |
@@ -96,6 +108,11 @@ jobs:
96108
cd test/csharp
97109
dotnet test /p:Configuration=Release /p:NativeBuildOutputDir="../../build/cpu/" /p:OrtLibDir="../../ort/lib/" --verbosity normal
98110
111+
- name: Build the Java API and Run the Java Tests
112+
run: |
113+
set -e -x
114+
python3 build.py --config=Release --build_dir build/cpu --build_java --parallel --cmake_generator "Ninja"
115+
99116
- name: Run tests
100117
run: |
101118
set -e -x

.github/workflows/mac-cpu-arm64-build.yml

+19
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,18 @@ jobs:
2525
with:
2626
python-version: '3.12.x'
2727

28+
- name: Setup Java 17
29+
uses: actions/setup-java@v4
30+
with:
31+
java-version: '17'
32+
distribution: 'temurin'
33+
cache: 'gradle'
34+
35+
- name: Setup Gradle
36+
uses: gradle/actions/setup-gradle@v3
37+
with:
38+
gradle-version: '8.6'
39+
2840
- name: Get the Latest OnnxRuntime Nightly Version
2941
run: |
3042
ORT_NIGHTLY_VERSION=$(curl -s "${{ env.ORT_NIGHTLY_REST_API }}" | jq -r '.value[0].versions[0].normalizedVersion')
@@ -76,6 +88,7 @@ jobs:
7688
source genai-macos-venv/bin/activate
7789
export HF_TOKEN="12345"
7890
export ORTGENAI_LOG_ORT_LIB=1
91+
python3 -m pip install requests
7992
python3 test/python/test_onnxruntime_genai.py --cwd test/python --test_models test/test_models
8093
8194
- name: Build the C# API and Run the C# Tests
@@ -84,6 +97,12 @@ jobs:
8497
cd test/csharp
8598
dotnet test /p:Configuration=Release /p:NativeBuildOutputDir="../../build/cpu/osx-arm64" --verbosity normal
8699
100+
- name: Build the Java API and Run the Java Tests
101+
run: |
102+
set -e -x
103+
source genai-macos-venv/bin/activate
104+
python3 build.py --config=Release --build_dir build/cpu/osx-arm64 --build_java --parallel --cmake_generator "Unix Makefiles"
105+
87106
- name: Run tests
88107
run: |
89108
set -e -x

.github/workflows/win-cpu-arm64-build.yml

+23-6
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,18 @@ jobs:
3434
with:
3535
nuget-version: '5.x'
3636

37+
- name: Setup Java 21
38+
uses: actions/setup-java@v4
39+
with:
40+
java-version: '21'
41+
distribution: 'temurin'
42+
cache: 'gradle'
43+
44+
- name: Setup Gradle
45+
uses: gradle/actions/setup-gradle@v3
46+
with:
47+
gradle-version: '8.6'
48+
3749
- name: Download OnnxRuntime Nightly
3850
shell: powershell
3951
run: |
@@ -54,18 +66,14 @@ jobs:
5466
5567
- name: Configure CMake
5668
run: |
57-
python -m pip install wheel
69+
python -m pip install wheel requests
70+
5871
cmake --preset windows_arm64_cpu_release
5972
6073
- name: Build with CMake
6174
run: |
6275
cmake --build --preset windows_arm64_cpu_release --parallel
6376
64-
- name: Build the C# API and Run the C# Tests
65-
run: |
66-
cd test\csharp
67-
dotnet test /p:NativeBuildOutputDir="$env:GITHUB_WORKSPACE\$env:binaryDir\Release" /p:OrtLibDir="$env:GITHUB_WORKSPACE\ort\lib"
68-
6977
- name: Install the Python Wheel and Test Dependencies
7078
run: |
7179
python -m pip install "numpy<2" coloredlogs flatbuffers packaging protobuf sympy pytest
@@ -76,6 +84,15 @@ jobs:
7684
run: |
7785
python test/python/test_onnxruntime_genai.py --cwd "test\python" --test_models "test\test_models"
7886
87+
- name: Build the C# API and Run the C# Tests
88+
run: |
89+
cd test\csharp
90+
dotnet test /p:NativeBuildOutputDir="$env:GITHUB_WORKSPACE\$env:binaryDir\Release" /p:OrtLibDir="$env:GITHUB_WORKSPACE\ort\lib"
91+
92+
- name: Build the Java API and Run the Java Tests
93+
run: |
94+
python build.py --config=Release --build_dir $env:binaryDir --build_java --parallel
95+
7996
- name: Verify Build Artifacts
8097
if: always()
8198
continue-on-error: true

.github/workflows/win-cpu-x64-build.yml

+16
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,18 @@ jobs:
4141
with:
4242
dotnet-version: '8.0.x'
4343

44+
- name: Setup Java 17
45+
uses: actions/setup-java@v4
46+
with:
47+
java-version: '17'
48+
distribution: 'temurin'
49+
cache: 'gradle'
50+
51+
- name: Setup Gradle
52+
uses: gradle/actions/setup-gradle@v3
53+
with:
54+
gradle-version: '8.6'
55+
4456
- name: Download OnnxRuntime Nightly
4557
shell: pwsh
4658
run: |
@@ -92,6 +104,10 @@ jobs:
92104
cd test\csharp
93105
dotnet test /p:NativeBuildOutputDir="$env:GITHUB_WORKSPACE\$env:binaryDir\Release" /p:OrtLibDir="$env:GITHUB_WORKSPACE\ort\lib" --verbosity normal
94106
107+
- name: Build the Java API and Run the Java Tests
108+
run: |
109+
python3 build.py --config=Release --build_dir $env:binaryDir --build_java --parallel
110+
95111
- name: Verify Build Artifacts
96112
if: always()
97113
continue-on-error: true

.gitignore

+2
Original file line numberDiff line numberDiff line change
@@ -35,3 +35,5 @@ examples/csharp/HelloPhi/models
3535
/src/java/.gradle
3636
/src/java/local.properties
3737
/src/java/build
38+
/src/java/CMakeFiles
39+
/src/java/CMakeCache.txt

build.py

+10-4
Original file line numberDiff line numberDiff line change
@@ -229,11 +229,13 @@ def _validate_build_dir(args: argparse.Namespace):
229229
# also tweak build directory name for mac builds
230230
target_sys = "macOS"
231231

232-
args.build_dir = Path("build") / target_sys
232+
# set to a config specific build dir if no build_dir specified from command arguments
233+
args.build_dir = Path("build") / target_sys / args.config
233234

234-
# set to a config specific build dir. it should exist unless we're creating the cmake setup
235235
is_strict = not args.update
236-
args.build_dir = args.build_dir.resolve(strict=is_strict) / args.config
236+
# Use user-specified build_dir and ignore args.config
237+
# This is to better accommodate the existing cmake presets which can uses arbitrary paths.
238+
args.build_dir = args.build_dir.resolve(strict=is_strict)
237239

238240

239241
def _validate_cuda_args(args: argparse.Namespace):
@@ -453,7 +455,7 @@ def update(args: argparse.Namespace, env: dict[str, str]):
453455

454456
is_x64_host = platform.machine() == "AMD64"
455457
if is_x64_host:
456-
toolset_options += ["host=x64"]
458+
pass
457459

458460
if args.use_cuda:
459461
toolset_options += ["cuda=" + str(args.cuda_home)]
@@ -624,6 +626,10 @@ def test(args: argparse.Namespace, env: dict[str, str]):
624626
csharp_test_command += _get_csharp_properties(args, ort_lib_dir=lib_dir)
625627
util.run(csharp_test_command, env=env, cwd=str(REPO_ROOT / "test" / "csharp"))
626628

629+
if args.build_java:
630+
ctest_cmd = [str(args.ctest_path), "--build-config", args.config, "--verbose", "--timeout", "10800"]
631+
util.run(ctest_cmd, cwd=str(args.build_dir / "src" / "java"))
632+
627633
if args.android:
628634
_run_android_tests(args)
629635

src/java/CMakeLists.txt

+46-27
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,9 @@ endif()
1313

1414
set(JAVA_SRC_ROOT ${CMAKE_CURRENT_SOURCE_DIR})
1515
# <build output dir>/src/java (path used with add_subdirectory in root CMakeLists.txt)
16-
set(JAVA_OUTPUT_DIR ${CMAKE_CURRENT_BINARY_DIR})
16+
set(JAVA_OUTPUT_DIR ${CMAKE_CURRENT_BINARY_DIR})
1717

18-
# Should we use onnxruntime-genai or onnxruntime-genai-static? Using onnxruntime-genai for now.
18+
# Should we use onnxruntime-genai or onnxruntime-genai-static? Using onnxruntime-genai for now.
1919
# Add dependency on native target
2020
set(JAVA_DEPENDS onnxruntime-genai)
2121

@@ -34,20 +34,20 @@ elseif (ANDROID)
3434
endif()
3535

3636
# this jar is solely used to signaling mechanism for dependency management in CMake
37-
# if any of the Java sources change, the jar (and generated headers) will be regenerated
37+
# if any of the Java sources change, the jar (and generated headers) will be regenerated
3838
# and the onnxruntime-genai-jni target will be rebuilt
3939
set(JAVA_OUTPUT_JAR ${JAVA_OUTPUT_DIR}/build/libs/onnxruntime-genai.jar)
4040
set(GRADLE_ARGS clean jar -x test)
4141

4242
# this jar is solely used to signaling mechanism for dependency management in CMake
43-
# if any of the Java sources change, the jar (and generated headers) will be regenerated
43+
# if any of the Java sources change, the jar (and generated headers) will be regenerated
4444
# and the onnxruntime-genai-jni target will be rebuilt
4545
set(JAVA_OUTPUT_JAR ${JAVA_SRC_ROOT}/build/libs/onnxruntime-genai.jar)
4646
set(GRADLE_ARGS clean jar -x test)
4747

48-
add_custom_command(OUTPUT ${JAVA_OUTPUT_JAR}
49-
COMMAND ${GRADLE_EXECUTABLE} ${GRADLE_OPTIONS} ${GRADLE_ARGS}
50-
WORKING_DIRECTORY ${JAVA_SRC_ROOT}
48+
add_custom_command(OUTPUT ${JAVA_OUTPUT_JAR}
49+
COMMAND ${GRADLE_EXECUTABLE} ${GRADLE_OPTIONS} ${GRADLE_ARGS}
50+
WORKING_DIRECTORY ${JAVA_SRC_ROOT}
5151
DEPENDS ${genai4j_gradle_files} ${genai4j_srcs})
5252
add_custom_target(onnxruntime-genai4j DEPENDS ${JAVA_OUTPUT_JAR})
5353

@@ -60,13 +60,13 @@ file(GLOB genai4j_native_src
6060
"${JAVA_SRC_ROOT}/src/main/native/*.h"
6161
"${SRC_ROOT}/ort_genai_c.h"
6262
)
63-
63+
6464
add_library(onnxruntime-genai-jni SHARED ${genai4j_native_src})
6565
set_property(TARGET onnxruntime-genai-jni PROPERTY CXX_STANDARD 17)
6666
add_dependencies(onnxruntime-genai-jni onnxruntime-genai4j)
6767
# the JNI headers are generated in the genai4j target
6868
target_include_directories(onnxruntime-genai-jni PRIVATE ${SRC_ROOT}
69-
${JAVA_SRC_ROOT}/build/headers
69+
${JAVA_SRC_ROOT}/build/headers
7070
${JNI_INCLUDE_DIRS})
7171
target_link_libraries(onnxruntime-genai-jni PUBLIC onnxruntime-genai)
7272

@@ -104,13 +104,13 @@ file(MAKE_DIRECTORY ${JAVA_PACKAGE_LIB_DIR})
104104

105105
# Add the native genai library to the native-lib dir
106106
add_custom_command(TARGET onnxruntime-genai-jni POST_BUILD
107-
COMMAND ${CMAKE_COMMAND} -E copy_if_different
108-
$<TARGET_FILE:onnxruntime-genai>
107+
COMMAND ${CMAKE_COMMAND} -E copy_if_different
108+
$<TARGET_FILE:onnxruntime-genai>
109109
${JAVA_PACKAGE_LIB_DIR}/$<TARGET_FILE_NAME:onnxruntime-genai>)
110110

111111
# Add the JNI bindings to the native-jni dir
112112
add_custom_command(TARGET onnxruntime-genai-jni POST_BUILD
113-
COMMAND ${CMAKE_COMMAND} -E copy_if_different
113+
COMMAND ${CMAKE_COMMAND} -E copy_if_different
114114
$<TARGET_FILE:onnxruntime-genai-jni>
115115
${JAVA_PACKAGE_LIB_DIR}/$<TARGET_FILE_NAME:onnxruntime-genai-jni>)
116116

@@ -140,21 +140,21 @@ if (ANDROID)
140140
file(MAKE_DIRECTORY ${ANDROID_PACKAGE_HEADERS_DIR})
141141
file(MAKE_DIRECTORY ${ANDROID_PACKAGE_ABI_DIR})
142142

143-
# copy C/C++ API headers to be packed into Android AAR package
144-
add_custom_command(TARGET onnxruntime-genai-jni POST_BUILD
143+
# copy C/C++ API headers to be packed into Android AAR package
144+
add_custom_command(TARGET onnxruntime-genai-jni POST_BUILD
145145
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${SRC_ROOT}/ort_genai.h ${ANDROID_PACKAGE_HEADERS_DIR})
146-
add_custom_command(TARGET onnxruntime-genai-jni POST_BUILD
146+
add_custom_command(TARGET onnxruntime-genai-jni POST_BUILD
147147
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${SRC_ROOT}/ort_genai_c.h ${ANDROID_PACKAGE_HEADERS_DIR})
148148

149149
# Copy onnxruntime-genai.so and onnxruntime-genai-jni.so for building Android AAR package
150150
add_custom_command(TARGET onnxruntime-genai-jni POST_BUILD
151-
COMMAND ${CMAKE_COMMAND} -E copy_if_different
151+
COMMAND ${CMAKE_COMMAND} -E copy_if_different
152152
$<TARGET_FILE:onnxruntime-genai>
153153
${ANDROID_PACKAGE_ABI_DIR}/$<TARGET_LINKER_FILE_NAME:onnxruntime-genai>)
154154

155155
add_custom_command(TARGET onnxruntime-genai-jni POST_BUILD
156-
COMMAND ${CMAKE_COMMAND} -E copy_if_different
157-
$<TARGET_FILE:onnxruntime-genai-jni>
156+
COMMAND ${CMAKE_COMMAND} -E copy_if_different
157+
$<TARGET_FILE:onnxruntime-genai-jni>
158158
${ANDROID_PACKAGE_ABI_DIR}/$<TARGET_LINKER_FILE_NAME:onnxruntime-genai-jni>)
159159

160160
# Generate the Android AAR package
@@ -176,20 +176,20 @@ if (ANDROID)
176176
file(GLOB android_test_files "${ANDROID_TEST_SRC_ROOT}/*")
177177
file(COPY ${android_test_files} DESTINATION ${ANDROID_TEST_PACKAGE_DIR})
178178

179-
set(ANDROID_TEST_PACKAGE_LIB_DIR ${ANDROID_TEST_PACKAGE_DIR}/app/libs)
179+
set(ANDROID_TEST_PACKAGE_LIB_DIR ${ANDROID_TEST_PACKAGE_DIR}/app/libs)
180180
set(ANDROID_TEST_PACKAGE_APP_ASSETS_DIR ${ANDROID_TEST_PACKAGE_DIR}/app/src/main/assets)
181181
file(MAKE_DIRECTORY ${ANDROID_TEST_PACKAGE_LIB_DIR})
182182
file(MAKE_DIRECTORY ${ANDROID_TEST_PACKAGE_APP_ASSETS_DIR})
183183

184184
# Copy the test model to the assets folder in the test app
185185
add_custom_command(TARGET onnxruntime-genai-jni POST_BUILD
186-
COMMAND ${CMAKE_COMMAND} -E copy_directory_if_different
186+
COMMAND ${CMAKE_COMMAND} -E copy_directory_if_different
187187
${REPO_ROOT}/test/test_models/hf-internal-testing/tiny-random-gpt2-fp32
188188
${ANDROID_TEST_PACKAGE_APP_ASSETS_DIR}/model)
189189

190190
# Copy the Android AAR package we built to the libs folder of our test app
191191
add_custom_command(TARGET onnxruntime-genai-jni POST_BUILD
192-
COMMAND ${CMAKE_COMMAND} -E copy_if_different
192+
COMMAND ${CMAKE_COMMAND} -E copy_if_different
193193
${ANDROID_PACKAGE_OUTPUT_DIR}/outputs/aar/onnxruntime-genai-debug.aar
194194
${ANDROID_TEST_PACKAGE_LIB_DIR}/onnxruntime-genai.aar)
195195

@@ -207,19 +207,38 @@ if (ENABLE_TESTS)
207207
# On windows ctest requires a test to be an .exe(.com) file
208208
# With gradle wrapper we get gradlew.bat. We delegate execution to a separate .cmake file
209209
# That can handle both .exe and .bat
210-
add_test(NAME onnxruntime-genai4j_test
211-
COMMAND ${CMAKE_COMMAND}
212-
-DGRADLE_EXECUTABLE=${GRADLE_EXECUTABLE}
213-
-DBIN_DIR=${JAVA_OUTPUT_DIR}
210+
add_test(NAME onnxruntime-genai4j_test
211+
COMMAND ${CMAKE_COMMAND}
212+
-DGRADLE_EXECUTABLE=${GRADLE_EXECUTABLE}
213+
-DBIN_DIR=${JAVA_OUTPUT_DIR}
214214
-DJAVA_SRC_ROOT=${JAVA_SRC_ROOT}
215215
-DJAVA_PACKAGE_LIB_DIR=${JAVA_PACKAGE_LIB_DIR}
216216
-P ${JAVA_SRC_ROOT}/windows-unittests.cmake)
217217
else()
218-
add_test(NAME onnxruntime-genai4j_test
219-
COMMAND ${GRADLE_EXECUTABLE} cmakeCheck
218+
add_test(NAME onnxruntime-genai4j_test
219+
COMMAND ${GRADLE_EXECUTABLE} cmakeCheck
220220
-DcmakeBuildDir=${JAVA_OUTPUT_DIR} -DnativeLibDir=${JAVA_PACKAGE_LIB_DIR}
221221
WORKING_DIRECTORY ${JAVA_SRC_ROOT})
222222
endif()
223223

224+
if(WIN32)
225+
set(ONNXRUNTIME_GENAI_DEPENDENCY "*.dll")
226+
elseif(APPLE)
227+
set(ONNXRUNTIME_GENAI_DEPENDENCY "*.dylib")
228+
else()
229+
set(ONNXRUNTIME_GENAI_DEPENDENCY "*.so")
230+
endif()
231+
232+
file(GLOB ort_native_libs "${ORT_LIB_DIR}/${ONNXRUNTIME_GENAI_DEPENDENCY}")
233+
234+
# Copy ORT native libs for Java tests
235+
foreach(LIB_FILE ${ort_native_libs})
236+
add_custom_command(
237+
TARGET onnxruntime-genai-jni POST_BUILD
238+
COMMAND ${CMAKE_COMMAND} -E copy
239+
${LIB_FILE}
240+
${JAVA_PACKAGE_LIB_DIR}/)
241+
endforeach()
242+
224243
set_property(TEST onnxruntime-genai4j_test APPEND PROPERTY DEPENDS onnxruntime-genai-jni)
225244
endif()

src/java/build-android.gradle

+1
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@ artifacts {
119119

120120
dependencies {
121121
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.7.0'
122+
testImplementation 'org.junit.platform:junit-platform-launcher:1.10.1'
122123
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.7.0'
123124
}
124125

src/java/build.gradle

+1
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,7 @@ if (cmakeNativeLibDir != null) {
153153

154154
dependencies {
155155
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.9.2'
156+
testImplementation 'org.junit.platform:junit-platform-launcher:1.10.1'
156157
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.9.2'
157158
}
158159

0 commit comments

Comments
 (0)