Build natively on the development Orin
Two units with different jobs: one builds and runs CI, the other is the deployment target. Building on the target architecture makes the glibc constraint structural rather than configured. The remaining risk is version parity between the two units, not architecture. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013kj58Jugkic783b8ZrtTVZ
This commit is contained in:
@@ -316,6 +316,7 @@ rewriting the document.
|
|||||||
| 5 | Rust for on-Orin services, Python for off-car tooling, Dart for the display client | Accepted | 2026-09-04 |
|
| 5 | Rust for on-Orin services, Python for off-car tooling, Dart for the display client | Accepted | 2026-09-04 |
|
||||||
| 21 | Two clocks per envelope; `monotonic` orders, `timestamp` references | Accepted | 2026-09-05 |
|
| 21 | Two clocks per envelope; `monotonic` orders, `timestamp` references | Accepted | 2026-09-05 |
|
||||||
| 22 | `signals.json` is the single source for signal name and unit; both are derived, never authored twice | Accepted | 2026-09-05 |
|
| 22 | `signals.json` is the single source for signal name and unit; both are derived, never authored twice | Accepted | 2026-09-05 |
|
||||||
|
| 23 | Services build natively on the development Orin; both units stay on the same L4T release | Accepted | 2026-09-05 |
|
||||||
| 6 | Local logging first; off-board LTE telemetry deferred | Accepted | 2026-08-14 |
|
| 6 | Local logging first; off-board LTE telemetry deferred | Accepted | 2026-08-14 |
|
||||||
| 7 | Camera/AI inference is a later, separate task | Accepted | 2026-08-14 |
|
| 7 | Camera/AI inference is a later, separate task | Accepted | 2026-08-14 |
|
||||||
| 8 | Self-hosted offline navigation (MapLibre GL + Valhalla + PMTiles) over a cloud maps SDK | Accepted | 2026-09-03 |
|
| 8 | Self-hosted offline navigation (MapLibre GL + Valhalla + PMTiles) over a cloud maps SDK | Accepted | 2026-09-03 |
|
||||||
|
|||||||
+31
-20
@@ -145,35 +145,46 @@ libraries.
|
|||||||
|
|
||||||
#### Building for the Orin
|
#### Building for the Orin
|
||||||
|
|
||||||
Services cross-compile from the workstation:
|
Services build **natively on the development Orin**. The sysroot is then the
|
||||||
|
target's own, so a binary cannot reference a symbol the car unit lacks — the
|
||||||
|
guarantee is structural rather than configured.
|
||||||
|
|
||||||
```bash
|
Two Orin Nanos, and they have different jobs:
|
||||||
cargo build --release --target aarch64-unknown-linux-gnu
|
|
||||||
```
|
|
||||||
|
|
||||||
Each service repo's `.cargo/config.toml` points at `aarch64-linux-gnu-gcc`, from
|
| Unit | Role |
|
||||||
the `gcc-aarch64-linux-gnu` package.
|
|---|---|
|
||||||
|
| Development Orin | Build, CI runner, bench testing. Always powered, on the LAN |
|
||||||
|
| Car Orin | Deployment target only |
|
||||||
|
|
||||||
⚠ **The linker binds each symbol to the newest version present in the sysroot**,
|
⚠ **The guarantee is version parity, not architecture.** An aarch64 binary built
|
||||||
so the cross sysroot (glibc 2.43) sets the floor, not the toolchain. Rust std
|
on a newer userland still fails to load on an older one. A JetPack or Ubuntu
|
||||||
itself targets 2.17 — making the toolchain older changes nothing.
|
upgrade applied to one unit and not the other reintroduces the problem, silently
|
||||||
|
and only at runtime. **Upgrade both, or neither.**
|
||||||
|
|
||||||
Currently the highest referenced version is **2.34**, below the Orin's 2.35. Every
|
The check that catches drift between them:
|
||||||
symbol above 2.30 comes from one event: glibc 2.34 merged `libpthread` and
|
|
||||||
`libdl` into `libc` and re-versioned the moved symbols (`__libc_start_main`, the
|
|
||||||
`pthread_*` family). Re-versioning is rare, so this ceiling is stable — exceeding
|
|
||||||
it would take a **dependency** calling a glibc function introduced after 2.35.
|
|
||||||
|
|
||||||
That failure lands at **runtime**, on the car, as a loader error; the build
|
|
||||||
succeeds. Check before deploying:
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
objdump -T <binary> | grep -o 'GLIBC_[0-9.]*' | sort -Vu | tail -1
|
objdump -T <binary> | grep -o 'GLIBC_[0-9.]*' | sort -Vu | tail -1
|
||||||
```
|
```
|
||||||
|
|
||||||
At or below `GLIBC_2.35` it will run. Above it, the control is the **sysroot**:
|
It detects, it does not fix — its job is to fail the build rather than let a bad
|
||||||
build in a container supplying an older one — `cross` does this with the host's
|
binary reach the car, and to name the symbol that caused it.
|
||||||
own toolchain — or build on the Orin.
|
|
||||||
|
##### Cross-compiling from the workstation
|
||||||
|
|
||||||
|
Available as a fallback. Each service repo's `.cargo/config.toml` points at
|
||||||
|
`aarch64-linux-gnu-gcc`, from the `gcc-aarch64-linux-gnu` package:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cargo build --release --target aarch64-unknown-linux-gnu
|
||||||
|
```
|
||||||
|
|
||||||
|
⚠ **The linker binds each symbol to the newest version present in the sysroot**,
|
||||||
|
so the workstation's glibc 2.43 sets the floor — not the toolchain, which targets
|
||||||
|
2.17. Currently the highest referenced version is 2.34, below the Orin's 2.35,
|
||||||
|
because everything above 2.30 comes from one event: glibc 2.34 merged
|
||||||
|
`libpthread` and `libdl` into `libc` and re-versioned the moved symbols. Stable,
|
||||||
|
but not guaranteed the way a native build is.
|
||||||
|
|
||||||
### Writing style
|
### Writing style
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user