Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 34 additions & 5 deletions .github/workflows/build-wheels-platforms.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ jobs:
- macOS ARM
- Linux ARM64
- Linux ARMv7
- Linux ARMv7 Legacy
include:
- os: Windows
runner: windows-latest
Expand All @@ -47,11 +48,14 @@ jobs:
- os: Linux ARMv7
runner: ubuntu-latest
arch: linux-armv7
- os: Linux ARMv7 Legacy
runner: ubuntu-latest
arch: linux-armv7-legacy
python-version: ['${{ needs.get-supported-versions.outputs.oldest_supported_python }}']

steps:
- name: Set up QEMU for ARMv7
if: matrix.os == 'Linux ARMv7'
if: matrix.os == 'Linux ARMv7' || matrix.os == 'Linux ARMv7 Legacy'
uses: docker/setup-qemu-action@v3
with:
platforms: linux/arm/v7
Expand Down Expand Up @@ -79,20 +83,20 @@ jobs:

- name: Setup Python
# Skip setting python on ARM because of missing compatibility: https://github.com/actions/setup-python/issues/108
if: matrix.os != 'Linux ARMv7'
if: matrix.os != 'Linux ARMv7' && matrix.os != 'Linux ARMv7 Legacy'
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}


- name: Install build dependencies
if: matrix.os != 'Linux ARMv7'
if: matrix.os != 'Linux ARMv7' && matrix.os != 'Linux ARMv7 Legacy'
run: |
python -m pip install --upgrade pip
python -m pip install -r build_requirements.txt

- name: Get Tools versions
if: matrix.os != 'Linux ARMv7'
if: matrix.os != 'Linux ARMv7' && matrix.os != 'Linux ARMv7 Legacy'
run: |
python --version
pip show pip setuptools
Expand Down Expand Up @@ -136,8 +140,33 @@ jobs:
python build_wheels.py
"

- name: Build wheels for IDF - ARMv7 Legacy (in Docker)
# Build on Bullseye (glibc 2.31) for compatibility with older systems
# Note: Buster has Python 3.7 which is too old for our dependencies
if: matrix.os == 'Linux ARMv7 Legacy'
run: |
docker run --rm --platform linux/arm/v7 \
-v $(pwd):/work \
-w /work \
-e MIN_IDF_MAJOR_VERSION=${{ needs.get-supported-versions.outputs.min_idf_major_version }} \
-e MIN_IDF_MINOR_VERSION=${{ needs.get-supported-versions.outputs.min_idf_minor_version }} \
-e GH_TOKEN="${GH_TOKEN}" \
-e PIP_NO_CACHE_DIR=1 \
python:${{ matrix.python-version }}-bullseye \
bash -c "
set -e
python --version
# Install pip packages without cache to reduce memory usage
python -m pip install --no-cache-dir --upgrade pip
python -m pip install --no-cache-dir -r build_requirements.txt
bash os_dependencies/linux_arm.sh
# Source Rust environment after installation
. \$HOME/.cargo/env
python build_wheels.py
"

- name: Build wheels for IDF - Linux/macOS
if: matrix.os != 'Windows' && matrix.os != 'Linux ARMv7'
if: matrix.os != 'Windows' && matrix.os != 'Linux ARMv7' && matrix.os != 'Linux ARMv7 Legacy'
run: |
# Set ARCHFLAGS for macOS to prevent universal2 wheels
if [ "${{ matrix.os }}" = "macOS ARM" ]; then
Expand Down
42 changes: 37 additions & 5 deletions .github/workflows/build-wheels-python-dependent.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ jobs:
- macOS ARM
- Linux ARM64
- Linux ARMv7
- Linux ARMv7 Legacy
include:
- os: Windows
runner: windows-latest
Expand All @@ -47,6 +48,9 @@ jobs:
- os: Linux ARMv7
runner: ubuntu-latest
arch: linux-armv7
- os: Linux ARMv7 Legacy
runner: ubuntu-latest
arch: linux-armv7-legacy
python-version: ${{ fromJson(inputs.supported_python_versions) }}
exclude:
# Exclude oldest supported Python since it's already built in the platform builds
Expand All @@ -62,10 +66,15 @@ jobs:
os: Linux ARM64
- python-version: ${{ inputs.oldest_supported_python }}
os: Linux ARMv7
- python-version: ${{ inputs.oldest_supported_python }}
os: Linux ARMv7 Legacy
# Python 3.14 doesn't have bullseye images for ARM
- python-version: '3.14'
os: Linux ARMv7 Legacy

steps:
- name: Set up QEMU for ARMv7
if: matrix.os == 'Linux ARMv7'
if: matrix.os == 'Linux ARMv7' || matrix.os == 'Linux ARMv7 Legacy'
uses: docker/setup-qemu-action@v3
with:
platforms: linux/arm/v7
Expand All @@ -75,19 +84,19 @@ jobs:

- name: Setup Python
# Skip setting python on ARMv7 (runs in Docker)
if: matrix.os != 'Linux ARMv7'
if: matrix.os != 'Linux ARMv7' && matrix.os != 'Linux ARMv7 Legacy'
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}

- name: Get Python version
if: matrix.os != 'Linux ARMv7'
if: matrix.os != 'Linux ARMv7' && matrix.os != 'Linux ARMv7 Legacy'
run: |
python --version
python -m pip install --upgrade pip

- name: Install dependencies
if: matrix.os != 'Linux ARMv7'
if: matrix.os != 'Linux ARMv7' && matrix.os != 'Linux ARMv7 Legacy'
run: python -m pip install -r build_requirements.txt

- name: Install additional OS dependencies - Ubuntu
Expand Down Expand Up @@ -138,8 +147,31 @@ jobs:
python build_wheels_from_file.py dependent_requirements_${{ matrix.arch }}
"

- name: Build Python dependent wheels - ARMv7 Legacy (in Docker)
# Build on Bullseye (glibc 2.31) for compatibility with older systems
if: matrix.os == 'Linux ARMv7 Legacy'
run: |
docker run --rm --platform linux/arm/v7 \
-v $(pwd):/work \
-w /work \
-e PYO3_USE_ABI3_FORWARD_COMPATIBILITY=1 \
-e GH_TOKEN="${GH_TOKEN}" \
-e PIP_NO_CACHE_DIR=1 \
python:${{ matrix.python-version }}-bullseye \
bash -c "
set -e
python --version
# Install pip packages without cache to reduce memory usage
python -m pip install --no-cache-dir --upgrade pip
python -m pip install --no-cache-dir -r build_requirements.txt
bash os_dependencies/linux_arm.sh
# Source Rust environment after installation
. \$HOME/.cargo/env
python build_wheels_from_file.py dependent_requirements_${{ matrix.arch }}
"

- name: Build Python dependent wheels - Linux/macOS
if: matrix.os != 'Windows' && matrix.os != 'Linux ARMv7'
if: matrix.os != 'Windows' && matrix.os != 'Linux ARMv7' && matrix.os != 'Linux ARMv7 Legacy'
run: |
# Set ARCHFLAGS for macOS to prevent universal2 wheels
if [ "${{ matrix.os }}" = "macOS ARM" ]; then
Expand Down
29 changes: 28 additions & 1 deletion .github/workflows/wheels-repair.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ jobs:
- Linux x86_64
- Linux ARM64
- Linux ARMv7
- Linux ARMv7 Legacy
include:
- platform: Windows
runner: windows-latest
Expand Down Expand Up @@ -58,6 +59,15 @@ jobs:
qemu_platform: arm
docker_platform: linux/arm/v7
arch: linux-armv7
- platform: Linux ARMv7 Legacy
runner: ubuntu-latest
tool: auditwheel
manylinux_platform: idf-python-wheels-armv7l-legacy
docker_image: ghcr.io/espressif/github-esp-dockerfiles/idf-python-wheels-armv7l-legacy:v1
setup_qemu: true
qemu_platform: arm
docker_platform: linux/arm/v7
arch: linux-armv7-legacy

steps:
- name: Checkout repository
Expand All @@ -66,7 +76,9 @@ jobs:
- name: Download wheel artifacts
uses: actions/download-artifact@v4
with:
pattern: wheels-download-directory-*
# Download only artifacts for this specific architecture to avoid mixing wheels
# (especially important for ARMv7 vs ARMv7 Legacy which produce same-named wheels)
pattern: wheels-download-directory-${{ matrix.arch }}-*
path: ./downloaded_wheels
merge-multiple: true

Expand Down Expand Up @@ -145,6 +157,21 @@ jobs:
python3 repair_wheels.py
"

- name: Repair Linux ARMv7 Legacy wheels in manylinux container
if: matrix.platform == 'Linux ARMv7 Legacy'
run: |
docker run --rm \
--platform ${{ matrix.docker_platform }} \
-v $(pwd):/work \
-w /work \
${{ matrix.docker_image }} \
bash -c "
bash os_dependencies/linux_arm.sh
python3 -m pip install --upgrade pip
python3 -m pip install -r build_requirements.txt
python3 repair_wheels.py
"

- name: Re-upload artifacts with repaired wheels
uses: actions/upload-artifact@v4
with:
Expand Down
7 changes: 4 additions & 3 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -23,20 +23,21 @@ repos:
- id: check-yaml

- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.13.3
rev: v0.14.10
hooks:
- id: ruff-check
args: [--fix, --exit-non-zero-on-fix]
- id: ruff-format

- repo: https://github.com/pre-commit/mirrors-mypy
rev: v1.18.2
# pre-commit autoupdate --skip mypy (newer versions require Python 3.9+)
rev: v1.18.2 # frozen: minimum Python version compatibility
hooks:
- id: mypy
additional_dependencies: ['types-all-latest']

- repo: https://github.com/espressif/conventional-precommit-linter
rev: v1.10.0
rev: v1.11.0
hooks:
- id: conventional-precommit-linter
stages: [commit-msg]
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -141,4 +141,7 @@ The main file is `build-wheels-platforms.yml` which is scheduled to run periodic
> Python dependent wheels are wheels which depend on the [CPython’s Application Binary Interface (ABI)](https://docs.python.org/3/c-api/stable.html). These are checked based on the [wheel filename format](https://peps.python.org/pep-0491/#file-format) where the `abi tag` is checked for `cp`. Such wheels need to be build also for all supported Python versions, not only for the minimum Python version supported by [ESP-IDF].


## Docker files
Docker files are here just as a copy for better understanding in the scope of one repository. Actual Docker files are in its own repository where there are build and published from. https://github.com/espressif/github-esp-dockerfiles

[ESP-IDF]: https://github.com/espressif/esp-idf
96 changes: 96 additions & 0 deletions docker/Dockerfile.manylinux_armv7l_legacy
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
# Minimal manylinux-compatible Docker image for ARMv7l (32-bit ARM)
# Based on Debian Bullseye for older glibc compatibility (2.31)
# Use this for compatibility with older systems (e.g., older Raspberry Pi OS)

FROM arm32v7/debian:bullseye

LABEL maintainer="Espressif Systems"
LABEL description="Minimal manylinux-compatible environment for building Python wheels on ARMv7l (legacy glibc 2.31)"

# Set environment variables
ENV DEBIAN_FRONTEND=noninteractive \
LC_ALL=C.UTF-8 \
LANG=C.UTF-8

# Install build dependencies and Python versions
RUN apt-get update && apt-get install -y \
# Build essentials
build-essential \
gcc \
g++ \
make \
cmake \
git \
wget \
curl \
ca-certificates \
patchelf \
# Python build dependencies
libssl-dev \
libffi-dev \
libbz2-dev \
libreadline-dev \
libsqlite3-dev \
libncurses5-dev \
libncursesw5-dev \
libgdbm-dev \
liblzma-dev \
tk-dev \
zlib1g-dev \
# Additional libraries commonly needed for wheels
libxml2-dev \
libxslt1-dev \
libyaml-dev \
libglib2.0-dev \
# PyGObject dependencies
libcairo2-dev \
pkg-config \
libgirepository1.0-dev \
# dbus-python dependencies
libdbus-1-dev \
libdbus-glib-1-dev \
# Pillow dependencies (include both -dev and runtime libs for auditwheel)
libjpeg-dev \
libpng-dev \
libtiff-dev \
libtiff5 \
libfreetype6-dev \
liblcms2-dev \
libwebp-dev \
libopenjp2-7-dev \
libfribidi-dev \
libharfbuzz-dev \
libxcb1-dev \
libxau-dev \
brotli \
libbrotli-dev \
# Python from Debian repos (Bullseye provides 3.9)
python3 \
python3-dev \
python3-venv \
python3-pip \
&& rm -rf /var/lib/apt/lists/*

# Install pip and wheel tools
RUN python3 -m pip install --no-cache-dir --upgrade \
pip \
setuptools \
wheel \
auditwheel

# Set up manylinux platform tag
# This makes auditwheel recognize the environment as manylinux-compatible
# Bullseye has glibc 2.31, so we use manylinux_2_31
RUN echo "manylinux_2_31_armv7l" > /etc/system-release-cpe

# Create a marker file for manylinux detection
RUN mkdir -p /opt/python && \
echo "manylinux_2_31_armv7l" > /opt/python/PLATFORM

# Set working directory
WORKDIR /workspace

# Default Python
ENV PATH="/usr/bin:${PATH}"

CMD ["/bin/bash"]
Loading