xref: /aosp_15_r20/external/executorch/build/build_apple_frameworks.sh (revision 523fa7a60841cd1ecfb9cc4201f1ca8b03ed023a)
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
8set -euo pipefail
9
10SOURCE_ROOT_DIR=""
11OUTPUT="cmake-out"
12MODE="Release"
13TOOLCHAIN=""
14PYTHON=$(which python3)
15FLATC=$(which flatc)
16COREML=OFF
17CUSTOM=OFF
18MPS=OFF
19OPTIMIZED=OFF
20PORTABLE=OFF
21QUANTIZED=OFF
22XNNPACK=OFF
23HEADERS_PATH="include"
24
25PLATFORMS=("ios" "simulator" "macos")
26PLATFORM_FLAGS=("OS64" "SIMULATORARM64" "MAC_ARM64")
27PLATFORM_TARGET=("17.0" "17.0" "10.15")
28
29FRAMEWORK_EXECUTORCH="executorch:\
30libexecutorch.a,\
31libexecutorch_core.a,\
32libextension_apple.a,\
33libextension_data_loader.a,\
34libextension_module.a,\
35libextension_tensor.a,\
36:$HEADERS_PATH"
37
38FRAMEWORK_BACKEND_COREML="backend_coreml:\
39libcoremldelegate.a,\
40:"
41
42FRAMEWORK_BACKEND_MPS="backend_mps:\
43libmpsdelegate.a,\
44:"
45
46FRAMEWORK_BACKEND_XNNPACK="backend_xnnpack:\
47libXNNPACK.a,\
48libcpuinfo.a,\
49libpthreadpool.a,\
50libxnnpack_backend.a,\
51libmicrokernels-prod.a,\
52:"
53
54FRAMEWORK_KERNELS_CUSTOM="kernels_custom:\
55libcustom_ops.a,\
56:"
57
58FRAMEWORK_KERNELS_OPTIMIZED="kernels_optimized:\
59liboptimized_kernels.a,\
60liboptimized_native_cpu_ops_lib.a,\
61:"
62
63FRAMEWORK_KERNELS_PORTABLE="kernels_portable:\
64libportable_kernels.a,\
65libportable_ops_lib.a,\
66:"
67
68FRAMEWORK_KERNELS_QUANTIZED="kernels_quantized:\
69libquantized_kernels.a,\
70libquantized_ops_lib.a,\
71:"
72
73usage() {
74  echo "Usage: $0 [SOURCE_ROOT_DIR] [OPTIONS]"
75  echo "Build frameworks for Apple platforms."
76  echo "SOURCE_ROOT_DIR defaults to the current directory if not provided."
77  echo
78  echo "Options:"
79  echo "  --output=DIR         Output directory. Default: 'cmake-out'"
80  echo "  --Debug              Use Debug build mode. Default: Uses Release build mode."
81  echo "  --toolchain=FILE     Cmake toolchain file. Default: '\$SOURCE_ROOT_DIR/third-party/ios-cmake/ios.toolchain.cmake'"
82  echo "  --python=FILE        Python executable path. Default: Path of python3 found in the current \$PATH"
83  echo "  --flatc=FILE         FlatBuffers Compiler executable path. Default: Path of flatc found in the current \$PATH"
84  echo "  --coreml             Include this flag to build the Core ML backend."
85  echo "  --custom             Include this flag to build the Custom kernels."
86  echo "  --mps                Include this flag to build the Metal Performance Shaders backend."
87  echo "  --optimized          Include this flag to build the Optimized kernels."
88  echo "  --portable           Include this flag to build the Portable kernels."
89  echo "  --quantized          Include this flag to build the Quantized kernels."
90  echo "  --xnnpack            Include this flag to build the XNNPACK backend."
91  echo
92  echo "Example:"
93  echo "  $0 /path/to/source/root --output=cmake-out --toolchain=/path/to/cmake/toolchain --python=/path/to/python3 --coreml --mps --xnnpack"
94  exit 0
95}
96
97for arg in "$@"; do
98  case $arg in
99      -h|--help) usage ;;
100      --output=*) OUTPUT="${arg#*=}" ;;
101      --Debug) MODE="Debug" ;;
102      --toolchain=*) TOOLCHAIN="${arg#*=}" ;;
103      --python=*) PYTHON="${arg#*=}" ;;
104      --flatc=*) FLATC="${arg#*=}" ;;
105      --coreml) COREML=ON ;;
106      --custom) CUSTOM=ON ;;
107      --mps) MPS=ON ;;
108      --optimized) OPTIMIZED=ON ;;
109      --portable) PORTABLE=ON ;;
110      --quantized) QUANTIZED=ON ;;
111      --xnnpack) XNNPACK=ON ;;
112      *)
113      if [[ -z "$SOURCE_ROOT_DIR" ]]; then
114          SOURCE_ROOT_DIR="$arg"
115      else
116          echo "Invalid argument: $arg"
117          exit 1
118      fi
119      ;;
120  esac
121done
122
123if [[ -z "$SOURCE_ROOT_DIR" ]]; then
124    SOURCE_ROOT_DIR=$(pwd)
125fi
126
127if [[ -z "$TOOLCHAIN" ]]; then
128    TOOLCHAIN="$SOURCE_ROOT_DIR/third-party/ios-cmake/ios.toolchain.cmake"
129fi
130[[ -f "$TOOLCHAIN" ]] || { echo >&2 "Toolchain file $TOOLCHAIN does not exist."; exit 1; }
131
132check_command() {
133  command -v "$1" >/dev/null 2>&1 || { echo >&2 "$1 is not installed"; exit 1; }
134}
135
136check_command cmake
137check_command rsync
138check_command "$PYTHON"
139check_command "$FLATC"
140
141echo "Building libraries"
142
143rm -rf "$OUTPUT" && mkdir -p "$OUTPUT" && cd "$OUTPUT" || exit 1
144
145cmake_build() {
146    local platform=$1
147    local platform_flag=$2
148    local platform_target=$3
149    echo "Building for $platform with flag $platform_flag"
150    mkdir "$platform" && cd "$platform" || exit 1
151    cmake "$SOURCE_ROOT_DIR" -G Xcode \
152        -DCMAKE_BUILD_TYPE="$MODE" \
153        -DCMAKE_PREFIX_PATH="$($PYTHON -c 'import torch as _; print(_.__path__[0])')" \
154        -DCMAKE_TOOLCHAIN_FILE="$TOOLCHAIN" \
155        -DCMAKE_XCODE_ATTRIBUTE_CLANG_CXX_LANGUAGE_STANDARD="c++17" \
156        -DCMAKE_XCODE_ATTRIBUTE_CLANG_CXX_LIBRARY="libc++" \
157        -DCMAKE_C_FLAGS="-ffile-prefix-map=$SOURCE_ROOT_DIR=/executorch -fdebug-prefix-map=$SOURCE_ROOT_DIR=/executorch" \
158        -DCMAKE_CXX_FLAGS="-ffile-prefix-map=$SOURCE_ROOT_DIR=/executorch -fdebug-prefix-map=$SOURCE_ROOT_DIR=/executorch" \
159        -DPYTHON_EXECUTABLE="$PYTHON" \
160        -DFLATC_EXECUTABLE="$FLATC" \
161        -DEXECUTORCH_BUILD_COREML=$COREML \
162        -DEXECUTORCH_BUILD_MPS=$MPS \
163        -DEXECUTORCH_BUILD_XNNPACK=$XNNPACK \
164        -DEXECUTORCH_XNNPACK_SHARED_WORKSPACE=ON \
165        -DEXECUTORCH_BUILD_EXTENSION_APPLE=ON \
166        -DEXECUTORCH_BUILD_EXTENSION_DATA_LOADER=ON \
167        -DEXECUTORCH_BUILD_EXTENSION_MODULE=ON \
168        -DEXECUTORCH_BUILD_EXTENSION_TENSOR=ON \
169        -DEXECUTORCH_BUILD_KERNELS_CUSTOM=$CUSTOM \
170        -DEXECUTORCH_BUILD_KERNELS_OPTIMIZED=$OPTIMIZED \
171        -DEXECUTORCH_BUILD_KERNELS_QUANTIZED=$QUANTIZED \
172        -DCMAKE_ARCHIVE_OUTPUT_DIRECTORY="$(pwd)" \
173        ${platform_flag:+-DPLATFORM=$platform_flag} \
174        ${platform_target:+-DDEPLOYMENT_TARGET=$platform_target} \
175        --log-level=VERBOSE
176    cmake --build . \
177        --config $MODE \
178        --verbose
179    cd ..
180}
181
182for index in ${!PLATFORMS[*]}; do
183  cmake_build "${PLATFORMS[$index]}" "${PLATFORM_FLAGS[$index]}" "${PLATFORM_TARGET[$index]}"
184done
185
186echo "Exporting headers"
187
188mkdir -p "$HEADERS_PATH"
189
190# Set BUCK2 to the path of the buck2 executable in $OUTPUT/*/buck2-bin/buck2-*
191BUCK2=$(find . -type f -path '*/buck2-bin/buck2-*' | head -n 1)
192if [[ -z "$BUCK2" ]]; then
193  echo "Could not find buck2 executable in any buck2-bin directory under $OUTPUT"
194  BUCK2=$(which buck2)
195fi
196
197check_command "$BUCK2"
198
199"$SOURCE_ROOT_DIR"/build/print_exported_headers.py --buck2=$(realpath "$BUCK2") --targets \
200  //extension/module: \
201  //extension/tensor: \
202| rsync -av --files-from=- "$SOURCE_ROOT_DIR" "$HEADERS_PATH/executorch"
203
204cp "$SOURCE_ROOT_DIR/extension/apple/ExecuTorch/Exported/"*.h "$HEADERS_PATH/executorch"
205cp "$SOURCE_ROOT_DIR/extension/apple/ExecuTorch/Exported/"*.modulemap "$HEADERS_PATH"
206
207echo "Creating frameworks"
208
209for platform in "${PLATFORMS[@]}"; do
210  echo "Directory: $platform/$MODE"
211  FRAMEWORK_FLAGS+=("--directory=$platform/$MODE")
212done
213
214append_framework_flag() {
215  local flag="$1"
216  local framework="$2"
217  if [[ $flag == ON ]]; then
218    echo "Framework: $framework"
219    FRAMEWORK_FLAGS+=("--framework=$framework")
220  fi
221}
222
223append_framework_flag "ON" "$FRAMEWORK_EXECUTORCH"
224append_framework_flag "$COREML" "$FRAMEWORK_BACKEND_COREML"
225append_framework_flag "$MPS" "$FRAMEWORK_BACKEND_MPS"
226append_framework_flag "$XNNPACK" "$FRAMEWORK_BACKEND_XNNPACK"
227append_framework_flag "$CUSTOM" "$FRAMEWORK_KERNELS_CUSTOM"
228append_framework_flag "$OPTIMIZED" "$FRAMEWORK_KERNELS_OPTIMIZED"
229append_framework_flag "$PORTABLE" "$FRAMEWORK_KERNELS_PORTABLE"
230append_framework_flag "$QUANTIZED" "$FRAMEWORK_KERNELS_QUANTIZED"
231
232"$SOURCE_ROOT_DIR"/build/create_frameworks.sh "${FRAMEWORK_FLAGS[@]}"
233
234echo "Cleaning up"
235
236for platform in "${PLATFORMS[@]}"; do
237  rm -rf "$platform"
238done
239
240rm -rf "$HEADERS_PATH"
241
242echo "Build succeeded!"
243