forked from zed-industries/zed
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathbundle-mac
More file actions
executable file
·340 lines (280 loc) · 12.8 KB
/
bundle-mac
File metadata and controls
executable file
·340 lines (280 loc) · 12.8 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
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
#!/usr/bin/env bash
set -euo pipefail
source script/lib/blob-store.sh
build_flag="--release"
target_dir="release"
open_result=false
local_install=false
can_code_sign=false
# This must match the team in the provisioning profile.
IDENTITY="Zed Industries, Inc."
APPLE_NOTARIZATION_TEAM="MQ55VZLNZQ"
# Function for displaying help info
help_info() {
echo "
Usage: ${0##*/} [options] [architecture=host]
Build the application bundle for macOS.
Options:
-d Compile in debug mode
-o Open dir with the resulting DMG or launch the app itself in local mode.
-i Install the resulting DMG into /Applications.
-h Display this help and exit.
"
}
while getopts 'dloih' flag
do
case "${flag}" in
o) open_result=true;;
d)
export CARGO_INCREMENTAL=true
export CARGO_BUNDLE_SKIP_BUILD=true
build_flag="";
target_dir="debug"
;;
i) local_install=true;;
h)
help_info
exit 0
;;
esac
done
shift $((OPTIND-1))
# Get release channel
pushd crates/zed
channel=$(<RELEASE_CHANNEL)
export ZED_RELEASE_CHANNEL="${channel}"
popd
export ZED_BUNDLE=true
cargo_bundle_version=$(cargo -q bundle --help 2>&1 | head -n 1 || echo "")
if [ "$cargo_bundle_version" != "cargo-bundle v0.6.1-zed" ]; then
cargo install cargo-bundle --git https://github.com/zed-industries/cargo-bundle.git --branch zed-deploy
fi
# Deal with versions of macOS that don't include libstdc++ headers
export CXXFLAGS="-stdlib=libc++"
version_info=$(rustc --version --verbose)
host_line=$(echo "$version_info" | grep host)
target_triple=${host_line#*: }
if [[ $# -gt 0 && -n "$1" ]]; then
target_triple="$1"
fi
arch_suffix=""
if [[ "$target_triple" = "x86_64-apple-darwin" ]]; then
arch_suffix="x86_64"
elif [[ "$target_triple" = "aarch64-apple-darwin" ]]; then
arch_suffix="aarch64"
else
echo "Unsupported architecture $target_triple"
exit 1
fi
# Generate the licenses first, so they can be baked into the binaries
script/generate-licenses
rustup target add $target_triple
echo "Compiling zed binaries"
cargo build ${build_flag} --package zed --package cli --target $target_triple
# Build remote_server in separate invocation to prevent feature unification from other crates
# from influencing dynamic libraries required by it.
cargo build ${build_flag} --package remote_server --target $target_triple
echo "Creating application bundle"
pushd crates/zed
cp Cargo.toml Cargo.toml.backup
sed \
-i.backup \
"s/package.metadata.bundle-${channel}/package.metadata.bundle/" \
Cargo.toml
app_path=$(cargo bundle ${build_flag} --target $target_triple --select-workspace-root | xargs)
mv Cargo.toml.backup Cargo.toml
popd
echo "Bundled ${app_path}"
# DocumentTypes.plist references CFBundleTypeIconFile "Document", so the bundle must contain Document.icns.
# We use the app icon as a placeholder document icon for now.
document_icon_source="crates/zed/resources/Document.icns"
document_icon_target="${app_path}/Contents/Resources/Document.icns"
if [[ -f "${document_icon_source}" ]]; then
mkdir -p "$(dirname "${document_icon_target}")"
cp "${document_icon_source}" "${document_icon_target}"
else
echo "cargo::warning=Missing ${document_icon_source}; macOS document icons may not appear in Finder."
fi
if [[ -n "${MACOS_CERTIFICATE:-}" && -n "${MACOS_CERTIFICATE_PASSWORD:-}" && -n "${APPLE_NOTARIZATION_KEY:-}" && -n "${APPLE_NOTARIZATION_KEY_ID:-}" && -n "${APPLE_NOTARIZATION_ISSUER_ID:-}" ]]; then
can_code_sign=true
echo "Setting up keychain for code signing..."
security create-keychain -p "$MACOS_CERTIFICATE_PASSWORD" zed.keychain || echo ""
security default-keychain -s zed.keychain
security unlock-keychain -p "$MACOS_CERTIFICATE_PASSWORD" zed.keychain
# Calling set-keychain-settings without `-t` disables the auto-lock timeout
security set-keychain-settings zed.keychain
echo "$MACOS_CERTIFICATE" | base64 --decode > /tmp/zed-certificate.p12
security import /tmp/zed-certificate.p12 -k zed.keychain -P "$MACOS_CERTIFICATE_PASSWORD" -T /usr/bin/codesign
rm /tmp/zed-certificate.p12
security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k "$MACOS_CERTIFICATE_PASSWORD" zed.keychain
function cleanup() {
echo "Cleaning up keychain"
security default-keychain -s login.keychain
security delete-keychain zed.keychain
}
trap cleanup EXIT
fi
GIT_VERSION="v2.43.3"
GIT_VERSION_SHA="fa29823"
function download_and_unpack() {
local url=$1
local path_to_unpack=$2
local target_path=$3
temp_dir=$(mktemp -d)
if ! command -v curl &> /dev/null; then
echo "curl is not installed. Please install curl to continue."
exit 1
fi
curl --silent --fail --location "$url" | tar -xvz -C "$temp_dir" -f - $path_to_unpack
mv "$temp_dir/$path_to_unpack" "$target_path"
rm -rf "$temp_dir"
}
function download_git() {
local architecture=$1
local target_binary=$2
tmp_dir=$(mktemp -d)
pushd "$tmp_dir"
case "$architecture" in
aarch64-apple-darwin)
download_and_unpack "https://github.com/desktop/dugite-native/releases/download/${GIT_VERSION}/dugite-native-${GIT_VERSION}-${GIT_VERSION_SHA}-macOS-arm64.tar.gz" bin/git ./git
;;
x86_64-apple-darwin)
download_and_unpack "https://github.com/desktop/dugite-native/releases/download/${GIT_VERSION}/dugite-native-${GIT_VERSION}-${GIT_VERSION_SHA}-macOS-x64.tar.gz" bin/git ./git
;;
*)
echo "Unsupported architecture: $architecture"
exit 1
;;
esac
popd
mv "${tmp_dir}/git" "${target_binary}"
rm -rf "$tmp_dir"
}
function sign_app_binaries() {
rm -rf "${app_path}/Contents/Frameworks"
mkdir -p "${app_path}/Contents/Frameworks"
echo "Downloading git binary"
download_git "${target_triple}" "${app_path}/Contents/MacOS/git"
# Note: The app identifier for our development builds is the same as the app identifier for nightly.
cp crates/zed/contents/$channel/embedded.provisionprofile "${app_path}/Contents/"
if [[ $can_code_sign = true ]]; then
echo "Code signing binaries"
# sequence of codesign commands modeled after this example: https://developer.apple.com/forums/thread/701514
/usr/bin/codesign --deep --force --timestamp --options runtime --sign "$IDENTITY" "${app_path}/Contents/MacOS/cli" -v
/usr/bin/codesign --deep --force --timestamp --options runtime --sign "$IDENTITY" "${app_path}/Contents/MacOS/git" -v
/usr/bin/codesign --deep --force --timestamp --options runtime --entitlements crates/zed/resources/zed.entitlements --sign "$IDENTITY" "${app_path}/Contents/MacOS/zed" -v
/usr/bin/codesign --force --timestamp --options runtime --entitlements crates/zed/resources/zed.entitlements --sign "$IDENTITY" "${app_path}" -v
else
echo "One or more of the following variables are missing: MACOS_CERTIFICATE, MACOS_CERTIFICATE_PASSWORD, APPLE_NOTARIZATION_KEY, APPLE_NOTARIZATION_KEY_ID, APPLE_NOTARIZATION_ISSUER_ID"
echo "====== WARNING ======"
echo "This bundle is being signed without all entitlements, some features (e.g. universal links) will not work"
echo "====== WARNING ======"
# NOTE: if you need to test universal links you have a few paths forward:
# - create a PR and tag it with the `run-bundling` label, and download the .dmg file from there.
# - get a signing key for the MQ55VZLNZQ team from Nathan.
# - create your own signing key, and update references to MQ55VZLNZQ to your own team ID
# then comment out this line.
cat crates/zed/resources/zed.entitlements | sed '/com.apple.developer.associated-domains/,+1d' > "${app_path}/Contents/Resources/zed.entitlements"
codesign --force --deep --entitlements "${app_path}/Contents/Resources/zed.entitlements" --sign ${MACOS_SIGNING_KEY:- -} "${app_path}" -v
fi
bundle_name=$(basename "$app_path")
if [ "$local_install" = true ]; then
rm -rf "/Applications/$bundle_name"
mv "$app_path" "/Applications/$bundle_name"
echo "Installed application bundle: /Applications/$bundle_name"
if [ "$open_result" = true ]; then
echo "Opening /Applications/$bundle_name"
open "/Applications/$bundle_name"
fi
elif [ "$open_result" = true ]; then
open "$app_path"
fi
if [[ "$target_dir" = "debug" ]]; then
echo "Debug build detected - skipping DMG creation and signing"
if [ "$local_install" = false ]; then
echo "Created application bundle:"
echo "$app_path"
fi
else
dmg_target_directory="target/${target_triple}/${target_dir}"
dmg_source_directory="${dmg_target_directory}/dmg"
dmg_file_path="${dmg_target_directory}/Zed-${arch_suffix}.dmg"
xcode_bin_dir_path="$(xcode-select -p)/usr/bin"
rm -rf ${dmg_source_directory}
mkdir -p ${dmg_source_directory}
mv "${app_path}" "${dmg_source_directory}"
notarization_key_file=$(mktemp)
echo "Adding symlink to /Applications to ${dmg_source_directory}"
ln -s /Applications ${dmg_source_directory}
echo "Creating final DMG at ${dmg_file_path} using ${dmg_source_directory}"
hdiutil create -volname Zed -srcfolder "${dmg_source_directory}" -ov -format UDZO "${dmg_file_path}"
# If someone runs this bundle script locally, a symlink will be placed in `dmg_source_directory`.
# This symlink causes CPU issues with Zed if the Zed codebase is the project being worked on, so we simply remove it for now.
echo "Removing symlink to /Applications from ${dmg_source_directory}"
rm ${dmg_source_directory}/Applications
echo "Adding license agreement to DMG"
npm install --global dmg-license minimist
dmg-license script/terms/terms.json "${dmg_file_path}"
if [[ $can_code_sign = true ]]; then
echo "Notarizing DMG with Apple"
/usr/bin/codesign --deep --force --timestamp --options runtime --sign "$IDENTITY" "$(pwd)/${dmg_file_path}" -v
echo "$APPLE_NOTARIZATION_KEY" > "$notarization_key_file"
"${xcode_bin_dir_path}/notarytool" submit --wait --key "$notarization_key_file" --key-id "$APPLE_NOTARIZATION_KEY_ID" --issuer "$APPLE_NOTARIZATION_ISSUER_ID" "${dmg_file_path}"
rm "$notarization_key_file"
"${xcode_bin_dir_path}/stapler" staple "${dmg_file_path}"
fi
if [ "$open_result" = true ]; then
open $dmg_target_directory
fi
fi
}
function sign_binary() {
local binary_path=$1
if [[ $can_code_sign = true ]]; then
echo "Code signing executable $binary_path"
/usr/bin/codesign --deep --force --timestamp --options runtime --entitlements crates/zed/resources/zed.entitlements --sign "$IDENTITY" "${binary_path}" -v
fi
}
function upload_debug_symbols() {
if [ "$local_install" = true ]; then
echo "local install; skipping sentry upload."
elif [[ -n "${SENTRY_AUTH_TOKEN:-}" ]]; then
echo "Uploading zed debug symbols to sentry..."
exe_path="target/${target_triple}/release/Zed"
if ! dsymutil --flat "target/${target_triple}/${target_dir}/zed" 2> target/dsymutil.log; then
echo "dsymutil failed"
cat target/dsymutil.log
exit 1
fi
if ! dsymutil --flat "target/${target_triple}/${target_dir}/remote_server" 2> target/dsymutil.log; then
echo "dsymutil failed"
cat target/dsymutil.log
exit 1
fi
# note: this uploads the unstripped binary which is needed because it contains
# .eh_frame data for stack unwinding. see https://github.com/getsentry/symbolic/issues/783
# Try uploading up to 3 times
for attempt in 1 2 3; do
echo "Sentry upload attempt $attempt..."
if sentry-cli debug-files upload --include-sources --wait -p zed -o zed-dev \
"target/${target_triple}/${target_dir}/zed.dwarf" \
"target/${target_triple}/${target_dir}/remote_server.dwarf"; then
break
else
echo "Sentry upload failed on attempt $attempt"
if [ $attempt -eq 3 ]; then
echo "All sentry upload attempts failed"
exit 1
fi
fi
done
else
echo "missing SENTRY_AUTH_TOKEN. skipping sentry upload."
fi
}
upload_debug_symbols
cp target/${target_triple}/${target_dir}/zed "${app_path}/Contents/MacOS/zed"
cp target/${target_triple}/${target_dir}/cli "${app_path}/Contents/MacOS/cli"
sign_app_binaries
sign_binary "target/$target_triple/release/remote_server"
gzip -f --stdout --best target/$target_triple/release/remote_server > target/zed-remote-server-macos-$arch_suffix.gz