-
Notifications
You must be signed in to change notification settings - Fork 870
Expand file tree
/
Copy pathcreate_frameworks.sh
More file actions
executable file
·178 lines (154 loc) · 6.54 KB
/
create_frameworks.sh
File metadata and controls
executable file
·178 lines (154 loc) · 6.54 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
#!/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 -eu
function usage() {
echo "This script creates XCFrameworks from libraries in specified directories."
echo "It merges libraries using libtool and creates an XCFramework using xcodebuild."
echo ""
echo "Usage: $0 --directory=<dir> --framework=<lib> [--output=<output>]"
echo " --directory: Directory containing the libs"
echo " --framework: Framework to create in the format 'target:lib1,lib2:headers:swiftmodule'"
echo " 'target' is the name of the target library."
echo " 'lib1,lib2' is a comma-separated list of input libraries."
echo " 'headers' is an optional path to a directory with headers."
echo " ':swiftmodule' is an optional module name to embed its .swiftmodule folder"
echo " --output: Optional output directory. Defaults to the current directory."
echo ""
echo "Example:"
echo "$0 --directory=ios-arm64 --directory=ios-arm64-simulator --framework=\"mylib:lib1.a,lib2.a:include:MyModule\" --output=output/dir"
exit 1
}
command -v libtool >/dev/null 2>&1 || { echo >&2 "libtool is required but it's not installed. Aborting."; exit 1; }
command -v xcodebuild >/dev/null 2>&1 || { echo >&2 "xcodebuild is required but it's not installed. Aborting."; exit 1; }
directories=()
frameworks=()
output=$(pwd)
for arg in "$@"; do
case $arg in
-h|--help) usage ;;
--directory=*) directories+=("${arg#*=}") ;;
--framework=*) frameworks+=("${arg#*=}") ;;
--output=*) output="${arg#*=}" ;;
*)
echo "Invalid argument: $arg"
exit 1
;;
esac
done
if [ ${#directories[@]} -eq 0 ] || [ ${#frameworks[@]} -eq 0 ]; then
echo "Both --directory and --framework options are required"
usage
fi
mkdir -p "${output}"
create_xcframework() {
local target_library_name
target_library_name=$(echo "$1" | cut -d: -f1)
local libraries_list
libraries_list=$(echo "$1" | cut -d: -f2 | tr ',' '\n')
local headers_directory
headers_directory=$(echo "$1" | cut -d: -f3)
local swift_module
swift_module=$(echo "$1" | cut -d: -f4)
local dir
local libraries=()
local merged_libs=()
if [[ -n "$headers_directory" && ! -d "$headers_directory" ]]; then
echo "Headers directory ${headers_directory} does not exist"
exit 1
fi
# For each directory, create a merged library using libtool.
for dir in "${directories[@]}"; do
if [ ! -d "${dir}" ]; then
echo "Directory ${dir} does not exist"
exit 1
fi
local dir_suffix
dir_suffix=$(echo "$dir" | cut -d'/' -f1 | tr '[:upper:]' '[:lower:]' | sed 's/[\/\.~]/_/g')
local merged_lib="${output}/lib${target_library_name}_${dir_suffix}.a"
# Remove the existing .a file if it exists.
if [ -f "${merged_lib}" ]; then
echo "Removing existing file ${merged_lib}"
rm "${merged_lib}"
fi
echo -e "\nMerging libraries:\n${libraries_list}\nfrom ${dir}\ninto library ${merged_lib}"
local lib_paths=()
for lib in ${libraries_list}; do
if [ ! -f "${dir}/${lib}" ]; then
echo "File ${dir}/${lib} does not exist"
exit 1
fi
lib_paths+=("${dir}/${lib}")
done
libtool -static -o "${merged_lib}" "${lib_paths[@]}"
merged_libs+=("${merged_lib}")
if [[ -n "$headers_directory" ]]; then
echo -e "\nIncluding headers from ${headers_directory}"
libraries+=("-library" "${merged_lib}" "-headers" "${headers_directory}")
else
libraries+=("-library" "${merged_lib}")
fi
done
# Remove the existing .xcframework if it exists.
local xcframework="${output}/${target_library_name}.xcframework"
if [ -d "${xcframework}" ]; then
echo -e "\nRemoving existing XCFramework ${xcframework}"
rm -rf "${xcframework}"
fi
echo -e "\nCreating XCFramework ${xcframework}"
# Create the new .xcframework.
xcodebuild -create-xcframework "${libraries[@]}" -output "${xcframework}"
# Copy the .swiftinterface files into the .xcframework if applicable.
if [[ -n "$swift_module" ]]; then
echo -e "\nCopying Swift interface ${swift_module}.swiftinterface into ${xcframework}"
for dir in "${directories[@]}"; do
local module_source_dir="${dir}/${swift_module}.swiftmodule"
if [ ! -d "$module_source_dir" ]; then
echo "Swiftmodule directory ${module_source_dir} does not exist"
exit 1
fi
local swiftinterface_file
swiftinterface_file=$(find "$module_source_dir" -maxdepth 1 \
-type f -name '*.swiftinterface' ! -name '*.private.swiftinterface' | head -n1)
if [[ -z "$swiftinterface_file" ]]; then
echo "No public .swiftinterface file found in ${module_source_dir}"
exit 1
fi
local base=$(basename "$swiftinterface_file" .swiftinterface)
local arch="${base%%-*}"
local rest="${base#*-apple-}"
local platform_tag
local variant
if [[ "$rest" == *-simulator ]]; then
platform_tag="${rest%-simulator}"
variant="-simulator"
else
platform_tag="$rest"
variant=""
fi
local slice_name="${platform_tag}-${arch}${variant}"
local slice_path="${xcframework}/${slice_name}"
if [ ! -d "$slice_path" ]; then
echo "Warning: slice '${slice_name}' not found in ${xcframework}, skipping"
continue
fi
echo " - Copying ${swift_module}.swiftinterface into slice ${slice_name}"
cp "$swiftinterface_file" "${slice_path}/${swift_module}.swiftinterface"
ln -sf "../${swift_module}.swiftinterface" "${slice_path}/Headers/${swift_module}.swiftinterface"
done
fi
echo -e "\nDeleting intermediate libraries:"
for merged_lib in "${merged_libs[@]}"; do
if [[ -f "${merged_lib}" ]]; then
echo "Deleting ${merged_lib}"
rm "${merged_lib}"
fi
done
}
# Create an XCFramework for each target library.
for target_lib in "${frameworks[@]}"; do
create_xcframework "$target_lib"
done