Skip to content

Commit d21304c

Browse files
authored
Initial Objective-C API (microsoft#7366)
Initial implementation of an Objective-C API.
1 parent 78e583d commit d21304c

29 files changed

+1131
-33
lines changed

Diff for: cmake/CMakeLists.txt

+6
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ option(onnxruntime_MSVC_STATIC_RUNTIME "Compile for the static CRT" OFF)
6565
option(onnxruntime_GCC_STATIC_CPP_RUNTIME "Compile for the static libstdc++" OFF)
6666
option(onnxruntime_BUILD_UNIT_TESTS "Build ONNXRuntime unit tests" ON)
6767
option(onnxruntime_BUILD_CSHARP "Build C# library" OFF)
68+
option(onnxruntime_BUILD_OBJC "Build Objective-C library" OFF)
6869
option(onnxruntime_USE_PREINSTALLED_EIGEN "Use pre-installed EIGEN. Need to provide eigen_SOURCE_PATH if turn this on." OFF)
6970
option(onnxruntime_BUILD_BENCHMARKS "Build ONNXRuntime micro-benchmarks" OFF)
7071

@@ -1574,6 +1575,11 @@ if (onnxruntime_ENABLE_PYTHON)
15741575
include(onnxruntime_python.cmake)
15751576
endif()
15761577

1578+
if (onnxruntime_BUILD_OBJC)
1579+
message(STATUS "Objective-C Build is enabled")
1580+
include(onnxruntime_objectivec.cmake)
1581+
endif()
1582+
15771583
if (onnxruntime_BUILD_UNIT_TESTS)
15781584
include(onnxruntime_unittests.cmake)
15791585
endif()

Diff for: cmake/onnxruntime.cmake

-1
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,6 @@ endif()
7979

8080
add_dependencies(onnxruntime onnxruntime_generate_def ${onnxruntime_EXTERNAL_DEPENDENCIES})
8181
target_include_directories(onnxruntime PRIVATE ${ONNXRUNTIME_ROOT})
82-
onnxruntime_add_include_to_target(onnxruntime)
8382

8483
target_compile_definitions(onnxruntime PRIVATE VER_MAJOR=${VERSION_MAJOR_PART})
8584
target_compile_definitions(onnxruntime PRIVATE VER_MINOR=${VERSION_MINOR_PART})

Diff for: cmake/onnxruntime_common.cmake

+1-2
Original file line numberDiff line numberDiff line change
@@ -119,10 +119,9 @@ target_include_directories(onnxruntime_common
119119
PRIVATE ${CMAKE_CURRENT_BINARY_DIR} ${ONNXRUNTIME_ROOT} ${eigen_INCLUDE_DIRS}
120120
# propagate include directories of dependencies that are part of public interface
121121
PUBLIC
122-
$<TARGET_PROPERTY:safeint_interface,INTERFACE_INCLUDE_DIRECTORIES>
123122
${OPTIONAL_LITE_INCLUDE_DIR})
124123

125-
target_link_libraries(onnxruntime_common Boost::mp11)
124+
target_link_libraries(onnxruntime_common safeint_interface Boost::mp11)
126125

127126
if(NOT WIN32)
128127
target_include_directories(onnxruntime_common PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/external/nsync/public")

Diff for: cmake/onnxruntime_objectivec.cmake

+124
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
# Copyright (c) Microsoft Corporation. All rights reserved.
2+
# Licensed under the MIT License.
3+
4+
if(${CMAKE_VERSION} VERSION_LESS "3.18")
5+
message(FATAL_ERROR "CMake 3.18+ is required when building the Objective-C API.")
6+
endif()
7+
8+
check_language(OBJC)
9+
if(CMAKE_OBJC_COMPILER)
10+
enable_language(OBJC)
11+
else()
12+
message(FATAL_ERROR "Objective-C is not supported.")
13+
endif()
14+
15+
check_language(OBJCXX)
16+
if(CMAKE_OBJCXX_COMPILER)
17+
enable_language(OBJCXX)
18+
else()
19+
message(FATAL_ERROR "Objective-C++ is not supported.")
20+
endif()
21+
22+
add_compile_options(
23+
"$<$<COMPILE_LANGUAGE:OBJC,OBJCXX>:-Wall>"
24+
"$<$<COMPILE_LANGUAGE:OBJC,OBJCXX>:-Wextra>")
25+
if(onnxruntime_DEV_MODE)
26+
add_compile_options(
27+
"$<$<COMPILE_LANGUAGE:OBJC,OBJCXX>:-Werror>")
28+
endif()
29+
30+
set(OBJC_ROOT "${REPO_ROOT}/objectivec")
31+
32+
set(OBJC_ARC_COMPILE_OPTIONS "-fobjc-arc" "-fobjc-arc-exceptions")
33+
34+
# onnxruntime_objc target
35+
36+
# these headers are the public interface
37+
# explicitly list them here so it is easy to see what is included
38+
set(onnxruntime_objc_headers
39+
"${OBJC_ROOT}/include/onnxruntime.h"
40+
"${OBJC_ROOT}/include/onnxruntime/ort_env.h"
41+
"${OBJC_ROOT}/include/onnxruntime/ort_session.h"
42+
"${OBJC_ROOT}/include/onnxruntime/ort_value.h")
43+
44+
file(GLOB onnxruntime_objc_srcs
45+
"${OBJC_ROOT}/src/*.h"
46+
"${OBJC_ROOT}/src/*.m"
47+
"${OBJC_ROOT}/src/*.mm")
48+
49+
# files common to implementation and test targets
50+
set(onnxruntime_objc_common_srcs
51+
"${OBJC_ROOT}/common/assert_arc_enabled.mm")
52+
53+
source_group(TREE "${OBJC_ROOT}" FILES
54+
${onnxruntime_objc_headers}
55+
${onnxruntime_objc_srcs}
56+
${onnxruntime_objc_common_srcs})
57+
58+
add_library(onnxruntime_objc SHARED
59+
${onnxruntime_objc_headers}
60+
${onnxruntime_objc_srcs}
61+
${onnxruntime_objc_common_srcs})
62+
63+
target_include_directories(onnxruntime_objc
64+
PUBLIC
65+
"${OBJC_ROOT}/include"
66+
PRIVATE
67+
"${ONNXRUNTIME_ROOT}"
68+
"${OBJC_ROOT}")
69+
70+
find_library(FOUNDATION_LIB Foundation REQUIRED)
71+
72+
target_link_libraries(onnxruntime_objc
73+
PRIVATE
74+
onnxruntime
75+
safeint_interface
76+
${FOUNDATION_LIB})
77+
78+
target_compile_options(onnxruntime_objc PRIVATE ${OBJC_ARC_COMPILE_OPTIONS})
79+
80+
set_target_properties(onnxruntime_objc PROPERTIES
81+
FRAMEWORK TRUE
82+
VERSION "1.0.0"
83+
SOVERSION "1.0.0"
84+
FRAMEWORK_VERSION "A"
85+
PUBLIC_HEADER "${onnxruntime_objc_headers}"
86+
FOLDER "ONNXRuntime"
87+
CXX_STANDARD 17) # TODO remove when everything else moves to 17
88+
89+
if(onnxruntime_BUILD_UNIT_TESTS)
90+
find_package(XCTest REQUIRED)
91+
92+
# onnxruntime_test_objc target
93+
94+
file(GLOB onnxruntime_objc_test_srcs
95+
"${OBJC_ROOT}/test/*.h"
96+
"${OBJC_ROOT}/test/*.m"
97+
"${OBJC_ROOT}/test/*.mm")
98+
99+
source_group(TREE "${OBJC_ROOT}" FILES ${onnxruntime_objc_test_srcs})
100+
101+
xctest_add_bundle(onnxruntime_objc_test onnxruntime_objc
102+
${onnxruntime_objc_headers}
103+
${onnxruntime_objc_test_srcs}
104+
${onnxruntime_objc_common_srcs})
105+
106+
target_include_directories(onnxruntime_objc_test
107+
PRIVATE
108+
"${OBJC_ROOT}")
109+
110+
target_compile_options(onnxruntime_objc_test PRIVATE ${OBJC_ARC_COMPILE_OPTIONS})
111+
112+
set_target_properties(onnxruntime_objc_test PROPERTIES
113+
FOLDER "ONNXRuntimeTest")
114+
115+
add_custom_command(TARGET onnxruntime_objc_test POST_BUILD
116+
COMMAND ${CMAKE_COMMAND} -E copy_directory
117+
"${OBJC_ROOT}/test/testdata"
118+
"$<TARGET_BUNDLE_CONTENT_DIR:onnxruntime_objc_test>/Resources/testdata")
119+
120+
xctest_add_test(XCTest.onnxruntime_objc_test onnxruntime_objc_test)
121+
122+
set_property(TEST XCTest.onnxruntime_objc_test APPEND PROPERTY
123+
ENVIRONMENT "DYLD_LIBRARY_PATH=$<TARGET_FILE_DIR:onnxruntime>")
124+
endif()

Diff for: cmake/onnxruntime_providers.cmake

+1-1
Original file line numberDiff line numberDiff line change
@@ -1041,7 +1041,7 @@ if (onnxruntime_USE_ROCM)
10411041
endif()
10421042
# During transition to separate hipFFT repo, put hipfft/include early
10431043
target_include_directories(onnxruntime_providers_rocm PRIVATE ${onnxruntime_ROCM_HOME}/hipfft/include ${onnxruntime_ROCM_HOME}/include ${onnxruntime_ROCM_HOME}/hipcub/include ${onnxruntime_ROCM_HOME}/hiprand/include ${onnxruntime_ROCM_HOME}/rocrand/include)
1044-
target_include_directories(onnxruntime_providers_rocm PRIVATE ${ONNXRUNTIME_ROOT} ${CMAKE_CURRENT_BINARY_DIR}/amdgpu/onnxruntime ${MPI_INCLUDE_DIRS} ${SAFEINT_INCLUDE_DIR} ${ONNXRUNTIME_ROOT}/../cmake/external/eigen)
1044+
target_include_directories(onnxruntime_providers_rocm PRIVATE ${ONNXRUNTIME_ROOT} ${CMAKE_CURRENT_BINARY_DIR}/amdgpu/onnxruntime ${MPI_INCLUDE_DIRS} ${ONNXRUNTIME_ROOT}/../cmake/external/eigen)
10451045

10461046
if (onnxruntime_ENABLE_TRAINING)
10471047
target_include_directories(onnxruntime_providers_rocm PRIVATE ${ORTTRAINING_ROOT} ${CMAKE_CURRENT_BINARY_DIR}/amdgpu/orttraining)

Diff for: docs/Coding_Conventions_and_Standards.md

+5
Original file line numberDiff line numberDiff line change
@@ -70,3 +70,8 @@ The [autopep8](https://pypi.org/project/autopep8/) tool can be used to automatic
7070

7171
Editors such as PyCharm [(see here)](https://www.jetbrains.com/help/pycharm/code-inspection.html) and Visual Studio Code [(see here)](https://code.visualstudio.com/docs/python/linting#_flake8) can be configured to check for PEP8 issues.
7272

73+
## Objective-C/C++ Code Style
74+
75+
Please follow the [Google Objective-C/C++ Style Guide](https://google.github.io/styleguide/objcguide.html).
76+
77+
Clang-format can be used to format Objective-C/C++ code. The .clang-format file is in the repository root directory.

Diff for: include/onnxruntime/core/session/onnxruntime_c_api.h

+18-18
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ ORT_RUNTIME_CLASS(Env);
157157
ORT_RUNTIME_CLASS(Status); // nullptr for Status* indicates success
158158
ORT_RUNTIME_CLASS(MemoryInfo);
159159
ORT_RUNTIME_CLASS(IoBinding);
160-
ORT_RUNTIME_CLASS(Session); //Don't call OrtReleaseSession from Dllmain (because session owns a thread pool)
160+
ORT_RUNTIME_CLASS(Session); //Don't call ReleaseSession from Dllmain (because session owns a thread pool)
161161
ORT_RUNTIME_CLASS(Value);
162162
ORT_RUNTIME_CLASS(RunOptions);
163163
ORT_RUNTIME_CLASS(TypeInfo);
@@ -343,12 +343,12 @@ struct OrtApi {
343343
const char*(ORT_API_CALL* GetErrorMessage)(_In_ const OrtStatus* status)NO_EXCEPTION ORT_ALL_ARGS_NONNULL;
344344

345345
/**
346-
* \param out Should be freed by `OrtReleaseEnv` after use
346+
* \param out Should be freed by `ReleaseEnv` after use
347347
*/
348348
ORT_API2_STATUS(CreateEnv, OrtLoggingLevel logging_level, _In_ const char* logid, _Outptr_ OrtEnv** out);
349349

350350
/**
351-
* \param out Should be freed by `OrtReleaseEnv` after use
351+
* \param out Should be freed by `ReleaseEnv` after use
352352
*/
353353
ORT_API2_STATUS(CreateEnvWithCustomLogger, OrtLoggingFunction logging_function, _In_opt_ void* logger_param,
354354
OrtLoggingLevel logging_level, _In_ const char* logid, _Outptr_ OrtEnv** out);
@@ -375,7 +375,7 @@ struct OrtApi {
375375
_Inout_updates_all_(output_names_len) OrtValue** output);
376376

377377
/**
378-
* \return A pointer of the newly created object. The pointer should be freed by OrtReleaseSessionOptions after use
378+
* \return A pointer of the newly created object. The pointer should be freed by ReleaseSessionOptions after use
379379
*/
380380
ORT_API2_STATUS(CreateSessionOptions, _Outptr_ OrtSessionOptions** options);
381381

@@ -432,7 +432,7 @@ struct OrtApi {
432432
ORT_API2_STATUS(SetInterOpNumThreads, _Inout_ OrtSessionOptions* options, int inter_op_num_threads);
433433

434434
/*
435-
Create a custom op domain. After all sessions using it are released, call OrtReleaseCustomOpDomain
435+
Create a custom op domain. After all sessions using it are released, call ReleaseCustomOpDomain
436436
*/
437437
ORT_API2_STATUS(CreateCustomOpDomain, _In_ const char* domain, _Outptr_ OrtCustomOpDomain** out);
438438

@@ -474,18 +474,18 @@ struct OrtApi {
474474
ORT_API2_STATUS(SessionGetOverridableInitializerCount, _In_ const OrtSession* sess, _Out_ size_t* out);
475475

476476
/**
477-
* \param out should be freed by OrtReleaseTypeInfo after use
477+
* \param out should be freed by ReleaseTypeInfo after use
478478
*/
479479
ORT_API2_STATUS(SessionGetInputTypeInfo, _In_ const OrtSession* sess, size_t index, _Outptr_ OrtTypeInfo** type_info);
480480

481481
/**
482-
* \param out should be freed by OrtReleaseTypeInfo after use
482+
* \param out should be freed by ReleaseTypeInfo after use
483483
*/
484484
ORT_API2_STATUS(SessionGetOutputTypeInfo, _In_ const OrtSession* sess, size_t index,
485485
_Outptr_ OrtTypeInfo** type_info);
486486

487487
/**
488-
* \param out should be freed by OrtReleaseTypeInfo after use
488+
* \param out should be freed by ReleaseTypeInfo after use
489489
*/
490490
ORT_API2_STATUS(SessionGetOverridableInitializerTypeInfo, _In_ const OrtSession* sess, size_t index,
491491
_Outptr_ OrtTypeInfo** type_info);
@@ -501,7 +501,7 @@ struct OrtApi {
501501
_Inout_ OrtAllocator* allocator, _Outptr_ char** value);
502502

503503
/**
504-
* \return A pointer to the newly created object. The pointer should be freed by OrtReleaseRunOptions after use
504+
* \return A pointer to the newly created object. The pointer should be freed by ReleaseRunOptions after use
505505
*/
506506
ORT_API2_STATUS(CreateRunOptions, _Outptr_ OrtRunOptions** out);
507507

@@ -520,17 +520,17 @@ struct OrtApi {
520520
ORT_API2_STATUS(RunOptionsUnsetTerminate, _Inout_ OrtRunOptions* options);
521521

522522
/**
523-
* Create a tensor from an allocator. OrtReleaseValue will also release the buffer inside the output value
524-
* \param out Should be freed by calling OrtReleaseValue
523+
* Create a tensor from an allocator. ReleaseValue will also release the buffer inside the output value
524+
* \param out Should be freed by calling ReleaseValue
525525
* \param type must be one of TENSOR_ELEMENT_DATA_TYPE_xxxx
526526
*/
527527
ORT_API2_STATUS(CreateTensorAsOrtValue, _Inout_ OrtAllocator* allocator, _In_ const int64_t* shape, size_t shape_len,
528528
ONNXTensorElementDataType type, _Outptr_ OrtValue** out);
529529

530530
/**
531531
* Create a tensor with user's buffer. You can fill the buffer either before calling this function or after.
532-
* p_data is owned by caller. OrtReleaseValue won't release p_data.
533-
* \param out Should be freed by calling OrtReleaseValue
532+
* p_data is owned by caller. ReleaseValue won't release p_data.
533+
* \param out Should be freed by calling ReleaseValue
534534
*/
535535
ORT_API2_STATUS(CreateTensorWithDataAsOrtValue, _In_ const OrtMemoryInfo* info, _Inout_ void* p_data,
536536
size_t p_data_len, _In_ const int64_t* shape, size_t shape_len, ONNXTensorElementDataType type,
@@ -578,7 +578,7 @@ struct OrtApi {
578578
ORT_API2_STATUS(GetOnnxTypeFromTypeInfo, _In_ const OrtTypeInfo*, _Out_ enum ONNXType* out);
579579

580580
/**
581-
* The 'out' value should be released by calling OrtReleaseTensorTypeAndShapeInfo
581+
* The 'out' value should be released by calling ReleaseTensorTypeAndShapeInfo
582582
*/
583583
ORT_API2_STATUS(CreateTensorTypeAndShapeInfo, _Outptr_ OrtTensorTypeAndShapeInfo** out);
584584

@@ -611,14 +611,14 @@ struct OrtApi {
611611
ORT_API2_STATUS(GetTensorShapeElementCount, _In_ const OrtTensorTypeAndShapeInfo* info, _Out_ size_t* out);
612612

613613
/**
614-
* \param out Should be freed by OrtReleaseTensorTypeAndShapeInfo after use
614+
* \param out Should be freed by ReleaseTensorTypeAndShapeInfo after use
615615
*/
616616
ORT_API2_STATUS(GetTensorTypeAndShape, _In_ const OrtValue* value, _Outptr_ OrtTensorTypeAndShapeInfo** out);
617617

618618
/**
619619
* Get the type information of an OrtValue
620620
* \param value
621-
* \param out The returned value should be freed by OrtReleaseTypeInfo after use
621+
* \param out The returned value should be freed by ReleaseTypeInfo after use
622622
*/
623623
ORT_API2_STATUS(GetTypeInfo, _In_ const OrtValue* value, _Outptr_result_maybenull_ OrtTypeInfo** out);
624624

@@ -793,7 +793,7 @@ struct OrtApi {
793793
ORT_CLASS_RELEASE(Env);
794794
ORT_CLASS_RELEASE(Status); // nullptr for Status* indicates success
795795
ORT_CLASS_RELEASE(MemoryInfo);
796-
ORT_CLASS_RELEASE(Session); //Don't call OrtReleaseSession from Dllmain (because session owns a thread pool)
796+
ORT_CLASS_RELEASE(Session); //Don't call ReleaseSession from Dllmain (because session owns a thread pool)
797797
ORT_CLASS_RELEASE(Value);
798798
ORT_CLASS_RELEASE(RunOptions);
799799
ORT_CLASS_RELEASE(TypeInfo);
@@ -1156,7 +1156,7 @@ struct OrtApi {
11561156
* Use this in conjunction with DisablePerSessionThreads API or else the session will use
11571157
* its own thread pools.
11581158
*
1159-
* \param out should be freed by `OrtReleaseEnv` after use
1159+
* \param out should be freed by `ReleaseEnv` after use
11601160
*/
11611161
ORT_API2_STATUS(CreateEnvWithCustomLoggerAndGlobalThreadPools, OrtLoggingFunction logging_function, _In_opt_ void* logger_param, OrtLoggingLevel logging_level,
11621162
_In_ const char* logid, _In_ const struct OrtThreadingOptions* tp_options, _Outptr_ OrtEnv** out);

Diff for: objectivec/common/assert_arc_enabled.mm

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT License.
3+
4+
static_assert(__has_feature(objc_arc), "Objective-C ARC must be enabled.");

Diff for: objectivec/format_objc.sh

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
#!/bin/bash
2+
3+
# formats Objective-C/C++ code
4+
5+
set -e
6+
7+
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
8+
9+
clang-format -i $(find ${SCRIPT_DIR} -name "*.h" -o -name "*.m" -o -name "*.mm")
10+

Diff for: objectivec/include/onnxruntime.h

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT License.
3+
4+
// this header contains the entire ONNX Runtime Objective-C API
5+
// the headers below can also be imported individually
6+
7+
#import "onnxruntime/ort_env.h"
8+
#import "onnxruntime/ort_session.h"
9+
#import "onnxruntime/ort_value.h"

Diff for: objectivec/include/onnxruntime/ort_env.h

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT License.
3+
4+
#import <Foundation/Foundation.h>
5+
6+
NS_ASSUME_NONNULL_BEGIN
7+
8+
/**
9+
* The ORT environment.
10+
*/
11+
@interface ORTEnv : NSObject
12+
13+
- (nullable instancetype)init NS_UNAVAILABLE;
14+
15+
/**
16+
* Creates an ORT Environment.
17+
*
18+
* @param[out] error Optional error information set if an error occurs.
19+
* @return The instance, or nil if an error occurs.
20+
*/
21+
- (nullable instancetype)initWithError:(NSError**)error NS_DESIGNATED_INITIALIZER;
22+
23+
@end
24+
25+
NS_ASSUME_NONNULL_END

0 commit comments

Comments
 (0)