Vendored LLVM toolchain (opt/llc/llvm-mc/ld.lld/llvm-objcopy) for the PyMCU ARM backend
Project description
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 |
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
File details
Details for the file pymcu_arm_toolchain-22.1.7.tar.gz.
File metadata
- Download URL: pymcu_arm_toolchain-22.1.7.tar.gz
- Upload date:
- Size: 14.8 kB
- Tags: Source
- Uploaded using 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}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f9f2d34a8ffd8bc97fcaa4cd1d28a1e50dc62ba608c2ba02fbfba757b30df109
|
|
| MD5 |
10938a42a92da56fbde335ea4bc59acb
|
|
| BLAKE2b-256 |
eb8a55f9a3a69f7570ac4cbb07e18f77a6e9181de2f5414d7f4f1c19550572a1
|