iOS cross build on MacOS (#3699)

* Enable iOS cross build on MacOS (step#1)

* Changed parallel option

* fixed style issues

* Enable ios arm64 crossbuild on MacOS

* Enable ios arm64 crossbuild on MacOS

* Enable parallel build for xcode

* Fix arm64 function not 4-byte aligned warning

* Rename onnxruntime_ios.cmake to onnxruntime_ios.toolchain.cmake

* change build.py to use the new ios toolchain file name
This commit is contained in:
gwang-msft 2020-04-28 17:09:31 -07:00 committed by GitHub
parent 29c12c0f07
commit 12d7c2f6e4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 126 additions and 40 deletions

View file

@ -0,0 +1,5 @@
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License.
set(CMAKE_SYSTEM_NAME iOS)
set(CMAKE_XCODE_ATTRIBUTE_CODE_SIGNING_ALLOWED NO)

View file

@ -98,12 +98,16 @@ else()
elseif (CMAKE_ANDROID_ARCH_ABI STREQUAL "x86")
set(X86 TRUE)
endif()
elseif(CMAKE_SYSTEM_NAME STREQUAL "iOSCross")
elseif(CMAKE_SYSTEM_NAME STREQUAL "iOS" OR CMAKE_SYSTEM_NAME STREQUAL "iOSCross")
set(IOS TRUE)
if (CMAKE_OSX_ARCHITECTURES STREQUAL "arm64")
set(ARM64 TRUE)
elseif (CMAKE_OSX_ARCHITECTURES STREQUAL "arm")
set(ARM TRUE)
elseif (CMAKE_OSX_ARCHITECTURES STREQUAL "x86_64")
set(X86_64 TRUE)
elseif (CMAKE_OSX_ARCHITECTURES STREQUAL "i386")
set(X86 TRUE)
endif()
else()
execute_process(

View file

@ -19,6 +19,8 @@ Abstract:
#include "asmmacro.h"
.text
.p2align 2
//
// ClearRowAccumulators
//
@ -431,7 +433,7 @@ Return Value:
.globl C_UNDERSCORE(MlasSgemmKernel\Mode\())
#ifndef __APPLE__
.type C_UNDERSCORE(MlasSgemmKernel\Mode\()),%function
#endif
#endif
C_UNDERSCORE(MlasSgemmKernel\Mode\()):
stp d8,d9,[sp,#-32]!

View file

@ -201,10 +201,27 @@ def parse_arguments():
parser.add_argument("--ios", action='store_true', help="build for ios")
parser.add_argument(
"--ios_sysroot", default="", help="Path to ios sysroot")
"--ios_sysroot", default="",
help="Specify the location name of the macOS platform SDK to be used")
parser.add_argument(
"--ios_toolchain_dir", default="",
help="Path to ios toolchain binaries")
parser.add_argument(
"--ios_toolchain_file", default="",
help="Path to ios toolchain file, "
"or cmake/onnxruntime_ios.toolchain.cmake will be used")
parser.add_argument(
"--use_xcode", action='store_true',
help="Use Xcode as cmake generator, this is only supported on MacOS.")
parser.add_argument(
"--osx_arch", type=str,
help="Specify the Target specific architectures for macOS and iOS"
"This is only supported on MacOS")
parser.add_argument(
"--apple_deploy_target", type=str,
help="Specify the minimum version of the target platform "
"(e.g. macOS or iOS)"
"This is only supported on MacOS")
# Arguments needed by CI
parser.add_argument(
@ -326,6 +343,10 @@ def is_windows():
return sys.platform.startswith("win")
def is_macOS():
return sys.platform.startswith("darwin")
def get_linux_distro():
try:
with open('/etc/os-release', 'r') as f:
@ -496,7 +517,8 @@ def generate_build_tree(cmake_path, source_dir, build_dir, cuda_home,
"OFF" if args.skip_winml_tests else "ON"),
"-Donnxruntime_GENERATE_TEST_REPORTS=ON",
"-Donnxruntime_DEV_MODE=" + (
"OFF" if args.android or args.use_acl else "ON"),
"OFF" if args.android or args.use_acl or
(args.ios and is_macOS()) else "ON"),
"-DPYTHON_EXECUTABLE=" + sys.executable,
"-Donnxruntime_USE_CUDA=" + ("ON" if args.use_cuda else "OFF"),
"-Donnxruntime_CUDNN_HOME=" + (cudnn_home if args.use_cuda else ""),
@ -539,8 +561,10 @@ def generate_build_tree(cmake_path, source_dir, build_dir, cuda_home,
"ON" if args.use_openvino else "OFF"),
"-Donnxruntime_USE_NNAPI=" + ("ON" if args.use_dnnlibrary else "OFF"),
"-Donnxruntime_USE_OPENMP=" + (
"ON" if args.use_openmp and not args.use_dnnlibrary and
not args.use_mklml and not args.use_ngraph and not args.android else "OFF"),
"ON" if args.use_openmp and not (
args.use_dnnlibrary or args.use_mklml or args.use_ngraph or
args.android or (args.ios and is_macOS()))
else "OFF"),
"-Donnxruntime_USE_TVM=" + ("ON" if args.use_tvm else "OFF"),
"-Donnxruntime_USE_LLVM=" + ("ON" if args.use_llvm else "OFF"),
"-Donnxruntime_ENABLE_MICROSOFT_INTERNAL=" + (
@ -626,40 +650,83 @@ def generate_build_tree(cmake_path, source_dir, build_dir, cuda_home,
"-DANDROID_ABI=" + str(args.android_abi)
]
if is_macOS() and args.use_xcode:
cmake_args += ["-GXcode"]
if args.ios:
needed_args = [
args.ios_sysroot,
args.arm64 or args.arm,
args.ios_toolchain_dir
]
arg_names = [
"--ios_sysroot <path to sysroot>",
"--arm or --arm64",
"--ios_toolchain_dir <path to toolchain>"
]
if not all(needed_args):
raise BuildError(
"iOS build canceled due to missing arguments: " + ', '.join(
val for val, cond in zip(arg_names, needed_args)
if not cond))
compilers = sorted(glob.glob(args.ios_toolchain_dir + "/bin/*-clang*"))
os.environ["PATH"] = os.path.join(
args.ios_toolchain_dir, "bin") + os.pathsep + os.environ.get(
"PATH", "")
os.environ["LD_LIBRARY_PATH"] = os.path.join(
args.ios_toolchain_dir, "/lib") + os.pathsep + os.environ.get(
"LD_LIBRARY_PATH", "")
if len(compilers) != 2:
raise BuildError(
"error identifying compilers in ios_toolchain_dir")
cmake_args += [
"-DCMAKE_OSX_ARCHITECTURES=" + ("arm64" if args.arm64 else "arm"),
"-DCMAKE_SYSTEM_NAME=iOSCross",
"-Donnxruntime_BUILD_UNIT_TESTS=OFF",
"-DCMAKE_OSX_SYSROOT=" + args.ios_sysroot,
"-DCMAKE_C_COMPILER=" + compilers[0],
"-DCMAKE_CXX_COMPILER=" + compilers[1]
]
if is_macOS():
needed_args = [
args.use_xcode,
args.ios_sysroot,
args.osx_arch,
args.apple_deploy_target,
]
arg_names = [
"--use_xcode " +
"<need use xcode to cross build iOS on MacOS>",
"--ios_sysroot " +
"<the location or name of the macOS platform SDK>",
"--osx_arch " +
"<the Target specific architectures for iOS>",
"--apple_deploy_target " +
"<the minimum version of the target platform>",
]
if not all(needed_args):
raise BuildError(
"iOS build on MacOS canceled due to missing arguments: " +
', '.join(
val for val, cond in zip(arg_names, needed_args)
if not cond))
cmake_args += [
"-DCMAKE_SYSTEM_NAME=iOS",
"-Donnxruntime_BUILD_UNIT_TESTS=OFF",
"-DCMAKE_OSX_SYSROOT=" + args.ios_sysroot,
"-DCMAKE_OSX_ARCHITECTURES=" + args.osx_arch,
"-DCMAKE_OSX_DEPLOYMENT_TARGET=" + args.apple_deploy_target,
# we do not need protoc binary for ios cross build
"-Dprotobuf_BUILD_PROTOC_BINARIES=OFF",
"-DCMAKE_TOOLCHAIN_FILE=" + (
args.ios_toolchain_file if args.ios_toolchain_file
else "../cmake/onnxruntime_ios.toolchain.cmake")
]
else:
# We are cross comppiling on linux
needed_args = [
args.ios_sysroot,
args.arm64 or args.arm,
args.ios_toolchain_dir
]
arg_names = [
"--ios_sysroot <path to sysroot>",
"--arm or --arm64",
"--ios_toolchain_dir <path to toolchain>"
]
if not all(needed_args):
raise BuildError(
"iOS build canceled due to missing arguments: " +
', '.join(
val for val, cond in zip(arg_names, needed_args)
if not cond))
compilers = sorted(
glob.glob(args.ios_toolchain_dir + "/bin/*-clang*"))
os.environ["PATH"] = os.path.join(
args.ios_toolchain_dir, "bin") + os.pathsep + os.environ.get(
"PATH", "")
os.environ["LD_LIBRARY_PATH"] = os.path.join(
args.ios_toolchain_dir, "/lib") + os.pathsep + os.environ.get(
"LD_LIBRARY_PATH", "")
if len(compilers) != 2:
raise BuildError(
"error identifying compilers in ios_toolchain_dir")
cmake_args += [
"-DCMAKE_OSX_ARCHITECTURES=" +
("arm64" if args.arm64 else "arm"),
"-DCMAKE_SYSTEM_NAME=iOSCross",
"-Donnxruntime_BUILD_UNIT_TESTS=OFF",
"-DCMAKE_OSX_SYSROOT=" + args.ios_sysroot,
"-DCMAKE_C_COMPILER=" + compilers[0],
"-DCMAKE_CXX_COMPILER=" + compilers[1]
]
if path_to_protoc_exe:
cmake_args += [
@ -766,6 +833,9 @@ def build_targets(args, cmake_path, build_dir, configs, parallel):
# if nodeReuse is true, msbuild processes will stay around for a bit after the build completes
"/nodeReuse:False",
]
elif (is_macOS() and args.use_xcode):
# CMake will generate correct build tool args for Xcode
cmd_args += ["--parallel", num_cores]
else:
build_tool_args += ["-j" + num_cores]
@ -1320,6 +1390,9 @@ def build_protoc_for_host(cmake_path, source_dir, build_dir, args):
if args.cmake_generator != 'Ninja':
cmd_args += ['-T', 'host=x64']
cmd_args += ['-G', args.cmake_generator]
elif is_macOS() and args.use_xcode:
cmd_args += ['-G', 'Xcode']
run_subprocess(cmd_args, cwd=protoc_build_dir)
# Build step
cmd_args = [cmake_path,
@ -1332,7 +1405,9 @@ def build_protoc_for_host(cmake_path, source_dir, build_dir, args):
expected_protoc_path = (
os.path.join(
protoc_build_dir, 'Release', 'protoc.exe') if is_windows()
else os.path.join(protoc_build_dir, 'protoc'))
else (os.path.join(protoc_build_dir, 'Release', 'protoc')
if is_macOS() and args.use_xcode
else os.path.join(protoc_build_dir, 'protoc')))
if not os.path.exists(expected_protoc_path):
raise BuildError("Couldn't build protoc for host. Failing build.")