pymcu-arm-toolchain
Vendored LLVM toolchain for the PyMCU ARM (Cortex-M) backend.
The ARM backend lowers PyMCU's architecture-agnostic IR to LLVM IR and then invokes five LLVM command-line tools to produce a flashable flat binary:
opt llc llvm-mc ld.lld llvm-objcopy
This package is the ARM counterpart of
pymcu-avr-toolchain: a
platform-specific wheel whose only job is to ship those tools so that
pip install pymcu-compiler[arm] is fully self-contained — no
brew install llvm or apt install lld step required on supported platforms.
License: MIT packaging + Apache-2.0 WITH LLVM-exception binaries
The Python packaging code in this repo is MIT.
The bundled LLVM binaries are distributed under the Apache License 2.0 with LLVM Exceptions — the official license of the LLVM Project. This is a permissive license with no copyleft. Specifically:
- LLVM is not GPL. There is no copyleft infection on this package, on PyMCU, or on firmware compiled with these tools.
- The LLVM Exception clause explicitly exempts compiled output: binary
firmware produced by PyMCU through
opt/llccarries no license obligation from LLVM. - Contrast with AVR:
pymcu-avr-toolchainbundlesavr-gcc(derived from GCC), which is GPL-3.0. That package must therefore be GPL- licensed. The isolation mechanism is the same — a separate optional package — but the license differs because the upstream compilers differ.
See LICENSE for the complete text and a plain-language explanation.
Installation
pip install pymcu-arm-toolchain
libLLVM.{dylib,so} is 200–300 MB of code even in a release build — too
large for PyPI's 100 MB per-file ceiling. The distribution is therefore split:
| Channel | What it contains |
|---|---|
PyPI (pip install pymcu-arm-toolchain) |
Lightweight stub (~20 KB) |
| GitHub Releases | Binary wheels with LLVM bundled (~300 MB each) |
The LLVM tools are downloaded automatically. The first call to
get_tool() (or any PyMCU ARM build) downloads the official LLVM
release for your platform from GitHub and extracts the five required tools
into the shared cache at ~/.pymcu/tools/. Subsequent calls are instant.
import pymcu_arm_toolchain
opt = pymcu_arm_toolchain.get_tool("opt") # downloads on first call
For CI or air-gapped environments, override the download URL or install the binary wheel directly:
# Linux x86-64
pip install https://github.com/PyMCU/pymcu-arm-toolchain/releases/download/v22.1.7/pymcu_arm_toolchain-22.1.7-py3-none-manylinux_2_17_x86_64.whl
# Linux arm64
pip install https://github.com/PyMCU/pymcu-arm-toolchain/releases/download/v22.1.7/pymcu_arm_toolchain-22.1.7-py3-none-manylinux_2_17_aarch64.whl
# macOS Apple Silicon
pip install https://github.com/PyMCU/pymcu-arm-toolchain/releases/download/v22.1.7/pymcu_arm_toolchain-22.1.7-py3-none-macosx_14_0_arm64.whl
# Windows x86-64
pip install https://github.com/PyMCU/pymcu-arm-toolchain/releases/download/v22.1.7/pymcu_arm_toolchain-22.1.7-py3-none-win_amd64.whl
System LLVM (alternative)
If you already have LLVM 18+ installed (brew install llvm lld /
apt install llvm lld), the Rp2040LlvmToolchain driver finds the tools via
the cache or PATH automatically — no package needed.
How the driver resolves tools
Rp2040LlvmToolchain (in pymcu-arm) checks these sources in order:
| Priority | Source |
|---|---|
| 1 | pymcu_arm_toolchain.get_tool(name) — wheel bundle or auto-downloaded cache |
| 2 | Shared cache ~/.pymcu/tools/<platform>/llvm-arm/bin/ |
| 3 | Common keg dirs (/opt/homebrew/opt/llvm/bin, /usr/lib/llvm/bin, …) |
| 4 | PATH |
A missing wheel never blocks a developer who already has LLVM installed.
Inspecting installed tools
pymcu-arm-toolchain-info # entry-point
python -m pymcu_arm_toolchain status
Example output:
pymcu-arm-toolchain (LLVM 22.1.7, platform darwin-arm64)
[ok] opt ~/.pymcu/tools/darwin-arm64/llvm-arm/bin/opt
[ok] llc ~/.pymcu/tools/darwin-arm64/llvm-arm/bin/llc
[ok] llvm-mc ~/.pymcu/tools/darwin-arm64/llvm-arm/bin/llvm-mc
[ok] ld.lld ~/.pymcu/tools/darwin-arm64/llvm-arm/bin/ld.lld
[ok] llvm-objcopy ~/.pymcu/tools/darwin-arm64/llvm-arm/bin/llvm-objcopy
Seeding the cache manually
For platforms without a published wheel, or to use a locally installed LLVM:
# Download the pinned LLVM release automatically:
python -m pymcu_arm_toolchain fetch --cache
# Use a Homebrew LLVM (symlinked, dev convenience):
python -m pymcu_arm_toolchain fetch --cache \
--from-dir /opt/homebrew/opt/llvm --link
# Copy from a system install:
python -m pymcu_arm_toolchain fetch --cache \
--from-dir /usr/lib/llvm-19
For maintainers: publishing a new wheel
Release process
- Update
LLVM_VERSIONinsrc/pymcu_arm_toolchain/__init__.pyandversioninpyproject.toml. - Tag and push:
git tag v22.1.7 git push origin v22.1.7
- The
build-wheels.ymlworkflow fires automatically:- Downloads the official LLVM
.tar.xz, slims to the five tools + shared libs viascripts/stage-llvm.sh, builds apy3-none-<platform>wheel per platform. - Binary wheels → GitHub Releases (too large for PyPI's 100 MB limit).
- PyPI receives only the pure-Python sdist stub.
publish-pypiuses OIDC trusted publishing (no stored token required).
- Downloads the official LLVM
Required GitHub configuration
| Item | Where | Purpose |
|---|---|---|
release environment |
Repo → Settings → Environments | Gates OIDC publishing; add tag protection rule v* |
Building a wheel locally
bash scripts/stage-llvm.sh /opt/homebrew/opt/llvm /tmp/staged-llvm
ARMT_TOOLCHAIN_DIR=/tmp/staged-llvm \
WHEEL_PLATFORM_TAG=macosx_14_0_arm64 \
uv build --wheel
Environment variables
| Variable | Effect |
|---|---|
ARMT_TOOLCHAIN_DIR |
Path to a staged LLVM tree for hatch_build.py |
WHEEL_PLATFORM_TAG |
Override the wheel platform tag (e.g. win_amd64) |
PYMCU_TOOLS_DIR |
Override the ~/.pymcu/tools cache root |
PYMCU_ARM_LLVM_URL |
Override the LLVM archive download URL (air-gapped installs) |
PYMCU_ARM_LLVM_SHA256 |
Expected SHA-256 of the downloaded archive |
PYMCU_SKIP_HASH_CHECK |
Set to 1 to skip SHA-256 verification |
Version history
| Package version | Bundled LLVM | Notes |
|---|---|---|
| 22.1.7 | LLVM 22.1.7 | Initial release |
Metadata
Release files for pymcu-arm-toolchain 22.1.7.post1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| pymcu_arm_toolchain-22.1.7.post1.tar.gz | 14.9 kB | Without provenance | Details |
Release files / pymcu_arm_toolchain-22.1.7.post1.tar.gz
| Download URL | pymcu_arm_toolchain-22.1.7.post1.tar.gz |
|---|---|
| Size | 14.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
21e38cba33184e7c4dfc02e0090723d04ef9d5fd1c60c606672eab5ce0605528
|
|
BLAKE2b-256 checksum How to use checksums |
5b718b6b58c805f34647d41ee46d342aa8f384bdf640efd937b9ddd1adf180c7
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.11.19 {"installer":{"name":"uv","version":"0.11.19","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Security for pymcu-arm-toolchain 22.1.7.post1
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.