Initial Java API for the JAR package. (#292)
* more C++ code fixing and polish for release * fixing for android build * build flags for android release * add missing exporting function * imint * first versoin * more C++ code fixing and polish for release (#275) * more C++ code fixing and polish for release * fixing for android build * build flags for android release * add missing exporting function * support build_id on Python package building (#281) * support buildid in package building * undo the change on build.sh * build.sh issue on macos * Add `$schema` to `cgmanifest.json` (#284) Co-authored-by: Jamie Magee <jamie.magee@microsoft.com> * test package with a simple java app * demo app * some fixing for windows platform * refine the example app * fix the missing symobls issue for Linux build * fix the package package build issue * typo * a missing change * fix PythonOp * fix Android test issue * one more Android change * replace build flags in ci pipeline * android AAR package build * refine the code for android package Co-authored-by: Jamie Magee <jamie.magee@gmail.com> Co-authored-by: Jamie Magee <jamie.magee@microsoft.com>
This commit is contained in:
Родитель
12392c9863
Коммит
08659eae90
|
@ -360,7 +360,7 @@ jobs:
|
|||
sh ./build.sh \
|
||||
-DCMAKE_TOOLCHAIN_FILE=$(Build.BinariesDirectory)/emsdk/upstream/emscripten/cmake/Modules/Platform/Emscripten.cmake \
|
||||
-DOCOS_ENABLE_SPM_TOKENIZER=ON \
|
||||
-DOCOS_ENABLE_PYTHON=OFF \
|
||||
-DOCOS_BUILD_PYTHON=OFF \
|
||||
-DOCOS_ENABLE_OPENCV=OFF
|
||||
displayName: build the customop library with onnxruntime
|
||||
# TODO add unittest for webassembly
|
||||
|
@ -425,13 +425,13 @@ jobs:
|
|||
workingDirectory: $(OnnxruntimeDirectory)
|
||||
|
||||
- script: |
|
||||
adb push out/Darwin/RelWithDebInfo/lib/libortcustomops.so /data/local/tmp
|
||||
adb push out/Darwin/RelWithDebInfo/lib/libortextensions.so /data/local/tmp
|
||||
adb push out/Darwin/RelWithDebInfo/data /data/local/tmp
|
||||
adb push out/Darwin/RelWithDebInfo/bin/operators_test /data/local/tmp
|
||||
adb push out/Darwin/RelWithDebInfo/bin/ortcustomops_test /data/local/tmp
|
||||
adb push out/Darwin/RelWithDebInfo/bin/ocos_test /data/local/tmp
|
||||
adb push out/Darwin/RelWithDebInfo/bin/extensions_test /data/local/tmp
|
||||
adb push $(OnnxruntimeDirectory)/build/Release/libonnxruntime.so /data/local/tmp
|
||||
adb shell 'cd /data/local/tmp/ && chmod a+x operators_test'
|
||||
adb shell 'cd /data/local/tmp/ && chmod a+x ortcustomops_test'
|
||||
adb shell 'cd /data/local/tmp/ && export LD_LIBRARY_PATH=$(pwd) && ./operators_test' && adb shell 'cd /data/local/tmp/ && export LD_LIBRARY_PATH=$(pwd) && ./ortcustomops_test'
|
||||
adb shell 'cd /data/local/tmp/ && chmod a+x ocos_test'
|
||||
adb shell 'cd /data/local/tmp/ && chmod a+x extensions_test'
|
||||
adb shell 'cd /data/local/tmp/ && export LD_LIBRARY_PATH=$(pwd) && ./ocos_test' && adb shell 'cd /data/local/tmp/ && export LD_LIBRARY_PATH=$(pwd) && ./extensions_test'
|
||||
displayName: Run Android test
|
||||
workingDirectory: $(Build.sourcesdirectory)
|
||||
|
|
|
@ -5,6 +5,7 @@ build_host_protoc
|
|||
build_android
|
||||
build_ios
|
||||
build_*
|
||||
.version.txt
|
||||
.venv/
|
||||
_subbuild/
|
||||
.build_debug/*
|
||||
|
@ -38,7 +39,15 @@ out/
|
|||
onnxruntime-*-*-*/
|
||||
temp_*.onnx
|
||||
test/data/*.py
|
||||
|
||||
# Java specific ignores
|
||||
java/gradlew
|
||||
java/gradlew.bat
|
||||
java/gradle
|
||||
java/.gradle
|
||||
java/hs_*.log
|
||||
*.class
|
||||
tutorials/demo4j/app/bin/
|
||||
tutorials/demo4j/app/libs
|
||||
# Compiled Dynamic libraries
|
||||
*.so
|
||||
*.dylib
|
||||
|
|
|
@ -99,7 +99,7 @@ extends:
|
|||
- task: SDLNativeRules@3
|
||||
inputs:
|
||||
msBuildArchitecture: amd64
|
||||
setupCommandlines: '"$(vscmake)" $(REPOROOT) -A x64 -B $(REPOROOT)\windows_out -DOCOS_ENABLE_PYTHON=ON -DOCOS_ENABLE_CTEST=OFF -DCMAKE_BUILD_TYPE=Release'
|
||||
setupCommandlines: '"$(vscmake)" $(REPOROOT) -A x64 -B $(REPOROOT)\windows_out -DOCOS_BUILD_PYTHON=ON -DOCOS_ENABLE_CTEST=OFF -DCMAKE_BUILD_TYPE=Release'
|
||||
msBuildCommandline: '"$(vsmsbuild)" "$(REPOROOT)\windows_out\onnxruntime_extensions.sln" /p:RunCodeAnalysis=true /p:platform=x64 /p:configuration=Release /p:VisualStudioVersion="16.0" /m /p:PreferredToolArchitecture=x64'
|
||||
excludedPaths: '$(REPOROOT)\windows_out#$(Build.SourcesDirectory)\cmake#C:\program files (x86)'
|
||||
displayName: 'Run the PREfast SDL Native Rules for MSBuild'
|
||||
|
|
|
@ -99,7 +99,7 @@ extends:
|
|||
- task: SDLNativeRules@3
|
||||
inputs:
|
||||
msBuildArchitecture: amd64
|
||||
setupCommandlines: '"$(vscmake)" $(REPOROOT) -A x64 -B $(REPOROOT)\windows_out -DOCOS_ENABLE_PYTHON=ON -DOCOS_ENABLE_CTEST=OFF -DCMAKE_BUILD_TYPE=Release'
|
||||
setupCommandlines: '"$(vscmake)" $(REPOROOT) -A x64 -B $(REPOROOT)\windows_out -DOCOS_BUILD_PYTHON=ON -DOCOS_ENABLE_CTEST=OFF -DCMAKE_BUILD_TYPE=Release'
|
||||
msBuildCommandline: '"$(vsmsbuild)" "$(REPOROOT)\windows_out\onnxruntime_extensions.sln" /p:RunCodeAnalysis=true /p:platform=x64 /p:configuration=Release /p:VisualStudioVersion="16.0" /m /p:PreferredToolArchitecture=x64'
|
||||
excludedPaths: '$(REPOROOT)\windows_out#$(Build.SourcesDirectory)\cmake#C:\program files (x86)'
|
||||
displayName: 'Run the PREfast SDL Native Rules for MSBuild'
|
||||
|
|
146
CMakeLists.txt
146
CMakeLists.txt
|
@ -13,7 +13,10 @@ set(CPACK_PACKAGE_VERSION_MAJOR "0")
|
|||
set(CPACK_PACKAGE_VERSION_MINOR "5")
|
||||
set(CPACK_PACKAGE_VERSION_PATCH "0")
|
||||
set(VERSION ${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH})
|
||||
file(WRITE ${PROJECT_SOURCE_DIR}/.version.txt ${VERSION})
|
||||
|
||||
# Needed for Java
|
||||
set(CMAKE_C_STANDARD 99)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
@ -22,7 +25,7 @@ include(CheckCXXCompilerFlag)
|
|||
include(CheckLanguage)
|
||||
|
||||
option(CC_OPTIMIZE "Allow compiler optimizations, Set to OFF to disable" ON)
|
||||
option(OCOS_ENABLE_PYTHON "Enable Python component building" OFF)
|
||||
option(OCOS_ENABLE_PYTHON "Enable Python component building, (deprecated)" OFF)
|
||||
option(OCOS_ENABLE_CTEST "Enable C++ test" OFF)
|
||||
option(OCOS_ENABLE_CPP_EXCEPTIONS "Enable C++ Exception" ON)
|
||||
option(OCOS_ENABLE_TF_STRING "Enable String Operator Set" ON)
|
||||
|
@ -38,7 +41,9 @@ option(OCOS_ENABLE_OPENCV "Enable operators depending on opencv" ON)
|
|||
option(OCOS_ENABLE_OPENCV_CODECS "Enable operators depending on opencv imgcodecs" ON)
|
||||
option(OCOS_ENABLE_STATIC_LIB "Enable generating static library" OFF)
|
||||
option(OCOS_ENABLE_SELECTED_OPLIST "Enable including the selected_ops tool file" OFF)
|
||||
|
||||
option(OCOS_BUILD_PYTHON "Enable building the Python package" OFF)
|
||||
option(OCOS_BUILD_JAVA "Enable building the Java package" OFF)
|
||||
option(OCOS_BUILD_ANDROID "Enable building the Android package" OFF)
|
||||
|
||||
function(disable_all_operators)
|
||||
set(OCOS_ENABLE_RE2_REGEX OFF CACHE INTERNAL "")
|
||||
|
@ -69,6 +74,18 @@ if(NOT CC_OPTIMIZE)
|
|||
endif()
|
||||
endif()
|
||||
|
||||
if (NOT OCOS_BUILD_PYTHON AND OCOS_ENABLE_PYTHON)
|
||||
message("OCOS_ENABLE_PYTHON IS DEPRECATED, USE OCOS_BUILD_PYTHON INSTEAD")
|
||||
set(OCOS_BUILD_PYTHON ON CACHE INTERNAL "")
|
||||
endif()
|
||||
|
||||
if (OCOS_BUILD_ANDROID)
|
||||
if (NOT ANDROID_SDK_ROOT OR NOT CMAKE_ANDROID_NDK)
|
||||
message("Cannot the find Android SDK/NDK")
|
||||
endif()
|
||||
set(OCOS_BUILD_JAVA ON CACHE INTERNAL "")
|
||||
endif()
|
||||
|
||||
# Build the libraries with -fPIC
|
||||
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
|
||||
|
||||
|
@ -305,30 +322,9 @@ list(REMOVE_DUPLICATES OCOS_COMPILE_DEFINITIONS)
|
|||
target_compile_definitions(ocos_operators PRIVATE ${OCOS_COMPILE_DEFINITIONS})
|
||||
target_link_libraries(ocos_operators PRIVATE ${ocos_libraries})
|
||||
|
||||
file(GLOB shared_TARGET_SRC "shared/*.cc" "shared/*.h")
|
||||
if(OCOS_ENABLE_PYTHON)
|
||||
set(Python3_FIND_REGISTRY NEVER CACHE STRING "...")
|
||||
if(NOT "${Python3_FIND_REGISTRY}" STREQUAL "NEVER")
|
||||
message(FATAL_ERROR "Python3_FIND_REGISTRY is not NEVER")
|
||||
endif()
|
||||
find_package(Python3 COMPONENTS Interpreter Development.Module NumPy)
|
||||
if (NOT Python3_FOUND)
|
||||
message(FATAL_ERROR "Python3 or NumPy not found!")
|
||||
endif()
|
||||
if (WIN32)
|
||||
list(APPEND shared_TARGET_SRC "${PROJECT_SOURCE_DIR}/onnxruntime_extensions/ortcustomops.def")
|
||||
endif()
|
||||
|
||||
file(GLOB TARGET_SRC_PYOPS "pyop/*.cc" "pyop/*.h")
|
||||
add_library(ortcustomops SHARED ${TARGET_SRC_PYOPS} ${shared_TARGET_SRC})
|
||||
standardize_output_folder(ortcustomops)
|
||||
list(APPEND OCOS_COMPILE_DEFINITIONS PYTHON_OP_SUPPORT)
|
||||
# building static lib has higher priority
|
||||
elseif(OCOS_ENABLE_STATIC_LIB)
|
||||
add_library(ortcustomops STATIC ${shared_TARGET_SRC})
|
||||
add_library(onnxruntime_extensions ALIAS ortcustomops)
|
||||
elseif(CMAKE_SYSTEM_NAME STREQUAL "Emscripten")
|
||||
add_executable(ortcustomops ${shared_TARGET_SRC})
|
||||
file(GLOB shared_TARGET_LIB_SRC "shared/lib/*.cc" "shared/lib/*.h")
|
||||
if(CMAKE_SYSTEM_NAME STREQUAL "Emscripten")
|
||||
add_executable(ortcustomops ${shared_TARGET_LIB_SRC})
|
||||
set_target_properties(ortcustomops PROPERTIES LINK_FLAGS " \
|
||||
-s WASM=1 \
|
||||
-s NO_EXIT_RUNTIME=0 \
|
||||
|
@ -346,42 +342,43 @@ elseif(CMAKE_SYSTEM_NAME STREQUAL "Emscripten")
|
|||
set_property(TARGET ortcustomops APPEND_STRING PROPERTY LINK_FLAGS " -s ASSERTIONS=0 -s DEMANGLE_SUPPORT=0")
|
||||
endif()
|
||||
else()
|
||||
list(APPEND shared_TARGET_SRC "${PROJECT_SOURCE_DIR}/shared/ortcustomops.def")
|
||||
add_library(ortcustomops SHARED ${shared_TARGET_SRC})
|
||||
if (CMAKE_SYSTEM_NAME STREQUAL "Android")
|
||||
if (OCOS_ENABLE_SPM_TOKENIZER)
|
||||
target_link_libraries(ortcustomops PUBLIC log)
|
||||
set_property(TARGET ortcustomops APPEND_STRING PROPERTY LINK_FLAGS "-Wl,-s -Wl,--version-script -Wl,${PROJECT_SOURCE_DIR}/shared/ortcustomops.ver")
|
||||
endif()
|
||||
endif()
|
||||
add_library(ortcustomops STATIC ${shared_TARGET_LIB_SRC})
|
||||
add_library(onnxruntime_extensions ALIAS ortcustomops)
|
||||
standardize_output_folder(ortcustomops)
|
||||
set(_BUILD_SHARED_LIBRARY TRUE)
|
||||
endif()
|
||||
|
||||
target_compile_definitions(ortcustomops PRIVATE ${OCOS_COMPILE_DEFINITIONS} ${GTEST_CXX_FLAGS})
|
||||
target_compile_definitions(ortcustomops PUBLIC ${OCOS_COMPILE_DEFINITIONS} ${GTEST_CXX_FLAGS})
|
||||
target_include_directories(ortcustomops PUBLIC
|
||||
"$<TARGET_PROPERTY:ocos_operators,INTERFACE_INCLUDE_DIRECTORIES>")
|
||||
target_link_libraries(ortcustomops PUBLIC ocos_operators)
|
||||
|
||||
if(OCOS_ENABLE_PYTHON)
|
||||
message(STATUS "Fetch pybind11")
|
||||
include(pybind11)
|
||||
target_include_directories(ortcustomops PRIVATE
|
||||
$<TARGET_PROPERTY:Python3::Module,INTERFACE_INCLUDE_DIRECTORIES>
|
||||
$<TARGET_PROPERTY:Python3::NumPy,INTERFACE_INCLUDE_DIRECTORIES>
|
||||
${pybind11_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
target_compile_definitions(ortcustomops PRIVATE
|
||||
$<TARGET_PROPERTY:Python3::Module,INTERFACE_COMPILE_DEFINITIONS>)
|
||||
|
||||
target_link_libraries(ortcustomops PRIVATE Python3::Module)
|
||||
|
||||
if(NOT "${OCOS_EXTENTION_NAME}" STREQUAL "")
|
||||
if(NOT WIN32)
|
||||
set_target_properties(ortcustomops PROPERTIES
|
||||
LIBRARY_OUTPUT_NAME ${OCOS_EXTENTION_NAME}
|
||||
PREFIX ""
|
||||
SUFFIX "")
|
||||
if (_BUILD_SHARED_LIBRARY)
|
||||
file(GLOB shared_TARGET_SRC "shared/*.cc" "shared/*.h" "shared/*.def")
|
||||
add_library(extensions_shared SHARED ${shared_TARGET_SRC})
|
||||
standardize_output_folder(extensions_shared)
|
||||
if (CMAKE_SYSTEM_NAME STREQUAL "Android")
|
||||
if (OCOS_ENABLE_SPM_TOKENIZER)
|
||||
target_link_libraries(extensions_shared PUBLIC log)
|
||||
endif()
|
||||
endif()
|
||||
if (LINUX OR CMAKE_SYSTEM_NAME STREQUAL "Android")
|
||||
set_property(TARGET extensions_shared APPEND_STRING PROPERTY LINK_FLAGS "-Wl,-s -Wl,--version-script -Wl,${PROJECT_SOURCE_DIR}/shared/ortcustomops.ver")
|
||||
endif()
|
||||
target_include_directories(extensions_shared PUBLIC
|
||||
"$<TARGET_PROPERTY:ortcustomops,INTERFACE_INCLUDE_DIRECTORIES>")
|
||||
target_link_libraries(extensions_shared PRIVATE ortcustomops)
|
||||
set_target_properties(extensions_shared PROPERTIES OUTPUT_NAME "ortextensions")
|
||||
endif()
|
||||
|
||||
if(OCOS_BUILD_PYTHON)
|
||||
message(STATUS "Python Build is enabled")
|
||||
include(ext_python)
|
||||
endif()
|
||||
|
||||
if(OCOS_BUILD_JAVA)
|
||||
message(STATUS "Java Build is enabled")
|
||||
include(ext_java)
|
||||
endif()
|
||||
|
||||
# clean up the requirements.txt files from 3rd party project folder to suppress the code security false alarms
|
||||
|
@ -399,12 +396,6 @@ endforeach()
|
|||
# test section
|
||||
if (OCOS_ENABLE_CTEST)
|
||||
# Enable CTest
|
||||
SET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY BOTH)
|
||||
find_library(ONNXRUNTIME onnxruntime HINTS "${ONNXRUNTIME_LIB_DIR}")
|
||||
if (NOT ONNXRUNTIME)
|
||||
message(FATAL_ERROR "The ctest needs the prebuilt onnxruntime libraries directory, please specify it by ONNXRUNTIME_LIB_DIR.")
|
||||
endif()
|
||||
|
||||
enable_testing()
|
||||
message(STATUS "Fetch CTest")
|
||||
include(CTest)
|
||||
|
@ -413,11 +404,17 @@ if (OCOS_ENABLE_CTEST)
|
|||
message(STATUS "Fetch googletest")
|
||||
include(googletest)
|
||||
file(GLOB static_TEST_SRC "${TEST_SRC_DIR}/static_test/*.cc")
|
||||
add_executable(operators_test ${static_TEST_SRC})
|
||||
standardize_output_folder(operators_test)
|
||||
target_link_libraries(operators_test PRIVATE gtest_main ocos_operators ${ocos_libraries})
|
||||
add_test(NAME operators_test COMMAND $<TARGET_FILE:operators_test>)
|
||||
add_executable(ocos_test ${static_TEST_SRC})
|
||||
standardize_output_folder(ocos_test)
|
||||
target_link_libraries(ocos_test PRIVATE gtest_main ocos_operators ${ocos_libraries})
|
||||
add_test(NAME ocos_test COMMAND $<TARGET_FILE:ocos_test>)
|
||||
|
||||
|
||||
SET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY BOTH)
|
||||
find_library(ONNXRUNTIME onnxruntime HINTS "${ONNXRUNTIME_LIB_DIR}")
|
||||
if (ONNXRUNTIME-NOTFOUND)
|
||||
message(WARNING "The prebuilt onnxruntime libraries directory cannot found (via ONNXRUNTIME_LIB_DIR), the extensions_test will be skipped.")
|
||||
else()
|
||||
set(LINUX_CC_FLAGS "")
|
||||
# needs to link with stdc++fs in Linux
|
||||
if(UNIX AND NOT APPLE AND NOT CMAKE_SYSTEM_NAME STREQUAL "Android")
|
||||
|
@ -425,18 +422,20 @@ if (OCOS_ENABLE_CTEST)
|
|||
endif()
|
||||
|
||||
file(GLOB shared_TEST_SRC "${TEST_SRC_DIR}/shared_test/*.cc")
|
||||
add_executable(ortcustomops_test ${shared_TEST_SRC})
|
||||
standardize_output_folder(ortcustomops_test)
|
||||
add_executable(extensions_test ${shared_TEST_SRC})
|
||||
standardize_output_folder(extensions_test)
|
||||
target_include_directories(extensions_test PRIVATE ${spm_INCLUDE_DIRS}
|
||||
"$<TARGET_PROPERTY:extensions_shared,INTERFACE_INCLUDE_DIRECTORIES>")
|
||||
if (ONNXRUNTIME_LIB_DIR)
|
||||
target_link_directories(ortcustomops_test PRIVATE ${ONNXRUNTIME_LIB_DIR})
|
||||
target_link_directories(extensions_test PRIVATE ${ONNXRUNTIME_LIB_DIR})
|
||||
endif()
|
||||
target_link_libraries(ortcustomops_test PRIVATE ortcustomops onnxruntime gtest_main ${ocos_libraries} ${LINUX_CC_FLAGS})
|
||||
target_link_libraries(extensions_test PRIVATE ocos_operators extensions_shared onnxruntime gtest_main ${ocos_libraries} ${LINUX_CC_FLAGS})
|
||||
if (WIN32)
|
||||
file(TO_CMAKE_PATH "${ONNXRUNTIME_LIB_DIR}/*" ONNXRUNTIME_LIB_FILEPATTERN)
|
||||
file(GLOB ONNXRUNTIME_LIB_FILES CONFIGURE_DEPENDS "${ONNXRUNTIME_LIB_FILEPATTERN}")
|
||||
add_custom_command(
|
||||
TARGET ortcustomops_test POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${ONNXRUNTIME_LIB_FILES} $<TARGET_FILE_DIR:ortcustomops_test>)
|
||||
TARGET extensions_test POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${ONNXRUNTIME_LIB_FILES} $<TARGET_FILE_DIR:extensions_test>)
|
||||
endif()
|
||||
|
||||
set(TEST_DATA_SRC ${TEST_SRC_DIR}/data)
|
||||
|
@ -444,9 +443,10 @@ if (OCOS_ENABLE_CTEST)
|
|||
|
||||
# Copy test data from source to destination.
|
||||
add_custom_command(
|
||||
TARGET ortcustomops_test POST_BUILD
|
||||
TARGET extensions_test POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_directory
|
||||
${TEST_DATA_SRC}
|
||||
${TEST_DATA_DES})
|
||||
add_test(NAME ortcustomops_test COMMAND $<TARGET_FILE:ortcustomops_test>)
|
||||
add_test(NAME extensions_test COMMAND $<TARGET_FILE:extensions_test>)
|
||||
endif()
|
||||
endif()
|
||||
|
|
|
@ -1,22 +1,27 @@
|
|||
#!/bin/bash
|
||||
|
||||
# The example file on building the static library for android
|
||||
# The example build file on building Android package.
|
||||
set -e -x -u
|
||||
|
||||
OSNAME=android
|
||||
if [[ -z ${NDK_ROOT+x} ]]; then NDK_ROOT=`ls -d $HOME/Android/Sdk/ndk/* 2>/dev/null`; fi
|
||||
if [[ -z ${NDK_ROOT+x} ]]; then NDK_ROOT=`ls -Ad $HOME/Android/Sdk/ndk/* 2>/dev/null | head -1`; fi
|
||||
if [[ -z "${NDK_ROOT}" ]]
|
||||
then
|
||||
echo "ERROR: cannot find where NDK was installed, using NDK_ROOT to specify it"
|
||||
exit 7
|
||||
fi
|
||||
|
||||
if [[ -z ${ANDROID_SDK_ROOT+x} ]]; then
|
||||
export ANDROID_SDK_ROOT=$(dirname $(dirname ${NDK_ROOT}))
|
||||
fi
|
||||
mkdir -p out/$OSNAME/Release && cd out/$OSNAME/Release
|
||||
|
||||
# ANDROID_ABI would be armeabi-v7a arm64-v8a x86 x86_64
|
||||
# ANDROID_PLATFORM, the minimum level is 24, i.e., due to
|
||||
# the great change of file system permission in Android 7
|
||||
cmake "$@" \
|
||||
-DCMAKE_TOOLCHAIN_FILE=${NDK_ROOT}/build/cmake/android.toolchain.cmake \
|
||||
-DANDROID_NDK=${NDK_ROOT} \
|
||||
-DANDROID_ABI=armeabi-v7a \
|
||||
-DANDROID_PLATFORM=android-19 \
|
||||
-DOCOS_ENABLE_SPM_TOKENIZER=ON \
|
||||
-DANDROID_PLATFORM=android-24 \
|
||||
-DOCOS_BUILD_ANDROID=ON \
|
||||
../../.. && cmake --build . --config Release --parallel
|
||||
|
|
|
@ -3,7 +3,7 @@ SETLOCAL ENABLEDELAYEDEXPANSION
|
|||
IF DEFINED VSINSTALLDIR GOTO :VSDEV_CMD
|
||||
IF NOT DEFINED VCVARS GOTO :NOT_FOUND
|
||||
|
||||
CALL %VCVARS%
|
||||
CALL "%VCVARS%"
|
||||
|
||||
:VSDEV_CMD
|
||||
set GENERATOR="Visual Studio 16 2019"
|
||||
|
|
|
@ -0,0 +1,193 @@
|
|||
include(FindJava)
|
||||
find_package(Java REQUIRED)
|
||||
include(UseJava)
|
||||
if (NOT CMAKE_SYSTEM_NAME STREQUAL "Android")
|
||||
find_package(JNI REQUIRED)
|
||||
endif()
|
||||
|
||||
set(JAVA_ROOT ${PROJECT_SOURCE_DIR}/java)
|
||||
set(JAVA_OUTPUT_TEMP ${CMAKE_CURRENT_BINARY_DIR}/java-temp)
|
||||
set(JAVA_OUTPUT_DIR ${CMAKE_CURRENT_BINARY_DIR}/java)
|
||||
|
||||
# use the gradle wrapper if it exists
|
||||
if(EXISTS "${JAVA_ROOT}/gradlew")
|
||||
set(GRADLE_EXECUTABLE "${JAVA_ROOT}/gradlew")
|
||||
else()
|
||||
# fall back to gradle on our PATH
|
||||
find_program(GRADLE_EXECUTABLE gradle)
|
||||
if(NOT GRADLE_EXECUTABLE)
|
||||
message(SEND_ERROR "Gradle installation not found")
|
||||
endif()
|
||||
endif()
|
||||
message(STATUS "Using gradle: ${GRADLE_EXECUTABLE}")
|
||||
|
||||
# Specify the Java source files
|
||||
file(GLOB_RECURSE onnxruntime_extensions4j_gradle_files "${JAVA_ROOT}/*.gradle")
|
||||
file(GLOB_RECURSE onnxruntime_extensions4j_src "${JAVA_ROOT}/src/main/java/ai/onnxruntime/extensions/*.java")
|
||||
set(JAVA_OUTPUT_JAR ${JAVA_OUTPUT_TEMP}/build/libs/onnxruntime_extensions.jar)
|
||||
# this jar is solely used to signaling mechanism for dependency management in CMake
|
||||
# if any of the Java sources change, the jar (and generated headers) will be regenerated and the onnxruntime_extensions4j_jni target will be rebuilt
|
||||
set(GRADLE_ARGS --console=plain clean jar -p ${JAVA_ROOT} -x test )
|
||||
if(WIN32)
|
||||
set(GRADLE_ARGS ${GRADLE_ARGS} -Dorg.gradle.daemon=false)
|
||||
elseif (CMAKE_SYSTEM_NAME STREQUAL "Android")
|
||||
# For Android build, we may run gradle multiple times in same build,
|
||||
# sometimes gradle JVM will run out of memory if we keep the daemon running
|
||||
# it is better to not keep a daemon running
|
||||
set(GRADLE_ARGS ${GRADLE_ARGS} --no-daemon)
|
||||
endif()
|
||||
|
||||
file(MAKE_DIRECTORY ${JAVA_OUTPUT_TEMP})
|
||||
add_custom_command(OUTPUT ${JAVA_OUTPUT_JAR} COMMAND ${GRADLE_EXECUTABLE} ${GRADLE_ARGS} WORKING_DIRECTORY ${JAVA_OUTPUT_TEMP} DEPENDS ${onnxruntime_extensions4j_gradle_files} ${onnxruntime_extensions4j_src})
|
||||
add_custom_target(onnxruntime_extensions4j DEPENDS ${JAVA_OUTPUT_JAR})
|
||||
set_source_files_properties(${JAVA_OUTPUT_JAR} PROPERTIES GENERATED TRUE)
|
||||
set_property(TARGET onnxruntime_extensions4j APPEND PROPERTY ADDITIONAL_CLEAN_FILES "${JAVA_OUTPUT_DIR}")
|
||||
|
||||
# Specify the native sources
|
||||
file(GLOB onnxruntime_extensions4j_native_src
|
||||
"${JAVA_ROOT}/src/main/native/*.c"
|
||||
"${JAVA_ROOT}/src/main/native/*.h"
|
||||
"${PROJECT_SOURCE_DIR}/include/*.h"
|
||||
)
|
||||
# Build the JNI library
|
||||
add_library(onnxruntime_extensions4j_jni SHARED ${onnxruntime_extensions4j_native_src})
|
||||
|
||||
# depend on java sources. if they change, the JNI should recompile
|
||||
add_dependencies(onnxruntime_extensions4j_jni onnxruntime_extensions4j)
|
||||
target_include_directories(onnxruntime_extensions4j_jni PRIVATE ortcustomops)
|
||||
# the JNI headers are generated in the onnxruntime_extensions4j target
|
||||
target_include_directories(onnxruntime_extensions4j_jni PRIVATE ${JAVA_ROOT}/build/headers ${JNI_INCLUDE_DIRS})
|
||||
target_link_libraries(onnxruntime_extensions4j_jni PRIVATE ortcustomops)
|
||||
standardize_output_folder(onnxruntime_extensions4j_jni)
|
||||
|
||||
set(JAVA_PACKAGE_OUTPUT_DIR ${JAVA_OUTPUT_DIR}/build)
|
||||
file(MAKE_DIRECTORY ${JAVA_PACKAGE_OUTPUT_DIR})
|
||||
if (CMAKE_SYSTEM_NAME STREQUAL "Android")
|
||||
set(ANDROID_PACKAGE_OUTPUT_DIR ${JAVA_PACKAGE_OUTPUT_DIR}/android)
|
||||
file(MAKE_DIRECTORY ${ANDROID_PACKAGE_OUTPUT_DIR})
|
||||
endif()
|
||||
|
||||
if (CMAKE_SYSTEM_NAME STREQUAL "Android")
|
||||
if (OCOS_ENABLE_SPM_TOKENIZER)
|
||||
target_link_libraries(onnxruntime_extensions4j_jni PUBLIC log)
|
||||
endif()
|
||||
endif()
|
||||
# Set platform and arch for packaging
|
||||
# Checks the names set by MLAS on non-Windows platforms first
|
||||
if(APPLE)
|
||||
get_target_property(ONNXRUNTIME4J_OSX_ARCH onnxruntime_extensions4j_jni OSX_ARCHITECTURES)
|
||||
list(LENGTH ONNXRUNTIME4J_OSX_ARCH ONNXRUNTIME4J_OSX_ARCH_LEN)
|
||||
if(ONNXRUNTIME4J_OSX_ARCH)
|
||||
if(ONNXRUNTIME4J_OSX_ARCH_LEN LESS_EQUAL 1)
|
||||
list(GET ONNXRUNTIME4J_OSX_ARCH 0 JNI_ARCH)
|
||||
message("Set Java ARCH TO macOS/iOS ${JNI_ARCH}")
|
||||
else()
|
||||
message(FATAL_ERROR "Java is currently not supported for macOS universal")
|
||||
endif()
|
||||
else()
|
||||
set(JNI_ARCH ${CMAKE_HOST_SYSTEM_PROCESSOR})
|
||||
message("Set Java ARCH TO macOS/iOS ${JNI_ARCH}")
|
||||
endif()
|
||||
if(JNI_ARCH STREQUAL "x86_64")
|
||||
set(JNI_ARCH x64)
|
||||
elseif(JNI_ARCH STREQUAL "arm64")
|
||||
set(JNI_ARCH aarch64)
|
||||
endif()
|
||||
elseif (CMAKE_SYSTEM_NAME STREQUAL "Android")
|
||||
set(JNI_ARCH ${ANDROID_ABI})
|
||||
elseif (CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64")
|
||||
set(JNI_ARCH x64)
|
||||
else()
|
||||
# Now mirror the checks used with MSVC
|
||||
if(MSVC)
|
||||
if(CMAKE_GENERATOR_PLATFORM STREQUAL "ARM64")
|
||||
set(JNI_ARCH aarch64)
|
||||
elseif(CMAKE_GENERATOR_PLATFORM STREQUAL "x64")
|
||||
set(JNI_ARCH x64)
|
||||
else()
|
||||
# if everything else failed then we're on a 32-bit arch and Java isn't supported
|
||||
message(FATAL_ERROR "Java is currently not supported on 32-bit x86 architecture")
|
||||
endif()
|
||||
else()
|
||||
# if everything else failed then we're on a 32-bit arch and Java isn't supported
|
||||
message(FATAL_ERROR "Java is currently not supported on 32-bit x86 architecture")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if (WIN32)
|
||||
set(JAVA_PLAT "win")
|
||||
elseif (APPLE)
|
||||
set(JAVA_PLAT "osx")
|
||||
elseif (${CMAKE_SYSTEM_NAME} MATCHES "Linux")
|
||||
set(JAVA_PLAT "linux")
|
||||
else()
|
||||
# We don't do distribution for Android
|
||||
# Set for completeness
|
||||
set(JAVA_PLAT "android")
|
||||
endif()
|
||||
|
||||
# Similar to Nuget schema
|
||||
set(JAVA_OS_ARCH ${JAVA_PLAT}-${JNI_ARCH})
|
||||
|
||||
# expose native libraries to the gradle build process
|
||||
set(JAVA_PACKAGE_DIR ai/onnxruntime/extensions/native/${JAVA_OS_ARCH})
|
||||
set(JAVA_NATIVE_LIB_DIR ${JAVA_OUTPUT_DIR}/native-lib)
|
||||
set(JAVA_NATIVE_JNI_DIR ${JAVA_OUTPUT_DIR}/native-jni)
|
||||
set(JAVA_PACKAGE_LIB_DIR ${JAVA_NATIVE_LIB_DIR}/${JAVA_PACKAGE_DIR})
|
||||
set(JAVA_PACKAGE_JNI_DIR ${JAVA_NATIVE_JNI_DIR}/${JAVA_PACKAGE_DIR})
|
||||
file(MAKE_DIRECTORY ${JAVA_PACKAGE_LIB_DIR})
|
||||
file(MAKE_DIRECTORY ${JAVA_PACKAGE_JNI_DIR})
|
||||
|
||||
# On Windows TARGET_LINKER_FILE_NAME is the .lib, TARGET_FILE_NAME is the .dll
|
||||
if (WIN32)
|
||||
#Our static analysis plugin set /p:LinkCompiled=false
|
||||
if(NOT onnxruntime_extensions_ENABLE_STATIC_ANALYSIS)
|
||||
add_custom_command(TARGET onnxruntime_extensions4j_jni POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different $<TARGET_FILE:onnxruntime_extensions> ${JAVA_PACKAGE_LIB_DIR}/$<TARGET_FILE_NAME:onnxruntime_extensions>)
|
||||
add_custom_command(TARGET onnxruntime_extensions4j_jni POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different $<TARGET_FILE:onnxruntime_extensions4j_jni> ${JAVA_PACKAGE_JNI_DIR}/$<TARGET_FILE_NAME:onnxruntime_extensions4j_jni>)
|
||||
endif()
|
||||
else()
|
||||
add_custom_command(TARGET onnxruntime_extensions4j_jni POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different $<TARGET_FILE:onnxruntime_extensions> ${JAVA_PACKAGE_LIB_DIR}/$<TARGET_LINKER_FILE_NAME:onnxruntime_extensions>)
|
||||
add_custom_command(TARGET onnxruntime_extensions4j_jni POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different $<TARGET_FILE:onnxruntime_extensions4j_jni> ${JAVA_PACKAGE_JNI_DIR}/$<TARGET_LINKER_FILE_NAME:onnxruntime_extensions4j_jni>)
|
||||
endif()
|
||||
|
||||
# run the build process (this copies the results back into CMAKE_CURRENT_BINARY_DIR)
|
||||
set(GRADLE_ARGS --console=plain cmakeBuild -p ${JAVA_ROOT} -DcmakeBuildDir=${CMAKE_CURRENT_BINARY_DIR})
|
||||
if(WIN32)
|
||||
set(GRADLE_ARGS ${GRADLE_ARGS} -Dorg.gradle.daemon=false)
|
||||
elseif (CMAKE_SYSTEM_NAME STREQUAL "Android")
|
||||
# For Android build, we may run gradle multiple times in same build,
|
||||
# sometimes gradle JVM will run out of memory if we keep the daemon running
|
||||
# it is better to not keep a daemon running
|
||||
set(GRADLE_ARGS ${GRADLE_ARGS} --no-daemon)
|
||||
endif()
|
||||
|
||||
message(STATUS "GRADLE_ARGS: ${GRADLE_ARGS}")
|
||||
add_custom_command(TARGET onnxruntime_extensions4j_jni POST_BUILD COMMAND ${GRADLE_EXECUTABLE} ${GRADLE_ARGS} WORKING_DIRECTORY ${JAVA_OUTPUT_TEMP})
|
||||
|
||||
if (CMAKE_SYSTEM_NAME STREQUAL "Android")
|
||||
set(ANDROID_PACKAGE_JNILIBS_DIR ${JAVA_OUTPUT_DIR}/android)
|
||||
set(ANDROID_PACKAGE_ABI_DIR ${ANDROID_PACKAGE_JNILIBS_DIR}/${ANDROID_ABI})
|
||||
file(MAKE_DIRECTORY ${ANDROID_PACKAGE_JNILIBS_DIR})
|
||||
file(MAKE_DIRECTORY ${ANDROID_PACKAGE_ABI_DIR})
|
||||
|
||||
# Copy onnxruntime_extensions.so and onnxruntime_extensions4j_jni.so for building Android AAR package
|
||||
add_custom_command(TARGET onnxruntime_extensions4j_jni POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different $<TARGET_FILE:onnxruntime_extensions> ${ANDROID_PACKAGE_ABI_DIR}/$<TARGET_LINKER_FILE_NAME:onnxruntime_extensions>)
|
||||
add_custom_command(TARGET onnxruntime_extensions4j_jni POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different $<TARGET_FILE:onnxruntime_extensions4j_jni> ${ANDROID_PACKAGE_ABI_DIR}/$<TARGET_LINKER_FILE_NAME:onnxruntime_extensions4j_jni>)
|
||||
# Generate the Android AAR package
|
||||
add_custom_command(TARGET onnxruntime_extensions4j_jni POST_BUILD COMMAND ${GRADLE_EXECUTABLE} -b build-android.gradle -c settings-android.gradle build -DjniLibsDir=${ANDROID_PACKAGE_JNILIBS_DIR} -DbuildDir=${ANDROID_PACKAGE_OUTPUT_DIR} -DminSdkVer=${ANDROID_MIN_SDK} -DheadersDir=${ANDROID_HEADERS_DIR} WORKING_DIRECTORY ${JAVA_ROOT})
|
||||
|
||||
if (onnxruntime_extensions_BUILD_UNIT_TESTS)
|
||||
set(ANDROID_TEST_PACKAGE_ROOT ${JAVA_ROOT}/src/test/android)
|
||||
set(ANDROID_TEST_PACKAGE_DIR ${JAVA_OUTPUT_DIR}/androidtest/android)
|
||||
#copy the androidtest project into cmake binary directory
|
||||
file(MAKE_DIRECTORY ${JAVA_OUTPUT_DIR}/androidtest)
|
||||
file(COPY ${ANDROID_TEST_PACKAGE_ROOT} DESTINATION ${JAVA_OUTPUT_DIR}/androidtest)
|
||||
set(ANDROID_TEST_PACKAGE_LIB_DIR ${ANDROID_TEST_PACKAGE_DIR}/app/libs)
|
||||
file(MAKE_DIRECTORY ${ANDROID_TEST_PACKAGE_LIB_DIR})
|
||||
# Copy the built Android AAR package to libs folder of our test app
|
||||
add_custom_command(TARGET onnxruntime_extensions4j_jni POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different ${ANDROID_PACKAGE_OUTPUT_DIR}/outputs/aar/onnxruntime_extensions-debug.aar ${ANDROID_TEST_PACKAGE_LIB_DIR}/onnxruntime_extensions-mobile.aar)
|
||||
# Build Android test apk for java package
|
||||
add_custom_command(TARGET onnxruntime_extensions4j_jni POST_BUILD COMMAND ${GRADLE_EXECUTABLE} clean WORKING_DIRECTORY ${ANDROID_TEST_PACKAGE_DIR})
|
||||
add_custom_command(TARGET onnxruntime_extensions4j_jni POST_BUILD COMMAND ${GRADLE_EXECUTABLE} assembleDebug assembleDebugAndroidTest -DminSdkVer=${ANDROID_MIN_SDK} WORKING_DIRECTORY ${ANDROID_TEST_PACKAGE_DIR})
|
||||
endif()
|
||||
endif()
|
|
@ -0,0 +1,39 @@
|
|||
set(Python3_FIND_REGISTRY NEVER CACHE STRING "...")
|
||||
if(NOT "${Python3_FIND_REGISTRY}" STREQUAL "NEVER")
|
||||
message(FATAL_ERROR "Python3_FIND_REGISTRY is not NEVER")
|
||||
endif()
|
||||
find_package(Python3 COMPONENTS Interpreter Development.Module NumPy)
|
||||
if (NOT Python3_FOUND)
|
||||
message(FATAL_ERROR "Python3 or NumPy not found!")
|
||||
endif()
|
||||
if (WIN32)
|
||||
list(APPEND shared_TARGET_SRC "${PROJECT_SOURCE_DIR}/pyop/extensions_pydll.def")
|
||||
endif()
|
||||
|
||||
file(GLOB TARGET_SRC_PYOPS "pyop/*.cc" "pyop/*.h" "shared/*.cc")
|
||||
add_library(extensions_pydll SHARED ${TARGET_SRC_PYOPS} ${shared_TARGET_LIB_SRC})
|
||||
standardize_output_folder(extensions_pydll)
|
||||
list(APPEND OCOS_COMPILE_DEFINITIONS PYTHON_OP_SUPPORT)
|
||||
target_compile_definitions(extensions_pydll PRIVATE ${OCOS_COMPILE_DEFINITIONS})
|
||||
|
||||
message(STATUS "Fetch pybind11")
|
||||
include(pybind11)
|
||||
target_include_directories(extensions_pydll PRIVATE
|
||||
${pybind11_INCLUDE_DIRS}
|
||||
$<TARGET_PROPERTY:Python3::Module,INTERFACE_INCLUDE_DIRECTORIES>
|
||||
$<TARGET_PROPERTY:Python3::NumPy,INTERFACE_INCLUDE_DIRECTORIES>
|
||||
$<TARGET_PROPERTY:ocos_operators,INTERFACE_INCLUDE_DIRECTORIES>)
|
||||
|
||||
target_compile_definitions(extensions_pydll PRIVATE
|
||||
$<TARGET_PROPERTY:Python3::Module,INTERFACE_COMPILE_DEFINITIONS>)
|
||||
|
||||
target_link_libraries(extensions_pydll PRIVATE Python3::Module ocos_operators)
|
||||
|
||||
if(NOT "${OCOS_EXTENTION_NAME}" STREQUAL "")
|
||||
if(NOT WIN32)
|
||||
set_target_properties(extensions_pydll PROPERTIES
|
||||
LIBRARY_OUTPUT_NAME ${OCOS_EXTENTION_NAME}
|
||||
PREFIX ""
|
||||
SUFFIX "")
|
||||
endif()
|
||||
endif()
|
|
@ -1,37 +0,0 @@
|
|||
# The pre/post processing code to ONNX model
|
||||
|
||||
Most pre and post processing of the DL models are written in Python code, when the user running the converted ONNX model with Python snippets, it would be very efficient and productive to convert these code snippets into the ONNX model, since the ONNX graph is actually a computation graph, it can represent the most programming code, theoretically.
|
||||
|
||||
In the onnxruntime_extensions package, there is a utility to help on that. This tool is to trace the data flow in the processing code and convert all operation in the tracing logging into the ONNX graph, and merge all these graphs into in one single ONNX model. It supports the Python numeric operators and PyTorch's operation APIs (only a subset of the tensor API)
|
||||
|
||||
###Usage
|
||||
In the onnxruntime_extensions.utils, there is an API ```trace_for_onnx```, when it was fed with the input variables in Python code, it start a tracing session to log all operation starting from these variables. Also if there are some PyTorch API calls in the processing code, you need replace the import statement from ```import torch``` to ```from onnxruntime_extensions.onnxprocess import torch_wrapper as torch```, which will enable these PyTorch API can be traced as well.
|
||||
|
||||
Overall, it will look like:
|
||||
|
||||
```python
|
||||
from onnxruntime_extensions.onnxprocess import trace_for_onnx
|
||||
from onnxruntime_extensions.onnxprocess import torch_wrapper as torch # overload torch API if it is needed
|
||||
|
||||
# the raw input, like text, image, or ...
|
||||
input_text = ...
|
||||
with trace_for_onnx(input_text, names=['string_input']) as tc_sess:
|
||||
# The pre or/and post processing code starts
|
||||
...
|
||||
...
|
||||
...
|
||||
output = ...
|
||||
# Save all trace objects into an ONNX model
|
||||
tc_sess.save_to_onnx('<all_in_one.onnx>', output)
|
||||
```
|
||||
|
||||
Then the all-in-one model can be inference from the raw text directly
|
||||
```python
|
||||
from onnxruntime_extensions.eager_op import EagerOp
|
||||
# the input raw text
|
||||
input_text = ...
|
||||
full_model = EagerOp.from_model('<all_in_one.onnx>')
|
||||
output = full_model(input_text)
|
||||
print(output)
|
||||
```
|
||||
Or you do inference on this model with any other programming ONNXRuntime API, like C++, C#, Java and etc.
|
|
@ -105,7 +105,6 @@ const OrtCustomOp** LoadCustomOpClasses() {
|
|||
#if defined(PYTHON_OP_SUPPORT)
|
||||
const OrtCustomOp* FetchPyCustomOps(size_t& count);
|
||||
OrtStatusPtr RegisterPythonDomainAndOps(OrtSessionOptions*, const OrtApi*);
|
||||
bool EnablePyCustomOps(bool enable = true);
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_MATH
|
||||
|
|
|
@ -4,11 +4,17 @@
|
|||
#pragma once
|
||||
#include "onnxruntime_c_api.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#define ORTX_EXPORT __declspec(dllexport)
|
||||
#else
|
||||
#define ORTX_EXPORT
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
OrtStatus* ORT_API_CALL RegisterCustomOps(OrtSessionOptions* options, const OrtApiBase* api);
|
||||
ORTX_EXPORT OrtStatus* ORT_API_CALL RegisterCustomOps(OrtSessionOptions* options, const OrtApiBase* api);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
# ONNXRuntime-Extensions Java/Android API and Package
|
||||
|
||||
This java and Android API and packaging principles were inspired by the https://github.com/microsoft/onnxruntime/tree/main/java, and openly share credits for API with the contributors in onnxruntime repo.
|
||||
|
||||
<br />
|
||||
|
||||
## Building
|
||||
|
||||
<br />
|
||||
|
||||
### Tools required
|
||||
1. install visual studio 2022 (with cmake, git, desktop C++)
|
||||
2. OpenJDK: https://docs.microsoft.com/en-us/java/openjdk/download
|
||||
(OpenJDK 11.0.15 LTS)
|
||||
3. Gradle: https://gradle.org/releases/
|
||||
(v6.9.2)
|
||||
|
||||
|
||||
### Build command
|
||||
./build.sh **-DOCOS_BUILD_JAVA=ON**
|
||||
|
||||
and find onnxruntime-extensions-0.5.0.jar at out/$OS/$CMake_BUILD_TYPE/java/build/libs
|
||||
|
||||
<br />
|
||||
|
||||
## Usage
|
||||
There is a Java example project checked in tutorial folder, [demo4j](../tutorials/demo4j) which provide a showcase how extensions package works with ONNXRuntime's Java API
|
|
@ -0,0 +1,167 @@
|
|||
apply plugin: 'com.android.library'
|
||||
apply plugin: 'maven-publish'
|
||||
|
||||
def jniLibsDir = System.properties['jniLibsDir']
|
||||
def buildDir = System.properties['buildDir']
|
||||
def headersDir = System.properties['headersDir']
|
||||
def publishDir = System.properties['publishDir']
|
||||
def minSdkVer = System.properties['minSdkVer']
|
||||
def targetSdkVer = System.properties['targetSdkVer']
|
||||
def buildVariant = System.properties['buildVariant'] ?: "Full"
|
||||
boolean isMobileBuild = (buildVariant == "Mobile")
|
||||
|
||||
// Since Android requires a higher numbers indicating more recent versions
|
||||
// This function assume ORT version number will be in formart of A.B.C such as 1.7.0
|
||||
// We generate version code A[0{0,1}]B[0{0,1}]C,
|
||||
// for example '1.7.0' -> 10700, '1.6.15' -> 10615
|
||||
def getVersionCode(String version){
|
||||
String[] codes = version.split('\\.');
|
||||
// This will have problem if we have 3 digit [sub]version number, such as 1.7.199
|
||||
// but it is highly unlikely to happen
|
||||
String versionCodeStr = String.format("%d%02d%02d", codes[0] as int, codes[1] as int, codes[2] as int);
|
||||
return versionCodeStr as int;
|
||||
}
|
||||
|
||||
project.buildDir = buildDir
|
||||
project.version = rootProject.file('../.version.txt').text.trim()
|
||||
project.group = "com.microsoft.onnxruntime.extensions"
|
||||
|
||||
def mavenArtifactId = isMobileBuild ? project.name + '-mobile' : project.name + '-android'
|
||||
def mobileDescription = 'ONNXRuntime-Extensions Mobile is a library for Android for pre- and post-processing on inference.'
|
||||
def defaultDescription = 'ONNXRuntime-Extensions is a library for Android for pre- and post-processing on inference.'
|
||||
|
||||
buildscript {
|
||||
repositories {
|
||||
google()
|
||||
mavenCentral()
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:4.0.1'
|
||||
|
||||
// NOTE: Do not place your application dependencies here; they belong
|
||||
// in the individual module build.gradle files
|
||||
}
|
||||
}
|
||||
|
||||
allprojects {
|
||||
repositories {
|
||||
google()
|
||||
mavenCentral()
|
||||
}
|
||||
}
|
||||
|
||||
android {
|
||||
compileSdkVersion 29
|
||||
buildToolsVersion "29.0.2"
|
||||
|
||||
defaultConfig {
|
||||
minSdkVersion minSdkVer
|
||||
targetSdkVersion targetSdkVer
|
||||
versionCode = getVersionCode(project.version)
|
||||
versionName = project.version
|
||||
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
}
|
||||
|
||||
android {
|
||||
lintOptions {
|
||||
abortOnError false
|
||||
}
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
release {
|
||||
minifyEnabled false
|
||||
debuggable false
|
||||
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
||||
}
|
||||
}
|
||||
|
||||
compileOptions {
|
||||
sourceCompatibility = JavaVersion.VERSION_1_8
|
||||
targetCompatibility = JavaVersion.VERSION_1_8
|
||||
}
|
||||
|
||||
sourceSets {
|
||||
main {
|
||||
jniLibs.srcDirs = [jniLibsDir]
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
task sourcesJar(type: Jar) {
|
||||
classifier "sources"
|
||||
from android.sourceSets.main.java.srcDirs
|
||||
}
|
||||
|
||||
task javadoc(type: Javadoc) {
|
||||
source = android.sourceSets.main.java.srcDirs
|
||||
classpath += project.files(android.getBootClasspath().join(File.pathSeparator))
|
||||
}
|
||||
|
||||
task javadocJar(type: Jar, dependsOn: javadoc) {
|
||||
classifier = 'javadoc'
|
||||
from javadoc.destinationDir
|
||||
}
|
||||
|
||||
artifacts {
|
||||
archives javadocJar
|
||||
archives sourcesJar
|
||||
}
|
||||
|
||||
dependencies {
|
||||
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.7.0'
|
||||
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.7.0'
|
||||
testImplementation 'com.google.protobuf:protobuf-java:3.20.1'
|
||||
}
|
||||
|
||||
publishing {
|
||||
publications {
|
||||
maven(MavenPublication) {
|
||||
groupId = project.group
|
||||
artifactId = mavenArtifactId
|
||||
version = project.version
|
||||
|
||||
// Three artifacts, the `aar`, the sources and the javadoc
|
||||
artifact("$buildDir/outputs/aar/${project.name}-release.aar")
|
||||
artifact javadocJar
|
||||
artifact sourcesJar
|
||||
|
||||
pom {
|
||||
name = 'onnxruntime-extensions'
|
||||
description = isMobileBuild ? mobileDescription : defaultDescription
|
||||
url = 'https://microsoft.github.io/onnxruntime/'
|
||||
licenses {
|
||||
license {
|
||||
name = 'MIT License'
|
||||
url = 'https://opensource.org/licenses/MIT'
|
||||
}
|
||||
}
|
||||
organization {
|
||||
name = 'Microsoft'
|
||||
url = 'http://www.microsoft.com'
|
||||
}
|
||||
scm {
|
||||
connection = 'scm:git:git://github.com:microsoft/onnxruntime-extensions.git'
|
||||
developerConnection = 'scm:git:ssh://github.com/microsoft/onnxruntime-extensions.git'
|
||||
url = 'http://github.com/microsoft/onnxruntime-extensions'
|
||||
}
|
||||
developers {
|
||||
developer {
|
||||
id = 'onnxruntime'
|
||||
name = 'ONNX Runtime'
|
||||
email = 'onnxruntime@microsoft.com'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//publish to filesystem repo
|
||||
repositories{
|
||||
maven {
|
||||
url "$publishDir"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,249 @@
|
|||
plugins {
|
||||
id 'java-library'
|
||||
id 'maven-publish'
|
||||
id 'signing'
|
||||
id 'jacoco'
|
||||
id 'com.diffplug.spotless' version '5.17.0'
|
||||
}
|
||||
|
||||
allprojects {
|
||||
repositories {
|
||||
mavenCentral()
|
||||
}
|
||||
}
|
||||
|
||||
project.group = "com.microsoft.onnxruntime"
|
||||
version = rootProject.file('../.version.txt').text.trim()
|
||||
|
||||
// cmake runs will inform us of the build directory of the current run
|
||||
def cmakeBuildDir = System.properties['cmakeBuildDir']
|
||||
def cmakeJavaDir = "${cmakeBuildDir}/java"
|
||||
def cmakeNativeLibDir = "${cmakeJavaDir}/native-lib"
|
||||
def cmakeNativeJniDir = "${cmakeJavaDir}/native-jni"
|
||||
def cmakeNativeTestDir = "${cmakeJavaDir}/native-test"
|
||||
def cmakeBuildOutputDir = "${cmakeJavaDir}/build"
|
||||
|
||||
def mavenUser = System.properties['mavenUser']
|
||||
def mavenPwd = System.properties['mavenPwd']
|
||||
|
||||
def mavenArtifactId = project.name
|
||||
|
||||
java {
|
||||
sourceCompatibility = JavaVersion.VERSION_1_8
|
||||
targetCompatibility = JavaVersion.VERSION_1_8
|
||||
}
|
||||
|
||||
// This jar tasks serves as a CMAKE signalling
|
||||
// mechanism. The jar will be overwritten by allJar task
|
||||
jar {
|
||||
}
|
||||
|
||||
// Add explicit sources jar with pom file.
|
||||
task sourcesJar(type: Jar, dependsOn: classes) {
|
||||
classifier = "sources"
|
||||
from sourceSets.main.allSource
|
||||
into("META-INF/maven/$project.group/$mavenArtifactId") {
|
||||
from { generatePomFileForMavenPublication }
|
||||
rename ".*", "pom.xml"
|
||||
}
|
||||
}
|
||||
|
||||
// Add explicit javadoc jar with pom file
|
||||
task javadocJar(type: Jar, dependsOn: javadoc) {
|
||||
classifier = "javadoc"
|
||||
from javadoc.destinationDir
|
||||
into("META-INF/maven/$project.group/$mavenArtifactId") {
|
||||
from { generatePomFileForMavenPublication }
|
||||
rename ".*", "pom.xml"
|
||||
}
|
||||
}
|
||||
|
||||
wrapper {
|
||||
gradleVersion = '6.1.1'
|
||||
}
|
||||
|
||||
spotless {
|
||||
java {
|
||||
removeUnusedImports()
|
||||
googleJavaFormat()
|
||||
}
|
||||
format 'gradle', {
|
||||
target '**/*.gradle'
|
||||
trimTrailingWhitespace()
|
||||
indentWithTabs()
|
||||
}
|
||||
}
|
||||
|
||||
compileJava {
|
||||
dependsOn spotlessJava
|
||||
options.compilerArgs += ["-h", "${project.buildDir}/headers/"]
|
||||
if (!JavaVersion.current().isJava8()) {
|
||||
// Ensures only methods present in Java 8 are used
|
||||
options.compilerArgs.addAll(['--release', '8'])
|
||||
// Gradle versions before 6.6 require that these flags are unset when using "-release"
|
||||
java.sourceCompatibility = null
|
||||
java.targetCompatibility = null
|
||||
}
|
||||
}
|
||||
|
||||
compileTestJava {
|
||||
if (!JavaVersion.current().isJava8()) {
|
||||
// Ensures only methods present in Java 8 are used
|
||||
options.compilerArgs.addAll(['--release', '8'])
|
||||
// Gradle versions before 6.6 require that these flags are unset when using "-release"
|
||||
java.sourceCompatibility = null
|
||||
java.targetCompatibility = null
|
||||
}
|
||||
}
|
||||
|
||||
sourceSets.test {
|
||||
// add test resource files
|
||||
resources.srcDirs += [
|
||||
"${rootProject.projectDir}/../java/testdata"
|
||||
]
|
||||
if (cmakeBuildDir != null) {
|
||||
// add compiled native libs
|
||||
resources.srcDirs += [
|
||||
cmakeNativeLibDir,
|
||||
cmakeNativeJniDir,
|
||||
cmakeNativeTestDir
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
if (cmakeBuildDir != null) {
|
||||
// generate tasks to be called from cmake
|
||||
|
||||
// Overwrite jar location
|
||||
task allJar(type: Jar) {
|
||||
manifest {
|
||||
attributes('Automatic-Module-Name': project.group,
|
||||
'Implementation-Title': 'onnxruntime-extensions',
|
||||
'Implementation-Version': project.version)
|
||||
}
|
||||
into("META-INF/maven/$project.group/$mavenArtifactId") {
|
||||
from { generatePomFileForMavenPublication }
|
||||
rename ".*", "pom.xml"
|
||||
}
|
||||
from sourceSets.main.output
|
||||
from cmakeNativeJniDir
|
||||
from cmakeNativeLibDir
|
||||
}
|
||||
|
||||
task cmakeBuild(type: Copy) {
|
||||
from project.buildDir
|
||||
include 'libs/**'
|
||||
include 'docs/**'
|
||||
into cmakeBuildOutputDir
|
||||
}
|
||||
cmakeBuild.dependsOn allJar
|
||||
cmakeBuild.dependsOn sourcesJar
|
||||
cmakeBuild.dependsOn javadocJar
|
||||
cmakeBuild.dependsOn javadoc
|
||||
|
||||
task cmakeCheck(type: Copy) {
|
||||
from project.buildDir
|
||||
include 'reports/**'
|
||||
into cmakeBuildOutputDir
|
||||
}
|
||||
cmakeCheck.dependsOn check
|
||||
}
|
||||
|
||||
dependencies {
|
||||
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.7.0'
|
||||
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.7.0'
|
||||
testImplementation 'com.google.protobuf:protobuf-java:3.20.1'
|
||||
}
|
||||
|
||||
processTestResources {
|
||||
duplicatesStrategy(DuplicatesStrategy.INCLUDE) // allows duplicates in the test resources
|
||||
}
|
||||
|
||||
test {
|
||||
java {
|
||||
dependsOn spotlessJava
|
||||
}
|
||||
if (System.getProperty("JAVA_FULL_TEST") != null) {
|
||||
// Forces each test class to be run in a separate JVM,
|
||||
// which is necessary for testing the environment thread pool which is ignored if full test is not set.
|
||||
forkEvery 1
|
||||
}
|
||||
useJUnitPlatform()
|
||||
if (cmakeBuildDir != null) {
|
||||
workingDir cmakeBuildDir
|
||||
}
|
||||
systemProperties System.getProperties().subMap(['JAVA_FULL_TEST'])
|
||||
testLogging {
|
||||
events "passed", "skipped", "failed"
|
||||
showStandardStreams = true
|
||||
showStackTraces = true
|
||||
exceptionFormat = "full"
|
||||
}
|
||||
}
|
||||
|
||||
jacocoTestReport {
|
||||
reports {
|
||||
xml.enabled true
|
||||
csv.enabled true
|
||||
html.destination file("${buildDir}/jacocoHtml")
|
||||
}
|
||||
}
|
||||
|
||||
publishing {
|
||||
publications {
|
||||
maven(MavenPublication) {
|
||||
groupId = project.group
|
||||
artifactId = mavenArtifactId
|
||||
|
||||
from components.java
|
||||
pom {
|
||||
name = 'onnxruntime-extensions'
|
||||
description = 'ONNXRuntime-Extensions is a library for Android for pre- and post-processing on inference.'
|
||||
url = 'https://microsoft.github.io/onnxruntime/'
|
||||
licenses {
|
||||
license {
|
||||
name = 'MIT License'
|
||||
url = 'https://opensource.org/licenses/MIT'
|
||||
}
|
||||
}
|
||||
organization {
|
||||
name = 'Microsoft'
|
||||
url = 'http://www.microsoft.com'
|
||||
}
|
||||
scm {
|
||||
connection = 'scm:git:git://github.com:microsoft/onnxruntime-extensions.git'
|
||||
developerConnection = 'scm:git:ssh://github.com/microsoft/onnxruntime-extensions.git'
|
||||
url = 'http://github.com/microsoft/onnxruntime-extensions'
|
||||
}
|
||||
developers {
|
||||
developer {
|
||||
id = 'onnxruntime'
|
||||
name = 'ONNX Runtime'
|
||||
email = 'onnxruntime@microsoft.com'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
repositories {
|
||||
maven {
|
||||
url 'https://oss.sonatype.org/service/local/staging/deploy/maven2/'
|
||||
credentials {
|
||||
username mavenUser
|
||||
password mavenPwd
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Generates a task signMavenPublication that will
|
||||
// build all artifacts.
|
||||
signing {
|
||||
// Queries env vars:
|
||||
// ORG_GRADLE_PROJECT_signingKey
|
||||
// ORG_GRADLE_PROJECT_signingPassword but can be changed to properties
|
||||
def signingKey = findProperty("signingKey")
|
||||
def signingPassword = findProperty("signingPassword")
|
||||
useInMemoryPgpKeys(signingKey, signingPassword)
|
||||
sign publishing.publications.maven
|
||||
}
|
|
@ -0,0 +1,2 @@
|
|||
rootProject.name = 'onnxruntime-extensions'
|
||||
rootProject.buildFileName = 'build-android.gradle'
|
|
@ -0,0 +1 @@
|
|||
rootProject.name = 'onnxruntime-extensions'
|
|
@ -0,0 +1,2 @@
|
|||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="ai.onnxruntime.extensions" />
|
|
@ -0,0 +1,128 @@
|
|||
package ai.onnxruntime.extensions;
|
||||
|
||||
import java.io.*;
|
||||
import java.nio.file.Files;
|
||||
import java.util.Locale;
|
||||
|
||||
import java.nio.file.StandardCopyOption;
|
||||
|
||||
|
||||
public final class OrtxLibrary {
|
||||
|
||||
// the default name in Android could be simple.
|
||||
private static String libraryFileName = "onnxruntime_extensions4j_jni";
|
||||
private static final String OS_ARCH_STR = getOsArch();
|
||||
/**
|
||||
* Check if we're running on Android.
|
||||
*
|
||||
* @return True if the property java.vendor equals The Android Project, false otherwise.
|
||||
*/
|
||||
static boolean isAndroid() {
|
||||
return System.getProperty("java.vendor", "generic").equals("The Android Project");
|
||||
}
|
||||
|
||||
/* Computes and initializes OS_ARCH_STR (such as linux-x64) */
|
||||
private static String getOsArch() {
|
||||
String detectedOS = null;
|
||||
String os = System.getProperty("os.name", "generic").toLowerCase(Locale.ENGLISH);
|
||||
if (os.contains("mac") || os.contains("darwin")) {
|
||||
detectedOS = "osx";
|
||||
} else if (os.contains("win")) {
|
||||
detectedOS = "win";
|
||||
} else if (os.contains("nux")) {
|
||||
detectedOS = "linux";
|
||||
} else if (isAndroid()) {
|
||||
detectedOS = "android";
|
||||
} else {
|
||||
throw new IllegalStateException("Unsupported os:" + os);
|
||||
}
|
||||
String detectedArch = null;
|
||||
String arch = System.getProperty("os.arch", "generic").toLowerCase(Locale.ENGLISH);
|
||||
if (arch.startsWith("amd64") || arch.startsWith("x86_64")) {
|
||||
detectedArch = "x64";
|
||||
} else if (arch.startsWith("x86")) {
|
||||
// 32-bit x86 is not supported by the Java API
|
||||
detectedArch = "x86";
|
||||
} else if (arch.startsWith("aarch64")) {
|
||||
detectedArch = "aarch64";
|
||||
} else if (arch.startsWith("ppc64")) {
|
||||
detectedArch = "ppc64";
|
||||
} else if (isAndroid()) {
|
||||
detectedArch = arch;
|
||||
} else {
|
||||
throw new IllegalStateException("Unsupported arch:" + arch);
|
||||
}
|
||||
return detectedOS + '-' + detectedArch;
|
||||
}
|
||||
|
||||
|
||||
private static String getLibraryResourceName(){
|
||||
return "/ai/onnxruntime/extensions/native/" + OS_ARCH_STR +
|
||||
"/" + System.mapLibraryName("onnxruntime_extensions4j_jni");
|
||||
}
|
||||
|
||||
static{
|
||||
try{
|
||||
File tempLibraryFile = null;
|
||||
if (!isAndroid()) {
|
||||
libraryFileName = getLibraryResourceName();
|
||||
// Obtain filename from path
|
||||
String[] parts = libraryFileName.split("/");
|
||||
String filename = parts[parts.length - 1];
|
||||
|
||||
// Prepare temporary file
|
||||
File temporaryDir = createTempDirectory("ortx4j");
|
||||
temporaryDir.deleteOnExit();
|
||||
|
||||
tempLibraryFile = new File(temporaryDir, filename);
|
||||
|
||||
try (InputStream is = OrtxLibrary.class.getResourceAsStream(libraryFileName)) {
|
||||
Files.copy(is, tempLibraryFile.toPath(), StandardCopyOption.REPLACE_EXISTING);
|
||||
} catch (IOException e) {
|
||||
tempLibraryFile.delete();
|
||||
throw e;
|
||||
} catch (NullPointerException e) {
|
||||
tempLibraryFile.delete();
|
||||
throw new FileNotFoundException("File " + libraryFileName + " was not found inside JAR.");
|
||||
}
|
||||
libraryFileName = tempLibraryFile.getAbsolutePath();
|
||||
}
|
||||
|
||||
try {
|
||||
if (isAndroid()) {
|
||||
System.loadLibrary(libraryFileName);
|
||||
}
|
||||
else {
|
||||
System.load(libraryFileName);
|
||||
}
|
||||
} finally {
|
||||
if (tempLibraryFile != null) {
|
||||
tempLibraryFile.deleteOnExit();
|
||||
}
|
||||
}
|
||||
} catch(IOException e1){
|
||||
throw new RuntimeException(e1);
|
||||
}
|
||||
}
|
||||
|
||||
public static String getExtractedLibraryPath() {
|
||||
if (isAndroid()) {
|
||||
return "lib" + libraryFileName + ".so";
|
||||
}
|
||||
else {
|
||||
return libraryFileName;
|
||||
}
|
||||
}
|
||||
|
||||
private static File createTempDirectory(String prefix) throws IOException {
|
||||
String tempDir = System.getProperty("java.io.tmpdir");
|
||||
File generatedDir = new File(tempDir, prefix + System.nanoTime());
|
||||
|
||||
if (!generatedDir.mkdir())
|
||||
throw new IOException("Failed to create temp directory " + generatedDir.getName());
|
||||
|
||||
return generatedDir;
|
||||
}
|
||||
|
||||
public static native long getNativeExtensionOperatorRegister();
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
package ai.onnxruntime.extensions;
|
||||
|
||||
|
||||
public final class OrtxPackage implements AutoCloseable {
|
||||
|
||||
private static volatile OrtxPackage INSTANCE;
|
||||
|
||||
public String getLibraryPath() {
|
||||
return OrtxLibrary.getExtractedLibraryPath();
|
||||
}
|
||||
|
||||
public static synchronized OrtxPackage getPackage() {
|
||||
if (INSTANCE == null) {
|
||||
return new OrtxPackage();
|
||||
}
|
||||
else {
|
||||
return INSTANCE;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
// Reserved
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
#include "ai_onnxruntime_extensions_OrtxLibrary.h"
|
||||
#include "onnxruntime_extensions.h"
|
||||
|
||||
/*
|
||||
* Class: ai_onnxruntime_extensions_OrtxLibrary
|
||||
* Method: getNativeExtensionOperatorRegister
|
||||
* Signature: ()J
|
||||
*/
|
||||
JNIEXPORT jlong JNICALL Java_ai_onnxruntime_extensions_Utils_getNativeExtensionOperatorRegister(JNIEnv* env, jclass cls) {
|
||||
return (jlong)(&RegisterCustomOps);
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
package ai.onnxruntime.extensions;
|
||||
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
|
||||
public class OrtxTest {
|
||||
@Test
|
||||
void getRegisterTest() {
|
||||
long handle = OrtxLibrary.getNativeExtensionOperatorRegister();
|
||||
Assertions.assertNotEquals(handle, Long.valueOf(0));
|
||||
}
|
||||
}
|
|
@ -7,7 +7,7 @@ import sys
|
|||
import copy
|
||||
import onnx
|
||||
from onnx import helper
|
||||
from ._ortcustomops import ( # noqa
|
||||
from ._extensions_pydll import ( # noqa
|
||||
PyCustomOpDef, enable_py_op, add_custom_op, hash_64, default_opset_domain)
|
||||
|
||||
|
||||
|
@ -16,7 +16,7 @@ def get_library_path():
|
|||
The custom operator library binary path
|
||||
:return: A string of the this library path.
|
||||
"""
|
||||
mod = sys.modules['onnxruntime_extensions._ortcustomops']
|
||||
mod = sys.modules['onnxruntime_extensions._extensions_pydll']
|
||||
return mod.__file__
|
||||
|
||||
|
||||
|
|
|
@ -1,4 +0,0 @@
|
|||
LIBRARY "ortcustomops.dll"
|
||||
EXPORTS
|
||||
RegisterCustomOps @1
|
||||
PyInit__ortcustomops @2
|
|
@ -0,0 +1,4 @@
|
|||
LIBRARY "extensions_pydll"
|
||||
EXPORTS
|
||||
RegisterCustomOps @1
|
||||
PyInit__extensions_pydll @2
|
|
@ -486,7 +486,7 @@ void AddObjectMethods(pybind11::module& m) {
|
|||
.def_readonly_static("dt_bfloat16", &PyCustomOpDef::dt_bfloat16);
|
||||
}
|
||||
|
||||
PYBIND11_MODULE(_ortcustomops, m) {
|
||||
PYBIND11_MODULE(_extensions_pydll, m) {
|
||||
m.doc() = "pybind11 stateful interface to ONNXRuntime-Extensions";
|
||||
|
||||
init_numpy();
|
||||
|
|
|
@ -92,3 +92,6 @@ struct PyCustomOpFactory : Ort::CustomOpBase<PyCustomOpFactory, PyCustomOpKernel
|
|||
std::string op_type_;
|
||||
std::string op_domain_;
|
||||
};
|
||||
|
||||
|
||||
bool EnablePyCustomOps(bool enable = true);
|
||||
|
|
11
setup.py
11
setup.py
|
@ -64,7 +64,7 @@ class BuildCMakeExt(_build_ext):
|
|||
Perform build_cmake before doing the 'normal' stuff
|
||||
"""
|
||||
for extension in self.extensions:
|
||||
if extension.name == 'onnxruntime_extensions._ortcustomops':
|
||||
if extension.name == 'onnxruntime_extensions._extensions_pydll':
|
||||
self.build_cmake(extension)
|
||||
|
||||
def build_cmake(self, extension):
|
||||
|
@ -76,7 +76,7 @@ class BuildCMakeExt(_build_ext):
|
|||
config = 'RelWithDebInfo' if self.debug else 'Release'
|
||||
cmake_args = [
|
||||
'-DCMAKE_LIBRARY_OUTPUT_DIRECTORY=' + str(ext_fullpath.parent.absolute()),
|
||||
'-DOCOS_ENABLE_PYTHON=ON',
|
||||
'-DOCOS_BUILD_PYTHON=ON',
|
||||
'-DOCOS_ENABLE_CTEST=OFF',
|
||||
'-DOCOS_EXTENTION_NAME=' + ext_fullpath.name,
|
||||
'-DCMAKE_BUILD_TYPE=' + config
|
||||
|
@ -106,7 +106,7 @@ class BuildCMakeExt(_build_ext):
|
|||
config_dir = '.'
|
||||
if not (build_temp / 'build.ninja').exists():
|
||||
config_dir = config
|
||||
self.copy_file(build_temp / 'bin' / config_dir / 'ortcustomops.dll', ext_fullpath)
|
||||
self.copy_file(build_temp / 'bin' / config_dir / 'extensions_pydll.dll', ext_fullpath)
|
||||
else:
|
||||
self.copy_file(build_temp / 'lib' / ext_fullpath.name, ext_fullpath)
|
||||
|
||||
|
@ -142,7 +142,7 @@ if sys.platform == "win32":
|
|||
|
||||
ext_modules = [
|
||||
setuptools.extension.Extension(
|
||||
name=str('onnxruntime_extensions._ortcustomops'),
|
||||
name=str('onnxruntime_extensions._extensions_pydll'),
|
||||
sources=[])
|
||||
]
|
||||
|
||||
|
@ -186,9 +186,6 @@ setup(
|
|||
'Operating System :: POSIX :: Linux',
|
||||
"Programming Language :: C++",
|
||||
'Programming Language :: Python',
|
||||
'Programming Language :: Python :: 3.7',
|
||||
'Programming Language :: Python :: 3.8',
|
||||
'Programming Language :: Python :: 3.9',
|
||||
"Programming Language :: Python :: Implementation :: CPython",
|
||||
'License :: OSI Approved :: MIT License'
|
||||
]
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
// this is a stub C++ file for DLL/dlib/so generation
|
||||
#include "onnxruntime_extensions.h"
|
||||
|
||||
// need a reference to a function from the static library for ld in Linux
|
||||
auto exported_func_1 = &RegisterCustomOps;
|
|
@ -62,7 +62,7 @@ extern "C" bool ORT_API_CALL AddExternalCustomOp(const OrtCustomOp* c_op) {
|
|||
return true;
|
||||
}
|
||||
|
||||
extern "C" OrtStatus* ORT_API_CALL RegisterCustomOps(OrtSessionOptions* options, const OrtApiBase* api) {
|
||||
extern "C" ORTX_EXPORT OrtStatus* ORT_API_CALL RegisterCustomOps(OrtSessionOptions* options, const OrtApiBase* api) {
|
||||
OrtCustomOpDomain* domain = nullptr;
|
||||
const OrtApi* ortApi = api->GetApi(ORT_API_VERSION);
|
||||
std::set<std::string> pyop_nameset;
|
|
@ -1,4 +1,4 @@
|
|||
LIBRARY "ortcustomops.dll"
|
||||
LIBRARY "ortextensions.dll"
|
||||
EXPORTS
|
||||
RegisterCustomOps @1
|
||||
AddExternalCustomOp @2
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
{ global:
|
||||
RegisterCustomOps;
|
||||
AddExternalCustomOp;
|
||||
local: *; };
|
||||
{
|
||||
global:
|
||||
RegisterCustomOps;
|
||||
AddExternalCustomOp;
|
||||
local: *;
|
||||
};
|
||||
|
|
|
@ -13,13 +13,13 @@
|
|||
|
||||
const char* GetLibraryPath() {
|
||||
#if defined(_WIN32)
|
||||
return "ortcustomops.dll";
|
||||
return "ortextensions.dll";
|
||||
#elif defined(__APPLE__)
|
||||
return "libortcustomops.dylib";
|
||||
return "libortextensions.dylib";
|
||||
#elif defined(ANDROID) || defined(__ANDROID__)
|
||||
return "libortcustomops.so";
|
||||
return "libortextensions.so";
|
||||
#else
|
||||
return "lib/libortcustomops.so";
|
||||
return "lib/libortextensions.so";
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
#
|
||||
# https://help.github.com/articles/dealing-with-line-endings/
|
||||
#
|
||||
# These are explicitly windows files and should use crlf
|
||||
*.bat text eol=crlf
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
# Ignore Gradle project-specific cache directory
|
||||
.gradle
|
||||
|
||||
# Ignore Gradle build output directory
|
||||
build
|
||||
libs/
|
||||
gradlew*
|
||||
gradle-wrapper*
|
|
@ -0,0 +1,4 @@
|
|||
# How to start
|
||||
|
||||
1. copy JAR package from $REPO/out/$OS/RelWithDebInfo/java/build/libs/onnxruntime-extensions-${VERSION}.jar into app/libs folder.
|
||||
2. build and run this java project.
|
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* This file was generated by the Gradle 'init' task.
|
||||
*
|
||||
* This generated file contains a sample Java application project to get you started.
|
||||
* For more details take a look at the 'Building Java & JVM projects' chapter in the Gradle
|
||||
* User Manual available at https://docs.gradle.org/7.3/userguide/building_java_projects.html
|
||||
*/
|
||||
|
||||
plugins {
|
||||
// Apply the application plugin to add support for building a CLI application in Java.
|
||||
application
|
||||
}
|
||||
|
||||
repositories {
|
||||
// Use Maven Central for resolving dependencies.
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
// Use JUnit Jupiter for testing.
|
||||
testImplementation("org.junit.jupiter:junit-jupiter:5.7.2")
|
||||
|
||||
// onnxruntime and its extensions package
|
||||
implementation("com.microsoft.onnxruntime:onnxruntime:1.12.1")
|
||||
implementation(files("libs/onnxruntime-extensions-0.5.0.jar"))
|
||||
|
||||
// This dependency is used by the application.
|
||||
implementation("com.google.guava:guava:30.1.1-jre")
|
||||
}
|
||||
|
||||
application {
|
||||
// Define the main class for the application.
|
||||
mainClass.set("demo4j.App")
|
||||
}
|
||||
|
||||
tasks.named<Test>("test") {
|
||||
// Use JUnit Platform for unit tests.
|
||||
useJUnitPlatform()
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* This Java source file was generated by the Gradle 'init' task.
|
||||
*/
|
||||
package demo4j;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Map;
|
||||
import java.nio.file.Paths;
|
||||
import ai.onnxruntime.*;
|
||||
import ai.onnxruntime.extensions.OrtxPackage;
|
||||
|
||||
public class App {
|
||||
public String inference(){
|
||||
try {
|
||||
var env = OrtEnvironment.getEnvironment();
|
||||
var sess_opt = new OrtSession.SessionOptions();
|
||||
|
||||
/* Register the custom ops from onnxruntime-extensions */
|
||||
sess_opt.registerCustomOpLibrary(OrtxPackage.getPackage().getLibraryPath());
|
||||
|
||||
/* do a quick inference on Bert Tokenizer custom ops with Ort */
|
||||
var modelPath = Paths.get(this.getClass().getClassLoader().getResource("test_bert_tokenizer.onnx").getPath());
|
||||
var session = env.createSession(modelPath.toString(), sess_opt);
|
||||
var t1 = OnnxTensor.createTensor(env, new String[]{"This is a test"});
|
||||
var inputs = Map.of("text", t1);
|
||||
try (var r = session.run(inputs)) {
|
||||
long[] tokenIds = (long[])r.get("input_ids").get().getValue();
|
||||
return Arrays.toString(tokenIds);
|
||||
}
|
||||
|
||||
} catch(OrtException e1) {
|
||||
return e1.getMessage();
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
System.out.println(new App().inference());
|
||||
}
|
||||
}
|
Двоичный файл не отображается.
|
@ -0,0 +1,14 @@
|
|||
/*
|
||||
* This Java source file was generated by the Gradle 'init' task.
|
||||
*/
|
||||
package demo4j;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
class AppTest {
|
||||
@Test void appHasAGreeting() {
|
||||
App classUnderTest = new App();
|
||||
assertNotNull(classUnderTest.inference(), "app should have a greeting");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
/*
|
||||
* This file was generated by the Gradle 'init' task.
|
||||
*
|
||||
* The settings file is used to specify which projects to include in your build.
|
||||
*
|
||||
* Detailed information about configuring a multi-project build in Gradle can be found
|
||||
* in the user manual at https://docs.gradle.org/7.3/userguide/multi_project_builds.html
|
||||
*/
|
||||
|
||||
rootProject.name = "demo4j"
|
||||
include("app")
|
Загрузка…
Ссылка в новой задаче