xref: /aosp_15_r20/external/executorch/build/create_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 -eu
9
10function usage() {
11    echo "This script creates XCFrameworks from libraries in specified directories."
12    echo "It merges libraries using libtool and creates an XCFramework using xcodebuild."
13    echo ""
14    echo "Usage: $0 --directory=<dir> --framework=<lib> [--output=<output>]"
15    echo "  --directory: Directory containing the libs"
16    echo "  --framework: Framework to create in the format 'target:lib1,lib2:headers'"
17    echo "               'target' is the name of the target library."
18    echo "               'lib1,lib2' is a comma-separated list of input libraries."
19    echo "               'headers' is an optional path to a directory with headers."
20    echo "  --output: Optional output directory. Defaults to the current directory."
21    echo ""
22    echo "Example:"
23    echo "$0 --directory=ios-arm64 --directory=ios-arm64-simulator --framework=\"mylib:lib1.a,lib2.a:include\" --output=output/dir"
24    exit 1
25}
26
27command -v libtool >/dev/null 2>&1 || { echo >&2 "libtool is required but it's not installed.  Aborting."; exit 1; }
28command -v xcodebuild >/dev/null 2>&1 || { echo >&2 "xcodebuild is required but it's not installed.  Aborting."; exit 1; }
29
30directories=()
31frameworks=()
32output=$(pwd)
33
34for arg in "$@"; do
35    case $arg in
36        -h|--help) usage ;;
37        --directory=*) directories+=("${arg#*=}") ;;
38        --framework=*) frameworks+=("${arg#*=}") ;;
39        --output=*) output="${arg#*=}" ;;
40        *)
41            echo "Invalid argument: $arg"
42            exit 1
43        ;;
44    esac
45done
46
47if [ ${#directories[@]} -eq 0 ] || [ ${#frameworks[@]} -eq 0 ]; then
48    echo "Both --directory and --framework options are required"
49    usage
50fi
51
52mkdir -p "${output}"
53
54create_xcframework() {
55    local target_library_name
56    target_library_name=$(echo "$1" | cut -d: -f1)
57    local libraries_list
58    libraries_list=$(echo "$1" | cut -d: -f2 | tr ',' '\n')
59    local headers_directory
60    headers_directory=$(echo "$1" | cut -d: -f3)
61    local dir
62    local libraries=()
63    local merged_libs=()
64
65    if [[ -n "$headers_directory" && ! -d "$headers_directory" ]]; then
66        echo "Headers directory ${headers_directory} does not exist"
67        exit 1
68    fi
69
70    # For each directory, create a merged library using libtool.
71    for dir in "${directories[@]}"; do
72
73        if [ ! -d "${dir}" ]; then
74            echo "Directory ${dir} does not exist"
75            exit 1
76        fi
77
78        local dir_suffix
79        dir_suffix=$(echo "$dir" | tr '[:upper:]' '[:lower:]' | sed 's/\//-/g')
80        local merged_lib="${output}/lib${target_library_name}-${dir_suffix}.a"
81
82        # Remove the existing .a file if it exists.
83        if [ -f "${merged_lib}" ]; then
84            echo "Removing existing file ${merged_lib}"
85            rm "${merged_lib}"
86        fi
87
88        echo -e "\nMerging libraries:\n${libraries_list}\nfrom ${dir}\ninto library ${merged_lib}"
89
90        local lib_paths=()
91        for lib in ${libraries_list}; do
92            if [ ! -f "${dir}/${lib}" ]; then
93                echo "File ${dir}/${lib} does not exist"
94                exit 1
95            fi
96            lib_paths+=("${dir}/${lib}")
97        done
98
99        libtool -static -o "${merged_lib}" "${lib_paths[@]}"
100
101        merged_libs+=("${merged_lib}")
102
103        if [[ -n "$headers_directory" ]]; then
104            echo -e "\nIncluding headers from ${headers_directory}"
105            libraries+=("-library" "${merged_lib}" "-headers" "${headers_directory}")
106        else
107            libraries+=("-library" "${merged_lib}")
108        fi
109    done
110
111    # Remove the existing .xcframework if it exists.
112    local xcframework="${output}/${target_library_name}.xcframework"
113    if [ -d "${xcframework}" ]; then
114        echo -e "\nRemoving existing XCFramework ${xcframework}"
115        rm -rf "${xcframework}"
116    fi
117
118    echo -e "\nCreating XCFramework ${xcframework}"
119
120    xcodebuild -create-xcframework "${libraries[@]}" -output "${xcframework}"
121
122    echo -e "\nDeleting intermediate libraries:"
123    for merged_lib in "${merged_libs[@]}"; do
124        if [[ -f "${merged_lib}" ]]; then
125            echo "Deleting ${merged_lib}"
126            rm "${merged_lib}"
127        fi
128    done
129}
130
131# Create an XCFramework for each target library.
132for target_lib in "${frameworks[@]}"; do
133    create_xcframework "$target_lib"
134done
135