Cherry picks for release - 1.8.2, 2nd attempt (#8620)

* Add test for iOS package (#7816)

* Add test for iOS package

* Add readme

* fix pep8 warning

* Addressed CR comments, fixed CI failure

* Address CR comments

* Update readme.md

* Update package name and readme, added comments to the podspec

* Add podspec template for ios package, update build settings (#7907)

* Add podspec template for ios package

* minor formatting update

* Add spec.source_files for header files

* Update spec.public_header_files to spec.source_files

* minor update

* Add iOS packaging pipeline (#8264)

Create a pipeline to produce the iOS package artifacts.

* [iOS] Packaging pipeline improvements. (#8324)

Updates to the iOS packaging pipeline:
- Make it harder to overwrite package archives accidentally when uploading (fails if the archive already exists)
- Only upload package archives for release builds
- Some clean up

* Add metadata_props to ORT model (#8340)

* Add metadata_props to ORT model

* Minor update

* Update python binding, and increase the minimal pipeline size threshold

* Fixed a small bug in serializing ir_version

* Remove temp ort.py.fbs and add it to .gitignore

* Add iOS/macOS static framework (#8357)

* Add ability to generate ios static framework

* Fix typos

* Add pod cache clean, update some comments of previous commit

* Fix CI failure with newly added cpuinfo library

* Update test model (CoreML requires node has a name)

* Addressed CR comments

* Fix iOS packaging pipeline failure (#8433)

* Fix optimizer crash (#8274)

* Update iOS packaging script to default build static framework, disable bitcode (#8533)

* default package build to static, disable bitcode

* fix pipeline failure

* Address CR comments

* Add HardSigmoid to mobile packages. Used by PyTorch MobileNet v3 (#8552)

* bump the version number to 1.8.2

* Change Windows GPU machine pool to onnxruntime-win-cuda11-0

* [Objective-C API] Fix ORTIsCoreMLExecutionProviderAvailable link error when used from Swift. (#8350)

Co-authored-by: Edward Chen <18449977+edgchen1@users.noreply.github.com>
Co-authored-by: RandySheriffH <48490400+RandySheriffH@users.noreply.github.com>
Co-authored-by: Scott McKay <skottmckay@gmail.com>
Co-authored-by: Changming Sun <chasun@microsoft.com>
This commit is contained in:
Guoyu Wang 2021-08-04 19:07:27 -07:00 committed by GitHub
parent 96bb4b1ce8
commit 55278056ad
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
53 changed files with 1947 additions and 140 deletions

View file

@ -1 +1 @@
1.8.1
1.8.2

View file

@ -66,10 +66,18 @@ elseif(onnxruntime_BUILD_APPLE_FRAMEWORK)
"${CMAKE_CURRENT_BINARY_DIR}/generated_source.c"
)
# create Info.plist for the framework and podspec for CocoaPods (optional)
set(MACOSX_FRAMEWORK_NAME "onnxruntime")
set(MACOSX_FRAMEWORK_IDENTIFIER "com.microsoft.onnxruntime")
configure_file(${REPO_ROOT}/cmake/Info.plist.in ${CMAKE_CURRENT_BINARY_DIR}/Info.plist)
# Need to include CoreML as a weaklink for CocoaPods package if the EP is enabled
if(onnxruntime_USE_COREML)
set(APPLE_WEAK_FRAMEWORK "\\\"CoreML\\\"")
endif()
set(INFO_PLIST_PATH "${CMAKE_CURRENT_BINARY_DIR}/Info.plist")
configure_file(${REPO_ROOT}/cmake/Info.plist.in ${INFO_PLIST_PATH})
configure_file(
${REPO_ROOT}/tools/ci_build/github/apple/framework_info.json.template
${CMAKE_CURRENT_BINARY_DIR}/framework_info.json)
set_target_properties(onnxruntime PROPERTIES
FRAMEWORK TRUE
FRAMEWORK_VERSION A
@ -145,40 +153,50 @@ if(CMAKE_SYSTEM_NAME STREQUAL "Android" AND onnxruntime_BUILD_JAVA)
# copy the header files one by one
foreach(h_ ${ANDROID_AAR_HEADERS})
get_filename_component(HEADER_NAME_ ${h_} NAME)
configure_file(${h_} ${ANDROID_HEADERS_DIR}/${HEADER_NAME_} COPYONLY)
add_custom_command(TARGET onnxruntime POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different ${h_} ${ANDROID_HEADERS_DIR}/${HEADER_NAME_})
endforeach()
endif()
target_link_libraries(onnxruntime PRIVATE
onnxruntime_session
${onnxruntime_libs}
${PROVIDERS_ACL}
${PROVIDERS_ARMNN}
${PROVIDERS_COREML}
${PROVIDERS_DML}
${PROVIDERS_MIGRAPHX}
${PROVIDERS_NNAPI}
${PROVIDERS_NUPHAR}
${PROVIDERS_RKNPU}
${PROVIDERS_ROCM}
${PROVIDERS_VITISAI}
${PROVIDERS_INTERNAL_TESTING}
${onnxruntime_winml}
onnxruntime_optimizer
onnxruntime_providers
onnxruntime_util
${onnxruntime_tvm_libs}
onnxruntime_framework
onnxruntime_graph
onnxruntime_common
onnxruntime_mlas
onnxruntime_flatbuffers
${onnxruntime_EXTERNAL_LIBRARIES})
set(onnxruntime_INTERNAL_LIBRARIES
onnxruntime_session
${onnxruntime_libs}
${PROVIDERS_ACL}
${PROVIDERS_ARMNN}
${PROVIDERS_COREML}
${PROVIDERS_DML}
${PROVIDERS_MIGRAPHX}
${PROVIDERS_NNAPI}
${PROVIDERS_NUPHAR}
${PROVIDERS_RKNPU}
${PROVIDERS_ROCM}
${PROVIDERS_VITISAI}
${PROVIDERS_INTERNAL_TESTING}
${onnxruntime_winml}
onnxruntime_optimizer
onnxruntime_providers
onnxruntime_util
${onnxruntime_tvm_libs}
onnxruntime_framework
onnxruntime_graph
onnxruntime_common
onnxruntime_mlas
onnxruntime_flatbuffers
)
if (onnxruntime_ENABLE_LANGUAGE_INTEROP_OPS)
target_link_libraries(onnxruntime PRIVATE onnxruntime_language_interop onnxruntime_pyop)
list(APPEND onnxruntime_INTERNAL_LIBRARIES
onnxruntime_language_interop
onnxruntime_pyop
)
endif()
# If you are linking a new library, please add it to the list onnxruntime_INTERNAL_LIBRARIES or onnxruntime_EXTERNAL_LIBRARIES,
# Please do not add a library directly to the target_link_libraries command
target_link_libraries(onnxruntime PRIVATE
${onnxruntime_INTERNAL_LIBRARIES}
${onnxruntime_EXTERNAL_LIBRARIES}
)
set_property(TARGET onnxruntime APPEND_STRING PROPERTY LINK_FLAGS ${ONNXRUNTIME_SO_LINK_FLAG} ${onnxruntime_DELAYLOAD_FLAGS})
set_target_properties(onnxruntime PROPERTIES LINK_DEPENDS ${SYMBOL_FILE})
@ -196,3 +214,47 @@ set_target_properties(onnxruntime PROPERTIES FOLDER "ONNXRuntime")
if (WINDOWS_STORE)
target_link_options(onnxruntime PRIVATE /DELAYLOAD:api-ms-win-core-libraryloader-l1-2-1.dll)
endif()
# Assemble the Apple static framework (iOS and macOS)
if(onnxruntime_BUILD_APPLE_FRAMEWORK)
set(STATIC_LIB_DIR ${CMAKE_CURRENT_BINARY_DIR}/static_libraries)
file(MAKE_DIRECTORY ${STATIC_LIB_DIR})
# Remove the existing files in the STATIC_LIB_DIR folder
file(GLOB _OLD_STATIC_LIBS ${STATIC_LIB_DIR}/*.a)
file(REMOVE "${_OLD_STATIC_LIBS}")
# Go through all the static libraries, and create symbolic links
foreach(_LIB ${onnxruntime_INTERNAL_LIBRARIES} ${onnxruntime_EXTERNAL_LIBRARIES})
GET_TARGET_PROPERTY(_LIB_TYPE ${_LIB} TYPE)
if(_LIB_TYPE STREQUAL "STATIC_LIBRARY")
add_custom_command(TARGET onnxruntime POST_BUILD COMMAND ${CMAKE_COMMAND} -E create_symlink $<TARGET_FILE:${_LIB}> ${STATIC_LIB_DIR}/$<TARGET_LINKER_FILE_NAME:${_LIB}>)
endif()
endforeach()
if(${CMAKE_SYSTEM_NAME} STREQUAL "iOS")
set(STATIC_FRAMEWORK_OUTPUT_DIR ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_BUILD_TYPE}-${CMAKE_OSX_SYSROOT})
else() # macOS
set(STATIC_FRAMEWORK_OUTPUT_DIR ${CMAKE_CURRENT_BINARY_DIR})
endif()
# Assemble the static framework
set(STATIC_FRAMEWORK_DIR ${STATIC_FRAMEWORK_OUTPUT_DIR}/static_framework/onnxruntime.framework)
set(STATIC_FRAMEWORK_HEADER_DIR ${STATIC_FRAMEWORK_DIR}/Headers)
file(MAKE_DIRECTORY ${STATIC_FRAMEWORK_DIR})
# Remove all files under STATIC_FRAMEWORK_DIR (if any)
file(GLOB_RECURSE _OLD_STATIC_FRAMEWORK ${STATIC_FRAMEWORK_DIR}/*.*)
file(REMOVE "${_OLD_STATIC_FRAMEWORK}")
file(MAKE_DIRECTORY ${STATIC_FRAMEWORK_HEADER_DIR})
# copy the header files one by one, and the Info.plist
foreach(h_ ${APPLE_FRAMEWORK_HEADERS})
get_filename_component(HEADER_NAME_ ${h_} NAME)
add_custom_command(TARGET onnxruntime POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different ${h_} ${STATIC_FRAMEWORK_HEADER_DIR}/${HEADER_NAME_})
endforeach()
add_custom_command(TARGET onnxruntime POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different ${INFO_PLIST_PATH} ${STATIC_FRAMEWORK_DIR}/Info.plist)
# link the static library
add_custom_command(TARGET onnxruntime POST_BUILD COMMAND libtool -static -o ${STATIC_FRAMEWORK_DIR}/onnxruntime *.a WORKING_DIRECTORY ${STATIC_LIB_DIR})
endif()

View file

@ -57,16 +57,16 @@ file(GLOB onnxruntime_providers_common_srcs CONFIGURE_DEPENDS
)
if(onnxruntime_USE_NUPHAR)
set(PROVIDERS_NUPHAR onnxruntime_providers_nuphar)
set(PROVIDERS_NUPHAR onnxruntime_providers_nuphar)
endif()
if(onnxruntime_USE_VITISAI)
set(PROVIDERS_VITISAI onnxruntime_providers_vitisai)
set(PROVIDERS_VITISAI onnxruntime_providers_vitisai)
endif()
if(onnxruntime_USE_CUDA)
set(PROVIDERS_CUDA onnxruntime_providers_cuda)
endif()
if(onnxruntime_USE_COREML)
set(PROVIDERS_COREML onnxruntime_providers_coreml)
set(PROVIDERS_COREML onnxruntime_providers_coreml onnxruntime_coreml_proto)
endif()
if(onnxruntime_USE_NNAPI_BUILTIN)
set(PROVIDERS_NNAPI onnxruntime_providers_nnapi)
@ -75,7 +75,7 @@ if(onnxruntime_USE_RKNPU)
set(PROVIDERS_RKNPU onnxruntime_providers_rknpu)
endif()
if(onnxruntime_USE_DML)
set(PROVIDERS_DML onnxruntime_providers_dml)
set(PROVIDERS_DML onnxruntime_providers_dml)
endif()
if(onnxruntime_USE_MIGRAPHX)
set(PROVIDERS_MIGRAPHX onnxruntime_providers_migraphx)
@ -84,13 +84,13 @@ if(onnxruntime_USE_WINML)
set(PROVIDERS_WINML onnxruntime_providers_winml)
endif()
if(onnxruntime_USE_ACL)
set(PROVIDERS_ACL onnxruntime_providers_acl)
set(PROVIDERS_ACL onnxruntime_providers_acl)
endif()
if(onnxruntime_USE_ARMNN)
set(PROVIDERS_ARMNN onnxruntime_providers_armnn)
set(PROVIDERS_ARMNN onnxruntime_providers_armnn)
endif()
if(onnxruntime_USE_ROCM)
set(PROVIDERS_ROCM onnxruntime_providers_rocm)
set(PROVIDERS_ROCM onnxruntime_providers_rocm)
endif()
source_group(TREE ${ONNXRUNTIME_ROOT}/core FILES ${onnxruntime_providers_common_srcs} ${onnxruntime_providers_srcs})

View file

@ -5,13 +5,21 @@
#import "ort_session.h"
NS_ASSUME_NONNULL_BEGIN
#ifdef __cplusplus
extern "C" {
#endif
/**
* Gets whether the CoreML execution provider is available.
*/
BOOL ORTIsCoreMLExecutionProviderAvailable(void);
#ifdef __cplusplus
}
#endif
NS_ASSUME_NONNULL_BEGIN
/**
* Options for configuring the CoreML execution provider.
*/

View file

@ -109,7 +109,32 @@ class Model(object):
return self._tab.String(o + self._tab.Pos)
return None
def ModelStart(builder): builder.StartObject(9)
# Model
def MetadataProps(self, j):
o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(22))
if o != 0:
x = self._tab.Vector(o)
x += flatbuffers.number_types.UOffsetTFlags.py_type(j) * 4
x = self._tab.Indirect(x)
from ort_flatbuffers_py.experimental.fbs.StringStringEntry import StringStringEntry
obj = StringStringEntry()
obj.Init(self._tab.Bytes, x)
return obj
return None
# Model
def MetadataPropsLength(self):
o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(22))
if o != 0:
return self._tab.VectorLen(o)
return 0
# Model
def MetadataPropsIsNone(self):
o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(22))
return o == 0
def ModelStart(builder): builder.StartObject(10)
def ModelAddIrVersion(builder, irVersion): builder.PrependInt64Slot(0, irVersion, 0)
def ModelAddOpsetImport(builder, opsetImport): builder.PrependUOffsetTRelativeSlot(1, flatbuffers.number_types.UOffsetTFlags.py_type(opsetImport), 0)
def ModelStartOpsetImportVector(builder, numElems): return builder.StartVector(4, numElems, 4)
@ -120,4 +145,6 @@ def ModelAddModelVersion(builder, modelVersion): builder.PrependInt64Slot(5, mod
def ModelAddDocString(builder, docString): builder.PrependUOffsetTRelativeSlot(6, flatbuffers.number_types.UOffsetTFlags.py_type(docString), 0)
def ModelAddGraph(builder, graph): builder.PrependUOffsetTRelativeSlot(7, flatbuffers.number_types.UOffsetTFlags.py_type(graph), 0)
def ModelAddGraphDocString(builder, graphDocString): builder.PrependUOffsetTRelativeSlot(8, flatbuffers.number_types.UOffsetTFlags.py_type(graphDocString), 0)
def ModelAddMetadataProps(builder, metadataProps): builder.PrependUOffsetTRelativeSlot(9, flatbuffers.number_types.UOffsetTFlags.py_type(metadataProps), 0)
def ModelStartMetadataPropsVector(builder, numElems): return builder.StartVector(4, numElems, 4)
def ModelEnd(builder): return builder.EndObject()

View file

@ -0,0 +1,44 @@
# automatically generated by the FlatBuffers compiler, do not modify
# namespace: fbs
import flatbuffers
from flatbuffers.compat import import_numpy
np = import_numpy()
class StringStringEntry(object):
__slots__ = ['_tab']
@classmethod
def GetRootAsStringStringEntry(cls, buf, offset):
n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
x = StringStringEntry()
x.Init(buf, n + offset)
return x
@classmethod
def StringStringEntryBufferHasIdentifier(cls, buf, offset, size_prefixed=False):
return flatbuffers.util.BufferHasIdentifier(buf, offset, b"\x4F\x52\x54\x4D", size_prefixed=size_prefixed)
# StringStringEntry
def Init(self, buf, pos):
self._tab = flatbuffers.table.Table(buf, pos)
# StringStringEntry
def Key(self):
o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
if o != 0:
return self._tab.String(o + self._tab.Pos)
return None
# StringStringEntry
def Value(self):
o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(6))
if o != 0:
return self._tab.String(o + self._tab.Pos)
return None
def StringStringEntryStart(builder): builder.StartObject(2)
def StringStringEntryAddKey(builder, key): builder.PrependUOffsetTRelativeSlot(0, flatbuffers.number_types.UOffsetTFlags.py_type(key), 0)
def StringStringEntryAddValue(builder, value): builder.PrependUOffsetTRelativeSlot(1, flatbuffers.number_types.UOffsetTFlags.py_type(value), 0)
def StringStringEntryEnd(builder): return builder.EndObject()

View file

@ -0,0 +1 @@
ort.py.fbs

View file

@ -194,6 +194,11 @@ table Graph{
sparse_initializers:[SparseTensor];
}
table StringStringEntry {
key:string;
value:string;
}
table Model {
ir_version:int64;
opset_import:[OperatorSetId];
@ -202,10 +207,11 @@ table Model {
domain:string;
model_version:int64;
doc_string:string;
graph:Graph;
graph_doc_string:string;
metadata_props:[StringStringEntry];
}
table KernelCreateInfos {

View file

@ -57,6 +57,9 @@ struct AttributeBuilder;
struct Graph;
struct GraphBuilder;
struct StringStringEntry;
struct StringStringEntryBuilder;
struct Model;
struct ModelBuilder;
@ -1805,6 +1808,72 @@ inline flatbuffers::Offset<Graph> CreateGraphDirect(
sparse_initializers__);
}
struct StringStringEntry FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
typedef StringStringEntryBuilder Builder;
enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
VT_KEY = 4,
VT_VALUE = 6
};
const flatbuffers::String *key() const {
return GetPointer<const flatbuffers::String *>(VT_KEY);
}
const flatbuffers::String *value() const {
return GetPointer<const flatbuffers::String *>(VT_VALUE);
}
bool Verify(flatbuffers::Verifier &verifier) const {
return VerifyTableStart(verifier) &&
VerifyOffset(verifier, VT_KEY) &&
verifier.VerifyString(key()) &&
VerifyOffset(verifier, VT_VALUE) &&
verifier.VerifyString(value()) &&
verifier.EndTable();
}
};
struct StringStringEntryBuilder {
typedef StringStringEntry Table;
flatbuffers::FlatBufferBuilder &fbb_;
flatbuffers::uoffset_t start_;
void add_key(flatbuffers::Offset<flatbuffers::String> key) {
fbb_.AddOffset(StringStringEntry::VT_KEY, key);
}
void add_value(flatbuffers::Offset<flatbuffers::String> value) {
fbb_.AddOffset(StringStringEntry::VT_VALUE, value);
}
explicit StringStringEntryBuilder(flatbuffers::FlatBufferBuilder &_fbb)
: fbb_(_fbb) {
start_ = fbb_.StartTable();
}
StringStringEntryBuilder &operator=(const StringStringEntryBuilder &);
flatbuffers::Offset<StringStringEntry> Finish() {
const auto end = fbb_.EndTable(start_);
auto o = flatbuffers::Offset<StringStringEntry>(end);
return o;
}
};
inline flatbuffers::Offset<StringStringEntry> CreateStringStringEntry(
flatbuffers::FlatBufferBuilder &_fbb,
flatbuffers::Offset<flatbuffers::String> key = 0,
flatbuffers::Offset<flatbuffers::String> value = 0) {
StringStringEntryBuilder builder_(_fbb);
builder_.add_value(value);
builder_.add_key(key);
return builder_.Finish();
}
inline flatbuffers::Offset<StringStringEntry> CreateStringStringEntryDirect(
flatbuffers::FlatBufferBuilder &_fbb,
const char *key = nullptr,
const char *value = nullptr) {
auto key__ = key ? _fbb.CreateString(key) : 0;
auto value__ = value ? _fbb.CreateString(value) : 0;
return onnxruntime::experimental::fbs::CreateStringStringEntry(
_fbb,
key__,
value__);
}
struct Model FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
typedef ModelBuilder Builder;
enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
@ -1816,7 +1885,8 @@ struct Model FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
VT_MODEL_VERSION = 14,
VT_DOC_STRING = 16,
VT_GRAPH = 18,
VT_GRAPH_DOC_STRING = 20
VT_GRAPH_DOC_STRING = 20,
VT_METADATA_PROPS = 22
};
int64_t ir_version() const {
return GetField<int64_t>(VT_IR_VERSION, 0);
@ -1845,6 +1915,9 @@ struct Model FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
const flatbuffers::String *graph_doc_string() const {
return GetPointer<const flatbuffers::String *>(VT_GRAPH_DOC_STRING);
}
const flatbuffers::Vector<flatbuffers::Offset<onnxruntime::experimental::fbs::StringStringEntry>> *metadata_props() const {
return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<onnxruntime::experimental::fbs::StringStringEntry>> *>(VT_METADATA_PROPS);
}
bool Verify(flatbuffers::Verifier &verifier) const {
return VerifyTableStart(verifier) &&
VerifyField<int64_t>(verifier, VT_IR_VERSION) &&
@ -1864,6 +1937,9 @@ struct Model FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
verifier.VerifyTable(graph()) &&
VerifyOffset(verifier, VT_GRAPH_DOC_STRING) &&
verifier.VerifyString(graph_doc_string()) &&
VerifyOffset(verifier, VT_METADATA_PROPS) &&
verifier.VerifyVector(metadata_props()) &&
verifier.VerifyVectorOfTables(metadata_props()) &&
verifier.EndTable();
}
};
@ -1899,6 +1975,9 @@ struct ModelBuilder {
void add_graph_doc_string(flatbuffers::Offset<flatbuffers::String> graph_doc_string) {
fbb_.AddOffset(Model::VT_GRAPH_DOC_STRING, graph_doc_string);
}
void add_metadata_props(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<onnxruntime::experimental::fbs::StringStringEntry>>> metadata_props) {
fbb_.AddOffset(Model::VT_METADATA_PROPS, metadata_props);
}
explicit ModelBuilder(flatbuffers::FlatBufferBuilder &_fbb)
: fbb_(_fbb) {
start_ = fbb_.StartTable();
@ -1921,10 +2000,12 @@ inline flatbuffers::Offset<Model> CreateModel(
int64_t model_version = 0,
flatbuffers::Offset<flatbuffers::String> doc_string = 0,
flatbuffers::Offset<onnxruntime::experimental::fbs::Graph> graph = 0,
flatbuffers::Offset<flatbuffers::String> graph_doc_string = 0) {
flatbuffers::Offset<flatbuffers::String> graph_doc_string = 0,
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<onnxruntime::experimental::fbs::StringStringEntry>>> metadata_props = 0) {
ModelBuilder builder_(_fbb);
builder_.add_model_version(model_version);
builder_.add_ir_version(ir_version);
builder_.add_metadata_props(metadata_props);
builder_.add_graph_doc_string(graph_doc_string);
builder_.add_graph(graph);
builder_.add_doc_string(doc_string);
@ -1945,13 +2026,15 @@ inline flatbuffers::Offset<Model> CreateModelDirect(
int64_t model_version = 0,
const char *doc_string = nullptr,
flatbuffers::Offset<onnxruntime::experimental::fbs::Graph> graph = 0,
const char *graph_doc_string = nullptr) {
const char *graph_doc_string = nullptr,
const std::vector<flatbuffers::Offset<onnxruntime::experimental::fbs::StringStringEntry>> *metadata_props = nullptr) {
auto opset_import__ = opset_import ? _fbb.CreateVector<flatbuffers::Offset<onnxruntime::experimental::fbs::OperatorSetId>>(*opset_import) : 0;
auto producer_name__ = producer_name ? _fbb.CreateString(producer_name) : 0;
auto producer_version__ = producer_version ? _fbb.CreateString(producer_version) : 0;
auto domain__ = domain ? _fbb.CreateString(domain) : 0;
auto doc_string__ = doc_string ? _fbb.CreateString(doc_string) : 0;
auto graph_doc_string__ = graph_doc_string ? _fbb.CreateString(graph_doc_string) : 0;
auto metadata_props__ = metadata_props ? _fbb.CreateVector<flatbuffers::Offset<onnxruntime::experimental::fbs::StringStringEntry>>(*metadata_props) : 0;
return onnxruntime::experimental::fbs::CreateModel(
_fbb,
ir_version,
@ -1962,7 +2045,8 @@ inline flatbuffers::Offset<Model> CreateModelDirect(
model_version,
doc_string__,
graph,
graph_doc_string__);
graph_doc_string__,
metadata_props__);
}
struct KernelCreateInfos FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {

View file

@ -652,18 +652,34 @@ common::Status Model::SaveToOrtFormat(flatbuffers::FlatBufferBuilder& builder,
}
auto op_set_ids = builder.CreateVector(op_set_ids_vec);
flatbuffers::Offset<flatbuffers::Vector<
flatbuffers::Offset<onnxruntime::experimental::fbs::StringStringEntry>>>
metadata_props{0};
// We will not serialize an empty metadata_props
if (!model_metadata_.empty()) {
std::vector<flatbuffers::Offset<onnxruntime::experimental::fbs::StringStringEntry>> metadata_props_vec;
metadata_props_vec.reserve(model_metadata_.size());
for (const auto& prop : model_metadata_) {
metadata_props_vec.push_back(
fbs::CreateStringStringEntryDirect(builder, prop.first.c_str(), prop.second.c_str()));
}
metadata_props = builder.CreateVector(metadata_props_vec);
}
flatbuffers::Offset<fbs::Graph> fbs_graph;
ORT_RETURN_IF_ERROR(graph_->SaveToOrtFormat(builder, fbs_graph));
fbs::ModelBuilder mb(builder);
mb.add_ir_version(model_proto_.ir_version());
mb.add_ir_version(IrVersion());
mb.add_opset_import(op_set_ids);
mb.add_producer_name(producer_name);
mb.add_producer_version(producer_version);
mb.add_domain(domain);
mb.add_model_version(model_proto_.model_version());
mb.add_model_version(ModelVersion());
mb.add_doc_string(doc_string);
mb.add_graph_doc_string(graph_doc_string);
mb.add_metadata_props(metadata_props);
mb.add_graph(fbs_graph);
// add graph
@ -686,6 +702,18 @@ common::Status Model::LoadFromOrtFormat(const fbs::Model& fbs_model,
std::unique_ptr<Model>& model) {
model.reset(new Model());
// Load the model metadata
if (const auto* fbs_metadata_props = fbs_model.metadata_props()) {
model->model_metadata_.reserve(fbs_metadata_props->size());
for (const auto* prop : *fbs_metadata_props) {
ORT_RETURN_IF(nullptr == prop, "Null entry in meta_props. Invalid ORT format model.");
std::string key, value;
experimental::utils::LoadStringFromOrtFormat(key, prop->key());
experimental::utils::LoadStringFromOrtFormat(value, prop->value());
model->model_metadata_.insert({key, value});
}
}
#if !defined(ORT_MINIMAL_BUILD)
LOAD_STR_FROM_ORT_FORMAT(model->model_proto_, producer_name, fbs_model.producer_name());
LOAD_STR_FROM_ORT_FORMAT(model->model_proto_, producer_version, fbs_model.producer_version());
@ -703,6 +731,13 @@ common::Status Model::LoadFromOrtFormat(const fbs::Model& fbs_model,
schema_registry->RegisterRegistry(schema_collection);
}
}
// Populate the metadata to model_proto
for (auto& metadata : model->model_metadata_) {
const gsl::not_null<StringStringEntryProto*> prop{model->model_proto_.add_metadata_props()};
prop->set_key(metadata.first);
prop->set_value(metadata.second);
}
#else
experimental::utils::LoadStringFromOrtFormat(model->producer_name_, fbs_model.producer_name());
experimental::utils::LoadStringFromOrtFormat(model->producer_version_, fbs_model.producer_version());

View file

@ -101,7 +101,7 @@ Status ConvActivationFusion::ApplyImpl(Graph& graph, bool& modified, int graph_l
}
if (node->GetExecutionProviderType() == onnxruntime::kCudaExecutionProvider) {
if (node->InputDefs()[0]->TypeAsProto()->tensor_type().elem_type() !=
if (node->InputDefs()[0]->TypeAsProto()->tensor_type().elem_type() !=
ONNX_NAMESPACE::TensorProto_DataType_FLOAT) {
continue;
}
@ -121,24 +121,32 @@ Status ConvActivationFusion::ApplyImpl(Graph& graph, bool& modified, int graph_l
graph_utils::FinalizeNodeFusion(graph, {conv_node, act_node}, fused_conv);
modified = true;
} else if (graph_utils::IsSupportedOptypeVersionAndDomain(next_node, "Add", {6, 7, 13, 14})) {
if (next_node.GetOutputEdgesCount() != 1) {
continue;
}
const auto& last_node = *(next_node.OutputNodesBegin());
if (last_node.GetExecutionProviderType() != node->GetExecutionProviderType()) {
continue;
}
if (graph_utils::IsSupportedOptypeVersionAndDomain(last_node, "Relu", {6, 13, 14}) &&
next_node.GetOutputEdgesCount() == 1) {
if (graph_utils::IsSupportedOptypeVersionAndDomain(last_node, "Relu", {6, 13, 14})) {
Node& conv_node = *node;
Node& add_node = *graph.GetNode(next_node.Index());
Node& act_node = *graph.GetNode(last_node.Index());
auto conv_inputs = conv_node.MutableInputDefs();
auto conv_outputs = conv_node.MutableOutputDefs();
auto add_inputs = add_node.MutableInputDefs();
int32_t dependent = 0, independent = 0;
for (auto add_input : add_inputs) {
if (add_input->Name() != conv_outputs[0]->Name()) {
if (add_input->Name() == conv_outputs[0]->Name()) {
dependent++;
} else {
conv_inputs.push_back(add_input);
break;
independent++;
}
}
if (dependent != 1 || independent != 1) {
continue;
}
auto node_name = graph.GenerateNodeName(conv_node.Name() + "_" +
add_node.Name() + "_" +
act_node.Name());

View file

@ -193,6 +193,31 @@ static void CompareGraphAndSessionState(const InferenceSessionWrapper& session_o
}
}
static void CompareSessionMetadata(const InferenceSessionWrapper& session_object_1,
const InferenceSessionWrapper& session_object_2) {
const auto pair_1 = session_object_1.GetModelMetadata();
ASSERT_STATUS_OK(pair_1.first);
const auto& metadata_1 = *pair_1.second;
const auto& model_1 = session_object_1.GetModel();
const auto pair_2 = session_object_2.GetModelMetadata();
ASSERT_STATUS_OK(pair_2.first);
const auto& metadata_2 = *pair_2.second;
const auto& model_2 = session_object_2.GetModel();
ASSERT_EQ(metadata_1.producer_name, metadata_2.producer_name);
// ORT format does not have graph name
// ASSERT_EQ(metadata_1.graph_name, metadata_2.graph_name);
ASSERT_EQ(metadata_1.domain, metadata_2.domain);
ASSERT_EQ(metadata_1.description, metadata_2.description);
ASSERT_EQ(metadata_1.graph_description, metadata_2.graph_description);
ASSERT_EQ(metadata_1.version, metadata_2.version);
ASSERT_EQ(metadata_1.custom_metadata_map, metadata_2.custom_metadata_map);
ASSERT_EQ(model_1.IrVersion(), model_2.IrVersion());
ASSERT_EQ(model_1.ProducerVersion(), model_2.ProducerVersion());
}
static void SaveAndCompareModels(const std::string& onnx_file, const std::basic_string<ORTCHAR_T>& ort_file) {
SessionOptions so;
so.session_logid = "SerializeToOrtFormat";
@ -216,6 +241,7 @@ static void SaveAndCompareModels(const std::string& onnx_file, const std::basic_
ASSERT_STATUS_OK(session_object2.Load(ort_file));
ASSERT_STATUS_OK(session_object2.Initialize());
CompareSessionMetadata(session_object, session_object2);
CompareGraphAndSessionState(session_object, session_object2);
}
@ -240,10 +266,10 @@ static void DumpOrtModelAsJson(const std::string& model_uri) {
}
*/
/*
/*
Validate we don't run optimizers on an ORT format model in a full build. The optimizers will remove nodes,
which will create a mismatch with the saved kernel information and result in a runtime error.
We could take steps to handle this scenario in a full build, but for consistency we choose to not run optimizers
which will create a mismatch with the saved kernel information and result in a runtime error.
We could take steps to handle this scenario in a full build, but for consistency we choose to not run optimizers
on any ORT format model.
*/
TEST(OrtModelOnlyTests, ValidateOrtFormatModelDoesNotRunOptimizersInFullBuild) {
@ -325,6 +351,12 @@ TEST(OrtModelOnlyTests, TensorAttributeSerialization) {
SaveAndCompareModels("testdata/ort_minimal_test_models/tensor_attribute.onnx", ort_file);
}
TEST(OrtModelOnlyTests, MetadataSerialization) {
const std::basic_string<ORTCHAR_T> ort_file =
ORT_TSTR("testdata/model_with_metadata.onnx.test_output.ort");
SaveAndCompareModels("testdata/model_with_metadata.onnx", ort_file);
}
#if !defined(DISABLE_ML_OPS)
TEST(OrtModelOnlyTests, SerializeToOrtFormatMLOps) {
const std::basic_string<ORTCHAR_T> ort_file =

View file

@ -658,6 +658,7 @@ TEST_F(GraphTransformationTests, NotWhereFusion) {
}
#if defined(USE_CUDA) && !defined(DISABLE_CONTRIB_OPS)
// Conv->Add->Relu will be transformed to FusedConv
TEST_F(GraphTransformationTests, FuseCudaConvAddRelu) {
auto model_uri = MODEL_FOLDER "fusion/conv_add_relu.onnx";
std::shared_ptr<Model> p_model;
@ -673,9 +674,50 @@ TEST_F(GraphTransformationTests, FuseCudaConvAddRelu) {
graph_transformation_mgr.Register(std::make_unique<ConvActivationFusion>(), TransformerLevel::Level2);
ASSERT_STATUS_OK(graph_transformation_mgr.ApplyTransformers(graph, TransformerLevel::Level2, *logger_));
op_to_count = CountOpsInGraph(graph);
ASSERT_TRUE(op_to_count["Add"] == 0);
ASSERT_TRUE(op_to_count["Relu"] == 0);
ASSERT_TRUE(op_to_count["Add"] == 0); //Add removed from graph
ASSERT_TRUE(op_to_count["Relu"] == 0); //Relu removed from graph
}
//Conv->Add->Relu will be left intact since there is Identity depend on Add
TEST_F(GraphTransformationTests, FuseCudaConvAddReluIdentity) {
auto model_uri = MODEL_FOLDER "fusion/conv_add_relu_identity.onnx";
std::shared_ptr<Model> p_model;
ASSERT_STATUS_OK(Model::Load(model_uri, p_model, nullptr, *logger_));
Graph& graph = p_model->MainGraph();
for (auto& node : p_model->MainGraph().Nodes()) {
node.SetExecutionProviderType(kCudaExecutionProvider);
}
std::map<std::string, int> op_to_count = CountOpsInGraph(graph);
ASSERT_TRUE(op_to_count["Add"] == 1);
ASSERT_TRUE(op_to_count["Relu"] == 1);
ASSERT_TRUE(op_to_count["Identity"] == 1);
onnxruntime::GraphTransformerManager graph_transformation_mgr{5};
graph_transformation_mgr.Register(std::make_unique<ConvActivationFusion>(), TransformerLevel::Level2);
ASSERT_STATUS_OK(graph_transformation_mgr.ApplyTransformers(graph, TransformerLevel::Level2, *logger_));
op_to_count = CountOpsInGraph(graph);
ASSERT_TRUE(op_to_count["Add"] == 1); //Add remains
ASSERT_TRUE(op_to_count["Relu"] == 1); //Relu remains
ASSERT_TRUE(op_to_count["Identity"] == 1); //Identity remains
}
//Conv->Add will be left intact since there is no Relu follows
TEST_F(GraphTransformationTests, FuseCudaConvAdd) {
auto model_uri = MODEL_FOLDER "fusion/conv_add.onnx";
std::shared_ptr<Model> p_model;
ASSERT_STATUS_OK(Model::Load(model_uri, p_model, nullptr, *logger_));
Graph& graph = p_model->MainGraph();
for (auto& node : p_model->MainGraph().Nodes()) {
node.SetExecutionProviderType(kCudaExecutionProvider);
}
std::map<std::string, int> op_to_count = CountOpsInGraph(graph);
ASSERT_TRUE(op_to_count["Add"] == 1);
onnxruntime::GraphTransformerManager graph_transformation_mgr{5};
graph_transformation_mgr.Register(std::make_unique<ConvActivationFusion>(), TransformerLevel::Level2);
ASSERT_STATUS_OK(graph_transformation_mgr.ApplyTransformers(graph, TransformerLevel::Level2, *logger_));
op_to_count = CountOpsInGraph(graph);
ASSERT_TRUE(op_to_count["Add"] == 1); //Add remains, no transform applied to the graph
}
#endif
#ifndef DISABLE_CONTRIB_OPS

View file

@ -0,0 +1,26 @@
# Xcode
#
# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
## User settings
xcuserdata/
## compatibility with Xcode 8 and earlier (ignoring not required starting Xcode 9)
*.xcscmblueprint
*.xccheckout
## compatibility with Xcode 3 and earlier (ignoring not required starting Xcode 4)
build/
DerivedData/
*.moved-aside
*.pbxuser
!default.pbxuser
*.mode1v3
!default.mode1v3
*.mode2v3
!default.mode2v3
*.perspectivev3
!default.perspectivev3
## Gcc Patch
/*.gcno

View file

@ -0,0 +1,12 @@
platform :ios, '13.0'
target 'ios_package_test' do
# Comment the next line if you don't want to use dynamic frameworks
use_frameworks!
target 'ios_package_testTests' do
inherit! :search_paths
pod 'onnxruntime-mobile-c', :podspec => './onnxruntime-mobile-c.podspec'
end
end

View file

@ -0,0 +1,47 @@
# iOS End-to-End Test App for ORT-Mobile
This End-to-End test app for iOS will test ORT Mobile C/C++ API framework using XCode and CocoaPods
## Requirements
- [Prerequisites for building ORT-Mobile for iOS](http://www.onnxruntime.ai/docs/how-to/build/android-ios.html#prerequisites-1)
- [CocoaPods](https://cocoapods.org/)
## iOS End-to-End Test App Overview
The iOS End-to-End Test App will use CocoaPods to install the Onnx Runtime C/C++ framework, and run basic End-to-End tests of Onnx Runtime C and C++ API.
### Model used
- [sigmoid ONNX model](https://github.com/onnx/onnx/blob/f9b0cc99344869c246b8f4011b8586a39841284c/onnx/backend/test/data/node/test_sigmoid/model.onnx) converted to ORT format
Here's the [document](http://www.onnxruntime.ai/docs/how-to/deploy-on-mobile.html#1-create-ort-format-model-and-configuration-file-with-required-operators) about how you can convert an ONNX model into ORT format.
### Tests
- [Tests for C API ](./ios_package_testTests/ios_package_test_c_api.m)
- [Tests for C++ API ](./ios_package_testTests/ios_package_test_cpp_api.mm)
## Build and Test iOS Framework using [build.py](../../../../../tools/ci_build/build.py)
Use the [build for iOS simulator](http://www.onnxruntime.ai/docs/how-to/build/android-ios.html#cross-build-for-ios-simulator) with `--build_apple_framework`
## Run the iOS End-to-End Test App standalone
### Requirements
- A pre-built ORT Mobile iOS framework, which can be built using the [instruction](#build-and-test-ios-framework-using-buildpy) above. The framework can be found as `<build_dir>/iOS/<build-config>/<build-config>-iphonesimulator/onnxruntime.framework`
### Steps
1. Go to this folder
2. Copy the [onnxruntime-mobile.podspec.template](./onnxruntime-mobile.podspec.template) to `onnxruntime-mobile.podspec`
3. Update the `onnxruntime-mobile.podspec`, replace `${ORT_BASE_FRAMEWORK_ARCHIVE}` with the path of a zip archive contains the pre-built ORT Mobile iOS framework
4. Run `pod install` to install the pre-built ORT Mobile iOS framework
5. Run the following command to perform the test
```
xcrun xcodebuild \
-workspace ./ios_package_test.xcworkspace \
-destination '<Your choice of test target device>' \
-scheme ios_package_test \
test
```

View file

@ -0,0 +1,470 @@
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 50;
objects = {
/* Begin PBXBuildFile section */
229E5921265869BF006E41AE /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 229E5920265869BF006E41AE /* AppDelegate.m */; };
229E592A265869BF006E41AE /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 229E5928265869BF006E41AE /* Main.storyboard */; };
229E592F265869C2006E41AE /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 229E592D265869C2006E41AE /* LaunchScreen.storyboard */; };
229E5932265869C2006E41AE /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 229E5931265869C2006E41AE /* main.m */; };
229E593C265869C2006E41AE /* ios_package_test_cpp_api.mm in Sources */ = {isa = PBXBuildFile; fileRef = 229E593B265869C2006E41AE /* ios_package_test_cpp_api.mm */; };
229E595926586B4A006E41AE /* sigmoid.ort in Resources */ = {isa = PBXBuildFile; fileRef = 229E595826586B4A006E41AE /* sigmoid.ort */; };
229E595A26586B4A006E41AE /* sigmoid.ort in Resources */ = {isa = PBXBuildFile; fileRef = 229E595826586B4A006E41AE /* sigmoid.ort */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
229E5938265869C2006E41AE /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 229E5914265869BF006E41AE /* Project object */;
proxyType = 1;
remoteGlobalIDString = 229E591B265869BF006E41AE;
remoteInfo = ios_package_test;
};
/* End PBXContainerItemProxy section */
/* Begin PBXFileReference section */
229E591C265869BF006E41AE /* ios_package_test.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ios_package_test.app; sourceTree = BUILT_PRODUCTS_DIR; };
229E591F265869BF006E41AE /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = "<group>"; };
229E5920265869BF006E41AE /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = "<group>"; };
229E5929265869BF006E41AE /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
229E592E265869C2006E41AE /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
229E5930265869C2006E41AE /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
229E5931265869C2006E41AE /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
229E5937265869C2006E41AE /* ios_package_testTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = ios_package_testTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
229E593B265869C2006E41AE /* ios_package_test_cpp_api.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = ios_package_test_cpp_api.mm; sourceTree = "<group>"; };
229E593D265869C2006E41AE /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
229E595826586B4A006E41AE /* sigmoid.ort */ = {isa = PBXFileReference; lastKnownFileType = file; path = sigmoid.ort; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
229E5919265869BF006E41AE /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
229E5934265869C2006E41AE /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
229E5913265869BF006E41AE = {
isa = PBXGroup;
children = (
229E595426586A77006E41AE /* models */,
229E591E265869BF006E41AE /* ios_package_test */,
229E593A265869C2006E41AE /* ios_package_testTests */,
229E591D265869BF006E41AE /* Products */,
);
sourceTree = "<group>";
};
229E591D265869BF006E41AE /* Products */ = {
isa = PBXGroup;
children = (
229E591C265869BF006E41AE /* ios_package_test.app */,
229E5937265869C2006E41AE /* ios_package_testTests.xctest */,
);
name = Products;
sourceTree = "<group>";
};
229E591E265869BF006E41AE /* ios_package_test */ = {
isa = PBXGroup;
children = (
229E591F265869BF006E41AE /* AppDelegate.h */,
229E5920265869BF006E41AE /* AppDelegate.m */,
229E5928265869BF006E41AE /* Main.storyboard */,
229E592D265869C2006E41AE /* LaunchScreen.storyboard */,
229E5930265869C2006E41AE /* Info.plist */,
229E5931265869C2006E41AE /* main.m */,
);
path = ios_package_test;
sourceTree = "<group>";
};
229E593A265869C2006E41AE /* ios_package_testTests */ = {
isa = PBXGroup;
children = (
229E593B265869C2006E41AE /* ios_package_test_cpp_api.mm */,
229E593D265869C2006E41AE /* Info.plist */,
);
path = ios_package_testTests;
sourceTree = "<group>";
};
229E595426586A77006E41AE /* models */ = {
isa = PBXGroup;
children = (
229E595826586B4A006E41AE /* sigmoid.ort */,
);
path = models;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
229E591B265869BF006E41AE /* ios_package_test */ = {
isa = PBXNativeTarget;
buildConfigurationList = 229E594B265869C2006E41AE /* Build configuration list for PBXNativeTarget "ios_package_test" */;
buildPhases = (
229E5918265869BF006E41AE /* Sources */,
229E5919265869BF006E41AE /* Frameworks */,
229E591A265869BF006E41AE /* Resources */,
);
buildRules = (
);
dependencies = (
);
name = ios_package_test;
productName = ios_package_test;
productReference = 229E591C265869BF006E41AE /* ios_package_test.app */;
productType = "com.apple.product-type.application";
};
229E5936265869C2006E41AE /* ios_package_testTests */ = {
isa = PBXNativeTarget;
buildConfigurationList = 229E594E265869C2006E41AE /* Build configuration list for PBXNativeTarget "ios_package_testTests" */;
buildPhases = (
229E5933265869C2006E41AE /* Sources */,
229E5934265869C2006E41AE /* Frameworks */,
229E5935265869C2006E41AE /* Resources */,
);
buildRules = (
);
dependencies = (
229E5939265869C2006E41AE /* PBXTargetDependency */,
);
name = ios_package_testTests;
productName = ios_package_testTests;
productReference = 229E5937265869C2006E41AE /* ios_package_testTests.xctest */;
productType = "com.apple.product-type.bundle.unit-test";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
229E5914265869BF006E41AE /* Project object */ = {
isa = PBXProject;
attributes = {
LastUpgradeCheck = 1250;
TargetAttributes = {
229E591B265869BF006E41AE = {
CreatedOnToolsVersion = 12.5;
};
229E5936265869C2006E41AE = {
CreatedOnToolsVersion = 12.5;
TestTargetID = 229E591B265869BF006E41AE;
};
};
};
buildConfigurationList = 229E5917265869BF006E41AE /* Build configuration list for PBXProject "ios_package_test" */;
compatibilityVersion = "Xcode 9.3";
developmentRegion = en;
hasScannedForEncodings = 0;
knownRegions = (
en,
Base,
);
mainGroup = 229E5913265869BF006E41AE;
productRefGroup = 229E591D265869BF006E41AE /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
229E591B265869BF006E41AE /* ios_package_test */,
229E5936265869C2006E41AE /* ios_package_testTests */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
229E591A265869BF006E41AE /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
229E592F265869C2006E41AE /* LaunchScreen.storyboard in Resources */,
229E595926586B4A006E41AE /* sigmoid.ort in Resources */,
229E592A265869BF006E41AE /* Main.storyboard in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
229E5935265869C2006E41AE /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
229E595A26586B4A006E41AE /* sigmoid.ort in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
229E5918265869BF006E41AE /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
229E5921265869BF006E41AE /* AppDelegate.m in Sources */,
229E5932265869C2006E41AE /* main.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
229E5933265869C2006E41AE /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
229E593C265869C2006E41AE /* ios_package_test_cpp_api.mm in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXTargetDependency section */
229E5939265869C2006E41AE /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 229E591B265869BF006E41AE /* ios_package_test */;
targetProxy = 229E5938265869C2006E41AE /* PBXContainerItemProxy */;
};
/* End PBXTargetDependency section */
/* Begin PBXVariantGroup section */
229E5928265869BF006E41AE /* Main.storyboard */ = {
isa = PBXVariantGroup;
children = (
229E5929265869BF006E41AE /* Base */,
);
name = Main.storyboard;
sourceTree = "<group>";
};
229E592D265869C2006E41AE /* LaunchScreen.storyboard */ = {
isa = PBXVariantGroup;
children = (
229E592E265869C2006E41AE /* Base */,
);
name = LaunchScreen.storyboard;
sourceTree = "<group>";
};
/* End PBXVariantGroup section */
/* Begin XCBuildConfiguration section */
229E5949265869C2006E41AE /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_ENABLE_OBJC_WEAK = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
GCC_C_LANGUAGE_STANDARD = gnu11;
GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
};
name = Debug;
};
229E594A265869C2006E41AE /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_ENABLE_OBJC_WEAK = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu11;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
MTL_ENABLE_DEBUG_INFO = NO;
MTL_FAST_MATH = YES;
SDKROOT = iphoneos;
VALIDATE_PRODUCT = YES;
};
name = Release;
};
229E594C265869C2006E41AE /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CODE_SIGN_STYLE = Automatic;
INFOPLIST_FILE = ios_package_test/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
PRODUCT_BUNDLE_IDENTIFIER = "ai.onnxruntime.tests.ios-package-test";
PRODUCT_NAME = "$(TARGET_NAME)";
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Debug;
};
229E594D265869C2006E41AE /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CODE_SIGN_STYLE = Automatic;
INFOPLIST_FILE = ios_package_test/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
PRODUCT_BUNDLE_IDENTIFIER = "ai.onnxruntime.tests.ios-package-test";
PRODUCT_NAME = "$(TARGET_NAME)";
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Release;
};
229E594F265869C2006E41AE /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
CODE_SIGN_STYLE = Automatic;
INFOPLIST_FILE = ios_package_testTests/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
"@loader_path/Frameworks",
);
PRODUCT_BUNDLE_IDENTIFIER = "ai.onnxruntime.tests.ios-package-testTests";
PRODUCT_NAME = "$(TARGET_NAME)";
TARGETED_DEVICE_FAMILY = "1,2";
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/ios_package_test.app/ios_package_test";
};
name = Debug;
};
229E5950265869C2006E41AE /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
CODE_SIGN_STYLE = Automatic;
INFOPLIST_FILE = ios_package_testTests/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
"@loader_path/Frameworks",
);
PRODUCT_BUNDLE_IDENTIFIER = "ai.onnxruntime.tests.ios-package-testTests";
PRODUCT_NAME = "$(TARGET_NAME)";
TARGETED_DEVICE_FAMILY = "1,2";
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/ios_package_test.app/ios_package_test";
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
229E5917265869BF006E41AE /* Build configuration list for PBXProject "ios_package_test" */ = {
isa = XCConfigurationList;
buildConfigurations = (
229E5949265869C2006E41AE /* Debug */,
229E594A265869C2006E41AE /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
229E594B265869C2006E41AE /* Build configuration list for PBXNativeTarget "ios_package_test" */ = {
isa = XCConfigurationList;
buildConfigurations = (
229E594C265869C2006E41AE /* Debug */,
229E594D265869C2006E41AE /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
229E594E265869C2006E41AE /* Build configuration list for PBXNativeTarget "ios_package_testTests" */ = {
isa = XCConfigurationList;
buildConfigurations = (
229E594F265869C2006E41AE /* Debug */,
229E5950265869C2006E41AE /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = 229E5914265869BF006E41AE /* Project object */;
}

View file

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "self:">
</FileRef>
</Workspace>

View file

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDEDidComputeMac32BitWarning</key>
<true/>
</dict>
</plist>

View file

@ -0,0 +1,14 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
//
// AppDelegate.h
// ios_package_test
//
#import <UIKit/UIKit.h>
@interface AppDelegate : UIResponder <UIApplicationDelegate>
@end

View file

@ -0,0 +1,40 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
//
// AppDelegate.m
// ios_package_test
//
#import "AppDelegate.h"
@interface AppDelegate ()
@end
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
return YES;
}
#pragma mark - UISceneSession lifecycle
- (UISceneConfiguration *)application:(UIApplication *)application configurationForConnectingSceneSession:(UISceneSession *)connectingSceneSession options:(UISceneConnectionOptions *)options {
// Called when a new scene session is being created.
// Use this method to select a configuration to create the new scene with.
return [[UISceneConfiguration alloc] initWithName:@"Default Configuration" sessionRole:connectingSceneSession.role];
}
- (void)application:(UIApplication *)application didDiscardSceneSessions:(NSSet<UISceneSession *> *)sceneSessions {
// Called when the user discards a scene session.
// If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions.
// Use this method to release any resources that were specific to the discarded scenes, as they will not return.
}
@end

View file

@ -0,0 +1,25 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="13122.16" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13104.12"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
<!--View Controller-->
<scene sceneID="EHf-IW-A2E">
<objects>
<viewController id="01J-lp-oVM" sceneMemberID="viewController">
<view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" xcode11CocoaTouchSystemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/>
<viewLayoutGuide key="safeArea" id="6Tk-OE-BBY"/>
</view>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="53" y="375"/>
</scene>
</scenes>
</document>

View file

@ -0,0 +1,24 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="13122.16" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="BYZ-38-t0r">
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13104.12"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
<!--View Controller-->
<scene sceneID="tne-QT-ifu">
<objects>
<viewController id="BYZ-38-t0r" customClass="ViewController" customModuleProvider="" sceneMemberID="viewController">
<view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC">
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" xcode11CocoaTouchSystemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/>
<viewLayoutGuide key="safeArea" id="6Tk-OE-BBY"/>
</view>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
</objects>
</scene>
</scenes>
</document>

View file

@ -0,0 +1,66 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleVersion</key>
<string>1</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>UIApplicationSceneManifest</key>
<dict>
<key>UIApplicationSupportsMultipleScenes</key>
<false/>
<key>UISceneConfigurations</key>
<dict>
<key>UIWindowSceneSessionRoleApplication</key>
<array>
<dict>
<key>UISceneConfigurationName</key>
<string>Default Configuration</string>
<key>UISceneDelegateClassName</key>
<string>SceneDelegate</string>
<key>UISceneStoryboardFile</key>
<string>Main</string>
</dict>
</array>
</dict>
</dict>
<key>UIApplicationSupportsIndirectInputEvents</key>
<true/>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIMainStoryboardFile</key>
<string>Main</string>
<key>UIRequiredDeviceCapabilities</key>
<array>
<string>armv7</string>
</array>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UISupportedInterfaceOrientations~ipad</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationPortraitUpsideDown</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
</dict>
</plist>

View file

@ -0,0 +1,18 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
//
// main.m
// ios_package_test
//
#import <UIKit/UIKit.h>
#import "AppDelegate.h"
int main(int argc, char * argv[]) {
NSString * appDelegateClassName;
@autoreleasepool {
// Setup code that might create autoreleased objects goes here.
appDelegateClassName = NSStringFromClass([AppDelegate class]);
}
return UIApplicationMain(argc, argv, nil, appDelegateClassName);
}

View file

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleVersion</key>
<string>1</string>
</dict>
</plist>

View file

@ -0,0 +1,97 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
//
// ios_package_test_cpp_api.mm
// ios_package_testTests
//
// This file hosts the tests of ORT C++ API, for tests of ORT C API, please see ios_package_test_c_api.mm
//
#import <XCTest/XCTest.h>
#include <math.h>
#include <onnxruntime/onnxruntime_cxx_api.h>
#if __has_include(<onnxruntime/coreml_provider_factory.h>)
#define COREML_EP_AVAILABLE 1
#else
#define COREML_EP_AVAILABLE 0
#endif
#if COREML_EP_AVAILABLE
#include <onnxruntime/coreml_provider_factory.h>
#endif
void testSigmoid(bool useCoreML) {
// This is an e2e test for ORT C++ API
Ort::Env env(ORT_LOGGING_LEVEL_WARNING, "testCppAPI");
// initialize session options if needed
Ort::SessionOptions session_options;
session_options.SetIntraOpNumThreads(1);
#if COREML_EP_AVAILABLE
if (useCoreML) {
const uint32_t flags = COREML_FLAG_USE_CPU_ONLY;
Ort::ThrowOnError(OrtSessionOptionsAppendExecutionProvider_CoreML(session_options, flags));
}
#else
(void)useCoreML;
#endif
NSString* ns_model_path = [[NSBundle mainBundle] pathForResource:@"sigmoid" ofType:@"ort"];
Ort::Session session(env, ns_model_path.UTF8String, session_options);
size_t input_tensor_size = 3 * 4 * 5;
float input_tensor_values[input_tensor_size];
float expected_output_values[input_tensor_size];
const char* input_node_names[] = {"x"};
const char* output_node_names[] = {"y"};
const int64_t input_node_dims[] = {3, 4, 5};
for (size_t i = 0; i < input_tensor_size; i++) {
input_tensor_values[i] = (float)i - 30;
expected_output_values[i] = 1.0f / (1 + exp(-input_tensor_values[i]));
}
auto memory_info = Ort::MemoryInfo::CreateCpu(OrtArenaAllocator, OrtMemTypeDefault);
Ort::Value input_tensor =
Ort::Value::CreateTensor<float>(memory_info, input_tensor_values, input_tensor_size, input_node_dims, 3);
XCTAssert(input_tensor.IsTensor());
auto output_tensors = session.Run(Ort::RunOptions{nullptr}, input_node_names,
&input_tensor, 1, output_node_names, 1);
XCTAssertEqual(output_tensors.size(), 1);
XCTAssert(output_tensors.front().IsTensor());
// Get pointer to output tensor float values
float* output_values = output_tensors.front().GetTensorMutableData<float>();
for (size_t i = 0; i < input_tensor_size; i++) {
XCTAssertEqualWithAccuracy(expected_output_values[i], output_values[i], 1e-6);
}
}
@interface ios_package_test_cpp_api : XCTestCase
@end
@implementation ios_package_test_cpp_api
- (void)setUp {
// Put setup code here. This method is called before the invocation of each test method in the class.
}
- (void)tearDown {
// Put teardown code here. This method is called after the invocation of each test method in the class.
}
- (void)testCppAPI_Basic {
testSigmoid(false /* useCoreML */);
}
#if COREML_EP_AVAILABLE
- (void)testCppAPI_Basic_CoreML {
testSigmoid(true /* useCoreML */);
}
#endif
@end

Binary file not shown.

View file

@ -0,0 +1,38 @@
import onnx
from onnx import helper
from onnx import TensorProto
# Create a model with metadata to test ORT conversion
def GenerateModel(model_name):
nodes = [
helper.make_node("Sigmoid", ["X"], ["Y"], "sigmoid"),
]
graph = helper.make_graph(
nodes,
"NNAPI_Internal_uint8_Test",
[helper.make_tensor_value_info('X', TensorProto.FLOAT, [1, 3])],
[helper.make_tensor_value_info('Y', TensorProto.FLOAT, [1, 3])],
)
model = helper.make_model(graph)
# Add meta data
model.doc_string = 'This is doc_string'
model.producer_name = 'TensorTorch'
model.model_version = 12345
model.domain = 'ai.onnx.ml'
helper.set_model_props(
model,
{
'I am key 1!': 'I am value 1!',
'': 'Value for empty key!',
'Key for empty value!': '',
}
)
onnx.save(model, model_name)
if __name__ == "__main__":
GenerateModel('model_with_metadata.onnx')

View file

@ -0,0 +1,44 @@


X
W
BC"Conv

C
AY"AddgraphZ
X




Z
W




Z
B

Z
A




b
Y




BB
com.microsoft.experimentalB
ai.onnx.preview.trainingB
com.microsoft.nchwcB
com.microsoft.mlfeaturizersB
ai.onnx.mlB
com.microsoftB
ai.onnx.training

View file

@ -0,0 +1,46 @@


X
W
BC"Conv

C
AS"Add
SY"Relu

SI"IdentitygraphZ
X




Z
W




Z
B

Z
A




b
Y




b
I




B

View file

@ -27,6 +27,10 @@ class InferenceSessionWrapper : public InferenceSession {
const SessionState& GetSessionState() const {
return InferenceSession::GetSessionState();
}
const Model& GetModel() const {
return *model_;
}
};
} // namespace test

View file

@ -331,8 +331,6 @@ def parse_arguments():
help="Specify the minimum version of the target platform "
"(e.g. macOS or iOS)"
"This is only supported on MacOS")
parser.add_argument("--apple_disable_bitcode", action='store_true',
help="Disable bitcode for iOS, bitcode is by default enabled for iOS.")
# WebAssembly build
parser.add_argument("--build_wasm", action='store_true', help="Build for WebAssembly")
@ -878,7 +876,6 @@ def generate_build_tree(cmake_path, source_dir, build_dir, cuda_home, cudnn_home
"-DCMAKE_OSX_DEPLOYMENT_TARGET=" + args.apple_deploy_target,
# we do not need protoc binary for ios cross build
"-Dprotobuf_BUILD_PROTOC_BINARIES=OFF",
"-Donnxruntime_ENABLE_BITCODE=" + ("OFF" if args.apple_disable_bitcode else "ON"),
"-DCMAKE_TOOLCHAIN_FILE=" + (
args.ios_toolchain_file if args.ios_toolchain_file
else "../cmake/onnxruntime_ios.toolchain.cmake")
@ -1255,16 +1252,29 @@ def run_android_tests(args, source_dir, build_dir, config, cwd):
def run_ios_tests(args, source_dir, config, cwd):
cpr = run_subprocess(["xcodebuild", "test-without-building", "-project", "./onnxruntime.xcodeproj",
"-configuration", config,
"-scheme", "onnxruntime_test_all_xc", "-destination",
"platform=iOS Simulator,OS=latest,name=iPhone SE (2nd generation)"], cwd=cwd)
if cpr.returncode == 0:
cpr = run_subprocess(["xcodebuild", "test-without-building", "-project", "./onnxruntime.xcodeproj",
"-configuration", config,
"-scheme", "onnxruntime_shared_lib_test_xc", "-destination",
"platform=iOS Simulator,OS=latest,name=iPhone SE (2nd generation)"], cwd=cwd)
cpr.check_returncode()
run_subprocess(["xcodebuild", "test-without-building", "-project", "./onnxruntime.xcodeproj",
"-configuration", config,
"-scheme", "onnxruntime_test_all_xc", "-destination",
"platform=iOS Simulator,OS=latest,name=iPhone SE (2nd generation)"], cwd=cwd)
run_subprocess(["xcodebuild", "test-without-building", "-project", "./onnxruntime.xcodeproj",
"-configuration", config,
"-scheme", "onnxruntime_shared_lib_test_xc", "-destination",
"platform=iOS Simulator,OS=latest,name=iPhone SE (2nd generation)"], cwd=cwd)
if args.build_apple_framework:
package_test_py = os.path.join(source_dir, 'tools', 'ci_build', 'github', 'apple', 'test_ios_packages.py')
framework_info_file = os.path.join(cwd, 'framework_info.json')
dynamic_framework_dir = os.path.join(cwd, config + '-' + args.ios_sysroot)
static_framework_dir = os.path.join(cwd, config + '-' + args.ios_sysroot, 'static_framework')
# test dynamic framework
run_subprocess([sys.executable, package_test_py,
'--c_framework_dir', dynamic_framework_dir,
'--framework_info_file', framework_info_file], cwd=cwd)
# test static framework
run_subprocess([sys.executable, package_test_py,
'--c_framework_dir', static_framework_dir,
'--framework_info_file', framework_info_file], cwd=cwd)
def run_orttraining_test_orttrainer_frontend_separately(cwd):

View file

@ -14,8 +14,8 @@ ai.onnx;12;Abs,Add,And,ArgMax,ArgMin,AveragePool,Cast,Ceil,Clip,Concat,ConstantO
ai.onnx;13;Abs,Add,And,ArgMax,ArgMin,AveragePool,Cast,Ceil,Clip,Concat,ConstantOfShape,Conv,ConvTranspose,Cos,CumSum,DepthToSpace,DequantizeLinear,Div,DynamicQuantizeLinear,Elu,Equal,Exp,Expand,Flatten,Floor,Gather,GatherND,Gemm,Greater,GreaterOrEqual,Identity,If,LRN,LeakyRelu,Less,LessOrEqual,Log,LogSoftmax,Loop,MatMul,Max,MaxPool,Mean,Min,Mul,Neg,NonMaxSuppression,NonZero,Not,Or,PRelu,Pad,Pow,QuantizeLinear,Range,Reciprocal,ReduceMax,ReduceMean,ReduceMin,ReduceProd,ReduceSum,Relu,Reshape,Resize,ReverseSequence,Round,ScatterND,Shape,Sigmoid,Sin,Size,Slice,Softmax,SpaceToDepth,Split,Sqrt,Squeeze,Sub,Sum,Tanh,ThresholdedRelu,Tile,TopK,Transpose,Unique,Unsqueeze,Where
# other ops found in test models
ai.onnx;12;Erf,GlobalAveragePool,InstanceNormalization,MatMulInteger,QLinearConv,QLinearMatMul
ai.onnx;13;Erf,GlobalAveragePool,InstanceNormalization,MatMulInteger,QLinearConv,QLinearMatMul
ai.onnx;12;Erf,GlobalAveragePool,InstanceNormalization,HardSigmoid,MatMulInteger,QLinearConv,QLinearMatMul
ai.onnx;13;Erf,GlobalAveragePool,InstanceNormalization,HardSigmoid,MatMulInteger,QLinearConv,QLinearMatMul
# Control flow ops
# - If and Loop are covered by the tflite converter list
@ -27,6 +27,7 @@ ai.onnx;13;Scan
# Note: LayerNormalization is an internal op even though it is (incorrectly) registered in the ONNX domain.
ai.onnx;1;LayerNormalization
com.microsoft;1;DynamicQuantizeMatMul,FusedConv,FusedGemm,FusedMatMul,Gelu,MatMulIntegerToFloat,NhwcMaxPool,QLinearAdd,QLinearAveragePool,QLinearConv,QLinearGlobalAveragePool,QLinearMul,QLinearSigmoid
# NHWC transformer also uses this, so assuming it's valuable enough to include
com.microsoft;1;QLinearLeakyRelu

View file

@ -68,9 +68,11 @@ Models from MLPerf Mobile
- ssd_mobilenet_v2_300-qdq.onnx
Other
Mobilenet v2 from pytorch
Mobilenet v2 and v3 from pytorch
- https://pytorch.org/vision/stable/models.html
- pytorch.mobilenet_v2_float.onnx
- pytorch.mobilenet_v2_uint8.onnx
- pytorch.mobilenet_v3_small.onnx
Other assorted pytorch models
- Huggingface mobilebert-uncased (https://huggingface.co/transformers/serialization.html, https://huggingface.co/google/mobilebert-uncased)
- SuperResolution (https://pytorch.org/tutorials/advanced/super_resolution_with_onnxruntime.html)

View file

@ -0,0 +1,63 @@
#!/bin/bash
# Note: This script is intended to be called from the iOS packaging build or a similar context
# See tools/ci_build/github/azure-pipelines/mac-ios-packaging-pipeline.yml
set -e
set -x
USAGE_TEXT="Usage: ${0} <binaries staging directory> <artifacts staging directory> <ORT pod version> <whether to upload the package archives, 'true' or 'false'>"
abspath() {
local INPUT_PATH=${1:?"Expected path as the first argument."}
echo "$(cd "$(dirname "${INPUT_PATH}")" && pwd)/$(basename "${INPUT_PATH}")"
}
# staging directory for binaries (source)
BINARIES_STAGING_DIR=$(abspath "${1:?${USAGE_TEXT}}")
# staging directory for build artifacts (destination)
ARTIFACTS_STAGING_DIR=$(abspath "${2:?${USAGE_TEXT}}")
ORT_POD_VERSION=${3:?${USAGE_TEXT}}
SHOULD_UPLOAD_ARCHIVES=${4:?${USAGE_TEXT}}
STORAGE_ACCOUNT_NAME="onnxruntimepackages"
STORAGE_ACCOUNT_CONTAINER_NAME="ortmobilestore"
STORAGE_URL_PREFIX="https://${STORAGE_ACCOUNT_NAME}.blob.core.windows.net/${STORAGE_ACCOUNT_CONTAINER_NAME}"
assemble_and_upload_pod() {
local POD_NAME=${1:?"Expected pod name as first argument."}
local POD_ARCHIVE_BASENAME="${POD_NAME}-${ORT_POD_VERSION}.zip"
local PODSPEC_BASENAME="${POD_NAME}.podspec"
pushd ${BINARIES_STAGING_DIR}/${POD_NAME}
# assemble the files in the artifacts staging directory
zip -r ${ARTIFACTS_STAGING_DIR}/${POD_ARCHIVE_BASENAME} * --exclude ${PODSPEC_BASENAME}
cp ${PODSPEC_BASENAME} ${ARTIFACTS_STAGING_DIR}/${PODSPEC_BASENAME}
if [[ "${SHOULD_UPLOAD_ARCHIVES}" == "true" ]]; then
# upload the pod archive and set the podspec source to the pod archive URL
az storage blob upload \
--account-name ${STORAGE_ACCOUNT_NAME} --container-name ${STORAGE_ACCOUNT_CONTAINER_NAME} \
--file ${ARTIFACTS_STAGING_DIR}/${POD_ARCHIVE_BASENAME} --name ${POD_ARCHIVE_BASENAME} \
--if-none-match "*"
sed -i "" -e "s|file:///http_source_placeholder|${STORAGE_URL_PREFIX}/${POD_ARCHIVE_BASENAME}|" \
${ARTIFACTS_STAGING_DIR}/${PODSPEC_BASENAME}
fi
popd
}
assemble_and_upload_pod "onnxruntime-mobile-c"
assemble_and_upload_pod "onnxruntime-mobile-objc"
cd ${BINARIES_STAGING_DIR}/objc_api_docs
zip -r ${ARTIFACTS_STAGING_DIR}/objc_api_docs.zip *
cat > ${ARTIFACTS_STAGING_DIR}/readme.txt <<'EOM'
Release TODO:
- publish the podspecs
- publish the Objective-C API documentation
EOM

View file

@ -72,20 +72,24 @@ def _build_package(args):
# get the compiled lib path
framework_dir = os.path.join(
build_dir_current_arch, build_config, build_config + "-" + sysroot, 'onnxruntime.framework')
build_dir_current_arch, build_config, build_config + "-" + sysroot,
'onnxruntime.framework' if args.build_dynamic_framework
else os.path.join('static_framework', 'onnxruntime.framework'))
ort_libs.append(os.path.join(framework_dir, 'onnxruntime'))
# We actually only need to define the Info.plist and headers once since they are all the same
# We only need to copy Info.plist, framework_info.json, and headers once since they are the same
if not info_plist_path:
info_plist_path = os.path.join(build_dir_current_arch, build_config, 'Info.plist')
framework_info_path = os.path.join(build_dir_current_arch, build_config, 'framework_info.json')
headers = glob.glob(os.path.join(framework_dir, 'Headers', '*.h'))
# manually create the fat framework
framework_dir = os.path.join(build_dir, 'framework_out', 'onnxruntime.framework')
pathlib.Path(framework_dir).mkdir(parents=True, exist_ok=True)
# copy the header files and Info.plist
# copy the Info.plist, framework_info.json, and header files
shutil.copy(info_plist_path, framework_dir)
shutil.copy(framework_info_path, build_dir)
header_dir = os.path.join(framework_dir, 'Headers')
pathlib.Path(header_dir).mkdir(parents=True, exist_ok=True)
for _header in headers:
@ -123,6 +127,9 @@ def parse_args():
parser.add_argument('build_settings_file', type=pathlib.Path,
help='Provide the file contains settings for building iOS framework')
parser.add_argument("--build_dynamic_framework", action='store_true',
help="Build Dynamic Framework (default is build static framework).")
args = parser.parse_args()
if not args.build_settings_file.resolve().is_file():

View file

@ -0,0 +1,73 @@
#!/usr/bin/env python3
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License.
import argparse
import pathlib
import shutil
import sys
_script_dir = pathlib.Path(__file__).parent.resolve(strict=True)
sys.path.append(str(_script_dir.parent))
from package_assembly_utils import ( # noqa: E402
copy_repo_relative_to_dir, gen_file_from_template, load_framework_info)
def parse_args():
parser = argparse.ArgumentParser(description="""
Assembles the files for the C/C++ pod package in a staging directory.
This directory can be validated (e.g., with `pod lib lint`) and then zipped to create a package for release.
""")
parser.add_argument("--staging-dir", type=pathlib.Path,
default=pathlib.Path("./onnxruntime-mobile-c-staging"),
help="Path to the staging directory for the C/C++ pod files.")
parser.add_argument("--pod-version", required=True,
help="C/C++ pod version.")
parser.add_argument("--framework-info-file", type=pathlib.Path, required=True,
help="Path to the framework_info.json file containing additional values for the podspec. "
"This file should be generated by CMake in the build directory.")
parser.add_argument("--framework-dir", type=pathlib.Path, required=True,
help="Path to the onnxruntime.framework directory to include in the pod.")
return parser.parse_args()
def main():
args = parse_args()
framework_info = load_framework_info(args.framework_info_file.resolve())
staging_dir = args.staging_dir.resolve()
print(f"Assembling files in staging directory: {staging_dir}")
if staging_dir.exists():
print("Warning: staging directory already exists", file=sys.stderr)
# copy the necessary files to the staging directory
framework_dir = args.framework_dir.resolve()
shutil.copytree(framework_dir, staging_dir / framework_dir.name, dirs_exist_ok=True)
copy_repo_relative_to_dir(["LICENSE"], staging_dir)
# generate the podspec file from the template
variable_substitutions = {
"VERSION": args.pod_version,
"IOS_DEPLOYMENT_TARGET": framework_info["IOS_DEPLOYMENT_TARGET"],
"WEAK_FRAMEWORK": framework_info["WEAK_FRAMEWORK"],
"LICENSE_FILE": '"LICENSE"',
}
podspec_template = _script_dir / "onnxruntime-mobile-c.podspec.template"
podspec = staging_dir / "onnxruntime-mobile-c.podspec"
gen_file_from_template(podspec_template, podspec, variable_substitutions)
return 0
if __name__ == "__main__":
sys.exit(main())

View file

@ -0,0 +1,24 @@
Pod::Spec.new do |spec|
spec.name = "onnxruntime-mobile-c"
spec.version = "@VERSION@"
spec.authors = { "ONNX Runtime" => "onnxruntime@microsoft.com" }
spec.license = { :type => "MIT", :file => @LICENSE_FILE@ }
spec.homepage = "https://github.com/microsoft/onnxruntime"
spec.source = { :http => "file:///http_source_placeholder" }
spec.summary = "ONNX Runtime Mobile C/C++ Pod"
spec.platform = :ios, "@IOS_DEPLOYMENT_TARGET@"
spec.vendored_frameworks = "onnxruntime.framework"
spec.static_framework = true
spec.weak_framework = [ @WEAK_FRAMEWORK@ ]
spec.source_files = "onnxruntime.framework/Headers/*.h"
spec.preserve_paths = [ @LICENSE_FILE@ ]
spec.description = <<-DESC
A pod for the ONNX Runtime Mobile C/C++ library.
DESC
spec.library = "c++"
spec.user_target_xcconfig = {
"OTHER_CPLUSPLUSFLAGS" => "-fvisibility=hidden -fvisibility-inlines-hidden",
# TODO workaround - support arm64 iphonesimulator later
"EXCLUDED_ARCHS[sdk=iphonesimulator*]" => "arm64"
}
end

View file

@ -14,11 +14,12 @@
"--parallel",
"--use_xcode",
"--build_apple_framework",
"--minimal_build",
"--minimal_build=extended",
"--disable_rtti",
"--disable_ml_ops",
"--disable_exceptions",
"--enable_reduced_operator_type_support",
"--use_coreml",
"--skip_tests",
"--apple_deploy_target=11.0"
]

View file

@ -0,0 +1,4 @@
{
"IOS_DEPLOYMENT_TARGET": "@CMAKE_OSX_DEPLOYMENT_TARGET@",
"WEAK_FRAMEWORK": "@APPLE_WEAK_FRAMEWORK@"
}

View file

@ -0,0 +1 @@
flatbuffers

View file

@ -4,15 +4,17 @@
# Licensed under the MIT License.
import argparse
import os
import pathlib
import re
import shutil
import sys
_script_dir = pathlib.Path(__file__).parent.resolve(strict=True)
_repo_root = _script_dir.parents[4]
sys.path.append(str(_script_dir.parent))
from package_assembly_utils import ( # noqa: E402
copy_repo_relative_to_dir, gen_file_from_template, load_framework_info)
# these variables contain paths or path patterns that are relative to the repo root
@ -61,71 +63,28 @@ def parse_args():
parser.add_argument("--staging-dir", type=pathlib.Path,
default=pathlib.Path("./onnxruntime-mobile-objc-staging"),
help="Staging directory for the Objective-C pod files.")
help="Path to the staging directory for the Objective-C pod files.")
parser.add_argument("--pod-version", required=True,
help="Objective-C pod version.")
parser.add_argument("--pod-source-http", required=True,
help="Objective-C pod source http value (e.g., the package download URL).")
parser.add_argument("--framework-info-file", type=pathlib.Path, required=True,
help="Path to the framework_info.json file containing additional values for the podspec. "
"This file should be generated by CMake in the build directory.")
return parser.parse_args()
_template_variable_pattern = re.compile(r"@(\w+)@") # match "@var@"
def gen_file_from_template(template_file: pathlib.Path, output_file: pathlib.Path,
variable_substitutions: dict[str, str]):
'''
Generates a file from a template file.
The template file may contain template variables that will be substituted
with the provided values in the generated output file.
In the template file, template variable names are delimited by "@"'s,
e.g., "@var@".
:param template_file The template file path.
:param output_file The generated output file path.
:variable_substitutions The mapping from template variable name to value.
'''
with open(template_file, mode="r") as template:
content = template.read()
def replace_template_variable(match):
variable_name = match.group(1)
return variable_substitutions.get(variable_name, match.group(0))
content = _template_variable_pattern.sub(replace_template_variable, content)
with open(output_file, mode="w") as output:
output.write(content)
def copy_to_staging_dir(patterns: list[str], staging_dir: pathlib.Path):
'''
Copies files to a staging directory.
The files are relative to the repo root, and the repo root-relative
intermediate directory structure is maintained.
:param patterns The paths or path patterns relative to the repo root.
:param staging_dir The staging directory.
'''
paths = [path for pattern in patterns for path in _repo_root.glob(pattern)]
for path in paths:
repo_relative_path = path.relative_to(_repo_root)
dst_path = staging_dir / repo_relative_path
os.makedirs(dst_path.parent, exist_ok=True)
shutil.copy(path, dst_path)
def main():
args = parse_args()
framework_info = load_framework_info(args.framework_info_file.resolve())
staging_dir = args.staging_dir.resolve()
print(f"Assembling files in staging directory: {staging_dir}")
if staging_dir.exists():
print("Warning: staging directory already exists", file=sys.stderr)
# copy the necessary files to the staging directory
copy_to_staging_dir(
copy_repo_relative_to_dir(
[license_file] + source_files + test_source_files + test_resource_files,
staging_dir)
@ -136,7 +95,7 @@ def main():
variable_substitutions = {
"VERSION": args.pod_version,
"SOURCE_HTTP": args.pod_source_http,
"IOS_DEPLOYMENT_TARGET": framework_info["IOS_DEPLOYMENT_TARGET"],
"LICENSE_FILE": path_patterns_as_variable_value([license_file]),
"INCLUDE_DIR_LIST": path_patterns_as_variable_value(include_dirs),
"PUBLIC_HEADER_FILE_LIST": path_patterns_as_variable_value(public_header_files),

View file

@ -1,19 +1,20 @@
Pod::Spec.new do |s|
s.name = 'onnxruntime-mobile-objc'
s.version = '@VERSION@'
s.summary = 'ONNX Runtime Objective-C Pod'
s.summary = 'ONNX Runtime Mobile Objective-C Pod'
s.description = <<-DESC
Preview pod for the ONNX Runtime Objective-C API.
A pod for the ONNX Runtime Mobile Objective-C API.
DESC
s.homepage = 'https://github.com/microsoft/onnxruntime'
s.license = { :type => 'MIT', :file => @LICENSE_FILE@ }
s.author = { "ONNX Runtime" => "onnxruntime@microsoft.com" }
s.source = { :http => "@SOURCE_HTTP@" }
s.ios.deployment_target = '11.0'
s.source = { :http => "file:///http_source_placeholder" }
s.ios.deployment_target = '@IOS_DEPLOYMENT_TARGET@'
s.preserve_paths = [ @LICENSE_FILE@ ]
s.default_subspec = "Core"
s.static_framework = true
s.subspec "Core" do |core|
core.dependency "onnxruntime-mobile-c", "#{s.version}"

View file

@ -0,0 +1,69 @@
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License.
import json
import os
import pathlib
import re
import shutil
from typing import Dict, List
_script_dir = pathlib.Path(__file__).parent.resolve(strict=True)
repo_root = _script_dir.parents[3]
_template_variable_pattern = re.compile(r"@(\w+)@") # match "@var@"
def gen_file_from_template(template_file: pathlib.Path, output_file: pathlib.Path,
variable_substitutions: Dict[str, str]):
'''
Generates a file from a template file.
The template file may contain template variables that will be substituted
with the provided values in the generated output file.
In the template file, template variable names are delimited by "@"'s,
e.g., "@var@".
:param template_file The template file path.
:param output_file The generated output file path.
:param variable_substitutions The mapping from template variable name to value.
'''
with open(template_file, mode="r") as template:
content = template.read()
def replace_template_variable(match):
variable_name = match.group(1)
return variable_substitutions.get(variable_name, match.group(0))
content = _template_variable_pattern.sub(replace_template_variable, content)
with open(output_file, mode="w") as output:
output.write(content)
def copy_repo_relative_to_dir(patterns: List[str], dest_dir: pathlib.Path):
'''
Copies file paths relative to the repo root to a directory.
The given paths or path patterns are relative to the repo root, and the
repo root-relative intermediate directory structure is maintained.
:param patterns The paths or path patterns relative to the repo root.
:param dest_dir The destination directory.
'''
paths = [path for pattern in patterns for path in repo_root.glob(pattern)]
for path in paths:
repo_relative_path = path.relative_to(repo_root)
dst_path = dest_dir / repo_relative_path
os.makedirs(dst_path.parent, exist_ok=True)
shutil.copy(path, dst_path)
def load_framework_info(framework_info_file: pathlib.Path):
'''
Loads framework info from a file.
:param framework_info_file The framework info file path.
:return The framework info values.
'''
with open(framework_info_file, mode="r") as framework_info:
return json.load(framework_info)

View file

@ -0,0 +1,124 @@
#!/usr/bin/env python3
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License.
import argparse
import os
import pathlib
import shutil
import subprocess
SCRIPT_DIR = os.path.dirname(os.path.realpath(__file__))
REPO_DIR = os.path.normpath(os.path.join(SCRIPT_DIR, "..", "..", "..", ".."))
from package_assembly_utils import ( # noqa: E402
gen_file_from_template, load_framework_info)
def _test_ios_packages(args):
# check if CocoaPods is installed
if shutil.which('pod') is None:
if args.fail_if_cocoapods_missing:
raise ValueError('CocoaPods is required for this test')
else:
print('CocoaPods is not installed, ignore this test')
return
# Now we need to create a zip file contains the framework and the podspec file, both of these 2 files
# should be under the c_framework_dir
c_framework_dir = args.c_framework_dir.resolve()
if not c_framework_dir.is_dir():
raise FileNotFoundError('c_framework_dir {} is not a folder.'.format(c_framework_dir))
framework_path = os.path.join(c_framework_dir, 'onnxruntime.framework')
if not pathlib.Path(framework_path).exists():
raise FileNotFoundError('{} does not have onnxruntime.framework'.format(c_framework_dir))
# create a temp folder
import tempfile
with tempfile.TemporaryDirectory() as temp_dir:
# This is for debugging only
# temp_dir = <a local directory>
# shutil.rmtree(temp_dir)
# create a zip file contains the framework
# TODO, move this into a util function
local_pods_dir = os.path.join(temp_dir, 'local_pods')
os.makedirs(local_pods_dir, exist_ok=True)
# shutil.make_archive require target file as full path without extension
zip_base_filename = os.path.join(local_pods_dir, 'onnxruntime-mobile-c')
zip_file_path = zip_base_filename + '.zip'
shutil.make_archive(zip_base_filename, 'zip', root_dir=c_framework_dir, base_dir='onnxruntime.framework')
# copy the test project to the temp_dir
test_proj_path = os.path.join(REPO_DIR, 'onnxruntime', 'test', 'platform', 'ios', 'ios_package_test')
target_proj_path = os.path.join(temp_dir, 'ios_package_test')
shutil.copytree(test_proj_path, target_proj_path)
# generate the podspec file from the template
framework_info = load_framework_info(args.framework_info_file.resolve())
with open(os.path.join(REPO_DIR, 'VERSION_NUMBER')) as version_file:
ORT_VERSION = version_file.readline().strip()
variable_substitutions = {
"VERSION": ORT_VERSION,
"IOS_DEPLOYMENT_TARGET": framework_info["IOS_DEPLOYMENT_TARGET"],
"WEAK_FRAMEWORK": framework_info["WEAK_FRAMEWORK"],
"LICENSE_FILE": '"LICENSE"',
}
podspec_template = os.path.join(SCRIPT_DIR, "c", "onnxruntime-mobile-c.podspec.template")
podspec = os.path.join(target_proj_path, "onnxruntime-mobile-c.podspec")
gen_file_from_template(podspec_template, podspec, variable_substitutions)
# update the podspec to point to the local framework zip file
with open(podspec, 'r') as file:
file_data = file.read()
file_data = file_data.replace('file:///http_source_placeholder', 'file:' + zip_file_path)
with open(podspec, 'w') as file:
file.write(file_data)
# clean the Cocoapods cache first, in case the same pod was cached in previous runs
subprocess.run(['pod', 'cache', 'clean', '--all'], shell=False, check=True, cwd=target_proj_path)
# install pods
subprocess.run(['pod', 'install'], shell=False, check=True, cwd=target_proj_path)
# run the tests
subprocess.run(['xcrun', 'xcodebuild', 'test',
'-workspace', './ios_package_test.xcworkspace',
'-scheme', 'ios_package_test',
'-destination', 'platform=iOS Simulator,OS=latest,name=iPhone SE (2nd generation)'],
shell=False, check=True, cwd=target_proj_path)
def parse_args():
parser = argparse.ArgumentParser(
os.path.basename(__file__),
description='Test iOS framework using CocoaPods package.'
)
parser.add_argument('--fail_if_cocoapods_missing', action='store_true',
help='This script will fail if CocoaPods is not installed, '
'will not throw error unless fail_if_cocoapod_missing is set.')
parser.add_argument("--framework_info_file", type=pathlib.Path, required=True,
help="Path to the framework_info.json file containing additional values for the podspec. "
"This file should be generated by CMake in the build directory.")
parser.add_argument('--c_framework_dir', type=pathlib.Path, required=True,
help='Provide the parent directory for C/C++ framework')
return parser.parse_args()
def main():
args = parse_args()
_test_ios_packages(args)
if __name__ == '__main__':
main()

View file

@ -13,6 +13,7 @@ jobs:
--apple_deploy_target 12.1 \
--use_xcode \
--config RelWithDebInfo \
--build_apple_framework \
--parallel
displayName: (CPU EP) Build onnxruntime for iOS x86_64 and run tests using simulator
- script: |
@ -25,5 +26,6 @@ jobs:
--apple_deploy_target 12.1 \
--use_xcode \
--config RelWithDebInfo \
--build_apple_framework \
--parallel
displayName: (CoreML EP) Build onnxruntime for iOS x86_64 and run tests using simulator

View file

@ -0,0 +1,109 @@
parameters:
- name: IsReleaseBuild
displayName: Is this a release build? Set this parameter to true if you are doing an Onnx Runtime release.
type: boolean
default: false
jobs:
- job: IosPackaging
displayName: "iOS Packaging"
pool:
vmImage: "macOS-10.15"
steps:
- task: UsePythonVersion@0
inputs:
versionSpec: "3.9"
addToPath: true
architecture: "x64"
- script: |
pip install -r tools/ci_build/github/apple/ios_packaging.requirements.txt
displayName: "Install Python requirements"
- bash: |
BASE_VERSION=$(cat VERSION_NUMBER)
IS_RELEASE_BUILD=$(echo "${{ parameters.IsReleaseBuild }}" | tr "[:upper:]" "[:lower:]")
if [[ "${IS_RELEASE_BUILD}" == "true" ]]; then
VERSION=${BASE_VERSION}
else
VERSION="${BASE_VERSION}-dev"
fi
set_var() {
local VAR_NAME=${1:?}
local VAR_VALUE=${2:?}
echo "##vso[task.setvariable variable=${VAR_NAME}]${VAR_VALUE}"
echo "${VAR_NAME}: ${VAR_VALUE}"
}
set_var "ORT_POD_VERSION" "${VERSION}"
set_var "ORT_SHOULD_UPLOAD_ARCHIVES" "${IS_RELEASE_BUILD}"
displayName: "Set variables"
- script: |
python tools/ci_build/github/apple/build_ios_framework.py \
--build_dir "$(Build.BinariesDirectory)/ios_framework" \
--include_ops_by_config tools/ci_build/github/android/mobile_package.required_operators.config \
tools/ci_build/github/apple/default_mobile_ios_framework_build_settings.json
displayName: "Build iOS framework"
- script: |
python tools/ci_build/github/apple/test_ios_packages.py \
--fail_if_cocoapods_missing \
--framework_info_file "$(Build.BinariesDirectory)/ios_framework/framework_info.json" \
--c_framework_dir "$(Build.BinariesDirectory)/ios_framework/framework_out"
displayName: "Test iOS framework"
- script: |
python tools/ci_build/github/apple/c/assemble_c_pod_package.py \
--staging-dir "$(Build.BinariesDirectory)/staging/onnxruntime-mobile-c" \
--pod-version ${ORT_POD_VERSION} \
--framework-info-file "$(Build.BinariesDirectory)/ios_framework/framework_info.json" \
--framework-dir "$(Build.BinariesDirectory)/ios_framework/framework_out/onnxruntime.framework"
displayName: "Assemble onnxruntime-mobile-c pod files"
- script: |
pod lib lint --verbose
workingDirectory: "$(Build.BinariesDirectory)/staging/onnxruntime-mobile-c"
displayName: "Check onnxruntime-mobile-c pod"
- script: |
python tools/ci_build/github/apple/objectivec/assemble_objc_pod_package.py \
--staging-dir "$(Build.BinariesDirectory)/staging/onnxruntime-mobile-objc" \
--pod-version ${ORT_POD_VERSION} \
--framework-info-file "$(Build.BinariesDirectory)/ios_framework/framework_info.json"
displayName: "Assemble onnxruntime-mobile-objc pod files"
- script: |
pod lib lint --verbose \
--include-podspecs="$(Build.BinariesDirectory)/staging/onnxruntime-mobile-c/onnxruntime-mobile-c.podspec"
workingDirectory: "$(Build.BinariesDirectory)/staging/onnxruntime-mobile-objc"
displayName: "Check onnxruntime-mobile-objc pod"
- bash: |
set -e
gem install jazzy
jazzy --config objectivec/docs/jazzy_config.yaml \
--output "$(Build.BinariesDirectory)/staging/objc_api_docs" \
--module-version ${ORT_POD_VERSION}
displayName: "Generate Objective-C API docs"
- task: AzureCLI@2
inputs:
azureSubscription: 'AIInfraBuildOnnxRuntimeOSS'
scriptType: 'bash'
scriptLocation: 'scriptPath'
scriptPath: 'tools/ci_build/github/apple/assemble_ios_packaging_artifacts.sh'
arguments: >-
"$(Build.BinariesDirectory)/staging"
"$(Build.ArtifactStagingDirectory)"
"$(ORT_POD_VERSION)"
"$(ORT_SHOULD_UPLOAD_ARCHIVES)"
displayName: "Assemble artifacts"
- publish: "$(Build.ArtifactStagingDirectory)"
artifact: ios_packaging_artifacts
displayName: "Publish artifacts"

View file

@ -3,7 +3,7 @@ trigger: none
jobs:
- template: templates/win-ci-2019.yml
parameters:
AgentPool : 'Win-GPU-2019'
AgentPool : 'onnxruntime-win-cuda11-0'
JobName: 'Win_GPU_Training'
# TODO fix test failures and remove --skip_onnx_tests
BuildCommand: >-

View file

@ -6,7 +6,7 @@ parameters:
jobs:
- job: 'build'
pool: 'Win-GPU-2019'
pool: 'onnxruntime-win-cuda11-0'
variables:
OrtPackageId: 'Microsoft.ML.OnnxRuntime.Gpu'
MsbuildArguments: '-maxcpucount'

View file

@ -1,6 +1,6 @@
jobs:
- job: 'build'
pool: 'Win-GPU-2019'
pool: 'onnxruntime-win-cuda11-0'
strategy:
maxParallel: 2
matrix:

View file

@ -30,7 +30,7 @@ python3 /onnxruntime_src/tools/ci_build/build.py \
# set current size limit to 1165KB.
python3 /onnxruntime_src/tools/ci_build/github/linux/ort_minimal/check_build_binary_size.py \
--threshold=1165000 \
--threshold=1175000 \
/build/MinSizeRel/libonnxruntime.so
# Post the binary size info to ort mysql DB