175 lines
No EOL
7.6 KiB
Bash
175 lines
No EOL
7.6 KiB
Bash
#!/usr/bin/env bash
|
|
# Built standing on the shoulders of billions of dwarves
|
|
# Created by John A. Hoeven with the ethical assistance of Claude AI
|
|
# Licence: The Unlicense — https://unlicense.org
|
|
# ---------------------------------------------------------------------------
|
|
# llama-cpp-update.sh
|
|
# /opt/llama-cpp/scripts/llama-cpp-update.sh
|
|
# Version: v0.0.1 | Status: DEVELOPMENT
|
|
# Role: Orchestrator
|
|
# ---------------------------------------------------------------------------
|
|
# Purpose: Build and stage a new pinned llama.cpp release on BigBoy, behind
|
|
# a btrfs snapshot safety net and a versioned-symlink release
|
|
# layout. Does NOT promote the new build automatically — that is
|
|
# a separate, deliberate step (see llama-cpp-promote.sh) taken
|
|
# only after Phase 12-style validation passes.
|
|
# Target: BigBoy — AlmaLinux 10.2, @llama-cpp btrfs subvolume at
|
|
# /opt/llama-cpp, NVIDIA RTX 5060 Ti (sm_120)
|
|
# Entry: sudo ./llama-cpp-update.sh <build-tag>
|
|
# e.g. sudo ./llama-cpp-update.sh b9985
|
|
# Depends: git, cmake, gcc, nvcc (CUDA toolkit), btrfs-progs
|
|
# Note: This is a standalone ops script for one Alma server, not part
|
|
# of the CEOS multi-distro installer framework — so it does not
|
|
# use ce_env.conf / pkg_* / CE_PRIV. Privilege is via sudo
|
|
# directly, detected explicitly below rather than assumed.
|
|
# ---------------------------------------------------------------------------
|
|
|
|
# No 'set -e' — every operation is checked explicitly (CE OS standard §1.8).
|
|
|
|
# ── Configuration ────────────────────────────────────────────────────────
|
|
|
|
LLAMA_ROOT="/opt/llama-cpp"
|
|
RELEASES_DIR="${LLAMA_ROOT}/releases"
|
|
SNAPSHOT_DIR="/opt/.snapshots/llama-cpp"
|
|
REPO_URL="https://github.com/ggml-org/llama.cpp"
|
|
CUDA_ARCH="120" # RTX 5060 Ti — Blackwell sm_120
|
|
LOG_DIR="${HOME}/.local/logs/bigboy-llama-update"
|
|
LOG_FILE="${LOG_DIR}/update-$(date '+%Y-%m-%d_%H%M%S').log"
|
|
|
|
BUILD_TAG="${1:-}"
|
|
|
|
# ── Logging ──────────────────────────────────────────────────────────────
|
|
|
|
mkdir -p "${LOG_DIR}"
|
|
|
|
_log() {
|
|
local level="${1}"
|
|
local msg="${2}"
|
|
local ts
|
|
ts="$(date '+%Y-%m-%d %H:%M:%S')"
|
|
printf '[%s] [%s] %s\n' "${ts}" "${level}" "${msg}" | tee -a "${LOG_FILE}"
|
|
}
|
|
log_info() { _log "INFO " "${1}"; }
|
|
log_warn() { _log "WARN " "${1}" >&2; }
|
|
log_error() { _log "ERROR" "${1}" >&2; }
|
|
|
|
# ── Cleanup ──────────────────────────────────────────────────────────────
|
|
|
|
BUILD_TMP=""
|
|
|
|
cleanup() {
|
|
local exit_code="${?}"
|
|
if [[ -n "${BUILD_TMP}" && -d "${BUILD_TMP}" && "${exit_code}" -ne 0 ]]; then
|
|
log_warn "Non-zero exit — leaving ${BUILD_TMP} in place for inspection."
|
|
log_warn "Remove it manually once reviewed: rm -rf ${BUILD_TMP}"
|
|
fi
|
|
log_info "Run finished. Log: ${LOG_FILE}"
|
|
}
|
|
trap cleanup EXIT INT TERM HUP
|
|
|
|
# ── Pre-flight checks ────────────────────────────────────────────────────
|
|
|
|
if [[ "${EUID}" -eq 0 ]]; then
|
|
log_error "Do not run this script directly as root. Run as your normal"
|
|
log_error "user; it will invoke sudo only for the specific steps that need it."
|
|
exit 1
|
|
fi
|
|
|
|
if [[ -z "${BUILD_TAG}" ]]; then
|
|
log_error "Usage: ${0} <build-tag> e.g. ${0} b9985"
|
|
log_error "Check https://github.com/ggml-org/llama.cpp/releases for current tags."
|
|
exit 1
|
|
fi
|
|
|
|
if [[ -d "${RELEASES_DIR}/${BUILD_TAG}" ]]; then
|
|
log_error "Release ${BUILD_TAG} already exists at ${RELEASES_DIR}/${BUILD_TAG}"
|
|
log_error "Remove it first if you intend to rebuild this tag."
|
|
exit 1
|
|
fi
|
|
|
|
for tool in git cmake nvcc; do
|
|
if ! command -v "${tool}" >/dev/null 2>&1; then
|
|
log_error "Required tool not found: ${tool}"
|
|
exit 1
|
|
fi
|
|
done
|
|
|
|
# ── Confirmation ─────────────────────────────────────────────────────────
|
|
|
|
printf '\nAbout to build llama.cpp %s into %s\n' "${BUILD_TAG}" "${RELEASES_DIR}/${BUILD_TAG}"
|
|
printf 'A btrfs snapshot of %s will be taken first.\n' "${LLAMA_ROOT}"
|
|
printf 'This will NOT restart the live service — that is a separate promote step.\n'
|
|
printf '\nProceed? [y/N] '
|
|
read -r response
|
|
case "${response}" in
|
|
[yY]|[yY][eE][sS]) ;;
|
|
*) log_info "Aborted by user."; exit 0 ;;
|
|
esac
|
|
|
|
# ── Step 1: btrfs snapshot (safety net) ──────────────────────────────────
|
|
|
|
mkdir -p "${SNAPSHOT_DIR}"
|
|
SNAPSHOT_PATH="${SNAPSHOT_DIR}/pre-${BUILD_TAG}-$(date '+%Y%m%d')"
|
|
|
|
log_info "Taking btrfs snapshot: ${SNAPSHOT_PATH}"
|
|
if ! sudo btrfs subvolume snapshot -r "${LLAMA_ROOT}" "${SNAPSHOT_PATH}" \
|
|
>>"${LOG_FILE}" 2>&1; then
|
|
log_error "Snapshot failed. Aborting before touching anything else."
|
|
exit 1
|
|
fi
|
|
log_info "Snapshot confirmed at ${SNAPSHOT_PATH}"
|
|
|
|
# ── Step 2: clone and checkout pinned tag ────────────────────────────────
|
|
|
|
BUILD_TMP="$(mktemp -d)"
|
|
log_info "Cloning llama.cpp (shallow, tag-only) into ${BUILD_TMP}"
|
|
|
|
# Shallow clone directly at the target tag — we only ever need this one
|
|
# pinned commit, not full history. Cuts clone size roughly in half versus
|
|
# a full clone + checkout, which matters once you're keeping many releases.
|
|
if ! git clone --quiet --depth 1 --branch "${BUILD_TAG}" \
|
|
"${REPO_URL}" "${BUILD_TMP}/llama.cpp" >>"${LOG_FILE}" 2>&1; then
|
|
log_error "Shallow clone of tag ${BUILD_TAG} failed."
|
|
log_error "Confirm the tag exists upstream: ${REPO_URL}/releases"
|
|
exit 1
|
|
fi
|
|
|
|
# ── Step 3: build (standard flags only — no exotic tuning, see notes) ────
|
|
|
|
log_info "Configuring CMake build (CUDA, sm_${CUDA_ARCH}, Release)"
|
|
if ! (cd "${BUILD_TMP}/llama.cpp" && cmake -B build \
|
|
-DGGML_CUDA=ON \
|
|
-DCMAKE_BUILD_TYPE=Release \
|
|
-DCMAKE_CUDA_ARCHITECTURES="${CUDA_ARCH}") >>"${LOG_FILE}" 2>&1; then
|
|
log_error "CMake configure failed. See ${LOG_FILE} for details."
|
|
exit 1
|
|
fi
|
|
|
|
log_info "Building — this takes a while, watch ${LOG_FILE} for progress"
|
|
if ! (cd "${BUILD_TMP}/llama.cpp" && cmake --build build --config Release -j) \
|
|
>>"${LOG_FILE}" 2>&1; then
|
|
log_error "Build failed. See ${LOG_FILE} for details."
|
|
log_error "Known issue: MXFP4 quant kernels can fail to compile on sm_120."
|
|
log_error "This build does not require MXFP4 — check for unrelated errors first."
|
|
exit 1
|
|
fi
|
|
|
|
if [[ ! -x "${BUILD_TMP}/llama.cpp/build/bin/llama-server" ]]; then
|
|
log_error "Build reported success but llama-server binary is missing. Aborting."
|
|
exit 1
|
|
fi
|
|
|
|
# ── Step 4: stage into versioned release directory ──────────────────────
|
|
|
|
log_info "Staging build into ${RELEASES_DIR}/${BUILD_TAG}"
|
|
sudo mkdir -p "${RELEASES_DIR}"
|
|
if ! sudo cp -a "${BUILD_TMP}/llama.cpp" "${RELEASES_DIR}/${BUILD_TAG}" \
|
|
>>"${LOG_FILE}" 2>&1; then
|
|
log_error "Failed to stage build into ${RELEASES_DIR}/${BUILD_TAG}"
|
|
exit 1
|
|
fi
|
|
|
|
log_info "Build ${BUILD_TAG} staged successfully."
|
|
log_info "Current live release is untouched — 'current' symlink not modified."
|
|
log_info "Next step: run Phase 12 validation against this build, then:"
|
|
log_info " sudo ./llama-cpp-promote.sh ${BUILD_TAG}" |