feat: implement setup and build scripts for MPVJ deployment and cross-compilation
This commit is contained in:
185
scripts/build.sh
Normal file
185
scripts/build.sh
Normal file
@ -0,0 +1,185 @@
|
||||
#!/bin/bash
|
||||
|
||||
# MPVJ Build Script
|
||||
# Runs on x86_64 (e.g., Docker) to cross-compile artifacts for aarch64 (RPi 3B).
|
||||
# Outputs:
|
||||
# frontend/dist/ — pre-built Vite bundle
|
||||
# bin/ofxPiMapper — aarch64 binary
|
||||
#
|
||||
# Usage: bash scripts/build.sh [REPO_DIR]
|
||||
# REPO_DIR defaults to the directory containing this script's parent.
|
||||
|
||||
set -e
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
REPO_DIR="${1:-$(dirname "$SCRIPT_DIR")}"
|
||||
OF_VERSION="0.12.1"
|
||||
OF_DIR="$REPO_DIR/.build/openFrameworks"
|
||||
OF_FILE="of_v${OF_VERSION}_linuxaarch64_release.tar.gz"
|
||||
OF_URL="https://github.com/openframeworks/openFrameworks/releases/download/${OF_VERSION}/${OF_FILE}"
|
||||
BIN_OUT="$REPO_DIR/bin"
|
||||
|
||||
# ── Validate repo ────────────────────────────────────────────────────────────
|
||||
if [ ! -d "$REPO_DIR/frontend" ] || [ ! -d "$REPO_DIR/backend" ]; then
|
||||
echo "ERROR: $REPO_DIR does not look like the mapper repo (missing frontend/ or backend/)."
|
||||
exit 1
|
||||
fi
|
||||
echo "Building from: $REPO_DIR"
|
||||
|
||||
# ── 1. Install build dependencies ───────────────────────────────────────────
|
||||
echo "Installing build dependencies..."
|
||||
if command -v apt-get > /dev/null 2>&1; then
|
||||
apt-get update -y
|
||||
DEBIAN_FRONTEND=noninteractive apt-get install -y \
|
||||
git curl wget unzip build-essential \
|
||||
gcc-aarch64-linux-gnu g++-aarch64-linux-gnu \
|
||||
binutils-aarch64-linux-gnu \
|
||||
libmpg123-dev libsndfile1-dev libopenal-dev libassimp-dev \
|
||||
libglew-dev libglfw3-dev liburiparser-dev \
|
||||
libcurl4-openssl-dev libpugixml-dev libasound2-dev \
|
||||
libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev \
|
||||
gstreamer1.0-plugins-good gstreamer1.0-plugins-bad \
|
||||
gstreamer1.0-plugins-ugly gstreamer1.0-libav \
|
||||
libgtk-3-dev libboost-filesystem-dev \
|
||||
libfontconfig1-dev libfreetype-dev libx11-dev \
|
||||
libxrandr-dev libxinerama-dev libxcursor-dev libxi-dev \
|
||||
libpulse-dev libudev-dev libfreeimage-dev librtaudio-dev \
|
||||
freeglut3-dev libxxf86vm-dev
|
||||
fi
|
||||
|
||||
# Install Node.js if missing
|
||||
if ! command -v node > /dev/null 2>&1; then
|
||||
echo "Installing Node.js 20..."
|
||||
curl -fsSL https://deb.nodesource.com/setup_20.x | bash -
|
||||
apt-get install -y nodejs
|
||||
fi
|
||||
|
||||
# ── 2. Build frontend ────────────────────────────────────────────────────────
|
||||
echo ""
|
||||
echo "=== Building frontend ==="
|
||||
cd "$REPO_DIR/frontend"
|
||||
rm -rf node_modules package-lock.json
|
||||
npm install --omit=optional --package-lock=false
|
||||
NODE_OPTIONS="--max-old-space-size=512" npm run build
|
||||
echo "Frontend built → $REPO_DIR/frontend/dist/"
|
||||
|
||||
# ── 3. Download OpenFrameworks (aarch64 pre-built release) ───────────────────
|
||||
echo ""
|
||||
echo "=== Downloading OpenFrameworks ${OF_VERSION} (aarch64) ==="
|
||||
mkdir -p "$REPO_DIR/.build"
|
||||
if [ ! -d "$OF_DIR" ]; then
|
||||
cd "$REPO_DIR/.build"
|
||||
if [ ! -f "$OF_FILE" ]; then
|
||||
wget "$OF_URL" || curl -L -O "$OF_URL"
|
||||
fi
|
||||
tar -xzf "$OF_FILE"
|
||||
mv of_v${OF_VERSION}_linux*_release openFrameworks
|
||||
rm -f "$OF_FILE"
|
||||
echo "OpenFrameworks extracted to $OF_DIR"
|
||||
else
|
||||
echo "OpenFrameworks already present, skipping download."
|
||||
fi
|
||||
|
||||
# ── 4. Clone & patch ofxPiMapper ────────────────────────────────────────────
|
||||
echo ""
|
||||
echo "=== Cloning ofxPiMapper ==="
|
||||
ADDON_DIR="$OF_DIR/addons/ofxPiMapper"
|
||||
rm -rf "$ADDON_DIR"
|
||||
git clone --depth 1 https://github.com/kr15h/ofxPiMapper.git "$ADDON_DIR"
|
||||
cd "$ADDON_DIR"
|
||||
|
||||
echo "Applying compatibility patches..."
|
||||
|
||||
# 4a. OscControl.cpp highlight patch
|
||||
OSC_FILE=$(find src -name "OscControl.cpp" | head -n 1)
|
||||
if [ -n "$OSC_FILE" ]; then
|
||||
echo "Patching $OSC_FILE..."
|
||||
sed -i '/if (m.getAddress() == "\/ofxPiMapper\/surface\/select"){/r /dev/stdin' "$OSC_FILE" <<'EOF_PATCH'
|
||||
if (m.getAddress() == "/ofxPiMapper/surface/highlight"){
|
||||
int surfaceIndex = m.getArgAsInt32(0);
|
||||
mapper->getSurfaceManager()->selectSurface(surfaceIndex);
|
||||
return;
|
||||
}
|
||||
EOF_PATCH
|
||||
fi
|
||||
|
||||
# 4b. C++11 compatibility header
|
||||
cat <<'EOF_COMPAT' > src/cpp11_compat.h
|
||||
#ifndef OFXPIMAPPER_CPP11_COMPAT_H
|
||||
#define OFXPIMAPPER_CPP11_COMPAT_H
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <algorithm>
|
||||
#if __cplusplus < 201402L
|
||||
namespace std {
|
||||
template<typename T, typename... Args>
|
||||
std::unique_ptr<T> make_unique(Args&&... args) {
|
||||
return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
using std::unique_ptr;
|
||||
using std::make_unique;
|
||||
using std::vector;
|
||||
using std::string;
|
||||
#endif
|
||||
EOF_COMPAT
|
||||
|
||||
# 4c. Inject compat header into the main addon header
|
||||
sed -i '1i #include "cpp11_compat.h"' src/ofxPiMapper.h
|
||||
|
||||
# 4d. Qualify unique_ptr / make_unique calls
|
||||
find src -type f \( -name "*.h" -o -name "*.cpp" \) \
|
||||
-exec sed -i 's/\([^:a-zA-Z0-9]\)unique_ptr\b/\1std::unique_ptr/g' {} + \
|
||||
-exec sed -i 's/\([^:a-zA-Z0-9]\)make_unique\b/\1std::make_unique/g' {} +
|
||||
|
||||
# 4e. Ensure <memory> is included where needed
|
||||
for f in $(grep -l "unique_ptr" src/*.h 2>/dev/null || true); do
|
||||
grep -q "<memory>" "$f" || sed -i '1i #include <memory>' "$f"
|
||||
done
|
||||
|
||||
# ── 5. Cross-compile ofxPiMapper for aarch64 ────────────────────────────────
|
||||
echo ""
|
||||
echo "=== Compiling ofxPiMapper (aarch64 target) ==="
|
||||
cd "$ADDON_DIR/example_basic"
|
||||
|
||||
CROSS_CC="aarch64-linux-gnu-gcc"
|
||||
CROSS_CXX="aarch64-linux-gnu-g++"
|
||||
CROSS_AR="aarch64-linux-gnu-ar"
|
||||
CROSS_LD="aarch64-linux-gnu-ld"
|
||||
|
||||
if ! command -v "$CROSS_CXX" > /dev/null 2>&1; then
|
||||
echo "ERROR: Cross-compiler $CROSS_CXX not found. Install gcc-aarch64-linux-gnu."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
GLOBAL_FLAGS="-Wno-error -Wno-reorder -Wno-sign-compare -Wno-delete-non-virtual-dtor -std=c++11 -O0 -fno-tree-vrp"
|
||||
|
||||
make clean 2>/dev/null || true
|
||||
env \
|
||||
CC="$CROSS_CC" CXX="$CROSS_CXX" AR="$CROSS_AR" LD="$CROSS_LD" \
|
||||
make -j1 \
|
||||
PLATFORM_CFLAGS="$GLOBAL_FLAGS -I$ADDON_DIR/src" \
|
||||
USER_CFLAGS="$GLOBAL_FLAGS" \
|
||||
USER_CPPFLAGS="-std=c++11" \
|
||||
OF_PROJECT_OPTIMIZATION_FLAGS="-O0"
|
||||
|
||||
# ── 6. Copy artifact to repo/bin/ ──────────────────────────────────────────
|
||||
echo ""
|
||||
echo "=== Collecting artifacts ==="
|
||||
mkdir -p "$BIN_OUT"
|
||||
cp bin/example_basic "$BIN_OUT/ofxPiMapper"
|
||||
chmod +x "$BIN_OUT/ofxPiMapper"
|
||||
|
||||
echo ""
|
||||
echo "============================================"
|
||||
echo " BUILD COMPLETE"
|
||||
echo "============================================"
|
||||
echo " Frontend: $REPO_DIR/frontend/dist/"
|
||||
echo " ofxPiMapper: $BIN_OUT/ofxPiMapper (aarch64)"
|
||||
echo ""
|
||||
echo " Commit and push these artifacts, then run"
|
||||
echo " setup.sh on the Pi to deploy."
|
||||
echo "============================================"
|
||||
Reference in New Issue
Block a user