Files
core/build/prepare.sh
T
2026-11-03 03:32:07 +00:00

107 lines
4.2 KiB
Bash

#!/usr/bin/env bash
# 在线包的唯一环境准备入口;安装器后台启动,编译入口等待同一把锁。
set -euo pipefail
package=$(cd -- "$(dirname -- "$0")/.." && pwd -P)
tools="$package/toolchain"
root=$(cd "$package/../.." && pwd -P)
[[ ! -f $tools/ready ]] || exit 0
exec 9>"$root/.prepare.lock"
previous=
until flock -w 1 9; do
status='Waiting for Dever environment preparation...'
if [[ -f $tools/status ]]; then read -r status < "$tools/status" || true; fi
if [[ $status != "$previous" ]]; then printf '%s\n' "$status" >&2; previous=$status; fi
done
[[ ! -f $tools/ready ]] || exit 0
exec 3>&2
exec >"$tools/prepare.log" 2>&1
stage=
rust_stage=
phase='Preparing Dever environment'
finish() {
local code=$?
if (( code )); then
printf 'Failed: %s (exit %s). Details: %s\n' "$phase" "$code" "$tools/prepare.log" > "$tools/status"
cat "$tools/status" >&3
fi
if [[ -n $stage ]]; then rm -rf -- "$stage"; fi
if [[ -n $rust_stage ]]; then rm -rf -- "$rust_stage"; fi
}
trap finish EXIT
trap 'exit 130' INT
trap 'exit 143' TERM
progress() {
phase=$1
printf '%s\n' "$phase" > "$tools/status"
printf '%s\n' "$phase" >&3
}
read -r rust_version native_id < "$tools/online"
mapfile -t sources < "$tools/sources"
release_url=${sources[0]}
rust_dist=${sources[1]}
triple=x86_64-unknown-linux-gnu
rust_root="$root/toolchains/rust-$rust_version-$triple"
native_root="$root/toolchains/native-$native_id"
downloads="$root/cache/downloads"
mkdir -p "$downloads"
stage=$(mktemp -d "$root/.prepare.XXXXXX")
transfers=()
archives=()
queue() {
local url=$1 name=$2
archives+=("$name")
if (( ${#transfers[@]} )); then transfers+=(--next); fi
transfers+=(--fail --location --silent --show-error --retry 2 --connect-timeout 15
--speed-limit 1024 --speed-time 60 --continue-at - --output "$downloads/$name.part" "$url")
transfers+=(--next --fail --location --silent --show-error --retry 2 --connect-timeout 15
--output "$downloads/$name.sha256" "$url.sha256")
}
native_archive="dever-native-linux-x86_64-$native_id.tar.xz"
if [[ ! -d $native_root ]]; then queue "$release_url/$native_archive" "$native_archive"; fi
if [[ ! -d $rust_root ]]; then
for component in rustc rust-std cargo; do
name="$component-$rust_version-$triple.tar.xz"
queue "$rust_dist/dist/$name" "$name"
done
fi
if (( ${#archives[@]} )); then
progress 'Downloading Dever build environment...'
curl --parallel --parallel-immediate --parallel-max 3 --fail-early "${transfers[@]}"
progress 'Verifying Dever build environment...'
for name in "${archives[@]}"; do
read -r expected remainder < "$downloads/$name.sha256"
if [[ $name == "$native_archive" && $expected != "$native_id" ]] ||
! printf '%s %s\n' "$expected" "$downloads/$name.part" | sha256sum --check --status; then
rm -f -- "$downloads/$name.part" "$downloads/$name.sha256"
echo "Checksum mismatch: $name" >&2
exit 1
fi
done
fi
progress 'Installing Dever build environment...'
if [[ ! -d $rust_root ]]; then
# 官方脚本不支持含空格的 prefix;先在独占临时目录安装,再原子发布。
rust_stage=$(mktemp -d /tmp/dever-toolchain.XXXXXX)
for component in rustc rust-std cargo; do
name="$component-$rust_version-$triple"
tar -xJf "$downloads/$name.tar.xz.part" -C "$rust_stage"
bash "$rust_stage/$name/install.sh" --prefix="$rust_stage/toolchain" --disable-ldconfig
rm -rf -- "$rust_stage/$name"
done
mv "$rust_stage/toolchain" "$stage/rust"
mv "$stage/rust" "$rust_root"
fi
if [[ ! -d $native_root ]]; then
tar -xJf "$downloads/$native_archive.part" -C "$stage"
mv "$stage/native-tools" "$native_root"
fi
"$tools/bin/rustc" --version
progress 'Preparing Dever project dependencies...'
"$tools/bin/cargo" fetch --locked --target "$triple" --manifest-path "$tools/project/Cargo.toml"
for name in "$native_archive" "rustc-$rust_version-$triple.tar.xz" \
"rust-std-$rust_version-$triple.tar.xz" "cargo-$rust_version-$triple.tar.xz"; do
rm -f -- "$downloads/$name.part" "$downloads/$name.sha256"
done
touch "$tools/ready"
progress 'Dever build environment is ready.'