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..5ba944dd 100644 --- a/livekit-rtc/pyproject.toml +++ b/livekit-rtc/pyproject.toml @@ -1,6 +1,10 @@ [build-system] -requires = ["hatchling", "requests"] -build-backend = "hatchling.build" +requires = [ + "setuptools>=61", + "wheel", + "requests", +] +build-backend = "setuptools.build_meta" [project] name = "livekit" @@ -35,28 +39,27 @@ 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.setuptools.dynamic] +version = { attr = "livekit.rtc.version.__version__" } -[tool.hatch.build.targets.wheel.hooks.custom] -path = "hatch_build.py" +[tool.setuptools.packages.find] +include = ["livekit.*"] -[tool.hatch.build.targets.sdist] -include = ["/livekit", "/rust-sdks"] +[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) 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+ @@ -66,4 +69,4 @@ environment = { MACOSX_DEPLOYMENT_TARGET = "10.15" } [[tool.cibuildwheel.overrides]] select = "*macosx_arm64" -environment = { MACOSX_DEPLOYMENT_TARGET = "11.0" } \ No newline at end of file +environment = { MACOSX_DEPLOYMENT_TARGET = "11.0" } diff --git a/livekit-rtc/setup.py b/livekit-rtc/setup.py new file mode 100644 index 00000000..279e8a19 --- /dev/null +++ b/livekit-rtc/setup.py @@ -0,0 +1,77 @@ +# 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 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 platform +import sys + +import setuptools # type: ignore +from wheel.bdist_wheel import bdist_wheel as _bdist_wheel # type: ignore + + +def get_platform_tag(): + """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") + 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_tag() + _bdist_wheel.finalize_options(self) + + +setuptools.setup( + cmdclass={ + "bdist_wheel": bdist_wheel, + }, +)