Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support xcframework for mac catalyst builds. #19534

Merged
merged 24 commits into from
Mar 20, 2024
Merged
Show file tree
Hide file tree
Changes from 16 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions cmake/adjust_global_compile_flags.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,15 @@ if (CMAKE_SYSTEM_NAME STREQUAL "Android")
string(APPEND CMAKE_ASM_FLAGS_RELEASE " -O3")
endif()

# Suggested by https://gitlab.kitware.com/cmake/cmake/-/issues/20132
# MacCatalyst is not well supported in CMake
# The error that can emerge without this flag can look like:
# "clang : error : overriding '-mmacosx-version-min=11.0' option with '-target x86_64-apple-ios14.0-macabi' [-Werror,-Woverriding-t-option]"
if (PLATFORM_NAME STREQUAL "macabi")
add_compile_options(-Wno-overriding-t-option)
add_link_options(-Wno-overriding-t-option)
endif()

# Enable space optimization for gcc/clang
# Cannot use "-ffunction-sections -fdata-sections" if we enable bitcode (iOS)
if (NOT MSVC AND NOT onnxruntime_ENABLE_BITCODE)
Expand Down
8 changes: 7 additions & 1 deletion cmake/onnxruntime.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -281,7 +281,13 @@ endif()

# Assemble the Apple static framework (iOS and macOS)
if(onnxruntime_BUILD_APPLE_FRAMEWORK)
set(STATIC_FRAMEWORK_OUTPUT_DIR ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_BUILD_TYPE}-${CMAKE_OSX_SYSROOT})
# when building for mac catalyst, the CMAKE_OSX_SYSROOT is set to MacOSX as well, to avoid duplication,
# we specify as `-macabi` in the name of the output static apple framework directory.
if (PLATFORM_NAME STREQUAL "macabi")
set(STATIC_FRAMEWORK_OUTPUT_DIR ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_BUILD_TYPE}-macabi)
else()
set(STATIC_FRAMEWORK_OUTPUT_DIR ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_BUILD_TYPE}-${CMAKE_OSX_SYSROOT})
endif()
YUNQIUGUO marked this conversation as resolved.
Show resolved Hide resolved

# Setup the various directories required. Remove any existing ones so we start with a clean directory.
set(STATIC_LIB_DIR ${CMAKE_CURRENT_BINARY_DIR}/static_libraries)
Expand Down
6 changes: 6 additions & 0 deletions cmake/onnxruntime_mlas.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -631,6 +631,12 @@ if (WIN32)
endif()
endif()

if (PLATFORM_NAME STREQUAL "macabi")
# Needed for maccatalyst C compilation
# i.e. the flags below add "--target=x86_64-apple-ios14.0-macabi -ffunction-sections -fdata-sections"
target_compile_options(onnxruntime_mlas PRIVATE ${CMAKE_C_FLAGS})
endif()

if (NOT onnxruntime_BUILD_SHARED_LIB)
install(TARGETS onnxruntime_mlas
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
229E595826586B4A006E41AE /* sigmoid.ort */ = {isa = PBXFileReference; lastKnownFileType = file; path = sigmoid.ort; sourceTree = "<group>"; };
22C1D8DE271A79AF002CEE67 /* ios_package_testUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = ios_package_testUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
22C1D8E9271A79FD002CEE67 /* ios_package_uitest_cpp_api.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ios_package_uitest_cpp_api.mm; sourceTree = "<group>"; };
513C65792B85789400E4EDFD /* ios_package_test.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = ios_package_test.entitlements; sourceTree = "<group>"; };
51C316B92B0881450033C70B /* macos_package_test.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = macos_package_test.app; sourceTree = BUILT_PRODUCTS_DIR; };
51C316BB2B0881450033C70B /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = "<group>"; };
51C316BC2B0881450033C70B /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = "<group>"; };
Expand Down Expand Up @@ -117,6 +118,7 @@
229E591E265869BF006E41AE /* ios_package_test */ = {
isa = PBXGroup;
children = (
513C65792B85789400E4EDFD /* ios_package_test.entitlements */,
229E591F265869BF006E41AE /* AppDelegate.h */,
229E5920265869BF006E41AE /* AppDelegate.m */,
229E5928265869BF006E41AE /* Main.storyboard */,
Expand Down Expand Up @@ -521,18 +523,21 @@
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CODE_SIGN_STYLE = Automatic;
CODE_SIGNING_REQUIRED = NO;
CODE_SIGNING_STYLE = Automatic;
CODE_SIGN_ENTITLEMENTS = ios_package_test/ios_package_test.entitlements;
INFOPLIST_FILE = ios_package_test/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
PRODUCT_BUNDLE_IDENTIFIER = "ai.onnxruntime.tests.ios-package-test";
PRODUCT_NAME = "$(TARGET_NAME)";
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
SUPPORTS_MACCATALYST = NO;
SUPPORTS_MACCATALYST = YES;
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
TARGETED_DEVICE_FAMILY = 1;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Debug;
};
Expand All @@ -541,18 +546,21 @@
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CODE_SIGN_STYLE = Automatic;
CODE_SIGNING_REQUIRED = NO;
CODE_SIGNING_STYLE = Automatic;
CODE_SIGN_ENTITLEMENTS = ios_package_test/ios_package_test.entitlements;
INFOPLIST_FILE = ios_package_test/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
PRODUCT_BUNDLE_IDENTIFIER = "ai.onnxruntime.tests.ios-package-test";
PRODUCT_NAME = "$(TARGET_NAME)";
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
SUPPORTS_MACCATALYST = NO;
SUPPORTS_MACCATALYST = YES;
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
TARGETED_DEVICE_FAMILY = 1;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Release;
};
Expand All @@ -563,7 +571,7 @@
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
GENERATE_INFOPLIST_FILE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
Expand All @@ -585,7 +593,7 @@
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
GENERATE_INFOPLIST_FILE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?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>com.apple.security.app-sandbox</key>
<true/>
<key>com.apple.security.network.client</key>
<true/>
</dict>
</plist>
50 changes: 43 additions & 7 deletions tools/ci_build/build.py
Original file line number Diff line number Diff line change
Expand Up @@ -402,6 +402,12 @@ def convert_arg_line_to_args(self, arg_line):

parser.add_argument("--ios", action="store_true", help="build for ios")

parser.add_argument(
"--macos",
choices=["MacOSX", "Catalyst"],
YUNQIUGUO marked this conversation as resolved.
Show resolved Hide resolved
help="Specify the target platform for macOS build. Default is MacOSX. Only specify when --build_apple_framework is present.",
)

parser.add_argument(
"--apple_sysroot", default="", help="Specify the location name of the macOS platform SDK to be used"
)
Expand All @@ -421,7 +427,7 @@ def convert_arg_line_to_args(self, arg_line):
action="store_const",
const="Xcode",
dest="cmake_generator",
help="Use Xcode as cmake generator, this is only supported on MacOS. Equivalent to '--cmake_generator Xcode'.",
help="Use Xcode as cmake generator, this is only supported on MacOS. (non Catalyst build). Equivalent to '--cmake_generator Xcode'.",
)
parser.add_argument(
"--osx_arch",
Expand Down Expand Up @@ -1325,8 +1331,12 @@ def generate_build_tree(
if args.use_snpe:
cmake_args += ["-Donnxruntime_USE_SNPE=ON"]

if args.build_apple_framework or args.ios:
if not args.cmake_generator == "Xcode":
if args.macos or args.ios:
# Note: Xcode CMake generator doesn't have a good support for Mac Catalyst yet.
if args.macos == "Catalyst" and args.cmake_generator == "Xcode":
raise BuildError("Xcode CMake generator ('--cmake_generator Xcode') doesn't support Mac Catalyst build.")

if (args.ios or args.macos == "MacOSX") and not args.cmake_generator == "Xcode":
raise BuildError(
"iOS/MacOS framework build requires use of the Xcode CMake generator ('--cmake_generator Xcode')."
)
Expand All @@ -1344,19 +1354,37 @@ def generate_build_tree(
"iOS/MacOS framework build on MacOS canceled due to missing arguments: "
+ ", ".join(val for val, cond in zip(arg_names, needed_args) if not cond)
)
# note: this value is mainly used in framework_info.json file to specify the build osx type
platform_name = "macabi" if args.macos == "Catalyst" else args.apple_sysroot
cmake_args += [
"-Donnxruntime_BUILD_SHARED_LIB=ON",
"-DCMAKE_OSX_SYSROOT=" + args.apple_sysroot,
"-DCMAKE_OSX_DEPLOYMENT_TARGET=" + args.apple_deploy_target,
# we do not need protoc binary for ios cross build
"-Dprotobuf_BUILD_PROTOC_BINARIES=OFF",
"-DPLATFORM_NAME=" + platform_name,
]
if args.ios:
cmake_args += [
"-DCMAKE_SYSTEM_NAME=iOS",
"-DCMAKE_TOOLCHAIN_FILE="
+ (args.ios_toolchain_file if args.ios_toolchain_file else "../cmake/onnxruntime_ios.toolchain.cmake"),
]
# for catalyst build, we need to manually specify cflags for target e.g. x86_64-apple-ios14.0-macabi, etc.
# https://forums.developer.apple.com/forums/thread/122571
if args.macos == "Catalyst":
macabi_target = f"{args.osx_arch}-apple-ios{args.apple_deploy_target}-macabi"
cmake_args += [
"-DCMAKE_CXX_COMPILER_TARGET=" + macabi_target,
"-DCMAKE_C_COMPILER_TARGET=" + macabi_target,
"-DCMAKE_CC_COMPILER_TARGET=" + macabi_target,
"-DCMAKE_CXX_FLAGS=" + f"--target={macabi_target}",
"-DCMAKE_CXX_FLAGS_RELEASE=" + f"-O3 -DNDEBUG --target={macabi_target}",
"-DCMAKE_C_FLAGS=" + f"--target={macabi_target}",
"-DCMAKE_C_FLAGS_RELEASE=" + f"-O3 -DNDEBUG --target={macabi_target}",
"-DCMAKE_CC_FLAGS=" + f"--target={macabi_target}",
"-DCMAKE_CC_FLAGS_RELEASE=" + f"-O3 -DNDEBUG --target={macabi_target}",
YUNQIUGUO marked this conversation as resolved.
Show resolved Hide resolved
]

if args.build_wasm:
emsdk_dir = os.path.join(cmake_dir, "external", "emsdk")
Expand Down Expand Up @@ -1631,9 +1659,11 @@ def generate_build_tree(
[
*temp_cmake_args,
f"-DCMAKE_BUILD_TYPE={config}",
f"-DCMAKE_PREFIX_PATH={build_dir}/{config}/installed"
if preinstalled_dir.exists() and not (args.arm64 or args.arm64ec or args.arm)
else "",
(
f"-DCMAKE_PREFIX_PATH={build_dir}/{config}/installed"
if preinstalled_dir.exists() and not (args.arm64 or args.arm64ec or args.arm)
else ""
),
],
cwd=config_build_dir,
cuda_home=cuda_home,
Expand Down Expand Up @@ -2726,7 +2756,13 @@ def main():
cmake_extra_args += ["-G", args.cmake_generator]

if is_macOS():
if not args.ios and not args.android and args.osx_arch == "arm64" and platform.machine() == "x86_64":
if (
not args.ios
and args.macos != "Catalyst"
and not args.android
and args.osx_arch == "arm64"
and platform.machine() == "x86_64"
Fixed Show fixed Hide fixed
):
if args.test:
log.warning("Cannot test ARM64 build on X86_64. Will skip test running after build.")
args.test = False
Expand Down
12 changes: 8 additions & 4 deletions tools/ci_build/github/apple/build_apple_framework.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,11 @@ def _build_for_apple_sysroot(
# Build binary for each arch, one by one
for current_arch in archs:
build_dir_current_arch = os.path.join(intermediates_dir, sysroot + "_" + current_arch)
# Use MacOS SDK for Catalyst builds
apple_sysroot = "macosx" if sysroot == "macabi" else sysroot
build_command = [
*base_build_command,
"--apple_sysroot=" + sysroot,
"--apple_sysroot=" + apple_sysroot,
"--osx_arch=" + current_arch,
"--build_dir=" + build_dir_current_arch,
]
Expand All @@ -65,9 +67,11 @@ def _build_for_apple_sysroot(
build_dir_current_arch,
build_config,
build_config + "-" + sysroot,
"onnxruntime.framework"
if build_dynamic_framework
else os.path.join("static_framework", "onnxruntime.framework"),
(
"onnxruntime.framework"
if build_dynamic_framework
else os.path.join("static_framework", "onnxruntime.framework")
),
)
ort_libs.append(os.path.join(framework_dir, "onnxruntime"))

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
"--cmake_extra_defines=onnxruntime_BUILD_UNIT_TESTS=OFF"
],
"macosx": [
"--macos=MacOSX",
"--apple_deploy_target=11.0"
],
"iphoneos": [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,25 +6,35 @@
"iphonesimulator": [
"arm64",
"x86_64"
],
"macabi": [
"arm64",
"x86_64"
]
},
"build_params": {
"base": [
"--parallel",
"--use_xcode",
"--build_apple_framework",
"--use_coreml",
"--use_xnnpack",
"--skip_tests",
"--cmake_extra_defines=onnxruntime_BUILD_UNIT_TESTS=OFF"
],
"iphoneos": [
"--ios",
"--use_xcode",
"--use_xnnpack",
"--apple_deploy_target=12.0"
],
"iphonesimulator": [
"--ios",
"--use_xcode",
"--use_xnnpack",
"--apple_deploy_target=12.0"
],
"macabi":[
"--macos=Catalyst",
"--apple_deploy_target=14.0"
]
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
"--apple_deploy_target=12.0"
],
"macosx": [
"--macos=MacOSX",
"--apple_deploy_target=11.0"
]
}
Expand Down
2 changes: 1 addition & 1 deletion tools/ci_build/github/apple/framework_info.json.template
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"@CMAKE_OSX_SYSROOT@": {
"@PLATFORM_NAME@": {
"APPLE_DEPLOYMENT_TARGET": "@CMAKE_OSX_DEPLOYMENT_TARGET@",
"WEAK_FRAMEWORK": "@APPLE_WEAK_FRAMEWORK@"
}
Expand Down
25 changes: 25 additions & 0 deletions tools/ci_build/github/apple/test_apple_packages.py
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,25 @@ def _test_apple_packages(args):
cwd=target_proj_path,
)

if args.mac_catalyst_enabled:
subprocess.run(
[
"xcrun",
"xcodebuild",
"test",
"-workspace",
"./apple_package_test.xcworkspace",
"-scheme",
"ios_package_test",
"-destination",
"platform=macOS,variant=Mac Catalyst",
"CODE_SIGNING_ALLOWED=NO",
],
shell=False,
check=True,
cwd=target_proj_path,
)

if PackageVariant[args.variant] != PackageVariant.Mobile and not args.skip_macos_test:
subprocess.run(
[
Expand Down Expand Up @@ -215,6 +234,12 @@ def parse_args():
help="Skip macos platform tests. Specify this argument when build targets only contain ios archs. ",
)

parser.add_argument(
"--mac_catalyst_enabled",
action="store_true",
help="Run tests for mac catalyst variants. Specify this argument when build targets contains catalyst archs. ",
)

return parser.parse_args()


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,8 @@ stages:
--framework_info_file "$(Build.BinariesDirectory)/ios_framework/xcframework_info.json" \
--c_framework_dir "$(Build.BinariesDirectory)/ios_framework/framework_out" \
--variant Full \
--skip_macos_test
--skip_macos_test \
--mac_catalyst_enabled
displayName: "Test Apple framework"

- task: PublishBuildArtifacts@1
Expand Down
Loading