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

Updates to apple packaging #21611

Merged
merged 1 commit into from
Aug 5, 2024
Merged
Show file tree
Hide file tree
Changes from all 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
23 changes: 0 additions & 23 deletions tools/ci_build/github/apple/assemble_apple_packaging_artifacts.sh
Original file line number Diff line number Diff line change
Expand Up @@ -23,29 +23,6 @@ ORT_POD_VERSION=${4:?${USAGE_TEXT}}
POD_ARCHIVE_BASENAME="pod-archive-${POD_NAME}-${ORT_POD_VERSION}.zip"
PODSPEC_BASENAME="${POD_NAME}.podspec"


# Macos requires a different structure for the framework
# This will create the necessary symlinks for the macos framework before packaging
# Adding the symlinks here rather than in the build script ensures that symlinks are not lost
for MACOS_DIR in "${BINARIES_STAGING_DIR}/${POD_NAME}/onnxruntime.xcframework/macos"*; do
if [ -d "${MACOS_DIR}" ]; then
echo "Creating symlinks for ${MACOS_DIR}"
pushd "${MACOS_DIR}/onnxruntime.framework"

rm -rf Headers Resources onnxruntime
rm -rf Versions/Current

ln -sfn A Versions/Current
ln -sfn Versions/Current/Headers Headers
ln -sfn Versions/Current/Resources Resources
ln -sfn Versions/Current/onnxruntime onnxruntime

popd

fi
done


echo "Contents of ${BINARIES_STAGING_DIR}/${POD_NAME}:"
ls -lR "${BINARIES_STAGING_DIR}/${POD_NAME}"

Expand Down
11 changes: 9 additions & 2 deletions tools/ci_build/github/apple/build_and_assemble_apple_pods.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,11 @@ def parse_args():
)

parser.add_argument("--test", action="store_true", help="Run tests on the framework and pod package files.")
parser.add_argument(
"--skip-build",
action="store_true",
help="Use build from previous run. Useful to debug test issues or packaging changes.",
)

build_framework_group = parser.add_argument_group(
title="iOS framework build arguments",
Expand Down Expand Up @@ -114,7 +119,8 @@ def main():

build_apple_framework_args += ["--build_dir", str(build_dir), args.build_settings_file]

run(build_apple_framework_args)
if not args.skip_build:
run(build_apple_framework_args)

if args.test:
test_apple_packages_args = [
Expand Down Expand Up @@ -171,7 +177,8 @@ def main():
def move_dir(src, dst):
if dst.is_dir():
shutil.rmtree(dst)
shutil.move(src, dst)
shutil.copytree(src, dst, symlinks=True)
shutil.rmtree(src)

move_dir(c_pod_staging_dir, staging_dir / c_pod_name)
move_dir(objc_pod_staging_dir, staging_dir / objc_pod_name)
Expand Down
2 changes: 1 addition & 1 deletion tools/ci_build/github/apple/build_apple_framework.py
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@ def _build_package(args):
xcframework_dir = os.path.join(build_dir, "framework_out")
pathlib.Path(xcframework_dir).mkdir(parents=True, exist_ok=True)
shutil.copy(os.path.join(REPO_DIR, "LICENSE"), xcframework_dir)
shutil.copytree(public_headers_path, os.path.join(xcframework_dir, "Headers"), dirs_exist_ok=True)
shutil.copytree(public_headers_path, os.path.join(xcframework_dir, "Headers"), dirs_exist_ok=True, symlinks=True)
_merge_framework_info_files(framework_info_files_to_merge, os.path.join(build_dir, "xcframework_info.json"))

# remove existing xcframework if any
Expand Down
13 changes: 8 additions & 5 deletions tools/ci_build/github/apple/c/assemble_c_pod_package.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
PackageVariant,
copy_repo_relative_to_dir,
gen_file_from_template,
get_podspec_values,
load_json_config,
)

Expand Down Expand Up @@ -66,23 +67,25 @@ def assemble_c_pod_package(
print("Warning: staging directory already exists", file=sys.stderr)

# copy the necessary files to the staging directory
shutil.copytree(framework_dir, staging_dir / framework_dir.name, dirs_exist_ok=True)
shutil.copytree(public_headers_dir, staging_dir / public_headers_dir.name, dirs_exist_ok=True)
shutil.copytree(framework_dir, staging_dir / framework_dir.name, dirs_exist_ok=True, symlinks=True)
shutil.copytree(public_headers_dir, staging_dir / public_headers_dir.name, dirs_exist_ok=True, symlinks=True)
copy_repo_relative_to_dir(["LICENSE"], staging_dir)

(ios_deployment_target, macos_deployment_target, weak_framework) = get_podspec_values(framework_info)

# generate the podspec file from the template
variable_substitutions = {
"DESCRIPTION": pod_config["description"],
# By default, we build both "iphoneos" and "iphonesimulator" architectures, and the deployment target should be the same between these two.
"IOS_DEPLOYMENT_TARGET": framework_info["iphonesimulator"]["APPLE_DEPLOYMENT_TARGET"],
"MACOSX_DEPLOYMENT_TARGET": framework_info.get("macosx", {}).get("APPLE_DEPLOYMENT_TARGET", ""),
"IOS_DEPLOYMENT_TARGET": ios_deployment_target,
"MACOSX_DEPLOYMENT_TARGET": macos_deployment_target,
"LICENSE_FILE": "LICENSE",
"NAME": pod_name,
"ORT_C_FRAMEWORK": framework_dir.name,
"ORT_C_HEADERS_DIR": public_headers_dir.name,
"SUMMARY": pod_config["summary"],
"VERSION": pod_version,
"WEAK_FRAMEWORK": framework_info["iphonesimulator"]["WEAK_FRAMEWORK"],
"WEAK_FRAMEWORK": weak_framework,
}

podspec_template = _script_dir / "c.podspec.template"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
copy_repo_relative_to_dir,
filter_files,
gen_file_from_template,
get_podspec_values,
load_json_config,
)

Expand Down Expand Up @@ -147,12 +148,14 @@ def assemble_objc_pod_package(
def path_patterns_as_variable_value(patterns: list[str]):
return ", ".join([f'"{pattern}"' for pattern in patterns])

(ios_deployment_target, macos_deployment_target, _) = get_podspec_values(framework_info)

variable_substitutions = {
"C_POD_NAME": c_pod_config["name"],
"DESCRIPTION": pod_config["description"],
"INCLUDE_DIR_LIST": path_patterns_as_variable_value(include_dirs),
"IOS_DEPLOYMENT_TARGET": framework_info["iphonesimulator"]["APPLE_DEPLOYMENT_TARGET"],
"MACOSX_DEPLOYMENT_TARGET": framework_info.get("macosx", {}).get("APPLE_DEPLOYMENT_TARGET", ""),
"IOS_DEPLOYMENT_TARGET": ios_deployment_target,
"MACOSX_DEPLOYMENT_TARGET": macos_deployment_target,
"LICENSE_FILE": license_file,
"NAME": pod_name,
"PUBLIC_HEADER_FILE_LIST": path_patterns_as_variable_value(pod_files["public_header_files"]),
Expand Down
38 changes: 38 additions & 0 deletions tools/ci_build/github/apple/package_assembly_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,44 @@ def load_json_config(json_config_file: pathlib.Path):
return json.load(config)


def get_podspec_values(framework_info):
"""
Get the podspec deployement targets and weak framework info from the dictionary that load_json_config returned.
Looks for iphonesimulator, iphoneos and macos settings.
Handles missing platforms and checks consistency.
Returns empty string for deployment target if that platofrm is not enabled.

:return (ios_deployment_target, macos_deployment_target, weak_framework)
"""
ios_deployment_target = ""
macos_deployment_target = ""
weak_framework = "" # should be the same for all platforms
# get info, allowing for a subset of platforms to be specified
for framework in ("iphonesimulator", "iphoneos", "macosx"):
if framework not in framework_info:
continue

target = framework_info[framework]["APPLE_DEPLOYMENT_TARGET"]
weak = framework_info[framework]["WEAK_FRAMEWORK"]

if not weak_framework:
weak_framework = weak
else:
# should be consistent
assert weak == weak_framework

if framework == "macosx":
macos_deployment_target = target
else:
if not ios_deployment_target:
ios_deployment_target = target
else:
# should be consistent
assert ios_deployment_target == target

return (ios_deployment_target, macos_deployment_target, weak_framework)


def get_ort_version():
"""
Gets the ONNX Runtime version string from the repo.
Expand Down
5 changes: 3 additions & 2 deletions tools/ci_build/github/apple/test_apple_packages.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,8 +89,9 @@ def _test_apple_packages(args):

# 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)

# shutil.make_archive doesn't preserve symlinks. we know this is running on macOS so use zip
subprocess.run(["zip", "-r", "-y", str(zip_file_path), "."], cwd=local_pods_dir, check=True)

# update the podspec to point to the local framework zip file
with open(podspec) as file:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ stages:
cp -R $(Build.BinariesDirectory)/ios_framework/framework_out/onnxruntime.xcframework \
$(Build.BinariesDirectory)/artifacts_staging/onnxruntime-ios-xcframework-$(OnnxRuntimeVersion)
pushd $(Build.BinariesDirectory)/artifacts_staging
zip -vr $(Build.BinariesDirectory)/artifacts/onnxruntime_xcframework.zip \
zip -vry $(Build.BinariesDirectory)/artifacts/onnxruntime_xcframework.zip \
onnxruntime-ios-xcframework-$(OnnxRuntimeVersion)
popd
displayName: "Build Apple xcframework"
Expand Down
Loading