#!/usr/bin/env bash set -euo pipefail source script/lib/blob-store.sh export ZED_BUNDLE=true export MACOSX_DEPLOYMENT_TARGET=10.15.7 # Deal with versions of macOS that don't include libstdc++ headers export CXXFLAGS="-stdlib=libc++" # Version of Git to Bundle with Zed from github.com/desktop/dugite-native GIT_VERSION="v2.43.3" GIT_VERSION_SHA="fa29823" build_flag="--release" target_dir="release" local_only=false bundle_name="" function help_info() { echo "Usage: ${0##*/} [options] [bundle_name]" echo "Build the application bundle for macOS." echo "Options:" echo " -d Compile in debug mode" echo " -l Compile for local architecture only." echo " -h Display this help and exit." } function handle_args { while getopts 'dlh' flag do case "${flag}" in d) export CARGO_INCREMENTAL=true export CARGO_BUNDLE_SKIP_BUILD=true build_flag=""; target_dir="debug" ;; l) export CARGO_INCREMENTAL=true export CARGO_BUNDLE_SKIP_BUILD=true local_only=true ;; h) help_info exit 0 ;; *) echo "Error: Invalid option -${OPTARG}" >&2 help_info exit 1 ;; esac done shift $((OPTIND-1)) if [[ $# -gt 0 ]]; then if [ "$1" ]; then bundle_name=$1 fi fi # Check if GNU Parallel is installed if ! command -v parallel &> /dev/null; then echo "GNU Parallel is not installed. Please install it to continue." exit 1 fi } function setup_cargo_bundle() { cargo_bundle_version=$(cargo -q bundle --help 2>&1 | head -n 1 || echo "") if [ "$cargo_bundle_version" != "cargo-bundle v0.6.0-zed" ]; then cargo install cargo-bundle --git https://github.com/zed-industries/cargo-bundle.git --branch zed-deploy fi } function build() { if [ "$local_only" = true ]; then echo "Building for local target only." cargo build ${build_flag} --package zed --package cli --package remote_server else echo "Compiling zed binaries" cargo build ${build_flag} --package zed --package cli --target aarch64-apple-darwin --target x86_64-apple-darwin # 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 aarch64-apple-darwin --target x86_64-apple-darwin fi echo "Creating application bundle" pushd crates/zed channel=$( /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" } # Download 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 ;; universal) 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_arm64 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_x64 lipo -create ./git_arm64 ./git_x64 -output ./git ;; *) echo "Unsupported architecture: $architecture" exit 1 ;; esac popd mv "${tmp_dir}/git" "${target_binary}" rm -rf "$tmp_dir" } # Prepare binaries for a specific architecture function prepare_binaries() { local architecture=$1 local app_path=$2 echo "Unpacking dSYMs for $architecture" if ! dsymutil --flat "target/${architecture}/${target_dir}/Zed" 2> target/dsymutil.log; then echo "dsymutil failed" cat target/dsymutil.log exit 1 fi version="$(cargo metadata --no-deps --manifest-path crates/zed/Cargo.toml --offline --format-version=1 | jq -r '.packages | map(select(.name == "zed"))[0].version')" if [ "$channel" == "nightly" ]; then version="$version-$(git rev-parse --short HEAD)" fi echo "Removing existing gzipped dSYMs for $architecture" rm -f "target/${architecture}/${target_dir}/Zed.dwarf.gz" echo "Gzipping dSYMs for $architecture" gzip "target/${architecture}/${target_dir}/Zed.dwarf" echo "Uploading dSYMs for $architecture" upload_to_blob_store_public \ "zed-debug-symbols" \ "target/${architecture}/${target_dir}/Zed.dwarf.gz" \ "$channel/Zed-$version-${architecture}.dwarf.gz" cp "target/${architecture}/${target_dir}/zed" "${app_path}/Contents/MacOS/zed" cp "target/${architecture}/${target_dir}/cli" "${app_path}/Contents/MacOS/cli" } function process() { if [ "$local_only" = true ]; then version_info=$(rustc --version --verbose) host_line=$(echo "$version_info" | grep host) local_target_triple=${host_line#*: } # script/notarize-mac sign_app_binaries ./script/sign-mac sign_app_binaries "$bundle_name" "$target_dir" "$channel" "$app_path" "$local_target_triple" "$local_target_triple" ./script/sign-mac sign_binary "target/release/remote_server" else # Create universal binary prepare_binaries "aarch64-apple-darwin" "$app_path_aarch64" prepare_binaries "x86_64-apple-darwin" "$app_path_x64" cp -R "$app_path_x64" target/release/ app_path=target/release/$(basename "$app_path_x64") lipo \ -create \ target/{x86_64-apple-darwin,aarch64-apple-darwin}/${target_dir}/zed \ -output \ "${app_path}/Contents/MacOS/zed" lipo \ -create \ target/{x86_64-apple-darwin,aarch64-apple-darwin}/${target_dir}/cli \ -output \ "${app_path}/Contents/MacOS/cli" # Piping output through these will add a prefix and colorize the line prefix1="sed 's/^/\x1b[35m[Bundle aarch64] \x1b[0m/'" # magenta prefix2="sed 's/^/\x1b[34m[Bundle x86_x64] \x1b[0m/'" # blue prefix3="sed 's/^/\x1b[36m[Bundle Combine] \x1b[0m/'" # cyan prefix4="sed 's/^/\x1b[33m[Remote x86_x64] \x1b[0m/'" # yellow prefix5="sed 's/^/\x1b[32m[Remote x86_x64] \x1b[0m/'" # green # ./script/sign-mac sign_app_binaries " # ./script/sign-mac sign_binary # These each take approximately 4minutes. Use GNU Parallel to submit them simultaneously. # Output is interlaced between all tasks, so add unique prefixes (sed) and line numbers (nl) # to preserve de-interlacing if necessary e.g. Copy output to clipboard and then: pbpaste | sort | pbcopy parallel --progress --line-buffer ::: \ "./script/sign-mac sign_app_binaries \"$bundle_name\" \"$target_dir\" \"$channel\" \"$app_path_aarch64\" aarch64-apple-darwin aarch64-apple-darwin | nl | $prefix1" \ "./script/sign-mac sign_app_binaries \"$bundle_name\" \"$target_dir\" \"$channel\" \"$app_path_x64\" x86_64-apple-darwin x86_64-apple-darwin | nl | $prefix2" \ "./script/sign-mac sign_app_binaries \"$bundle_name\" \"$target_dir\" \"$channel\" \"$app_path\" universal . | nl | $prefix3" \ "./script/sign-mac sign_binary target/x86_64-apple-darwin/release/remote_server | nl | $prefix4" \ "./script/sign-mac sign_binary target/aarch64-apple-darwin/release/remote_server | nl | $prefix5" gzip --stdout --best target/x86_64-apple-darwin/release/remote_server > target/zed-remote-server-macos-x86_64.gz gzip --stdout --best target/aarch64-apple-darwin/release/remote_server > target/zed-remote-server-macos-aarch64.gz fi } handle_args "$@" setup_cargo_bundle build process