Document gplan.so build-from-source procedure

Build in armv7 QEMU Docker, compile with Python 3.9 SCons,
relink final .so against Python 3.5m from the Pi.
This commit is contained in:
2026-04-30 13:52:58 +02:00
parent 1625b768d8
commit 7306464440

View File

@@ -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 <Python.h>` 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