blob: 348111e2b4cb25e1ee5a20eac48cc55b62ded3e3 [file] [log] [blame]
#!/bin/bash
# Copyright (c) Meta Platforms, Inc. and affiliates.
# All rights reserved.
#
# This source code is licensed under the BSD-style license found in the
# LICENSE file in the root directory of this source tree.
set -euo pipefail
SOURCE_ROOT_DIR=""
OUTPUT="cmake-out"
MODE="Release"
TOOLCHAIN=""
BUCK2=$(which buck2)
PYTHON=$(which python3)
FLATC=$(which flatc)
COREML=OFF
CUSTOM=OFF
MPS=OFF
OPTIMIZED=OFF
PORTABLE=OFF
QUANTIZED=OFF
XNNPACK=OFF
HEADERS_PATH="include"
PLATFORMS=("ios" "simulator" "macos")
PLATFORM_FLAGS=("OS64" "SIMULATORARM64" "MAC_ARM64")
PLATFORM_TARGET=("17.0" "17.0" "10.15")
FRAMEWORK_EXECUTORCH="executorch:\
libexecutorch.a,\
libexecutorch_no_prim_ops.a,\
libextension_apple.a,\
libextension_data_loader.a,\
libextension_module.a,\
libextension_tensor.a,\
:$HEADERS_PATH"
FRAMEWORK_BACKEND_COREML="backend_coreml:\
libcoremldelegate.a,\
:"
FRAMEWORK_BACKEND_MPS="backend_mps:\
libmpsdelegate.a,\
:"
FRAMEWORK_BACKEND_XNNPACK="backend_xnnpack:\
libXNNPACK.a,\
libcpuinfo.a,\
libpthreadpool.a,\
libxnnpack_backend.a,\
:"
FRAMEWORK_KERNELS_CUSTOM="kernels_custom:\
libcustom_ops.a,\
:"
FRAMEWORK_KERNELS_OPTIMIZED="kernels_optimized:\
liboptimized_kernels.a,\
liboptimized_ops_lib.a,\
:"
FRAMEWORK_KERNELS_PORTABLE="kernels_portable:\
libportable_kernels.a,\
libportable_ops_lib.a,\
:"
FRAMEWORK_KERNELS_QUANTIZED="kernels_quantized:\
libquantized_kernels.a,\
libquantized_ops_lib.a,\
:"
usage() {
echo "Usage: $0 [SOURCE_ROOT_DIR] [OPTIONS]"
echo "Build frameworks for Apple platforms."
echo "SOURCE_ROOT_DIR defaults to the current directory if not provided."
echo
echo "Options:"
echo " --output=DIR Output directory. Default: 'cmake-out'"
echo " --Debug Use Debug build mode. Default: Uses Release build mode."
echo " --toolchain=FILE Cmake toolchain file. Default: '\$SOURCE_ROOT_DIR/third-party/ios-cmake/ios.toolchain.cmake'"
echo " --buck2=FILE Buck2 executable path. Default: Path of buck2 found in the current \$PATH"
echo " --python=FILE Python executable path. Default: Path of python3 found in the current \$PATH"
echo " --flatc=FILE FlatBuffers Compiler executable path. Default: Path of flatc found in the current \$PATH"
echo " --coreml Include this flag to build the Core ML backend."
echo " --custom Include this flag to build the Custom kernels."
echo " --mps Include this flag to build the Metal Performance Shaders backend."
echo " --optimized Include this flag to build the Optimized kernels."
echo " --portable Include this flag to build the Portable kernels."
echo " --quantized Include this flag to build the Quantized kernels."
echo " --xnnpack Include this flag to build the XNNPACK backend."
echo
echo "Example:"
echo " $0 /path/to/source/root --output=cmake-out --toolchain=/path/to/cmake/toolchain --buck2=/path/to/buck2 --python=/path/to/python3 --coreml --mps --xnnpack"
exit 0
}
for arg in "$@"; do
case $arg in
-h|--help) usage ;;
--output=*) OUTPUT="${arg#*=}" ;;
--Debug) MODE="Debug" ;;
--toolchain=*) TOOLCHAIN="${arg#*=}" ;;
--buck2=*) BUCK2="${arg#*=}" ;;
--python=*) PYTHON="${arg#*=}" ;;
--flatc=*) FLATC="${arg#*=}" ;;
--coreml) COREML=ON ;;
--custom) CUSTOM=ON ;;
--mps) MPS=ON ;;
--optimized) OPTIMIZED=ON ;;
--portable) PORTABLE=ON ;;
--quantized) QUANTIZED=ON ;;
--xnnpack) XNNPACK=ON ;;
*)
if [[ -z "$SOURCE_ROOT_DIR" ]]; then
SOURCE_ROOT_DIR="$arg"
else
echo "Invalid argument: $arg"
exit 1
fi
;;
esac
done
if [[ -z "$SOURCE_ROOT_DIR" ]]; then
SOURCE_ROOT_DIR=$(pwd)
fi
if [[ -z "$TOOLCHAIN" ]]; then
TOOLCHAIN="$SOURCE_ROOT_DIR/third-party/ios-cmake/ios.toolchain.cmake"
fi
[[ -f "$TOOLCHAIN" ]] || { echo >&2 "Toolchain file $TOOLCHAIN does not exist."; exit 1; }
check_command() {
command -v "$1" >/dev/null 2>&1 || { echo >&2 "$1 is not installed"; exit 1; }
}
check_command cmake
check_command rsync
check_command "$BUCK2"
check_command "$PYTHON"
check_command "$FLATC"
echo "Building libraries"
rm -rf "$OUTPUT" && mkdir -p "$OUTPUT" && cd "$OUTPUT" || exit 1
cmake_build() {
local platform=$1
local platform_flag=$2
local platform_target=$3
echo "Building for $platform with flag $platform_flag"
mkdir "$platform" && cd "$platform" || exit 1
cmake "$SOURCE_ROOT_DIR" -G Xcode \
-DCMAKE_BUILD_TYPE="$MODE" \
-DCMAKE_PREFIX_PATH="$($PYTHON -c 'import torch as _; print(_.__path__[0])')" \
-DCMAKE_TOOLCHAIN_FILE="$TOOLCHAIN" \
-DCMAKE_XCODE_ATTRIBUTE_CLANG_CXX_LANGUAGE_STANDARD="c++17" \
-DCMAKE_XCODE_ATTRIBUTE_CLANG_CXX_LIBRARY="libc++" \
-DBUCK2="$BUCK2" \
-DPYTHON_EXECUTABLE="$PYTHON" \
-DFLATC_EXECUTABLE="$FLATC" \
-DEXECUTORCH_BUILD_COREML=$COREML \
-DEXECUTORCH_BUILD_MPS=$MPS \
-DEXECUTORCH_BUILD_XNNPACK=$XNNPACK \
-DEXECUTORCH_XNNPACK_SHARED_WORKSPACE=ON \
-DEXECUTORCH_BUILD_EXTENSION_APPLE=ON \
-DEXECUTORCH_BUILD_EXTENSION_DATA_LOADER=ON \
-DEXECUTORCH_BUILD_EXTENSION_MODULE=ON \
-DEXECUTORCH_BUILD_EXTENSION_TENSOR=ON \
-DEXECUTORCH_BUILD_KERNELS_CUSTOM=$CUSTOM \
-DEXECUTORCH_BUILD_KERNELS_OPTIMIZED=$OPTIMIZED \
-DEXECUTORCH_BUILD_KERNELS_QUANTIZED=$QUANTIZED \
-DCMAKE_ARCHIVE_OUTPUT_DIRECTORY="$(pwd)" \
${platform_flag:+-DPLATFORM=$platform_flag} \
${platform_target:+-DDEPLOYMENT_TARGET=$platform_target} \
--log-level=VERBOSE
cmake --build . \
--config $MODE \
--verbose
cd ..
}
for index in ${!PLATFORMS[*]}; do
cmake_build "${PLATFORMS[$index]}" "${PLATFORM_FLAGS[$index]}" "${PLATFORM_TARGET[$index]}"
done
echo "Exporting headers"
mkdir -p "$HEADERS_PATH"
"$SOURCE_ROOT_DIR"/build/print_exported_headers.py --buck2="$BUCK2" --targets \
//extension/module: \
//extension/tensor: \
| rsync -av --files-from=- "$SOURCE_ROOT_DIR" "$HEADERS_PATH/executorch"
cp "$SOURCE_ROOT_DIR/extension/apple/ExecuTorch/Exported/"*.h "$HEADERS_PATH/executorch"
cp "$SOURCE_ROOT_DIR/extension/apple/ExecuTorch/Exported/"*.modulemap "$HEADERS_PATH"
echo "Creating frameworks"
for platform in "${PLATFORMS[@]}"; do
echo "Directory: $platform/$MODE"
FRAMEWORK_FLAGS+=("--directory=$platform/$MODE")
done
append_framework_flag() {
local flag="$1"
local framework="$2"
if [[ $flag == ON ]]; then
echo "Framework: $framework"
FRAMEWORK_FLAGS+=("--framework=$framework")
fi
}
append_framework_flag "ON" "$FRAMEWORK_EXECUTORCH"
append_framework_flag "$COREML" "$FRAMEWORK_BACKEND_COREML"
append_framework_flag "$MPS" "$FRAMEWORK_BACKEND_MPS"
append_framework_flag "$XNNPACK" "$FRAMEWORK_BACKEND_XNNPACK"
append_framework_flag "$CUSTOM" "$FRAMEWORK_KERNELS_CUSTOM"
append_framework_flag "$OPTIMIZED" "$FRAMEWORK_KERNELS_OPTIMIZED"
append_framework_flag "$PORTABLE" "$FRAMEWORK_KERNELS_PORTABLE"
append_framework_flag "$QUANTIZED" "$FRAMEWORK_KERNELS_QUANTIZED"
"$SOURCE_ROOT_DIR"/build/create_frameworks.sh "${FRAMEWORK_FLAGS[@]}"
echo "Cleaning up"
for platform in "${PLATFORMS[@]}"; do
rm -rf "$platform"
done
rm -rf "$HEADERS_PATH"
echo "Build succeeded!"