install.sh: stop dying on macOS at the compile step
"$RUST_HOST;" is one variable name to macOS /bin/sh (bash 3.2): it swallows the first byte of the full-width punctuation, so with set -u a plain \`sh install.sh app\` aborted at [3/4] with "RUST_HOST\*: unbound variable". Four such lines in install.sh, one in the server setup. Brace them, add make lint-sh (sh -n for every shipped script plus a check for this pattern) so it stays fixed.
This commit is contained in:
parent
818e551e6b
commit
983a2c2f02
6
Makefile
6
Makefile
|
|
@ -20,7 +20,7 @@ APPDIR ?= $(HOME)/Applications
|
||||||
BIN := $(TARGET)/release/anybot
|
BIN := $(TARGET)/release/anybot
|
||||||
RELAY := $(if $(CARGO_TARGET_DIR),$(CARGO_TARGET_DIR),relay/target)/release/anybot-relay
|
RELAY := $(if $(CARGO_TARGET_DIR),$(CARGO_TARGET_DIR),relay/target)/release/anybot-relay
|
||||||
|
|
||||||
.PHONY: all build app relay run serve setup relay-run test deps doctor install uninstall hands server dist clean help check-rust
|
.PHONY: all build app relay run serve setup relay-run test deps doctor install uninstall hands server dist clean help check-rust lint-sh
|
||||||
|
|
||||||
all: build
|
all: build
|
||||||
|
|
||||||
|
|
@ -34,6 +34,7 @@ help:
|
||||||
@echo " make deps 裝好建置需要的東西:系統套件和 Rust(Linux 會問 sudo 密碼)"
|
@echo " make deps 裝好建置需要的東西:系統套件和 Rust(Linux 會問 sudo 密碼)"
|
||||||
@echo " make doctor 檢查這台缺什麼"
|
@echo " make doctor 檢查這台缺什麼"
|
||||||
@echo " make test 跑測試"
|
@echo " make test 跑測試"
|
||||||
|
@echo " make lint-sh 檢查 shell 腳本(語法、中文標點黏變數)"
|
||||||
@echo ""
|
@echo ""
|
||||||
@echo " make serve 不開視窗執行(伺服器、一直開著的電腦)"
|
@echo " make serve 不開視窗執行(伺服器、一直開著的電腦)"
|
||||||
@echo " make setup 把這台接到你的 AnyBot(終端機裡的引導畫面)"
|
@echo " make setup 把這台接到你的 AnyBot(終端機裡的引導畫面)"
|
||||||
|
|
@ -72,6 +73,9 @@ test: check-rust
|
||||||
$(CARGO) test --bin anybot
|
$(CARGO) test --bin anybot
|
||||||
cd relay && $(CARGO) test
|
cd relay && $(CARGO) test
|
||||||
|
|
||||||
|
lint-sh:
|
||||||
|
@sh deploy/ci/lint-sh.sh
|
||||||
|
|
||||||
deps:
|
deps:
|
||||||
sh ./install.sh deps
|
sh ./install.sh deps
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,44 @@
|
||||||
|
#!/bin/sh
|
||||||
|
# Shell lint for the install scripts. Two checks:
|
||||||
|
# 1. POSIX syntax (sh -n) for every .sh we ship.
|
||||||
|
# 2. $VAR or ${VAR} glued to a non-ASCII character, which macOS's /bin/sh
|
||||||
|
# (bash 3.2) reads as part of the variable name: "($X;…" is an unbound
|
||||||
|
# variable there even when X is set, and install.sh runs with set -u.
|
||||||
|
# Write ${X}與… — braces fix it.
|
||||||
|
# Run: make lint-sh
|
||||||
|
set -u
|
||||||
|
cd "$(dirname "$0")/../.." || exit 1
|
||||||
|
fail=0
|
||||||
|
|
||||||
|
for f in install.sh $(find deploy -name '*.sh' | sort); do
|
||||||
|
if sh -n "$f" 2>/tmp/anybot-sh-lint.log; then
|
||||||
|
printf ' ✓ %s\n' "$f"
|
||||||
|
else
|
||||||
|
printf ' ✗ %s\n' "$f"; sed 's/^/ /' /tmp/anybot-sh-lint.log; fail=1
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
printf '\n'
|
||||||
|
python3 - <<'PY' || fail=1
|
||||||
|
import glob, re, os, sys
|
||||||
|
pat = re.compile(r'(?<![A-Za-z0-9_$\\])\$([A-Za-z_][A-Za-z0-9_]*)([^\x00-\x7f])')
|
||||||
|
root = os.getcwd()
|
||||||
|
files = []
|
||||||
|
for d, dirs, fs in os.walk('.'):
|
||||||
|
dirs[:] = [x for x in dirs if x not in ('target', '.git', 'node_modules')]
|
||||||
|
files += [os.path.join(d, x) for x in fs if x.endswith('.sh')]
|
||||||
|
bad = 0
|
||||||
|
for f in sorted(files):
|
||||||
|
for i, line in enumerate(open(f, encoding='utf-8'), 1):
|
||||||
|
if line.strip().startswith('#'):
|
||||||
|
continue
|
||||||
|
for m in pat.finditer(line):
|
||||||
|
print(f' ✗ {f}:{i}: ${m.group(1)}{m.group(2)} → 在 macOS 的 /bin/sh 是未設定變數(改用 ${{{m.group(1)}}}{m.group(2)})')
|
||||||
|
print(f' {line.strip()[:100]}')
|
||||||
|
bad += 1
|
||||||
|
print(' ✓ no $VAR glued to Chinese punctuation' if not bad else f' {bad} places to fix')
|
||||||
|
sys.exit(1 if bad else 0)
|
||||||
|
PY
|
||||||
|
|
||||||
|
[ "$fail" = 0 ] && printf '\n 都過了。\n' || printf '\n 有東西要修。\n'
|
||||||
|
exit $fail
|
||||||
|
|
@ -204,7 +204,7 @@ if [ "${SKIP:-0}" != 1 ]; then
|
||||||
fi
|
fi
|
||||||
while [ "$LAN" = 1 ] && [ "$AUTO" = 0 ]; do
|
while [ "$LAN" = 1 ] && [ "$AUTO" = 0 ]; do
|
||||||
header; card_open "這台在區網的 IP"
|
header; card_open "這台在區網的 IP"
|
||||||
note "手機和電腦在同一個區網打開 https://這個 IP。$LANDESC。"
|
note "手機和電腦在同一個區網打開 https://這個 IP。${LANDESC}。"
|
||||||
line ""
|
line ""
|
||||||
[ -n "$MSG" ] && { printf '%s\n' "$MSG"; line ""; }
|
[ -n "$MSG" ] && { printf '%s\n' "$MSG"; line ""; }
|
||||||
ask LANIP "IP" "${LANIP:-$(lan_ip)}"
|
ask LANIP "IP" "${LANIP:-$(lan_ip)}"
|
||||||
|
|
|
||||||
|
|
@ -180,7 +180,7 @@ $1"
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
[ -z "$RUST_HOST" ] && note "這個 CPU 架構($ARCH)沒有對應的 Rust 目標,一鍵安裝不會編譯。"
|
[ -z "$RUST_HOST" ] && note "這個 CPU 架構(${ARCH})沒有對應的 Rust 目標,一鍵安裝不會編譯。"
|
||||||
[ "$MUSL" = 1 ] && note "這是 musl(多半是 Alpine)。可以編譯,桌面視窗比 glibc 發行版容易缺函式庫;當手腳比較穩。"
|
[ "$MUSL" = 1 ] && note "這是 musl(多半是 Alpine)。可以編譯,桌面視窗比 glibc 發行版容易缺函式庫;當手腳比較穩。"
|
||||||
[ "$WSL" = 1 ] && [ "$DESKTOP" = 0 ] && note "這是沒有 WSLg 的 WSL。這裡裝的是 Linux 手腳(虛擬螢幕)。要操控 Windows 桌面,請在 Windows 的 PowerShell 執行 install.ps1,不要在 WSL 裡裝。"
|
[ "$WSL" = 1 ] && [ "$DESKTOP" = 0 ] && note "這是沒有 WSLg 的 WSL。這裡裝的是 Linux 手腳(虛擬螢幕)。要操控 Windows 桌面,請在 Windows 的 PowerShell 執行 install.ps1,不要在 WSL 裡裝。"
|
||||||
[ "$WSL" = 1 ] && [ "$DESKTOP" = 1 ] && note "偵測到 WSLg,會用 Linux 桌面。要操控 Windows 自己的視窗,另外在 Windows 裝 install.ps1。"
|
[ "$WSL" = 1 ] && [ "$DESKTOP" = 1 ] && note "偵測到 WSLg,會用 Linux 桌面。要操控 Windows 自己的視窗,另外在 Windows 裝 install.ps1。"
|
||||||
|
|
@ -478,14 +478,14 @@ ensure_rust() {
|
||||||
[ -f "$HOME/.cargo/env" ] && . "$HOME/.cargo/env"
|
[ -f "$HOME/.cargo/env" ] && . "$HOME/.cargo/env"
|
||||||
else
|
else
|
||||||
if have rustc; then warn "系統的 Rust $(rustc --version | cut -d' ' -f2) 太舊(要 1.$RUST_MIN 以上),另外用 rustup 裝新版"; fi
|
if have rustc; then warn "系統的 Rust $(rustc --version | cut -d' ' -f2) 太舊(要 1.$RUST_MIN 以上),另外用 rustup 裝新版"; fi
|
||||||
info "安裝 Rust(rustup,目標 $RUST_HOST,裝在 ~/.cargo,不用 root)…"
|
info "安裝 Rust(rustup,目標 ${RUST_HOST},裝在 ~/.cargo,不用 root)…"
|
||||||
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y -q --profile minimal --default-host "$RUST_HOST" --no-modify-path >/dev/null 2>&1 \
|
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y -q --profile minimal --default-host "$RUST_HOST" --no-modify-path >/dev/null 2>&1 \
|
||||||
|| die "安裝 Rust 失敗。" "手動:curl --proto '=https' -sSf https://sh.rustup.rs | sh"
|
|| die "安裝 Rust 失敗。" "手動:curl --proto '=https' -sSf https://sh.rustup.rs | sh"
|
||||||
. "$HOME/.cargo/env"
|
. "$HOME/.cargo/env"
|
||||||
fi
|
fi
|
||||||
# 有人用 Rosetta 或跨架構:確保這個目標有標準庫。
|
# 有人用 Rosetta 或跨架構:確保這個目標有標準庫。
|
||||||
if ! rustup target list --installed 2>/dev/null | grep -q "^${RUST_HOST}$"; then
|
if ! rustup target list --installed 2>/dev/null | grep -q "^${RUST_HOST}$"; then
|
||||||
rustup target add "$RUST_HOST" >/dev/null 2>&1 || warn "沒能加上 Rust 目標 $RUST_HOST,仍用 rustup 預設的主機目標試試"
|
rustup target add "$RUST_HOST" >/dev/null 2>&1 || warn "沒能加上 Rust 目標 ${RUST_HOST},仍用 rustup 預設的主機目標試試"
|
||||||
fi
|
fi
|
||||||
rust_ok || die "Rust 還是太舊:$(rustc --version 2>/dev/null)" "執行 rustup update stable,或移除系統的 rustc/cargo 套件。"
|
rust_ok || die "Rust 還是太舊:$(rustc --version 2>/dev/null)" "執行 rustup update stable,或移除系統的 rustc/cargo 套件。"
|
||||||
ok "Rust $(rustc --version | cut -d' ' -f2)"
|
ok "Rust $(rustc --version | cut -d' ' -f2)"
|
||||||
|
|
@ -535,7 +535,7 @@ build_jobs() {
|
||||||
|
|
||||||
build() {
|
build() {
|
||||||
jobs=$(build_jobs)
|
jobs=$(build_jobs)
|
||||||
info "編譯中,第一次約 5–15 分鐘($RUST_HOST;之後更新只重編改過的部分)…"
|
info "編譯中,第一次約 5–15 分鐘(${RUST_HOST};之後更新只重編改過的部分)…"
|
||||||
log="$SRC/target/install-build.log"; mkdir -p "$SRC/target"
|
log="$SRC/target/install-build.log"; mkdir -p "$SRC/target"
|
||||||
if (cd "$SRC" && cargo build --release --bin anybot ${jobs:+-j "$jobs"}) >"$log" 2>&1; then
|
if (cd "$SRC" && cargo build --release --bin anybot ${jobs:+-j "$jobs"}) >"$log" 2>&1; then
|
||||||
ok "編譯完成"
|
ok "編譯完成"
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue