diff --git a/scripts/build.sh b/scripts/build.sh index c8692cf..0bafaab 100644 --- a/scripts/build.sh +++ b/scripts/build.sh @@ -14,10 +14,6 @@ set -e REPO_URL="${1:-}" REPO_DIR="${2:-$(pwd)/mapper}" -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" if [ -z "$REPO_URL" ]; then @@ -69,132 +65,22 @@ npm install --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) ─────────────────── +# ── 3. Commit and push frontend artifact back to repo ─────────────────────── 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 -#include -#include -#include -#include -#if __cplusplus < 201402L -namespace std { - template - std::unique_ptr make_unique(Args&&... args) { - return std::unique_ptr(new T(std::forward(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 is included where needed -for f in $(grep -l "unique_ptr" src/*.h 2>/dev/null || true); do - grep -q "" "$f" || sed -i '1i #include ' "$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" - -# ── 7. Commit and push artifacts back to repo ─────────────────────────────── -echo "" -echo "=== Pushing artifacts to remote ===" +echo "=== Pushing frontend/dist to remote ===" cd "$REPO_DIR" git config user.email "build-bot@mpvj" 2>/dev/null || true git config user.name "MPVJ Build Bot" 2>/dev/null || true -git add frontend/dist/ bin/ofxPiMapper -git commit -m "ci: add pre-built artifacts (frontend/dist + bin/ofxPiMapper)" || echo "(nothing new to commit)" +git add frontend/dist/ +git commit -m "ci: add pre-built frontend/dist" || echo "(nothing new to commit)" git push echo "" echo "============================================" echo " BUILD COMPLETE + PUSHED" echo "============================================" -echo " Frontend: $REPO_DIR/frontend/dist/" -echo " ofxPiMapper: $BIN_OUT/ofxPiMapper (aarch64)" +echo " Frontend: $REPO_DIR/frontend/dist/" echo "" -echo " Run setup.sh on the Pi to deploy." +echo " ofxPiMapper will be compiled natively on" +echo " the Pi when you run setup.sh." echo "============================================" diff --git a/scripts/setup.sh b/scripts/setup.sh index a7e6a7c..c6ca14e 100644 --- a/scripts/setup.sh +++ b/scripts/setup.sh @@ -125,29 +125,121 @@ echo "Deploying application from $REPO_URL ..." [ -d "$REAL_HOME/mpvj" ] && mv "$REAL_HOME/mpvj" "$REAL_HOME/mpvj.old.$(date +%s)" sudo -u "$REAL_USER" git clone "$REPO_URL" "$REAL_HOME/mpvj" -# Verify pre-built artifacts exist +# Verify pre-built frontend exists if [ ! -d "$REAL_HOME/mpvj/frontend/dist" ]; then echo "ERROR: frontend/dist/ not found in repo." echo "Run scripts/build.sh on your x86_64 machine first and commit the dist folder." exit 1 fi -if [ ! -f "$REAL_HOME/mpvj/bin/ofxPiMapper" ]; then - echo "ERROR: bin/ofxPiMapper not found in repo." - echo "Run scripts/build.sh on your x86_64 machine first and commit the binary." - exit 1 -fi # Install npm deps for backend only (no build needed) cd "$REAL_HOME/mpvj/backend" sudo -u "$REAL_USER" npm install --omit=optional --package-lock=false -# Install ofxPiMapper binary -install -m 755 "$REAL_HOME/mpvj/bin/ofxPiMapper" /usr/local/bin/ofxPiMapper - # Media directory mkdir -p "$REAL_HOME/media" chown -R "$REAL_USER:$REAL_USER" "$REAL_HOME/mpvj" "$REAL_HOME/media" +# ── 4.5 BUILD ofxPiMapper NATIVELY ─────────────────────────────────────────── +echo "Building ofxPiMapper natively (this takes a while)..." +OF_VERSION="0.12.1" +OF_FILE="of_v${OF_VERSION}_linuxaarch64_release.tar.gz" +OF_URL="https://github.com/openframeworks/openFrameworks/releases/download/${OF_VERSION}/${OF_FILE}" + +# Install build deps +DEBIAN_FRONTEND=noninteractive apt-get install -y \ + build-essential libzmq3-dev \ + 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 + +# Temporary swap so the Pi doesn't OOM during compilation +if [ ! -f /swapfile_mpvj ]; then + fallocate -l 2G /swapfile_mpvj || dd if=/dev/zero of=/swapfile_mpvj bs=1M count=2048 + chmod 600 /swapfile_mpvj + mkswap /swapfile_mpvj + swapon /swapfile_mpvj +fi + +cd "$REAL_HOME" +if [ ! -d "openFrameworks" ]; then + sudo -u "$REAL_USER" wget "$OF_URL" || sudo -u "$REAL_USER" curl -L -O "$OF_URL" + sudo -u "$REAL_USER" tar -xzf "$OF_FILE" + sudo -u "$REAL_USER" mv "of_v${OF_VERSION}_linux"*"_release" openFrameworks + sudo -u "$REAL_USER" rm -f "$OF_FILE" +fi + +ADDON_DIR="$REAL_HOME/openFrameworks/addons/ofxPiMapper" +rm -rf "$ADDON_DIR" +sudo -u "$REAL_USER" git clone --depth 1 https://github.com/kr15h/ofxPiMapper.git "$ADDON_DIR" +cd "$ADDON_DIR" + +# Patches +OSC_FILE=$(find src -name "OscControl.cpp" | head -n 1) +if [ -n "$OSC_FILE" ]; then + 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 + +cat <<'EOF_COMPAT' > src/cpp11_compat.h +#ifndef OFXPIMAPPER_CPP11_COMPAT_H +#define OFXPIMAPPER_CPP11_COMPAT_H +#include +#include +#include +#include +#include +#if __cplusplus < 201402L +namespace std { + template + std::unique_ptr make_unique(Args&&... args) { + return std::unique_ptr(new T(std::forward(args)...)); + } +} +#endif +using std::unique_ptr; +using std::make_unique; +using std::vector; +using std::string; +#endif +EOF_COMPAT + +sed -i '1i #include "cpp11_compat.h"' src/ofxPiMapper.h +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' {} + +for f in $(grep -l "unique_ptr" src/*.h 2>/dev/null || true); do + grep -q "" "$f" || sed -i '1i #include ' "$f" +done + +cd "$ADDON_DIR/example_basic" +GLOBAL_FLAGS="-Wno-error -Wno-reorder -Wno-sign-compare -Wno-delete-non-virtual-dtor -std=c++11 -O0 -fno-tree-vrp" +sudo -u "$REAL_USER" make clean 2>/dev/null || true +sudo -u "$REAL_USER" make -j1 \ + PLATFORM_CFLAGS="$GLOBAL_FLAGS -I$ADDON_DIR/src" \ + USER_CFLAGS="$GLOBAL_FLAGS" \ + USER_CPPFLAGS="-std=c++11" \ + OF_PROJECT_OPTIMIZATION_FLAGS="-O0" + +install -m 755 bin/example_basic /usr/local/bin/ofxPiMapper + +# Remove swap +swapoff /swapfile_mpvj 2>/dev/null || true +rm -f /swapfile_mpvj + # ── 5. SYSTEMD SERVICE ─────────────────────────────────────────────────────── cat < /etc/systemd/system/mpvj-backend.service [Unit]