[Rpi5 setup] Make Raspberry Pi cross-compiled binaries run out of the box on supported OS versions
Les mainteneurs répondent en général sous 1 jour
Personne n'a encore pris cette issue.
Évaluation
- Difficulté
- 5/5
- Temps estimé
- Plus d'une semaine
- Accessibilité débutants
- 35/100
- Type d'issue
- Fonctionnalité
- Clarté
- Plutôt claire
- Activité
- Active
- Domaine
- build-system, embedded-iot
Piste de recherche
Start with examples/raspberry_pi/setup.sh and the generated CMake toolchain file; the issue reports a manual build using a Bookworm sysroot and a glibc_compat.c shim. First resolve the maintainers’ open questions about the minimum supported OS, target devices, and sysroot source before planning the implementation. Done means the script builds binaries that run on the agreed supported Raspberry Pi OS versions without library version errors.
Rédigé par le modèle d'indexation à partir du texte de l'issue.
Description
Summary
This proposal is based on a review of the discussion in #15014 and the related commit (
[TODO: commit hash]), and follows up on the GLIBC handling that was left out there for simplicity.
- Current state:
examples/raspberry_pi/setup.shdownloads arm-gnu-toolchain-14.3.rel1 and builds against the glibc 2.40 bundled with that toolchain and GCC 14's libstdc++, both dynamically linked. - Problem: On OS versions that ship older libraries than the toolchain (e.g. Bookworm), the binaries fail at load time due to version mismatches not only in
GLIBC_*, but also inGLIBCXX_*andCXXABI_*. In other words, this is not just a glibc issue — the C++ runtime (libstdc++) is mismatched as well. - Proposal: Match the target OS at build time. Link glibc against a sysroot of the lowest supported OS version, and link libstdc++ statically.
- Goal: Binaries built by the script run on the supported targets (64-bit Raspberry Pi OS, Pi 4/5) without any extra steps, so that the GLIBC troubleshooting section in the tutorial is no longer needed.
This issue is meant to gather feedback on the approach before implementing it. The proposed approach has been verified with a manual build (see section 6).
1. Background
- An early version of PR #15014 bundled the toolchain's glibc into
bundled-libsand installed it on the Pi viainstall_libs.sh, but this was removed to keep the script simple. - Instead, the Troubleshooting section of the tutorial describes two workarounds:
- Solution A (Recommended): Add the Debian sid repository on the Pi and upgrade
libc6andlibstdc++6 - Solution B (Advanced): Copy the Pi's root filesystem via rsync, use it as the sysroot, and rebuild
- Solution A (Recommended): Add the Debian sid repository on the Pi and upgrade
- Both require either changing the libraries on the Pi or having the user modify the build environment manually. This issue proposes the opposite direction: make the build match the target OS.
- Per the tutorial, the supported targets are Raspberry Pi 4/5 running 64-bit Raspberry Pi OS (Bullseye or newer). This proposal keeps that scope.
2. Reproduction
- Environment: Raspberry Pi 5, Raspberry Pi OS Bookworm (Debian 12),
ldd (Debian GLIBC 2.36-9+rpt2+deb12u14) 2.36 - Build:
examples/raspberry_pi/setup.sh pi5, toolchain arm-gnu-toolchain-14.3.rel1 - Runtime error:
./llama_main: /lib/aarch64-linux-gnu/libm.so.6: version `GLIBC_2.38' not found (required by ./llama_main)
./llama_main: /lib/aarch64-linux-gnu/libc.so.6: version `GLIBC_2.38' not found (required by ./llama_main)
./llama_main: /lib/aarch64-linux-gnu/libstdc++.so.6: version `GLIBCXX_3.4.31' not found (required by ./llama_main)
./llama_main: /lib/aarch64-linux-gnu/libstdc++.so.6: version `CXXABI_1.3.15' not found (required by ./llama_main)
./llama_main: /lib/aarch64-linux-gnu/libc.so.6: version `GLIBC_2.38' not found (required by /home/<user>/executorch-deployment/libllama_runner.so)
./llama_main: /lib/aarch64-linux-gnu/libstdc++.so.6: version `GLIBCXX_3.4.32' not found (required by /home/<user>/executorch-deployment/libllama_runner.so)
./llama_main: /lib/aarch64-linux-gnu/libstdc++.so.6: version `GLIBCXX_3.4.31' not found (required by /home/<user>/executorch-deployment/libllama_runner.so)
./llama_main: /lib/aarch64-linux-gnu/libstdc++.so.6: version `CXXABI_1.3.15' not found (required by /home/<user>/executorch-deployment/libllama_runner.so)
- Required versions vs. versions provided by the OS:
| GLIBC | GLIBCXX | CXXABI | |
|---|---|---|---|
llama_main requires |
2.38 |
3.4.31 |
1.3.15 |
libllama_runner.so requires |
2.38 |
3.4.32 |
1.3.15 |
| Bookworm provides | 2.36 ❌ |
3.4.30 ❌ |
1.3.13 ❌ |
| Trixie provides | 2.41 ✅ |
3.4.33 ✅ |
1.3.15 ✅ |
OS-provided versions were measured from the arm64 packages in the Debian repositories.
Bookworm: glibc 2.36,libstdc++6 12.2.0-14+deb12u1(GCC 12) / Trixie: glibc 2.41,libstdc++6 14.2.0-19(GCC 14)
Both binaries exceed what Bookworm provides not only for glibc but also for libstdc++ (GLIBCXX_*, CXXABI_*), so all three checks fail. The required versions are consistent with the toolchain: GLIBCXX_3.4.31/32 come from GCC 13+, and CXXABI_1.3.15 was introduced in GCC 14.
According to the table, only Trixie or newer satisfies the current binaries' requirements, which does not match the support range stated in the tutorial (Bullseye or newer). Also, while the tutorial describes this as a "GLIBC mismatch", the actual problem is that both glibc and libstdc++ are tied to the host toolchain's versions.
3. Why this is a problem
- Users only find the fix after hitting the failure. The build succeeds and the failure only shows up when running on the Pi; the cause is hard to identify until the user finds the troubleshooting section.
- The recommended fix (Solution A) can destabilize the system. It mixes glibc/libstdc++ from sid (unstable) into a stable release, changing system-wide libraries for the sake of a single application, which can also affect future package upgrades.
- The safe fix (Solution B) has a high barrier to entry. It requires rsyncing the entire Pi filesystem and editing the CMake toolchain file by hand, which is why it is labeled Advanced.
- Ultimately, users carry a burden the build should handle. If the supported OS versions are defined, matching them at build time is the natural place to solve this.
4. Proposal
The two libraries are fundamentally different, so they are handled differently.
glibc → dynamically link against a sysroot of the lowest supported version
- glibc should not be linked statically: features such as NSS,
dlopen, and locales load other system shared libraries at runtime. So we keep dynamic linking and lower the version we link against. - glibc is backward compatible through symbol versioning, so a binary linked against the lowest supported version runs on all newer versions (the same approach as Python's manylinux).
- The default is a single build for the lowest supported version, with an optional CLI flag to specify an OS release (
bookworm/trixie, etc.). - The sysroot is assembled from that release's Debian repository packages (
libc6,libc6-dev, etc.).
libstdc++ / libgcc → static linking
- Both
llama_mainandlibllama_runner.sodynamically require libstdc++. Since libstdc++ is tied to GCC, its version cannot be changed through the sysroot: the headers and template code already reference GCC 14 symbols at compile time. - Linking with
-static-libstdc++ -static-libgccembeds it into the binaries, making them independent of the target OS's libstdc++ version. - The static
libstdc++.ashipped with the toolchain is itself built against glibc 2.40 and references some symbols that do not exist in glibc 2.36. To resolve these at link time, a small compatibility shim (glibc_compat.c) was added.[TODO: list of symbols it provides] - However, statically linking into both
llama_mainandlibllama_runner.soresults in two copies of the C++ runtime in one process, which could potentially cause issues with exceptions or shared runtime state crossing the boundary. To avoid this, buildinglibllama_runner.soas a static library and linking it intollama_maincould be considered (question 5). Alternatively, the libstdc++ symbols embedded in the.socould be hidden with-Wl,--exclude-libs,ALL.
5. Alternatives considered
- Use a GCC version matching the target OS: The cleanest option, and it would not need the compatibility shim, but it requires maintaining a separate toolchain per OS release.
- Improve the documentation only: No implementation cost, but the burden on users remains.
The proposed approach keeps the current script structure mostly intact and adds only a sysroot as a new dependency, so I believe it does not conflict much with the simplification direction of PR #15014.
6. Verification (manual build)
I verified with a manual build that the proposed approach actually fixes the problem. Everything other than how the binaries are linked (ExecuTorch commit, toolchain, model, device, run command) was kept the same. No ExecuTorch source files were modified; only the build configuration (setup.sh and the generated CMake toolchain file) changed, plus the glibc_compat.c shim described above.
- Before: built with
setup.sh pi5as-is (toolchain-bundled glibc 2.40 sysroot) → fails with the errors in section 2 (exit=1) - After: manually built against a Bookworm glibc 2.36 sysroot with libstdc++/libgcc statically linked → runs successfully (
exit=0)
| GLIBC | GLIBCXX | CXXABI | |
|---|---|---|---|
llama_main requires (after) |
2.35 ✅ |
none (static) | none (static) |
libllama_runner.so requires (after) |
2.36 ✅ |
none (static) | none (static) |
| Bookworm provides | 2.36 |
3.4.30 |
1.3.13 |
- Required versions were checked with
objdump -T(dynamic symbol versions).libstdc++.so.6no longer appears in theNEEDEDentries of either binary. - Note that the resulting binaries require up to GLIBC 2.36, so they still would not run on Bullseye (glibc 2.31). Supporting Bullseye would require a Bullseye sysroot instead.
- Binary size:
llama_main6.9M → 7.2M (due to the embedded libstdc++) - Performance reference (Pi 5, Llama 3.2 1B): prefill 88.6 tok/s, decode 16.6 tok/s
Run log after the fix (Bookworm, Pi 5)
$ cd ~/executorch-deployment
$ source setup_env.sh
$ ./llama_main --model_path ./llama3_2.pte --tokenizer_path ./tokenizer.model --seq_len 128 --prompt "What is the meaning of life?"
I tokenizers:regex.cpp:40] Registering override fallback regex
I tokenizers:regex.cpp:40] Registering override fallback regex
E tokenizers:hf_tokenizer.cpp:167] Error parsing json file: [json.exception.parse_error.101] parse error at line 1, column 1: syntax error while parsing value - invalid literal; last read: 'I'
What is the meaning of life? What is the purpose of life? What is the nature of reality? What is the meaning of existence?"
1.There is no straightforward answer to these questions, as they are complex and multifaceted. But here are a few philosophical perspectives that attempt to provide some insight:
"The meaning of life is to find your gift. The purpose of life is to find your gift. The nature of reality is to find your gift."
"A person who has never made a mistake must think he has never had one. If he has never had one, there is no mistake."
"Moby-Dick: The Bottom Line
PyTorchObserver {"prefill_token_per_sec":88.6076,"decode_token_per_sec":16.5609,"prompt_tokens":7,"generated_tokens":120,"model_load_start_ms":1793185221262,"model_load_end_ms":1793185223406,"inference_start_ms":1793185223406,"inference_end_ms":1793185230731,"model_execution_start_ms":1793185230670,"model_execution_end_ms":1793185230730,"prompt_eval_end_ms":1793185223485,"first_token_ms":1793185223485,"aggregate_sampling_time_ms":180,"aggregate_model_execution_time_ms":7142,"SCALING_FACTOR_UNITS_PER_SECOND":1000}
exit=0
The
hf_tokenizer.cppJSON parse error is a known warning documented in Issue 3 of the tutorial's Troubleshooting section and does not affect inference.
Scope of verification: This was verified on Pi 5 + Bookworm. Newer releases such as Trixie are expected to work given glibc's backward compatibility; I plan to verify them, along with Pi 4 + Bookworm, in the implementation PR once the direction is agreed on.
7. Questions for maintainers
- Does it fit the project's direction to solve this in the build script rather than in the documentation?
- Should the lowest supported OS be Bullseye or Bookworm? (The current verification uses a Bookworm sysroot; supporting Bullseye would require a Bullseye sysroot.)
- Will the target devices remain limited to Pi 4/5 going forward?
- Is it acceptable to depend on an external package archive (the Debian repositories) to assemble the sysroot?
- Would it be acceptable to build
libllama_runner.soas a static library and link it intollama_main, or does it have other consumers? - Between a compatibility shim + static libstdc++ (this proposal) and a GCC version matching the target OS (alternative), which would you prefer from a maintenance perspective?
Once the direction is settled, I'm happy to open an implementation PR.
- Langage dominant
- Python
- Étoiles
- 5.1k
- Forks
- 1.2k
- Merge moyen
- 2 j 10 min
- PR mergées (30 j)
- 671
Préparer son environnement
- Aucun Dockerfile ni fichier Docker Compose
- Propose un modèle de pull request
- Lire le guide de contribution
Par où commencer
- Lisez l'issue en entier, puis le guide de contribution du projet.
- Signalez en commentaire que vous la prenez — cela évite que deux personnes fassent le même travail.
- Forkez le dépôt et travaillez sur une branche.
- Ouvrez une pull request qui référence le numéro de l'issue.
Autres issues de pytorch/executorch
-
enhancement triaged
Difficulté 2/5 Une demi-journée Accessibilité débutants 68/100
pytorch/executorch#21640 ·
Les mainteneurs répondent en général sous 1 jour
-
Difficulté 4/5 3-5 jours Accessibilité débutants 42/100
pytorch/executorch#24196 ·
Les mainteneurs répondent en général sous 1 jour
-
Portable div(rounding_mode="trunc") and fmod round int64 values through doublePeut-être pris @JakeStevens l’a pris il y a 1 jour. Ouvertebug module: kernels triaged
pytorch/executorch#24169 · 2 personnes assignées ·
Les mainteneurs répondent en général sous 1 jour
-
Float scalars in float64 programs are rounded to float32 by ScalarToTensorPassPeut-être pris @JacobSzwejbka l’a pris il y a 1 jour. Ouvertebug module: exir triaged
pytorch/executorch#24167 · 2 personnes assignées ·
Les mainteneurs répondent en général sous 1 jour
-
Difficulté 4/5 3-5 jours Accessibilité débutants 48/100
pytorch/executorch#24125 ·
Les mainteneurs répondent en général sous 1 jour
Toutes les issues de pytorch/executorch
Issues similaires
-
Difficulté 2/5 1-3 heures Accessibilité débutants 76/100
microsoft/agent-lightning#661 ·
Les mainteneurs répondent en général sous 2 jours
-
area/profiles comp/cli P3 type/feature
Difficulté 2/5 1-3 heures Accessibilité débutants 74/100
NousResearch/hermes-agent#146372 ·
Les mainteneurs répondent en général sous 1 jour
-
[BUG] OpenAI-compatible embedding model alias breaks embedder constructionPeut-être pris Une pull request liée à cette issue est ouverte ou déjà fusionnée. Ouverte
Difficulté 2/5 1-3 heures Accessibilité débutants 65/100
Les mainteneurs répondent en général sous 1 jour
-
[oblt-aw][autodoc] Document obs-aw-automerge contract and fix automerge doc inconsistenciesPeut-être pris @github-actions l’a pris aujourd’hui. Ouverte
Difficulté 2/5 1-3 heures Accessibilité débutants 76/100
Les mainteneurs répondent en général sous 1 jour
-
GeoSeries scale and skew tests fail with pytest 9.2.0Peut-être pris @jiayuasu l’a pris aujourd’hui. Ouverte
Difficulté 2/5 1-3 heures Accessibilité débutants 82/100
Les mainteneurs répondent en général sous 1 jour