Skip to content

Commit 57fae73

Browse files
shoumikhinfacebook-github-bot
authored andcommitted
A tool to automate iOS frameworks creation. (#688)
Summary: It builds all necessary libs with CMake, collects exported headers and creates xcframeworks. Reviewed By: kimishpatel Differential Revision: D50063617
1 parent 4418dfd commit 57fae73

File tree

2 files changed

+170
-1
lines changed

2 files changed

+170
-1
lines changed

build/build_apple_frameworks.sh

Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
#!/bin/bash
2+
# Copyright (c) Meta Platforms, Inc. and affiliates.
3+
# All rights reserved.
4+
#
5+
# This source code is licensed under the BSD-style license found in the
6+
# LICENSE file in the root directory of this source tree.
7+
8+
set -euo pipefail
9+
10+
PLATFORMS=("iphoneos" "iphonesimulator")
11+
PLATFORM_FLAGS=("OS" "SIMULATOR")
12+
SOURCE_ROOT_DIR=""
13+
OUTPUT="cmake-out"
14+
MODE="Debug"
15+
TOOLCHAIN=""
16+
BUCK2="/tmp/buck2"
17+
PYTHON=$(which python3)
18+
IOS_DEPLOYMENT_TARGET="17.0"
19+
COREML=OFF
20+
MPS=OFF
21+
XNNPACK=OFF
22+
HEADERS_PATH="include"
23+
EXECUTORCH_FRAMEWORK="executorch:libexecutorch.a,libextension_data_loader.a:$HEADERS_PATH"
24+
PORTABLE_FRAMEWORK="portable_backend:libportable_kernels.a,libportable_ops_lib.a:"
25+
COREML_FRAMEWORK="coreml_backend:libcoremldelegate.a:"
26+
MPS_FRAMEWORK="mps_backend:libmpsdelegate.a:"
27+
XNNPACK_FRAMEWORK="xnnpack_backend:libXNNPACK.a,libclog.a,libcpuinfo.a,libpthreadpool.a,libxnnpack_backend.a:"
28+
29+
usage() {
30+
echo "Usage: $0 [SOURCE_ROOT_DIR] [OPTIONS]"
31+
echo "Build frameworks for Apple platforms."
32+
echo "SOURCE_ROOT_DIR defaults to the current directory if not provided."
33+
echo
34+
echo "Options:"
35+
echo " --output=DIR Output directory. Default: 'cmake-out'"
36+
echo " --Release Use Release build mode. Default: 'Debug'"
37+
echo " --toolchain=FILE Cmake toolchain file. Default: '\$SOURCE_ROOT_DIR/third-party/pytorch/cmake/iOS.cmake'"
38+
echo " --buck2=FILE Buck2 executable path. Default: '/tmp/buck2'"
39+
echo " --python=FILE Python executable path. Default: Path of python3 found in the current \$PATH"
40+
echo " --coreml Include this flag to build Core ML backend."
41+
echo " --mps Include this flag to build Metal Performance Shaders backend."
42+
echo " --xnnpack Include this flag to build XNNPACK backend."
43+
echo
44+
echo "Example:"
45+
echo " $0 /path/to/source/root --output=cmake-out --Release --toolchain=/path/to/cmake/toolchain --buck2=/path/to/buck2 --python=/path/to/python3 --coreml --mps --xnnpack"
46+
exit 0
47+
}
48+
49+
for arg in "$@"; do
50+
case $arg in
51+
-h|--help) usage ;;
52+
--output=*) OUTPUT="${arg#*=}" ;;
53+
--Release) MODE="Release" ;;
54+
--toolchain=*) TOOLCHAIN="${arg#*=}" ;;
55+
--buck2=*) BUCK2="${arg#*=}" ;;
56+
--python=*) PYTHON="${arg#*=}" ;;
57+
--ios-deployment-target=*) IOS_DEPLOYMENT_TARGET="${arg#*=}" ;;
58+
--coreml) COREML=ON ;;
59+
--mps) MPS=ON ;;
60+
--xnnpack) XNNPACK=ON ;;
61+
*)
62+
if [[ -z "$SOURCE_ROOT_DIR" ]]; then
63+
SOURCE_ROOT_DIR="$arg"
64+
else
65+
echo "Invalid argument: $arg"
66+
exit 1
67+
fi
68+
;;
69+
esac
70+
done
71+
72+
if [[ -z "$SOURCE_ROOT_DIR" ]]; then
73+
SOURCE_ROOT_DIR=$(pwd)
74+
fi
75+
76+
if [[ -z "$TOOLCHAIN" ]]; then
77+
TOOLCHAIN="$SOURCE_ROOT_DIR/third-party/pytorch/cmake/iOS.cmake"
78+
fi
79+
[[ -f "$TOOLCHAIN" ]] || { echo >&2 "Toolchain file $TOOLCHAIN does not exist."; exit 1; }
80+
81+
check_command() {
82+
command -v "$1" >/dev/null 2>&1 || { echo >&2 "$1 is not installed"; exit 1; }
83+
}
84+
85+
check_command cmake
86+
check_command rsync
87+
check_command "$BUCK2"
88+
check_command "$PYTHON"
89+
90+
echo "Building libraries"
91+
92+
if [[ -z "$SOURCE_ROOT_DIR" ]]; then
93+
SOURCE_ROOT_DIR=$(pwd)
94+
fi
95+
96+
rm -rf "$OUTPUT" && mkdir -p "$OUTPUT" && cd "$OUTPUT" || exit 1
97+
98+
cmake_build() {
99+
local platform=$1
100+
local platform_flag=$2
101+
echo "Building for $platform with flag $platform_flag"
102+
mkdir "$platform" && cd "$platform" || exit 1
103+
cmake "$SOURCE_ROOT_DIR" -G Xcode \
104+
-DCMAKE_TOOLCHAIN_FILE="$TOOLCHAIN" \
105+
-DBUCK2="$BUCK2" \
106+
-DPYTHON_EXECUTABLE="$PYTHON" \
107+
-DFLATC_EXECUTABLE="$SOURCE_ROOT_DIR/third-party/flatbuffers/cmake-out/flatc" \
108+
-DEXECUTORCH_BUILD_EXTENSION_DATA_LOADER=ON \
109+
-DCMAKE_ARCHIVE_OUTPUT_DIRECTORY="$(pwd)" \
110+
-DIOS_DEPLOYMENT_TARGET="$IOS_DEPLOYMENT_TARGET" \
111+
-DEXECUTORCH_BUILD_COREML=$COREML \
112+
-DEXECUTORCH_BUILD_MPS=$MPS \
113+
-DEXECUTORCH_BUILD_XNNPACK=$XNNPACK \
114+
${platform_flag:+-DIOS_PLATFORM=$platform_flag}
115+
cmake --build . --config $MODE
116+
cd ..
117+
}
118+
119+
for index in ${!PLATFORMS[*]}; do
120+
cmake_build "${PLATFORMS[$index]}" "${PLATFORM_FLAGS[$index]}"
121+
done
122+
123+
echo "Exporting headers"
124+
125+
mkdir -p "$HEADERS_PATH"
126+
127+
"$SOURCE_ROOT_DIR"/build/print_exported_headers.py --buck2="$BUCK2" --targets \
128+
//runtime/executor:program \
129+
//extension/data_loader: \
130+
//extension/memory_allocator: \
131+
| rsync -av --files-from=- "$SOURCE_ROOT_DIR" "$HEADERS_PATH/executorch"
132+
133+
echo "Creating frameworks"
134+
135+
for platform in "${PLATFORMS[@]}"; do
136+
echo "Directory: $platform/$MODE"
137+
FRAMEWORK_FLAGS+=("--directory=$platform/$MODE")
138+
done
139+
140+
append_framework_flag() {
141+
local flag="$1"
142+
local framework="$2"
143+
if [[ $flag == ON ]]; then
144+
echo "Framework: $framework"
145+
FRAMEWORK_FLAGS+=("--framework=$framework")
146+
fi
147+
}
148+
149+
append_framework_flag "ON" "$EXECUTORCH_FRAMEWORK"
150+
append_framework_flag "ON" "$PORTABLE_FRAMEWORK"
151+
append_framework_flag "$COREML" "$COREML_FRAMEWORK"
152+
append_framework_flag "$MPS" "$MPS_FRAMEWORK"
153+
append_framework_flag "$XNNPACK" "$XNNPACK_FRAMEWORK"
154+
155+
"$SOURCE_ROOT_DIR"/build/create_frameworks.sh "${FRAMEWORK_FLAGS[@]}"
156+
157+
echo "Cleaning up"
158+
159+
for platform in "${PLATFORMS[@]}"; do
160+
rm -rf "$platform"
161+
done
162+
163+
rm -rf "$HEADERS_PATH"
164+
165+
echo "Build succeeded!"

build/print_exported_headers.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,17 @@
1212

1313
import argparse
1414
import json
15+
import os
1516
import subprocess
1617
from typing import List, Set
1718

19+
# Run buck2 from the same directory (and thus repo) as this script.
20+
BUCK_CWD: str = os.path.dirname(os.path.realpath(__file__))
21+
1822

1923
def run(command: List[str]) -> str:
2024
"""Run subprocess and return its output."""
21-
result = subprocess.run(command, capture_output=True, check=True)
25+
result = subprocess.run(command, capture_output=True, check=True, cwd=BUCK_CWD)
2226
return result.stdout.decode()
2327

2428

0 commit comments

Comments
 (0)