#!/usr/bin/env bash # # Build a macOS .dmg from a .app bundle. # # hack/make-dmg.sh # # On macOS this uses hdiutil. On Linux it uses hfsprogs + hfsplus to create an # HFS+ image and mozilla/libdmg-hfsplus (`dmg build`) to convert it to UDIF; # both are installed in the builder image. # # The Linux image is functional (the app plus an /Applications symlink) but # has no Finder background or icon placement: those live in a .DS_Store # generated by hdiutil, which is macOS-only. set -euo pipefail if [ "$#" -ne 3 ]; then echo "usage: $0 " >&2 exit 2 fi APP="$1" VOLUME="$2" OUT="$3" if [ ! -d "$APP" ]; then echo "$APP is not a directory" >&2 exit 1 fi TMP="$(mktemp -d "${TMPDIR:-/tmp}/streamplace-dmg.XXXXXX")" trap 'rm -rf "$TMP"' EXIT ROOT="$TMP/root" mkdir -p "$ROOT" # -a preserves the nested framework symlinks and executable modes; the code # signature is embedded in the Mach-O files, so nothing else needs carrying. cp -a "$APP" "$ROOT/" ln -s /Applications "$ROOT/Applications" mkdir -p "$(dirname "$OUT")" rm -f "$OUT" if command -v hdiutil >/dev/null; then hdiutil create \ -volname "$VOLUME" \ -srcfolder "$ROOT" \ -ov \ -format UDZO \ "$OUT" >/dev/null exit 0 fi for tool in mkfs.hfsplus hfsplus dmg; do if ! command -v "$tool" >/dev/null; then echo "$tool not found; the builder image is stale (recreate the container" >&2 echo "after .ci/dockerfile-hash.yaml changes) or this is not the container." >&2 exit 1 fi done USED_KB="$(du -sk "$ROOT" | cut -f1)" SIZE_MB=$(( USED_KB / 1024 + 64 )) dd if=/dev/zero of="$TMP/image.img" bs=1M count="$SIZE_MB" status=none mkfs.hfsplus -v "$VOLUME" "$TMP/image.img" >/dev/null hfsplus "$TMP/image.img" addall "$ROOT" -s clone_link >/dev/null dmg build "$TMP/image.img" "$OUT" >/dev/null