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