|
1 | | -#!/usr/bin/env bash -ex |
| 1 | +#!/usr/bin/env bash |
2 | 2 | # scripts/macos-deploy.bash |
3 | 3 |
|
4 | | -set -o pipefail |
| 4 | +set -euxo pipefail |
| 5 | + |
| 6 | +BUILD_DIR=build |
| 7 | +BIN_DIR=bin |
| 8 | +APP="$BIN_DIR/lem.app" |
| 9 | +EXE="$APP/Contents/MacOS/lem" |
| 10 | +LIBDIR="$APP/Contents/MacOS" |
5 | 11 |
|
6 | 12 | script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" |
7 | 13 | parent_dir="$(dirname "$script_dir")" |
8 | 14 | cd "$parent_dir" |
9 | 15 |
|
10 | | -# ===== 1) ビルド ===== |
| 16 | +# ===== 0) クリーンアップ ===== |
| 17 | +# ===== 0) Cleanup ===== |
| 18 | +rm -rf "$BUILD_DIR" |
| 19 | +rm -rf "$BIN_DIR" |
| 20 | +mkdir -p "$BUILD_DIR" |
| 21 | +mkdir -p "$BIN_DIR" |
| 22 | + |
| 23 | +# ===== 1) ビルド用SBCLの準備 ===== |
| 24 | +# ===== 1) Prepare SBCL for building ===== |
| 25 | +# SBCLはlibzstdに依存しており、実行ファイル(lem)はその共有依存関係を継承します。 |
| 26 | +# SBCLのダンプ構造のため、実行ファイルに対してinstall_name_toolは機能しません。 |
| 27 | +# そのため、代わりにSBCL実行ファイルのコピーに対してdylib参照を置換する必要があります。 |
| 28 | +# SBCL depends on libzstd and the app executable (lem) inherits those shared deps |
| 29 | +# `install_name_tool` doesn't work on the app executable because of the SBCL dump structure so |
| 30 | +# we have to replace dylib references on a copy of the sbcl executable instead |
| 31 | +SBCL_BIN=$(realpath "$(which sbcl)") |
| 32 | +SBCL_HOME="$(dirname "$SBCL_BIN")/../lib/sbcl" |
| 33 | +# Homebrew uses a shell script so we have to find the real executable |
| 34 | +if [[ $(file "$SBCL_BIN") == *"shell script"* ]]; then |
| 35 | + SBCL_ROOT="$(dirname "$(dirname "$SBCL_BIN")")" |
| 36 | + SBCL_BIN="$SBCL_ROOT/libexec/bin/sbcl" |
| 37 | + SBCL_HOME="$SBCL_ROOT/lib/sbcl" |
| 38 | +fi |
| 39 | +install -m 0755 "$SBCL_BIN" "$BUILD_DIR/sbcl" |
| 40 | +export SBCL_HOME |
| 41 | + |
| 42 | +LIBZSTD_DIR="$(pkg-config --variable=libdir libzstd)" |
| 43 | +install -m 0755 "$LIBZSTD_DIR/libzstd.1.dylib" "$BUILD_DIR/libzstd.1.dylib" |
| 44 | +install_name_tool -id @loader_path/libzstd.1.dylib "$BUILD_DIR/libzstd.1.dylib" |
| 45 | +install_name_tool -change "$LIBZSTD_DIR/libzstd.1.dylib" @loader_path/libzstd.1.dylib "$BUILD_DIR/sbcl" |
| 46 | + |
| 47 | +codesign --force --sign - "$BUILD_DIR/libzstd.1.dylib" |
| 48 | +codesign --force --sign - --preserve-metadata=entitlements,requirements "$BUILD_DIR/sbcl" |
| 49 | + |
| 50 | +# ===== 2) ビルド ===== |
| 51 | +# ===== 2) Build ===== |
11 | 52 | qlot install |
12 | | -qlot exec sbcl --eval '(ql:quickload :lem)' --eval '(asdf:make :lem)' |
| 53 | +PATH="$PWD/build:$PATH" qlot exec sbcl --eval '(ql:quickload :lem)' --eval '(asdf:make :lem)' |
13 | 54 |
|
14 | 55 | # アイコン(存在しなくても続行) |
15 | | -cp resources/lem.png bin/lem.app/Contents/Resources/ || true |
16 | | - |
17 | | -# ===== 2) OpenSSL を同梱し、参照先を @loader_path 化 ===== |
18 | | -APP="bin/lem.app" |
19 | | -EXE="$APP/Contents/MacOS/lem" |
20 | | -LIBDIR="$APP/Contents/MacOS" |
| 56 | +# Icon (Continue even if it does not exist) |
| 57 | +install -m 0644 resources/lem.png "$APP/Contents/Resources/" || true |
21 | 58 |
|
| 59 | +# ===== 3) OpenSSL を同梱し、参照先を @loader_path 化 ===== |
| 60 | +# ===== 3) Bundle OpenSSL and convert reference targets to @loader_path ===== |
22 | 61 | if [[ ! -x "$EXE" ]]; then |
23 | 62 | echo "error: executable not found: $EXE" >&2 |
24 | 63 | exit 1 |
25 | 64 | fi |
26 | 65 |
|
27 | | -if ! command -v brew >/dev/null 2>&1; then |
28 | | - echo "error: Homebrew not found. Install brew before packaging." >&2 |
| 66 | +if ! command -v pkg-config >/dev/null 2>&1; then |
| 67 | + echo "error: pkg-config not found. Install pkg-config before packaging." >&2 |
29 | 68 | exit 1 |
30 | 69 | fi |
31 | 70 |
|
32 | | -OPENSSL_PREFIX="$(brew --prefix openssl@3)" |
33 | | -OPENSSL_LIB="$OPENSSL_PREFIX/lib" |
| 71 | +# deploy によって追加されたライブラリを削除 |
| 72 | +# Remove libs added by deploy |
| 73 | +rm "$LIBDIR"/libtree-sitter.*.dylib || true |
| 74 | +rm "$LIBDIR"/libzstd.*.dylib || true |
| 75 | + |
| 76 | +OPENSSL_LIB="$(pkg-config --variable=libdir openssl)" |
34 | 77 |
|
35 | 78 | # Cellar の実体(バージョン付きディレクトリ)を解決 |
| 79 | +# Resolve the actual path in the Cellar (versioned directory) |
36 | 80 | LIBCRYPTO_REAL="$(realpath "$OPENSSL_LIB/libcrypto.3.dylib")" |
37 | | -LIBSSL_REAL="$(realpath "$OPENSSL_LIB/libssl.3.dylib")" |
38 | 81 |
|
39 | 82 | # deploy が同名を置いている場合もあるので上書き |
40 | | -cp -f "$OPENSSL_LIB/libssl.3.dylib" "$LIBDIR/libssl.3.dylib" |
41 | | -cp -f "$OPENSSL_LIB/libcrypto.3.dylib" "$LIBDIR/libcrypto.3.dylib" |
| 83 | +# Overwrite because deploy may have placed a file with the same name |
| 84 | +install -m 0755 "$OPENSSL_LIB/libssl.3.dylib" "$LIBDIR/libssl.3.dylib" |
| 85 | +install -m 0755 "$OPENSSL_LIB/libcrypto.3.dylib" "$LIBDIR/libcrypto.3.dylib" |
42 | 86 |
|
43 | 87 | # dylib 自身の ID を @loader_path に揃える |
| 88 | +# Align the dylib's own ID to @loader_path |
44 | 89 | install_name_tool -id @loader_path/libssl.3.dylib "$LIBDIR/libssl.3.dylib" |
45 | 90 | install_name_tool -id @loader_path/libcrypto.3.dylib "$LIBDIR/libcrypto.3.dylib" |
46 | 91 |
|
47 | 92 | # libssl → libcrypto の参照を絶対パスから置換 |
| 93 | +# Replace libssl -> libcrypto references from absolute paths |
48 | 94 | # 1) Cellar 実体パス |
| 95 | +# 1) Cellar resolved path |
49 | 96 | install_name_tool -change "$LIBCRYPTO_REAL" @loader_path/libcrypto.3.dylib "$LIBDIR/libssl.3.dylib" || true |
50 | 97 | # 2) opt 経由のパス |
| 98 | +# 2) Path via opt |
51 | 99 | install_name_tool -change "$OPENSSL_LIB/libcrypto.3.dylib" @loader_path/libcrypto.3.dylib "$LIBDIR/libssl.3.dylib" || true |
52 | 100 | # 3) @rpath の場合も @loader_path に寄せる(冪等) |
| 101 | +# 3) Also shift @rpath cases to @loader_path (idempotent) |
53 | 102 | install_name_tool -change @rpath/libcrypto.3.dylib @loader_path/libcrypto.3.dylib "$LIBDIR/libssl.3.dylib" || true |
54 | 103 |
|
55 | | -# 互換用シンボリックリンク(無印名で探すケースに備える) |
56 | | -( cd "$LIBDIR" && { ln -sf libssl.3.dylib libssl.dylib; ln -sf libcrypto.3.dylib libcrypto.dylib; } ) |
| 104 | +# 必要に応じて zlib を同梱 (MacPorts の OpenSSL は zlib に依存するため) |
| 105 | +# Bundle zlib if needed (MacPorts OpenSSL depends on zlib) |
| 106 | +if otool -L "$LIBDIR/libssl.3.dylib" "$LIBDIR/libcrypto.3.dylib" | grep -q "libz"; then |
| 107 | + ZLIB_DIR="$(pkg-config --variable=libdir zlib)" |
| 108 | + install -m 0755 "$ZLIB_DIR/libz.1.dylib" "$LIBDIR/libz.1.dylib" |
| 109 | + |
| 110 | + # libz 自身の ID を @loader_path に変更 |
| 111 | + # Change libz's own ID to @loader_path |
| 112 | + install_name_tool -id @loader_path/libz.1.dylib "$LIBDIR/libz.1.dylib" |
| 113 | + |
| 114 | + # libssl/libcrypto からの参照を置換 |
| 115 | + # Replace references from libssl/libcrypto |
| 116 | + install_name_tool -change "$ZLIB_DIR/libz.1.dylib" @loader_path/libz.1.dylib "$LIBDIR/libssl.3.dylib" || true |
| 117 | + install_name_tool -change "$ZLIB_DIR/libz.1.dylib" @loader_path/libz.1.dylib "$LIBDIR/libcrypto.3.dylib" || true |
| 118 | +fi |
| 119 | + |
| 120 | +# tree-sitter を同梱 |
| 121 | +# Bundle tree-sitter |
| 122 | +LIBTREE_SITTER_DIR="$(pkg-config --variable=libdir tree-sitter)" |
| 123 | +install -m 0755 "$LIBTREE_SITTER_DIR/libtree-sitter.0.dylib" "$LIBDIR/libtree-sitter.0.dylib" |
| 124 | + |
| 125 | +# vterm を同梱 |
| 126 | +# Bundle vterm |
| 127 | +VTERM_DIR="$(pkg-config --variable=libdir vterm)" |
| 128 | +install -m 0755 "$VTERM_DIR/libvterm.0.dylib" "$LIBDIR/libvterm.0.dylib" |
| 129 | + |
| 130 | +# zstd を同梱 |
| 131 | +# Bundle zstd |
| 132 | +install -m 0755 "$BUILD_DIR/libzstd.1.dylib" "$LIBDIR/libzstd.1.dylib" |
| 133 | + |
| 134 | +# dylib の自認パス (ID) を @loader_path に変更 |
| 135 | +# Change dylib IDs to @loader_path |
| 136 | +install_name_tool -id @loader_path/libtree-sitter.0.dylib "$LIBDIR/libtree-sitter.0.dylib" |
| 137 | +install_name_tool -id @loader_path/libts-wrapper.dylib "$LIBDIR/libts-wrapper.dylib" |
| 138 | +install_name_tool -id @loader_path/libvterm.0.dylib "$LIBDIR/libvterm.0.dylib" |
| 139 | +install_name_tool -id @loader_path/libwebview.0.12.dylib "$LIBDIR/libwebview.dylib" |
| 140 | +install_name_tool -id @loader_path/terminal.so "$LIBDIR/terminal.so" |
| 141 | + |
| 142 | +# dylib の参照先を @loader_path に変更 |
| 143 | +# Change dylib references to @loader_path |
| 144 | +install_name_tool -change /opt/homebrew/opt/tree-sitter/lib/libtree-sitter.0.26.dylib @loader_path/libtree-sitter.0.dylib "$LIBDIR/libts-wrapper.dylib" |
| 145 | +install_name_tool -change /opt/homebrew/opt/libvterm/lib/libvterm.0.dylib @loader_path/libvterm.0.dylib "$LIBDIR/terminal.so" |
57 | 146 |
|
58 | 147 | # 実行ファイル(lem)は SBCL のダンプ構造のため install_name_tool は当てない |
| 148 | +# Do not apply install_name_tool to the executable (lem) because of the SBCL dump structure |
59 | 149 |
|
60 | | -# ===== 3) 署名(必須ではないが念のため。失敗しても続行) ===== |
61 | | -codesign --force --sign - --timestamp=none "$LIBDIR/libcrypto.3.dylib" || true |
62 | | -codesign --force --sign - --timestamp=none "$LIBDIR/libssl.3.dylib" || true |
63 | | -codesign --force --deep --sign - --timestamp=none "$APP" || true |
| 150 | +# ===== 4) 署名(必須ではないが念のため。失敗しても続行) ===== |
| 151 | +# ===== 4) Signing (Not required, but just in case. Continue even if it fails) ===== |
| 152 | +codesign --force --sign - "$LIBDIR/libcrypto.3.dylib" || true |
| 153 | +codesign --force --sign - "$LIBDIR/libssl.3.dylib" || true |
| 154 | +codesign --force --deep --sign - "$APP" || true |
64 | 155 |
|
65 | | -# ===== 4) 検査(絶対パスが残っていないか) ===== |
66 | | -echo "== otool -L libssl.3.dylib ==" |
67 | | -otool -L "$LIBDIR/libssl.3.dylib" | sed 's/^/ /' |
68 | | -echo "== otool -L libcrypto.3.dylib ==" |
69 | | -otool -L "$LIBDIR/libcrypto.3.dylib" | sed 's/^/ /' |
| 156 | +# ===== 5) 検査(絶対パスが残っていないか) ===== |
| 157 | +# ===== 5) Inspection (Check if any absolute paths remain) ===== |
| 158 | +echo "== otool -L * ==" |
| 159 | +otool -L "$LIBDIR"/* | sed 's/^/ /' |
70 | 160 |
|
71 | | -if otool -L "$LIBDIR/libssl.3.dylib" | grep -q '/opt/homebrew' \ |
72 | | -|| otool -L "$LIBDIR/libcrypto.3.dylib" | grep -q '/opt/homebrew'; then |
73 | | - echo "error: absolute Homebrew paths remain in libssl/libcrypto. Fixing failed." >&2 |
| 161 | +if otool -L "$LIBDIR"/* | grep -q '/opt'; then |
| 162 | + echo "error: absolute paths remain in lem executable or bundled dylibs. Fixing failed." >&2 |
74 | 163 | exit 1 |
75 | 164 | fi |
76 | 165 |
|
77 | | -# ===== 5) 配布用 ZIP ===== |
| 166 | +# ===== 6) 配布用 ZIP ===== |
| 167 | +# ===== 6) ZIP for distribution ===== |
78 | 168 | README_PATH="bin/README.md" |
79 | | -echo "The following command must be executed for lem.app to start. |
| 169 | +echo 'The following command must be executed for lem.app to start. |
80 | 170 | ``` |
81 | 171 | xattr -dr com.apple.quarantine lem.app/ |
82 | 172 | ``` |
83 | | -" > "$README_PATH" |
| 173 | +' > "$README_PATH" |
84 | 174 |
|
85 | 175 | rm -f lem-macos.zip |
86 | 176 | ( |
|
0 commit comments