Files
neuron-tai/packages/node/native/scripts/build_llama_worker.sh
2026-07-15 23:42:58 +03:00

188 lines
5.6 KiB
Bash

#!/usr/bin/env bash
# Apply the numbered llama.cpp patch stack and build the worker scaffold.
#
# Default flow:
# 1. Fetch the pinned llama.cpp source into a build directory if needed.
# 2. Verify the checkout matches the pinned commit.
# 3. Check/apply the numbered patch stack from packages/node/native/llama/.
# 4. Compile and build the standalone worker scaffold.
# 5. Copy upstream LICENSE/AUTHORS notices into the staging directory.
#
# This script is intentionally model-free and does not contact any inference
# endpoint. It is a source/build reproducibility check.
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
NATIVE_ROOT="$(cd "${SCRIPT_DIR}/.." && pwd)"
LLAMA_ROOT="${NATIVE_ROOT}/llama"
UPSTREAM_COMMIT="$(tr -d '\n\r' < "${LLAMA_ROOT}/UPSTREAM_COMMIT")"
UPSTREAM_REPOSITORY="$(tr -d '\n\r' < "${LLAMA_ROOT}/UPSTREAM_REPOSITORY")"
PATCH_DIR="${LLAMA_ROOT}/patches"
DEFAULT_SOURCE_DIR="${NATIVE_ROOT}/build/llama.cpp-src"
DEFAULT_BUILD_DIR="${NATIVE_ROOT}/build/llama-worker"
SOURCE_DIR="${DEFAULT_SOURCE_DIR}"
BUILD_DIR="${DEFAULT_BUILD_DIR}"
WORKTREE_DIR=""
FETCH=1
CXX_BIN="${CXX:-}"
usage() {
cat <<'EOF'
Usage: build_llama_worker.sh [--source-dir PATH] [--build-dir PATH] [--no-fetch]
Builds the project-owned worker scaffold from a pinned llama.cpp checkout.
EOF
}
fail() {
echo "error: $*" >&2
exit 1
}
while (($#)); do
case "$1" in
--source-dir)
SOURCE_DIR="${2:-}"
shift 2
;;
--build-dir)
BUILD_DIR="${2:-}"
shift 2
;;
--no-fetch)
FETCH=0
shift
;;
-h|--help)
usage
exit 0
;;
*)
fail "unknown argument: $1"
;;
esac
done
[[ -n "${SOURCE_DIR}" ]] || fail "source dir is empty"
[[ -n "${BUILD_DIR}" ]] || fail "build dir is empty"
checkout_commit() {
if [[ -f "${SOURCE_DIR}/.meshnet-upstream-commit" ]]; then
tr -d '\n\r' < "${SOURCE_DIR}/.meshnet-upstream-commit"
return 0
fi
if git -C "${SOURCE_DIR}" rev-parse --is-inside-work-tree >/dev/null 2>&1; then
git -C "${SOURCE_DIR}" rev-parse HEAD
return 0
fi
return 1
}
ensure_source() {
if [[ -d "${SOURCE_DIR}" ]]; then
return 0
fi
if [[ "${FETCH}" -ne 1 ]]; then
fail "source dir ${SOURCE_DIR} does not exist and --no-fetch was set"
fi
mkdir -p "${SOURCE_DIR}"
git clone --quiet "${UPSTREAM_REPOSITORY}" "${SOURCE_DIR}" || fail "unable to clone ${UPSTREAM_REPOSITORY}"
git -C "${SOURCE_DIR}" checkout --quiet "${UPSTREAM_COMMIT}" || fail "unable to checkout ${UPSTREAM_COMMIT}"
printf '%s\n' "${UPSTREAM_COMMIT}" > "${SOURCE_DIR}/.meshnet-upstream-commit"
printf '%s\n' "${UPSTREAM_REPOSITORY}" > "${SOURCE_DIR}/.meshnet-upstream-repository"
}
verify_assumptions() {
local observed_commit
observed_commit="$(checkout_commit)" || fail "source tree does not expose a commit pin; write ${SOURCE_DIR}/.meshnet-upstream-commit or use a git checkout"
if [[ "${observed_commit}" != "${UPSTREAM_COMMIT}" ]]; then
fail "llama.cpp pin mismatch: expected ${UPSTREAM_COMMIT}, got ${observed_commit}"
fi
for required in LICENSE AUTHORS CMakeLists.txt; do
[[ -e "${SOURCE_DIR}/${required}" ]] || fail "missing upstream assumption file: ${required}"
done
}
apply_patches() {
shopt -s nullglob
local patches=("${PATCH_DIR}"/*.patch)
shopt -u nullglob
if ((${#patches[@]} == 0)); then
fail "no patch files found in ${PATCH_DIR}"
fi
for patch in "${patches[@]}"; do
git -C "${SOURCE_DIR}" apply --check "${patch}" || fail "patch check failed: $(basename "${patch}")"
done
for patch in "${patches[@]}"; do
git -C "${SOURCE_DIR}" apply "${patch}" || fail "patch apply failed: $(basename "${patch}")"
done
}
build_worker() {
rm -rf "${BUILD_DIR}"
mkdir -p "${BUILD_DIR}"
WORKTREE_DIR="${BUILD_DIR}/llama.cpp-worktree"
rm -rf "${WORKTREE_DIR}"
mkdir -p "${WORKTREE_DIR}"
cp -a "${SOURCE_DIR}/." "${WORKTREE_DIR}/"
if [[ -f "${SOURCE_DIR}/.meshnet-upstream-commit" ]]; then
cp "${SOURCE_DIR}/.meshnet-upstream-commit" "${WORKTREE_DIR}/.meshnet-upstream-commit"
fi
if [[ -f "${SOURCE_DIR}/.meshnet-upstream-repository" ]]; then
cp "${SOURCE_DIR}/.meshnet-upstream-repository" "${WORKTREE_DIR}/.meshnet-upstream-repository"
fi
SOURCE_DIR="${WORKTREE_DIR}"
apply_patches
local worker_dir="${SOURCE_DIR}/examples/meshnet-worker"
cp "${LLAMA_ROOT}/templates/meshnet_worker.cpp" "${worker_dir}/meshnet_worker.cpp"
cat > "${worker_dir}/version.h" <<EOF
#pragma once
#define MESHNET_LLAMA_UPSTREAM_COMMIT "${UPSTREAM_COMMIT}"
#define MESHNET_LLAMA_PATCHSET_VERSION "0001"
EOF
local compiler=""
if [[ -n "${CXX_BIN}" ]] && command -v "${CXX_BIN}" >/dev/null 2>&1; then
compiler="${CXX_BIN}"
elif command -v g++ >/dev/null 2>&1; then
compiler="g++"
elif command -v c++ >/dev/null 2>&1; then
compiler="c++"
elif command -v clang++ >/dev/null 2>&1; then
compiler="clang++"
else
fail "no C++ compiler found (need g++, c++, clang++, or $CXX)"
fi
"${compiler}" -std=c++17 -O2 -Wall -Wextra \
-I "${worker_dir}" \
-o "${BUILD_DIR}/meshnet_worker" \
"${worker_dir}/meshnet_worker.cpp"
}
stage_notices() {
local notice_dir="${BUILD_DIR}/upstream-notices"
mkdir -p "${notice_dir}"
cp "${SOURCE_DIR}/LICENSE" "${notice_dir}/LICENSE"
cp "${SOURCE_DIR}/AUTHORS" "${notice_dir}/AUTHORS"
printf '%s\n' "${UPSTREAM_COMMIT}" > "${notice_dir}/UPSTREAM_COMMIT"
printf '%s\n' "${UPSTREAM_REPOSITORY}" > "${notice_dir}/UPSTREAM_REPOSITORY"
}
main() {
ensure_source
verify_assumptions
build_worker
stage_notices
"${BUILD_DIR}/meshnet_worker" --smoke
echo "build ok: ${BUILD_DIR}/meshnet_worker"
}
main "$@"