From 10773d7b89201f5aa11744962e7ad4013d6becb8 Mon Sep 17 00:00:00 2001 From: lukasIO Date: Fri, 16 Jan 2026 17:57:07 +0100 Subject: [PATCH 1/4] update cibuildwheels and simplify os detection --- .github/workflows/build-rtc.yml | 12 +--- livekit-rtc/hatch_build.py | 97 ++++++++++++++++++--------------- livekit-rtc/pyproject.toml | 12 +--- 3 files changed, 56 insertions(+), 65 deletions(-) diff --git a/.github/workflows/build-rtc.yml b/.github/workflows/build-rtc.yml index 61e4d24a..c9e3f318 100644 --- a/.github/workflows/build-rtc.yml +++ b/.github/workflows/build-rtc.yml @@ -79,18 +79,10 @@ jobs: with: submodules: true - - uses: actions/setup-python@v4 - - - name: Install cibuildwheel - if: runner.os != 'macOS' - run: python3 -m pip install cibuildwheel==2.17.0 - - - name: Install cibuildwheel on macOS - if: runner.os == 'macOS' - run: python3 -m pip install --break-system-packages cibuildwheel==2.17.0 + - uses: actions/setup-python@v5 - name: Build wheels - run: python3 -m cibuildwheel --output-dir dist + run: pipx run cibuildwheel==3.3.1 --output-dir dist env: CIBW_ARCHS: ${{ matrix.archs }} diff --git a/livekit-rtc/hatch_build.py b/livekit-rtc/hatch_build.py index 1afc69f1..b274e46b 100644 --- a/livekit-rtc/hatch_build.py +++ b/livekit-rtc/hatch_build.py @@ -12,6 +12,21 @@ # See the License for the specific language governing permissions and # limitations under the License. +"""Custom build hook for platform-specific wheel tagging. + +This hook generates py3-none-{platform} wheels because the native FFI libraries +(.so/.dylib/.dll) don't use the Python C API - they're loaded via ctypes at +runtime. This makes them compatible with any Python 3.x version. + +Why not use sysconfig.get_platform()? + - On macOS, it returns the Python interpreter's compile-time deployment target, + not the MACOSX_DEPLOYMENT_TARGET from the environment that cibuildwheel sets. + +Why not let hatchling infer the tag? + - hatchling doesn't recognize bundled .so/.dylib/.dll as platform-specific + unless we explicitly set pure_python=False and provide the tag. +""" + import os import platform import sys @@ -21,65 +36,57 @@ class CustomBuildHook(BuildHookInterface): def initialize(self, version, build_data): - """Force platform-specific wheel with py3-none tag. - - The native libraries (.so, .dylib, .dll) are not Python C extensions - - they're standalone FFI libraries loaded at runtime. This means they - don't depend on a specific CPython ABI, so we use py3-none to indicate - compatibility with any Python 3.x version while keeping the platform tag. - """ build_data["pure_python"] = False build_data["infer_tag"] = False + build_data["tag"] = f"py3-none-{self._get_platform_tag()}" + def _get_platform_tag(self): + """Get the wheel platform tag for the current/target platform.""" if sys.platform == "darwin": - plat_tag = self._get_macos_platform_tag() + return self._get_macos_tag() + elif sys.platform == "linux": + # Return linux tag; cibuildwheel's auditwheel converts to manylinux + return f"linux_{platform.machine()}" + elif sys.platform == "win32": + return f"win_{self._normalize_arch(platform.machine())}" else: - from packaging.tags import sys_tags + return f"{platform.system().lower()}_{platform.machine()}" - tag = next( - t - for t in sys_tags() - if "manylinux" not in t.platform and "musllinux" not in t.platform - ) - plat_tag = tag.platform + def _get_macos_tag(self): + """Build macOS platform tag respecting cross-compilation settings. - build_data["tag"] = f"py3-none-{plat_tag}" - - def _get_macos_platform_tag(self): - """Build macOS platform tag from MACOSX_DEPLOYMENT_TARGET env var.""" - deployment_target = os.environ.get("MACOSX_DEPLOYMENT_TARGET") - if not deployment_target: - # Fall back to current macOS version - deployment_target = platform.mac_ver()[0] - # Use only major.minor - parts = deployment_target.split(".") - deployment_target = f"{parts[0]}.{parts[1] if len(parts) > 1 else '0'}" - - # Convert version to wheel tag format (e.g., "11.0" -> "11_0") - version_tag = deployment_target.replace(".", "_") - - # Get target architecture from ARCHFLAGS (set by cibuildwheel for cross-compilation) - # or fall back to host machine architecture - arch = self._get_macos_target_arch() + cibuildwheel sets MACOSX_DEPLOYMENT_TARGET and ARCHFLAGS when building. + We must use these rather than the host machine's values. + """ + target = os.environ.get("MACOSX_DEPLOYMENT_TARGET") + if not target: + # Fall back to current macOS version (for local dev builds) + target = platform.mac_ver()[0] + parts = target.split(".") + target = f"{parts[0]}.{parts[1] if len(parts) > 1 else '0'}" + version_tag = target.replace(".", "_") + arch = self._get_target_arch() return f"macosx_{version_tag}_{arch}" - def _get_macos_target_arch(self): - """Detect target architecture for macOS builds. + def _get_target_arch(self): + """Detect target architecture, respecting ARCHFLAGS for cross-compilation. - Cibuildwheel sets ARCHFLAGS for cross-compilation (e.g., "-arch x86_64"). - Falls back to host machine architecture if not set. + cibuildwheel sets ARCHFLAGS="-arch arm64" or "-arch x86_64" when + cross-compiling on macOS. """ archflags = os.environ.get("ARCHFLAGS", "") if "-arch arm64" in archflags: return "arm64" - elif "-arch x86_64" in archflags: + if "-arch x86_64" in archflags: return "x86_64" + return self._normalize_arch(platform.machine()) - # Fall back to host architecture - machine = platform.machine() - if machine == "x86_64": - return "x86_64" - elif machine == "arm64": - return "arm64" - return machine + def _normalize_arch(self, arch): + """Normalize architecture names to wheel tag format.""" + return { + "AMD64": "amd64", + "x86_64": "x86_64", + "arm64": "arm64", + "aarch64": "aarch64", + }.get(arch, arch.lower()) diff --git a/livekit-rtc/pyproject.toml b/livekit-rtc/pyproject.toml index 675c38af..84e5b53b 100644 --- a/livekit-rtc/pyproject.toml +++ b/livekit-rtc/pyproject.toml @@ -54,17 +54,9 @@ include = ["/livekit", "/rust-sdks"] [tool.cibuildwheel] build = "cp39-*" -skip = "*-musllinux_*" # not supported (libwebrtc is using glibc) +skip = "*-musllinux_*" # not supported (libwebrtc requires glibc) before-build = "pip install requests && python rust-sdks/download_ffi.py --output livekit/rtc/resources" - -manylinux-x86_64-image = "manylinux_2_28" -manylinux-i686-image = "manylinux_2_28" -manylinux-aarch64-image = "manylinux_2_28" -manylinux-ppc64le-image = "manylinux_2_28" -manylinux-s390x-image = "manylinux_2_28" -manylinux-pypy_x86_64-image = "manylinux_2_28" -manylinux-pypy_i686-image = "manylinux_2_28" -manylinux-pypy_aarch64-image = "manylinux_2_28" +# Note: manylinux_2_28 is the default in cibuildwheel 3.x, no explicit config needed # macOS deployment targets must match the FFI binaries (see rust-sdks/.github/workflows/ffi-builds.yml) # x86_64 supports macOS 10.15+, arm64 requires macOS 11.0+ From 00b436356b45b968bdb2fd18a6bd1553c93f99ea Mon Sep 17 00:00:00 2001 From: lukasIO Date: Fri, 16 Jan 2026 18:06:38 +0100 Subject: [PATCH 2/4] update build to py3.11 --- .github/workflows/build-rtc.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/build-rtc.yml b/.github/workflows/build-rtc.yml index c9e3f318..323a5ff8 100644 --- a/.github/workflows/build-rtc.yml +++ b/.github/workflows/build-rtc.yml @@ -34,6 +34,8 @@ jobs: ref: ${{ github.event.pull_request.head.ref }} - uses: actions/setup-python@v4 + with: + python-version: "3.11" - name: Install Protoc uses: arduino/setup-protoc@v3 From 4c9f5a795e37f836fe999190e1d86ad76651dd58 Mon Sep 17 00:00:00 2001 From: lukasIO Date: Fri, 16 Jan 2026 18:13:01 +0100 Subject: [PATCH 3/4] fix --- .github/workflows/build-rtc.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-rtc.yml b/.github/workflows/build-rtc.yml index 323a5ff8..114b969d 100644 --- a/.github/workflows/build-rtc.yml +++ b/.github/workflows/build-rtc.yml @@ -34,8 +34,6 @@ jobs: ref: ${{ github.event.pull_request.head.ref }} - uses: actions/setup-python@v4 - with: - python-version: "3.11" - name: Install Protoc uses: arduino/setup-protoc@v3 @@ -82,6 +80,8 @@ jobs: submodules: true - uses: actions/setup-python@v5 + with: + python-version: "3.11" - name: Build wheels run: pipx run cibuildwheel==3.3.1 --output-dir dist From 65cc7318f3567f04da771b439ad518d897877a08 Mon Sep 17 00:00:00 2001 From: lukasIO Date: Fri, 16 Jan 2026 18:19:05 +0100 Subject: [PATCH 4/4] update python version used with pipx --- .github/workflows/build-rtc.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build-rtc.yml b/.github/workflows/build-rtc.yml index 114b969d..52b8c10b 100644 --- a/.github/workflows/build-rtc.yml +++ b/.github/workflows/build-rtc.yml @@ -80,11 +80,12 @@ jobs: submodules: true - uses: actions/setup-python@v5 + id: setup-python with: python-version: "3.11" - name: Build wheels - run: pipx run cibuildwheel==3.3.1 --output-dir dist + run: pipx run --python '${{ steps.setup-python.outputs.python-path }}' cibuildwheel==3.3.1 --output-dir dist env: CIBW_ARCHS: ${{ matrix.archs }}