diff --git a/.pi/BUILD.md b/.pi/BUILD.md index 1b16032..80b0b80 100644 --- a/.pi/BUILD.md +++ b/.pi/BUILD.md @@ -46,19 +46,97 @@ Produces: `dist/bbctrl-1.6.7.tar.bz2` (~3MB) `gplan.so` is the CAMotics G-code planner compiled as a Python C extension. It **must be a 32-bit ARM binary** linked against **Python 3.5** to run on the Pi. -**Do NOT build gplan.so in the devcontainer.** The devcontainer runs arm64/Debian Bullseye with Python 3.9. The resulting `.so` will be the wrong architecture and wrong Python ABI. Cross-compiling also fails because SCons ignores CC/CXX overrides. +**Do NOT build gplan.so in the devcontainer.** The devcontainer runs arm64/Debian Bullseye with Python 3.9. The resulting `.so` will be the wrong architecture and wrong Python ABI. Cross-compiling with `CXX=arm-linux-gnueabihf-g++` also fails because SCons ignores CC/CXX env vars. -**Where to get it:** -1. From the official release: `https://github.com/OneFinityCNC/onefinity-firmware/releases/download/v1.6.6/onefinity-1.6.6.tar.bz2` — extract `src/py/camotics/gplan.so` -2. From a working Pi: `scp bbmc@10.1.10.55:/usr/local/lib/python3.5/dist-packages/bbctrl-*.egg/camotics/gplan.so src/py/camotics/` -3. From a backup image - -The correct file is: +The correct file must be: ``` -ELF 32-bit LSB shared object, ARM, EABI5 version 1 (GNU/Linux), dynamically linked +ELF 32-bit LSB shared object, ARM, EABI5 (linked against libpython3.5m.so.1.0) +``` +If you see `ELF 64-bit LSB shared object, ARM aarch64` or `libpython3.9` — wrong. + +**Option A: Build from source (recommended)** + +Uses Docker's armv7 QEMU emulation on Apple Silicon. Requires a one-time +copy of Python 3.5 headers from the Pi (~1.7MB): + +```bash +# One-time: grab Python 3.5 headers + lib from Pi +ssh bbmc@10.1.10.55 'tar czf - /usr/include/python3.5m \ + /usr/lib/arm-linux-gnueabihf/libpython3.5m.so*' > /tmp/pi-python35.tar.gz ``` -If you see `ELF 64-bit LSB shared object, ARM aarch64` — that's the wrong one. +Then build (takes ~30min under QEMU): + +```bash +docker run --rm --platform linux/arm/v7 \ + -v "$(pwd):/workspace" -w /workspace \ + -v /tmp/pi-python35.tar.gz:/tmp/pi-python35.tar.gz \ + debian:bullseye bash -c ' + set -e + tar xzf /tmp/pi-python35.tar.gz -C / + apt-get update -qq && apt-get install -y -qq build-essential scons git \ + ca-certificates python3-dev libssl-dev libexpat1-dev libbz2-dev \ + liblz4-dev zlib1g-dev perl file + ln -sf /usr/lib/arm-linux-gnueabihf/libpython3.5m.so.1.0 \ + /usr/lib/arm-linux-gnueabihf/libpython3.5m.so + + # Clone cbang + camotics at pinned commits + mkdir -p /tmp/cbang && cd /tmp/cbang && git init -q + git remote add origin https://github.com/CauldronDevelopmentLLC/cbang + git fetch --depth 1 -q origin 18f1e963107ef26abe750c023355a5c40dd07853 + git reset --hard FETCH_HEAD -q + + mkdir -p /tmp/camotics && cd /tmp/camotics && git init -q + git remote add origin https://github.com/CauldronDevelopmentLLC/camotics + git fetch --depth 1 -q origin ec876c80d20fc19837133087cef0c447df5a939d + git reset --hard FETCH_HEAD -q + + # Build cbang + cd /tmp/cbang && scons -j2 disable_local="re2 libevent" + export CBANG_HOME="/tmp/cbang" + + # Patch camotics (clamp div-by-zero in planner) + P="/tmp/camotics/src/gcode/plan" + mkdir -p /tmp/camotics/build && touch /tmp/camotics/build/version.txt + for F in LineCommand.cpp LinePlanner.cpp; do + for V in maxVel maxJerk maxAccel; do + perl -i -0pe "s/(fabs\\((config\\.$V\\[axis\\]) \\/ unit\\[axis\\]\\));/std::min(\\2, \\1);/gm" $P/$F + done + done + + # Compile with Python 3.9 (SCons needs python3-dev to find headers) + cd /tmp/camotics && scons -j2 gplan.so with_gui=0 with_tpl=0 + + # Relink against Python 3.5m (the Pi target) + g++ -o /workspace/src/py/camotics/gplan.so \ + -Wl,--as-needed -Wl,-s -Wl,-x -Wl,--gc-sections -pthread -shared \ + build/gplan.os -L/tmp/cbang/lib \ + build/libCAMoticsPy.a build/libCAMotics.a build/libDXF.a \ + build/libSTL.a build/libGCode.a \ + -lstdc++ -lutil -lm -ldl -lz -lcbang -lcbang-boost \ + -lssl -lcrypto -llz4 -lexpat -lbz2 -lcrypt -lpthread \ + -lpython3.5m build/dxflib/libdxflib.a + ' +``` + +Why the relink step: SCons compiles `.o` files that are Python-version-agnostic +(they only use `#include ` which is ABI-compatible between 3.5-3.9 +for the subset camotics uses). The only version-specific part is the final +`-lpython3.X` link. So we let SCons build with 3.9 (since it ignores overrides) +then relink the same objects against 3.5m. + +**Option B: From official release** + +```bash +curl -L https://github.com/OneFinityCNC/onefinity-firmware/releases/download/v1.6.6/onefinity-1.6.6.tar.bz2 \ + | tar xjf - --include='*/gplan.so' --strip-components=3 -C src/py/camotics/ +``` + +**Option C: From a working Pi** + +```bash +scp bbmc@10.1.10.55:/usr/local/lib/python3.5/dist-packages/bbctrl-*.egg/camotics/gplan.so src/py/camotics/ +``` ### bbserial.ko — kernel module