mirror of
https://github.com/saymrwulf/onnxruntime.git
synced 2026-05-16 21:00:14 +00:00
158 lines
6.9 KiB
Python
158 lines
6.9 KiB
Python
#!/usr/bin/env python3
|
|
# Copyright (c) Microsoft Corporation. All rights reserved.
|
|
# Licensed under the MIT License.
|
|
|
|
import argparse
|
|
import contextlib
|
|
import os
|
|
import pathlib
|
|
import shutil
|
|
import subprocess
|
|
import tempfile
|
|
|
|
|
|
from c.assemble_c_pod_package import assemble_c_pod_package
|
|
from package_assembly_utils import gen_file_from_template, get_ort_version, PackageVariant
|
|
|
|
|
|
SCRIPT_PATH = pathlib.Path(__file__).resolve(strict=True)
|
|
REPO_DIR = SCRIPT_PATH.parents[4]
|
|
|
|
|
|
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))
|
|
|
|
has_framework = (c_framework_dir / 'onnxruntime.framework').exists()
|
|
has_xcframework = (c_framework_dir / 'onnxruntime.xcframework').exists()
|
|
|
|
if not has_framework and not has_xcframework:
|
|
raise FileNotFoundError('{} does not have onnxruntime.framework/xcframework'.format(c_framework_dir))
|
|
|
|
if has_framework and has_xcframework:
|
|
raise ValueError('Cannot proceed when both onnxruntime.framework '
|
|
'and onnxruntime.xcframework exist')
|
|
|
|
framework_name = 'onnxruntime.framework' if has_framework else 'onnxruntime.xcframework'
|
|
|
|
# create a temp folder
|
|
|
|
with contextlib.ExitStack() as context_stack:
|
|
if args.test_project_stage_dir is None:
|
|
stage_dir = pathlib.Path(context_stack.enter_context(tempfile.TemporaryDirectory())).resolve()
|
|
else:
|
|
# If we specify the stage dir, then use it to create test project
|
|
stage_dir = args.test_project_stage_dir.resolve()
|
|
if os.path.exists(stage_dir):
|
|
shutil.rmtree(stage_dir)
|
|
os.makedirs(stage_dir)
|
|
|
|
# assemble the test project here
|
|
target_proj_path = stage_dir / 'ios_package_test'
|
|
|
|
# copy the test project source files to target_proj_path
|
|
test_proj_path = pathlib.Path(REPO_DIR, 'onnxruntime/test/platform/ios/ios_package_test')
|
|
shutil.copytree(test_proj_path, target_proj_path)
|
|
|
|
# assemble local pod files here
|
|
local_pods_dir = stage_dir / 'local_pods'
|
|
|
|
# We will only publish xcframework, however, assembly of the xcframework is a post process
|
|
# and it cannot be done by CMake for now. See, https://gitlab.kitware.com/cmake/cmake/-/issues/21752
|
|
# For a single sysroot and arch built by build.py or cmake, we can only generate framework
|
|
# We still need a way to test it. framework_dir and public_headers_dir have different values when testing a
|
|
# framework and a xcframework.
|
|
framework_dir = args.c_framework_dir / framework_name
|
|
public_headers_dir = framework_dir / "Headers" if has_framework else args.c_framework_dir / "Headers"
|
|
|
|
pod_name, podspec = assemble_c_pod_package(staging_dir=local_pods_dir,
|
|
pod_version=get_ort_version(),
|
|
framework_info_file=args.framework_info_file,
|
|
public_headers_dir=public_headers_dir,
|
|
framework_dir=framework_dir,
|
|
package_variant=PackageVariant[args.variant])
|
|
|
|
# move podspec out to target_proj_path first
|
|
podspec = shutil.move(podspec, target_proj_path / podspec.name)
|
|
|
|
# create a zip file contains the framework
|
|
zip_file_path = local_pods_dir / f'{pod_name}.zip'
|
|
# shutil.make_archive require target file as full path without extension
|
|
shutil.make_archive(zip_file_path.with_suffix(''), 'zip', root_dir=local_pods_dir)
|
|
|
|
# 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', f'file:///{zip_file_path}')
|
|
|
|
with open(podspec, 'w') as file:
|
|
file.write(file_data)
|
|
|
|
# generate Podfile to point to pod
|
|
gen_file_from_template(target_proj_path / "Podfile.template", target_proj_path / "Podfile",
|
|
{"C_POD_NAME": pod_name,
|
|
"C_POD_PODSPEC": f"./{podspec.name}"})
|
|
|
|
# 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
|
|
if not args.prepare_test_project_only:
|
|
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')
|
|
|
|
parser.add_argument("--variant", choices=PackageVariant.all_variant_names(), default=PackageVariant.Test.name,
|
|
help="Pod package variant.")
|
|
|
|
parser.add_argument('--test_project_stage_dir', type=pathlib.Path,
|
|
help='The stage dir for the test project, if not specified, will use a temporary path')
|
|
|
|
parser.add_argument('--prepare_test_project_only', action='store_true',
|
|
help='Prepare the test project only, without running the tests')
|
|
|
|
return parser.parse_args()
|
|
|
|
|
|
def main():
|
|
args = parse_args()
|
|
_test_ios_packages(args)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
main()
|