From c0096aa427b08d724652ca23fbe5f166d0dd8b7e Mon Sep 17 00:00:00 2001 From: lukasIO Date: Sun, 18 Jan 2026 10:12:30 +0100 Subject: [PATCH 1/4] Use setuptools instead of hatch --- livekit-rtc/hatch_build.py | 92 -------------------------------------- livekit-rtc/pyproject.toml | 67 +++------------------------ livekit-rtc/setup.py | 78 ++++++++++++++++++++++++++++++++ 3 files changed, 83 insertions(+), 154 deletions(-) delete mode 100644 livekit-rtc/hatch_build.py create mode 100644 livekit-rtc/setup.py diff --git a/livekit-rtc/hatch_build.py b/livekit-rtc/hatch_build.py deleted file mode 100644 index b274e46b..00000000 --- a/livekit-rtc/hatch_build.py +++ /dev/null @@ -1,92 +0,0 @@ -# Copyright 2023 LiveKit, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# 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 - -from hatchling.builders.hooks.plugin.interface import BuildHookInterface - - -class CustomBuildHook(BuildHookInterface): - def initialize(self, version, build_data): - 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": - 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: - return f"{platform.system().lower()}_{platform.machine()}" - - def _get_macos_tag(self): - """Build macOS platform tag respecting cross-compilation settings. - - 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_target_arch(self): - """Detect target architecture, respecting ARCHFLAGS for cross-compilation. - - 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" - if "-arch x86_64" in archflags: - return "x86_64" - return self._normalize_arch(platform.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 84e5b53b..0399290c 100644 --- a/livekit-rtc/pyproject.toml +++ b/livekit-rtc/pyproject.toml @@ -1,69 +1,12 @@ [build-system] -requires = ["hatchling", "requests"] -build-backend = "hatchling.build" - -[project] -name = "livekit" -dynamic = ["version"] -description = "Python Real-time SDK for LiveKit" -readme = "README.md" -requires-python = ">=3.9.0" -license = "Apache-2.0" -keywords = ["webrtc", "realtime", "audio", "video", "livekit"] -authors = [ - { name = "LiveKit", email = "support@livekit.io" } -] -classifiers = [ - "Intended Audience :: Developers", - "Topic :: Multimedia :: Sound/Audio", - "Topic :: Multimedia :: Video", - "Topic :: Scientific/Engineering :: Artificial Intelligence", - "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3.9", - "Programming Language :: Python :: 3.10", - "Programming Language :: Python :: 3 :: Only", -] -dependencies = [ - "protobuf>=4.25.0", - "types-protobuf>=3", - "aiofiles>=24", - "numpy>=1.26", +requires = [ + "setuptools>=42", + "wheel", + "requests", ] - -[project.urls] -Documentation = "https://docs.livekit.io" -Website = "https://livekit.io/" -Source = "https://github.com/livekit/python-sdks/" - -[tool.hatch.version] -path = "livekit/rtc/version.py" - -[tool.hatch.build.targets.wheel] -packages = ["livekit"] -artifacts = [ - "livekit/rtc/resources/*.so", - "livekit/rtc/resources/*.dylib", - "livekit/rtc/resources/*.dll", -] - -[tool.hatch.build.targets.wheel.hooks.custom] -path = "hatch_build.py" - -[tool.hatch.build.targets.sdist] -include = ["/livekit", "/rust-sdks"] +build-backend = "setuptools.build_meta" [tool.cibuildwheel] build = "cp39-*" skip = "*-musllinux_*" # not supported (libwebrtc requires glibc) before-build = "pip install requests && python rust-sdks/download_ffi.py --output livekit/rtc/resources" -# 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+ -[[tool.cibuildwheel.overrides]] -select = "*macosx_x86_64" -environment = { MACOSX_DEPLOYMENT_TARGET = "10.15" } - -[[tool.cibuildwheel.overrides]] -select = "*macosx_arm64" -environment = { MACOSX_DEPLOYMENT_TARGET = "11.0" } \ No newline at end of file diff --git a/livekit-rtc/setup.py b/livekit-rtc/setup.py new file mode 100644 index 00000000..484c007f --- /dev/null +++ b/livekit-rtc/setup.py @@ -0,0 +1,78 @@ +# Copyright 2023 LiveKit, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import os +import pathlib +from sysconfig import get_platform +from typing import Any, Dict + +import setuptools # type: ignore +import setuptools.command.build_py # type: ignore +from wheel.bdist_wheel import bdist_wheel as _bdist_wheel # type: ignore + +here = pathlib.Path(__file__).parent.resolve() +about: Dict[Any, Any] = {} +with open(os.path.join(here, "livekit", "rtc", "version.py"), "r") as f: + exec(f.read(), about) + + +class bdist_wheel(_bdist_wheel): + def finalize_options(self): + self.plat_name = get_platform() # force a platform tag + _bdist_wheel.finalize_options(self) + + +setuptools.setup( + name="livekit", + version=about["__version__"], + description="Python Real-time SDK for LiveKit", + long_description=(here / "README.md").read_text(encoding="utf-8"), + long_description_content_type="text/markdown", + url="https://github.com/livekit/python-sdks", + cmdclass={ + "bdist_wheel": bdist_wheel, + }, + classifiers=[ + "Intended Audience :: Developers", + "License :: OSI Approved :: Apache Software License", + "Topic :: Multimedia :: Sound/Audio", + "Topic :: Multimedia :: Video", + "Topic :: Scientific/Engineering :: Artificial Intelligence", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3 :: Only", + ], + keywords=["webrtc", "realtime", "audio", "video", "livekit"], + license="Apache-2.0", + packages=setuptools.find_namespace_packages(include=["livekit.*"]), + python_requires=">=3.9.0", + install_requires=["protobuf>=4.25.0", "types-protobuf>=3", "aiofiles>=24", "numpy>=1.26"], + package_data={ + "livekit.rtc": ["_proto/*.py", "py.typed", "*.pyi", "**/*.pyi"], + "livekit.rtc.resources": [ + "*.so", + "*.dylib", + "*.dll", + "LICENSE.md", + "*.h", + "jupyter-html/index.html", + ], + }, + project_urls={ + "Documentation": "https://docs.livekit.io", + "Website": "https://livekit.io/", + "Source": "https://github.com/livekit/python-sdks/", + }, +) From 950f732df63f8e17c22affe7ce2cc7c023381b14 Mon Sep 17 00:00:00 2001 From: lukasIO Date: Sun, 18 Jan 2026 10:20:03 +0100 Subject: [PATCH 2/4] fix macosx target --- livekit-rtc/pyproject.toml | 10 +++++++++ livekit-rtc/setup.py | 44 +++++++++++++++++++++++++++++++++++--- 2 files changed, 51 insertions(+), 3 deletions(-) diff --git a/livekit-rtc/pyproject.toml b/livekit-rtc/pyproject.toml index 0399290c..2dd8c12a 100644 --- a/livekit-rtc/pyproject.toml +++ b/livekit-rtc/pyproject.toml @@ -10,3 +10,13 @@ build-backend = "setuptools.build_meta" build = "cp39-*" skip = "*-musllinux_*" # not supported (libwebrtc requires glibc) before-build = "pip install requests && python rust-sdks/download_ffi.py --output livekit/rtc/resources" + +# 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+ +[[tool.cibuildwheel.overrides]] +select = "*macosx_x86_64" +environment = { MACOSX_DEPLOYMENT_TARGET = "10.15" } + +[[tool.cibuildwheel.overrides]] +select = "*macosx_arm64" +environment = { MACOSX_DEPLOYMENT_TARGET = "11.0" } diff --git a/livekit-rtc/setup.py b/livekit-rtc/setup.py index 484c007f..50760d72 100644 --- a/livekit-rtc/setup.py +++ b/livekit-rtc/setup.py @@ -14,11 +14,11 @@ import os import pathlib -from sysconfig import get_platform +import platform +import sys from typing import Any, Dict import setuptools # type: ignore -import setuptools.command.build_py # type: ignore from wheel.bdist_wheel import bdist_wheel as _bdist_wheel # type: ignore here = pathlib.Path(__file__).parent.resolve() @@ -27,9 +27,47 @@ exec(f.read(), about) +def get_platform_tag(): + """Get the wheel platform tag for the current/target platform. + + On macOS, we must respect MACOSX_DEPLOYMENT_TARGET and ARCHFLAGS environment + variables that cibuildwheel sets, rather than using sysconfig.get_platform() + which returns Python's compile-time values. + """ + if sys.platform == "darwin": + # Get deployment target from environment (set by cibuildwheel) or fall back + target = os.environ.get("MACOSX_DEPLOYMENT_TARGET") + if not target: + target = platform.mac_ver()[0] + parts = target.split(".") + target = f"{parts[0]}.{parts[1] if len(parts) > 1 else '0'}" + + version_tag = target.replace(".", "_") + + # Check ARCHFLAGS for cross-compilation (cibuildwheel sets this) + archflags = os.environ.get("ARCHFLAGS", "") + if "-arch arm64" in archflags: + arch = "arm64" + elif "-arch x86_64" in archflags: + arch = "x86_64" + else: + arch = platform.machine() + + return f"macosx_{version_tag}_{arch}" + elif sys.platform == "linux": + return f"linux_{platform.machine()}" + elif sys.platform == "win32": + arch = platform.machine() + if arch == "AMD64": + arch = "amd64" + return f"win_{arch}" + else: + return f"{platform.system().lower()}_{platform.machine()}" + + class bdist_wheel(_bdist_wheel): def finalize_options(self): - self.plat_name = get_platform() # force a platform tag + self.plat_name = get_platform_tag() _bdist_wheel.finalize_options(self) From 4256f90ea423b92379970f8c74fd60be5f76f43d Mon Sep 17 00:00:00 2001 From: lukasIO Date: Sun, 18 Jan 2026 10:27:49 +0100 Subject: [PATCH 3/4] fix project table --- livekit-rtc/pyproject.toml | 53 +++++++++++++++++++++++++++++++- livekit-rtc/setup.py | 63 ++++++++------------------------------ 2 files changed, 64 insertions(+), 52 deletions(-) diff --git a/livekit-rtc/pyproject.toml b/livekit-rtc/pyproject.toml index 2dd8c12a..9418c492 100644 --- a/livekit-rtc/pyproject.toml +++ b/livekit-rtc/pyproject.toml @@ -1,11 +1,62 @@ [build-system] requires = [ - "setuptools>=42", + "setuptools>=61", "wheel", "requests", ] build-backend = "setuptools.build_meta" +[project] +name = "livekit" +dynamic = ["version"] +description = "Python Real-time SDK for LiveKit" +readme = "README.md" +requires-python = ">=3.9.0" +license = "Apache-2.0" +keywords = ["webrtc", "realtime", "audio", "video", "livekit"] +authors = [ + { name = "LiveKit", email = "support@livekit.io" } +] +classifiers = [ + "Intended Audience :: Developers", + "License :: OSI Approved :: Apache Software License", + "Topic :: Multimedia :: Sound/Audio", + "Topic :: Multimedia :: Video", + "Topic :: Scientific/Engineering :: Artificial Intelligence", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3 :: Only", +] +dependencies = [ + "protobuf>=4.25.0", + "types-protobuf>=3", + "aiofiles>=24", + "numpy>=1.26", +] + +[project.urls] +Documentation = "https://docs.livekit.io" +Website = "https://livekit.io/" +Source = "https://github.com/livekit/python-sdks/" + +[tool.setuptools.dynamic] +version = { attr = "livekit.rtc.version.__version__" } + +[tool.setuptools.packages.find] +include = ["livekit.*"] + +[tool.setuptools.package-data] +"livekit.rtc" = ["_proto/*.py", "py.typed", "*.pyi", "**/*.pyi"] +"livekit.rtc.resources" = [ + "*.so", + "*.dylib", + "*.dll", + "LICENSE.md", + "*.h", + "jupyter-html/index.html", +] + [tool.cibuildwheel] build = "cp39-*" skip = "*-musllinux_*" # not supported (libwebrtc requires glibc) diff --git a/livekit-rtc/setup.py b/livekit-rtc/setup.py index 50760d72..279e8a19 100644 --- a/livekit-rtc/setup.py +++ b/livekit-rtc/setup.py @@ -12,28 +12,27 @@ # See the License for the specific language governing permissions and # limitations under the License. +"""Custom setup.py for platform-specific wheel tagging. + +This file exists solely to customize the wheel platform tag. All package metadata +is defined in pyproject.toml. + +The native FFI libraries (.so/.dylib/.dll) require specific platform tags that +respect MACOSX_DEPLOYMENT_TARGET and ARCHFLAGS environment variables set by +cibuildwheel, rather than using sysconfig.get_platform() which returns Python's +compile-time values. +""" + import os -import pathlib import platform import sys -from typing import Any, Dict import setuptools # type: ignore from wheel.bdist_wheel import bdist_wheel as _bdist_wheel # type: ignore -here = pathlib.Path(__file__).parent.resolve() -about: Dict[Any, Any] = {} -with open(os.path.join(here, "livekit", "rtc", "version.py"), "r") as f: - exec(f.read(), about) - def get_platform_tag(): - """Get the wheel platform tag for the current/target platform. - - On macOS, we must respect MACOSX_DEPLOYMENT_TARGET and ARCHFLAGS environment - variables that cibuildwheel sets, rather than using sysconfig.get_platform() - which returns Python's compile-time values. - """ + """Get the wheel platform tag for the current/target platform.""" if sys.platform == "darwin": # Get deployment target from environment (set by cibuildwheel) or fall back target = os.environ.get("MACOSX_DEPLOYMENT_TARGET") @@ -72,45 +71,7 @@ def finalize_options(self): setuptools.setup( - name="livekit", - version=about["__version__"], - description="Python Real-time SDK for LiveKit", - long_description=(here / "README.md").read_text(encoding="utf-8"), - long_description_content_type="text/markdown", - url="https://github.com/livekit/python-sdks", cmdclass={ "bdist_wheel": bdist_wheel, }, - classifiers=[ - "Intended Audience :: Developers", - "License :: OSI Approved :: Apache Software License", - "Topic :: Multimedia :: Sound/Audio", - "Topic :: Multimedia :: Video", - "Topic :: Scientific/Engineering :: Artificial Intelligence", - "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3.9", - "Programming Language :: Python :: 3.10", - "Programming Language :: Python :: 3 :: Only", - ], - keywords=["webrtc", "realtime", "audio", "video", "livekit"], - license="Apache-2.0", - packages=setuptools.find_namespace_packages(include=["livekit.*"]), - python_requires=">=3.9.0", - install_requires=["protobuf>=4.25.0", "types-protobuf>=3", "aiofiles>=24", "numpy>=1.26"], - package_data={ - "livekit.rtc": ["_proto/*.py", "py.typed", "*.pyi", "**/*.pyi"], - "livekit.rtc.resources": [ - "*.so", - "*.dylib", - "*.dll", - "LICENSE.md", - "*.h", - "jupyter-html/index.html", - ], - }, - project_urls={ - "Documentation": "https://docs.livekit.io", - "Website": "https://livekit.io/", - "Source": "https://github.com/livekit/python-sdks/", - }, ) From 15c611740b1fa4d071ddda8c1236b40b5a5ab114 Mon Sep 17 00:00:00 2001 From: lukasIO Date: Sun, 18 Jan 2026 10:33:32 +0100 Subject: [PATCH 4/4] fix license --- livekit-rtc/pyproject.toml | 1 - 1 file changed, 1 deletion(-) diff --git a/livekit-rtc/pyproject.toml b/livekit-rtc/pyproject.toml index 9418c492..5ba944dd 100644 --- a/livekit-rtc/pyproject.toml +++ b/livekit-rtc/pyproject.toml @@ -19,7 +19,6 @@ authors = [ ] classifiers = [ "Intended Audience :: Developers", - "License :: OSI Approved :: Apache Software License", "Topic :: Multimedia :: Sound/Audio", "Topic :: Multimedia :: Video", "Topic :: Scientific/Engineering :: Artificial Intelligence",