Files
2026-08-16 18:24:52 +07:00

258 lines
8.6 KiB
Bash
Executable File

#!/bin/bash
# HOT-Step CPP — macOS Build-from-Source Installer
#
# One command to go from fresh clone to working app:
# ./install.sh
#
# What this does:
# 1. Checks prerequisites (Xcode, Metal Toolchain, Node.js, CMake)
# 2. Initializes git submodules
# 3. Builds the C++ engine with Metal GPU acceleration
# 4. Installs server + UI dependencies
# 5. Builds the production UI
#
# After install completes, run ./launch.sh to start the app.
set -e
cd "$(dirname "$0")"
ROOT_DIR="$(pwd)"
# ── Colors ──────────────────────────────────────────────────────────
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
CYAN='\033[0;36m'
BOLD='\033[1m'
NC='\033[0m'
step() { echo -e "\n${CYAN}${BOLD}[$1/$TOTAL_STEPS]${NC} ${BOLD}$2${NC}"; }
ok() { echo -e " ${GREEN}${NC} $1"; }
warn() { echo -e " ${YELLOW}${NC} $1"; }
fail() { echo -e " ${RED}$1${NC}"; exit 1; }
TOTAL_STEPS=6
echo ""
echo -e "${BOLD}╔══════════════════════════════════════════╗${NC}"
echo -e "${BOLD}║ HOT-Step CPP — macOS Installer ║${NC}"
echo -e "${BOLD}║ Build from Source (Apple Silicon) ║${NC}"
echo -e "${BOLD}╚══════════════════════════════════════════╝${NC}"
echo ""
# ── Step 1: Check Prerequisites ─────────────────────────────────────
step 1 "Checking prerequisites..."
# macOS check
if [[ "$(uname)" != "Darwin" ]]; then
fail "This script is for macOS only."
fi
ok "macOS $(sw_vers -productVersion) ($(uname -m))"
# Xcode or Command Line Tools
if xcode-select -p &>/dev/null; then
XCODE_PATH="$(xcode-select -p)"
if [[ "$XCODE_PATH" == *"Xcode.app"* ]]; then
ok "Xcode installed at ${XCODE_PATH}"
else
ok "Command Line Tools installed"
fi
else
fail "Xcode or Command Line Tools required.\n Install: xcode-select --install"
fi
# Metal compiler
if xcrun metal --version &>/dev/null; then
ok "Metal compiler available"
else
warn "Metal compiler not found."
echo " This is required for GPU acceleration."
echo ""
echo " If you have Xcode installed, download the Metal Toolchain:"
echo " sudo xcodebuild -runFirstLaunch"
echo " xcodebuild -downloadComponent MetalToolchain"
echo ""
echo " Without Metal, the engine will still build but will use CPU only."
echo ""
read -p " Continue without Metal? [y/N] " -n 1 -r
echo
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
exit 1
fi
NO_METAL=1
fi
# CMake
if command -v cmake &>/dev/null; then
ok "CMake $(cmake --version | head -1 | grep -oE '[0-9]+\.[0-9]+\.[0-9]+')"
else
fail "CMake not found.\n Install: brew install cmake"
fi
# Git
if command -v git &>/dev/null; then
ok "Git $(git --version | grep -oE '[0-9]+\.[0-9]+\.[0-9]+')"
else
fail "Git not found."
fi
# ── Step 2: Find or install Node.js ──────────────────────────────────
step 2 "Checking Node.js..."
find_compatible_node() {
# Priority: brew node@22 > system node (if compatible)
local candidates=(
"/opt/homebrew/opt/node@22/bin/node"
"/usr/local/opt/node@22/bin/node"
)
for candidate in "${candidates[@]}"; do
if [ -x "$candidate" ]; then
local ver
ver="$("$candidate" --version 2>/dev/null | tr -d 'v')"
local major="${ver%%.*}"
if [ "$major" -ge 18 ] && [ "$major" -lt 24 ] 2>/dev/null; then
echo "$candidate"
return 0
fi
fi
done
# Check system node
if command -v node &>/dev/null; then
local ver
ver="$(node --version 2>/dev/null | tr -d 'v')"
local major="${ver%%.*}"
if [ "$major" -ge 18 ] && [ "$major" -lt 24 ] 2>/dev/null; then
echo "$(command -v node)"
return 0
fi
fi
return 1
}
NODE_BIN=""
if NODE_BIN=$(find_compatible_node); then
NODE_VER="$("$NODE_BIN" --version)"
NODE_DIR="$(dirname "$NODE_BIN")"
ok "Node.js ${NODE_VER} at ${NODE_BIN}"
else
# Try to install via brew
echo " Node.js 18-22 required (Node 24+ is not supported)."
if command -v brew &>/dev/null; then
echo ""
read -p " Install Node.js 22 via Homebrew? [Y/n] " -n 1 -r
echo
if [[ ! $REPLY =~ ^[Nn]$ ]]; then
echo " Installing node@22..."
brew install node@22
NODE_BIN="/opt/homebrew/opt/node@22/bin/node"
if [ ! -x "$NODE_BIN" ]; then
NODE_BIN="/usr/local/opt/node@22/bin/node"
fi
if [ -x "$NODE_BIN" ]; then
NODE_DIR="$(dirname "$NODE_BIN")"
ok "Node.js $("$NODE_BIN" --version) installed"
else
fail "Node.js installation failed."
fi
else
fail "Node.js 18-22 is required. Install manually:\n brew install node@22"
fi
else
fail "Node.js 18-22 required.\n Install Homebrew first: https://brew.sh\n Then: brew install node@22"
fi
fi
# Export so npm/npx use the right Node
export PATH="${NODE_DIR}:${PATH}"
# ── Step 3: Initialize submodules ────────────────────────────────────
step 3 "Initializing git submodules..."
if [ -f "engine/ggml/CMakeLists.txt" ] && [ -f "engine/vendor/vst3sdk/CMakeLists.txt" ]; then
ok "Submodules already initialized"
else
git submodule update --init --recursive
ok "Submodules initialized"
fi
# ── Step 4: Build the C++ engine ─────────────────────────────────────
step 4 "Building C++ engine (this may take a few minutes)..."
cd engine
mkdir -p build
cd build
CMAKE_FLAGS=(
-DCMAKE_BUILD_TYPE=Release
-DGGML_BACKEND_DL=OFF
)
if [ -z "${NO_METAL}" ]; then
CMAKE_FLAGS+=(-DGGML_METAL=ON -DGGML_METAL_EMBED_LIBRARY=ON)
echo " GPU: Metal (Apple Silicon)"
else
echo " GPU: None (CPU-only build)"
fi
# Detect Ninja for faster builds
if command -v ninja &>/dev/null; then
CMAKE_FLAGS+=(-G Ninja)
echo " Generator: Ninja"
else
echo " Generator: Make (install ninja for faster builds: brew install ninja)"
fi
cmake .. "${CMAKE_FLAGS[@]}" 2>&1 | tail -5
echo ""
NCPU=$(sysctl -n hw.ncpu 2>/dev/null || echo 4)
cmake --build . --config Release -j "${NCPU}" 2>&1 | grep -E '^\[|Built target|Linking|error:'
echo ""
[ -f ace-server ] && ok "ace-server" || warn "ace-server not built"
[ -f mastering ] && ok "mastering" || warn "mastering not built"
[ -f mp3-codec ] && ok "mp3-codec" || warn "mp3-codec not built"
[ -f vst-host ] && ok "vst-host" || warn "vst-host not built"
cd "${ROOT_DIR}"
# ── Step 5: Install Node.js dependencies ─────────────────────────────
step 5 "Installing Node.js dependencies..."
echo " Server..."
cd server && npm install --loglevel=warn 2>&1 | tail -3 && cd ..
ok "Server dependencies installed"
echo " UI..."
cd ui && npm install --loglevel=warn 2>&1 | tail -3 && cd ..
ok "UI dependencies installed"
# ── Step 6: Build the UI ─────────────────────────────────────────────
step 6 "Building production UI..."
cd ui
npx vite build 2>&1 | tail -5
cd ..
ok "UI built → ui/dist/"
# ── Done! ─────────────────────────────────────────────────────────────
echo ""
echo -e "${GREEN}${BOLD}╔══════════════════════════════════════════╗${NC}"
echo -e "${GREEN}${BOLD}║ Installation complete! 🎉 ║${NC}"
echo -e "${GREEN}${BOLD}╚══════════════════════════════════════════╝${NC}"
echo ""
echo " Next steps:"
echo ""
echo " 1. Start the app:"
echo -e " ${CYAN}./launch.sh${NC}"
echo ""
echo " 2. Open in your browser:"
echo -e " ${CYAN}http://localhost:3001${NC}"
echo ""
echo " 3. Download AI models (~7 GB):"
echo " Click Models → Get More Models in the app"
echo ""