Skip to content

Commit 61ed3e5

Browse files
committed
feat: add support for wheels without redundant binaries
Originally, wheels were being built with all dynamic libs included across all different platforms, which made size of the wheel large. Now wheels are built only with the one platform compatible library. Other changes: - Removed setuptools-scm as a runtime dependency, as that's undesirable - Added custom build backend to create py3-none wheels to be compatible with all versions of python Signed-off-by: Tomas Jaros <tomas.jaros@nxp.com>
1 parent 8a2154a commit 61ed3e5

8 files changed

Lines changed: 150 additions & 43 deletions

File tree

wrapper/.pylintrc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ fail-under=10
4242
#from-stdin=
4343

4444
# Files or directories to be skipped. They should be base names, not paths.
45-
ignore=CVS, __version__.py
45+
ignore=CVS, __version__.py, build_backend.py
4646

4747
# Add files or directories matching the regular expressions patterns to the
4848
# ignore-list. The regex matches against paths and can be in Posix or Windows

wrapper/MANIFEST.in

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
include requirements*
22

33
recursive-include libuuu *
4+
include build_backend.py
45

56
recursive-exclude * __pycache__
67
recursive-exclude * *.py[co]
7-
recursive-exclude .github*
88

wrapper/build_backend.py

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
#!/usr/bin/env python
2+
# -*- coding: utf-8 -*-
3+
#
4+
# Copyright 2025 NXP
5+
#
6+
# SPDX-License-Identifier: BSD-3-Clause
7+
"""Custom build backend that wraps setuptools and forces platform wheels."""
8+
9+
import os
10+
from typing import Any, Tuple
11+
12+
from setuptools.build_meta import build_editable as _build_editable
13+
from setuptools.build_meta import build_sdist as _build_sdist
14+
from setuptools.build_meta import build_wheel as _build_wheel
15+
from setuptools.dist import Distribution
16+
from wheel.bdist_wheel import bdist_wheel
17+
18+
19+
def patch() -> None:
20+
"""Patch the bdist wheel build."""
21+
# Apply the monkey patch when the module is imported
22+
original_has_ext_modules = getattr(Distribution, "has_ext_modules", None)
23+
if original_has_ext_modules is not None:
24+
Distribution.has_ext_modules = lambda self: True
25+
26+
# Also patch the is_pure method to return False
27+
original_is_pure = getattr(Distribution, "is_pure", None)
28+
if original_is_pure is not None:
29+
Distribution.is_pure = lambda self: False
30+
31+
# Override the wheel tag generation
32+
33+
original_get_tag = getattr(bdist_wheel, "get_tag", None)
34+
if original_get_tag is not None:
35+
36+
def tag(self: Any) -> Tuple[str, str, str]:
37+
_, _, platform_tag = original_get_tag(self)
38+
return ("py3", "none", platform_tag)
39+
40+
bdist_wheel.get_tag = tag
41+
42+
print("Custom build backend loaded: Platform-specific wheels enabled")
43+
44+
45+
def validate_native_libraries() -> None:
46+
"""Validate that native libraries exist in the expected locations."""
47+
lib_dir = os.path.join(os.path.dirname(__file__), "libuuu", "lib")
48+
49+
if os.path.exists(lib_dir):
50+
print(f"Native libraries found in: {lib_dir}")
51+
# List found libraries
52+
for root, _, files in os.walk(lib_dir):
53+
for file in files:
54+
if file.endswith((".dll", ".so", ".dylib")):
55+
print(f" - {os.path.relpath(os.path.join(root, file), lib_dir)}")
56+
else:
57+
print(f"Warning: No native libraries found in {lib_dir}")
58+
59+
60+
def build_wheel(wheel_directory, config_settings=None, metadata_directory=None) -> str: # type: ignore
61+
"""Build wheel."""
62+
patch()
63+
validate_native_libraries()
64+
return _build_wheel(wheel_directory, config_settings, metadata_directory)
65+
66+
67+
def build_sdist(sdist_directory, config_settings=None) -> str: # type: ignore
68+
"""Build source."""
69+
patch()
70+
validate_native_libraries()
71+
return _build_sdist(sdist_directory, config_settings)
72+
73+
74+
def build_editable(wheel_directory, config_settings=None, metadata_directory=None) -> str: # type: ignore
75+
"""Build editable."""
76+
patch()
77+
validate_native_libraries()
78+
return _build_editable(wheel_directory, config_settings, metadata_directory)

wrapper/libuuu/__init__.py

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,15 @@
11
#!/usr/bin/env python
22
# -*- coding: UTF-8 -*-
33
#
4-
# Copyright 2024 NXP
4+
# Copyright 2024-2025 NXP
55
#
66
# SPDX-License-Identifier: BSD-3-Clause
77

88
"""Wrapper for libuuu."""
99

10+
from .__version__ import __version__ as version
1011
from .libuuu import LibUUU, UUUNotifyCallback, UUUShowConfig, UUUState
11-
from .misc import get_libuuu_version
12-
13-
version = get_libuuu_version()
1412

1513
__author__ = """NXP"""
16-
__version__ = str(version)
14+
__version__ = version
1715
__all__ = ["LibUUU", "UUUNotifyCallback", "UUUShowConfig", "UUUState"]

wrapper/libuuu/libuuu.py

Lines changed: 42 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
#!/usr/bin/env python
22
# -*- coding: UTF-8 -*-
33
#
4-
# Copyright 2024 NXP
4+
# Copyright 2024-2025 NXP
55
#
66
# SPDX-License-Identifier: BSD-3-Clause
7+
78
"""Main module for libuuu wrapper."""
89

910
import logging
@@ -174,13 +175,45 @@ def update(self, struct: UUUNotifyStruct) -> None:
174175
self.logger.debug(f"{self.cmd=},{self.dev=},{self.waiting=}")
175176

176177

177-
def get_dll() -> str:
178-
"""Return name of shared library based on platform."""
179-
if platform.system() == "Windows":
180-
return "libuuu.dll"
181-
if platform.system() == "Darwin":
182-
return "libuuu.dylib"
183-
return "libuuu.so"
178+
def get_platform_info() -> tuple[str, str]:
179+
"""Get platform and architecture information."""
180+
system = platform.system().lower()
181+
machine = platform.machine().lower()
182+
183+
# Normalize architecture names
184+
arch_mapping = {
185+
"x86_64": "x86_64",
186+
"amd64": "x86_64",
187+
"aarch64": "aarch64",
188+
"arm64": "arm64",
189+
}
190+
191+
arch = arch_mapping.get(machine, machine)
192+
if system == "linux" and arch == "arm64":
193+
# For Linux on ARM64, we can use the 'aarch64' architecture name
194+
arch = "aarch64"
195+
196+
return system, arch
197+
198+
199+
def get_dll_path() -> str:
200+
"""Return path to the appropriate shared library based on platform and architecture."""
201+
system, arch = get_platform_info()
202+
203+
base_path = pathlib.Path(__file__).parent / "lib"
204+
205+
if system == "windows":
206+
lib_name = "libuuu.dll"
207+
lib_path = base_path / "windows" / arch / lib_name
208+
elif system == "darwin":
209+
lib_name = "libuuu.dylib"
210+
# macOS uses universal binary
211+
lib_path = base_path / "darwin" / arch / lib_name
212+
else: # Linux and other Unix-like systems
213+
lib_name = "libuuu.so"
214+
lib_path = base_path / "linux" / arch / lib_name
215+
216+
return str(lib_path)
184217

185218

186219
@UUUNotifyCallback
@@ -200,7 +233,7 @@ def _default_notify_callback(struct: UUUNotifyStruct, data) -> int: # type: ign
200233
class LibUUU:
201234
"""Wrapper for the libuuu library."""
202235

203-
DLL = str(pathlib.Path(__file__).parent / "lib" / get_dll())
236+
DLL = get_dll_path()
204237
NULL = POINTER(c_void_p)()
205238

206239
_response = UUUCommandResponse()

wrapper/libuuu/misc.py

Lines changed: 0 additions & 20 deletions
This file was deleted.

wrapper/pyproject.toml

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
[build-system]
2-
requires = ["setuptools >= 61.0", "wheel", "setuptools-scm>=8"]
3-
build-backend = "setuptools.build_meta"
2+
requires = ["setuptools>=68.0", "wheel", "setuptools-scm>=8"]
3+
build-backend = "build_backend"
4+
backend-path = ["."]
45

5-
[tool.setuptools]
6-
packages = ["libuuu"]
76

87
[project]
98
dynamic = ["version", "dependencies"]
@@ -28,14 +27,33 @@ classifiers = [
2827
"Programming Language :: Python :: 3.11",
2928
]
3029

30+
[tool.setuptools]
31+
packages = ["libuuu"]
32+
3133
[tool.setuptools.package-data]
32-
libuuu = ["*.dll", "*.so", "*.dylib"]
34+
"libuuu.lib.windows.x86_64" = [
35+
"*.dll"
36+
]
37+
"libuuu.lib.linux.x86_64" = [
38+
"*.so"
39+
]
40+
"libuuu.lib.linux.aarch64" = [
41+
"*.so"
42+
]
43+
"libuuu.lib.darwin.arm64" = [
44+
"*.dylib"
45+
]
46+
"libuuu.lib.darwin.x86_64" = [
47+
"*.dylib"
48+
]
49+
3350

3451
[tool.setuptools_scm]
3552
root = ".."
3653
version_file = "libuuu/__version__.py"
3754
tag_regex = "^(?P<prefix>uuu_)?(?P<version>\\d+(\\.\\d+)*)$"
3855
local_scheme = "no-local-version"
56+
fallback_version = "0.0.0"
3957

4058
[tool.setuptools.dynamic]
4159
dependencies = {file = ["requirements.txt"]}
@@ -79,7 +97,7 @@ format = { max-line-length = 120 }
7997
[tool.nxp_codecheck]
8098
git_parent_branch = "origin/master"
8199
output_directory = "reports"
82-
default_check_paths = ["libuuu"]
100+
default_check_paths = ["libuuu", "tests", "build_backend.py"]
83101

84102
# *********************************** Checker list ***********************************
85103
[[tool.nxp_codecheck.checkers]]

wrapper/requirements.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
setuptools-scm<8.2
1+

0 commit comments

Comments
 (0)