Skip to content

Commit ba3053f

Browse files
committed
Add skeleton for WheelRepairer
Signed-off-by: Cristian Le <[email protected]>
1 parent 8ad4228 commit ba3053f

File tree

7 files changed

+202
-0
lines changed

7 files changed

+202
-0
lines changed
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
scikit\_build\_core.repair\_wheel package
2+
=========================================
3+
4+
.. automodule:: scikit_build_core.repair_wheel
5+
:members:
6+
:show-inheritance:
7+
:undoc-members:
8+
9+
Submodules
10+
----------
11+
12+
scikit\_build\_core.repair\_wheel.darwin module
13+
-----------------------------------------------
14+
15+
.. automodule:: scikit_build_core.repair_wheel.darwin
16+
:members:
17+
:show-inheritance:
18+
:undoc-members:
19+
20+
scikit\_build\_core.repair\_wheel.linux module
21+
----------------------------------------------
22+
23+
.. automodule:: scikit_build_core.repair_wheel.linux
24+
:members:
25+
:show-inheritance:
26+
:undoc-members:
27+
28+
scikit\_build\_core.repair\_wheel.windows module
29+
------------------------------------------------
30+
31+
.. automodule:: scikit_build_core.repair_wheel.windows
32+
:members:
33+
:show-inheritance:
34+
:undoc-members:

docs/api/scikit_build_core.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ Subpackages
1818
scikit_build_core.file_api
1919
scikit_build_core.hatch
2020
scikit_build_core.metadata
21+
scikit_build_core.repair_wheel
2122
scikit_build_core.resources
2223
scikit_build_core.settings
2324
scikit_build_core.setuptools

src/scikit_build_core/build/wheel.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
from ..cmake import CMake, CMaker
2121
from ..errors import FailedLiveProcessError
2222
from ..format import pyproject_format
23+
from ..repair_wheel import WheelRepairer
2324
from ..settings.skbuild_read_settings import SettingsReader
2425
from ._editable import editable_redirect, libdir_to_installed, mapping_to_modules
2526
from ._init import setup_logging
@@ -515,6 +516,12 @@ def _build_wheel_impl_impl(
515516
f"_{normalized_name}_editable.pth",
516517
"\n".join(str_pkgs).encode(),
517518
)
519+
if settings.wheel.repair:
520+
repairer = WheelRepairer.get_wheel_repairer(
521+
wheel=wheel,
522+
builder=builder,
523+
)
524+
repairer.repair_wheel()
518525

519526
if metadata_directory is not None:
520527
dist_info_contents = wheel.dist_info_contents()
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
"""
2+
Repair wheel
3+
"""
4+
5+
from __future__ import annotations
6+
7+
import dataclasses
8+
import platform
9+
from abc import ABC, abstractmethod
10+
from importlib import import_module
11+
from typing import TYPE_CHECKING, ClassVar, Final
12+
13+
from .._logging import logger
14+
15+
if TYPE_CHECKING:
16+
from ..build._wheelfile import WheelWriter
17+
from ..builder.builder import Builder
18+
19+
20+
__all__ = [
21+
"WheelRepairer",
22+
]
23+
24+
25+
@dataclasses.dataclass()
26+
class WheelRepairer(ABC):
27+
"""Abstract wheel repairer."""
28+
29+
wheel: WheelWriter
30+
"""The current wheel creator."""
31+
builder: Builder
32+
"""CMake builder used."""
33+
_platform_repairers: ClassVar[dict[str, type[WheelRepairer]]] = {}
34+
"""Dictionary of platform specific repairers"""
35+
_platform: ClassVar[str | None] = None
36+
"""The ``platform.system()`` corresponding to the current repairer."""
37+
_initialized: Final[bool] = False
38+
"""Whether all ``WheelRepairer`` have been initialized."""
39+
40+
def __init_subclass__(cls) -> None:
41+
if cls._platform:
42+
WheelRepairer._platform_repairers[cls._platform] = cls
43+
44+
@abstractmethod
45+
def repair_wheel(self) -> None:
46+
"""Repair the current wheel."""
47+
48+
@classmethod
49+
def get_wheel_repairer(
50+
cls,
51+
wheel: WheelWriter,
52+
builder: Builder,
53+
) -> WheelRepairer:
54+
"""Construct the platform specific wheel repairer"""
55+
WheelRepairer.initialize()
56+
if not (
57+
repairer_cls := WheelRepairer._platform_repairers.get(platform.system())
58+
):
59+
return NoopWheelRepairer(
60+
wheel=wheel,
61+
builder=builder,
62+
)
63+
return repairer_cls(
64+
wheel=wheel,
65+
builder=builder,
66+
)
67+
68+
@classmethod
69+
def initialize(cls) -> None:
70+
"""Get all known wheel repairers."""
71+
if cls._initialized:
72+
return
73+
# TODO: Allow for other wheel repairers defined as entry-points
74+
try:
75+
if (platform_system := platform.system().lower()) in (
76+
"linux",
77+
"darwin",
78+
"windows",
79+
):
80+
import_module(f".{platform_system}", package=__name__)
81+
except ImportError:
82+
logger.error(
83+
"Could not load the platform specific wheel repairer. Make sure you include "
84+
"the optional dependency [wheel-repair] in the build-system.requires"
85+
)
86+
raise
87+
88+
89+
class NoopWheelRepairer(WheelRepairer):
90+
"""Dummy wheel repairer that just shows a warning."""
91+
92+
def repair_wheel(self) -> None:
93+
# Do nothing
94+
logger.warning("Unknown platform {}. Not doing any repair.", platform.system())
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
"""
2+
Repair MacOS RPATH
3+
"""
4+
5+
from __future__ import annotations
6+
7+
import macholib # noqa: F401
8+
9+
from . import WheelRepairer
10+
11+
__all__ = ["MacOSWheelRepairer"]
12+
13+
14+
class MacOSWheelRepairer(WheelRepairer):
15+
"""
16+
Adjust the RPATH with @loader_path.
17+
"""
18+
19+
_platform = "Darwin"
20+
21+
def repair_wheel(self) -> None:
22+
raise NotImplementedError
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
"""
2+
Repair Linux RPATH
3+
"""
4+
5+
from __future__ import annotations
6+
7+
import elftools # noqa: F401
8+
9+
from . import WheelRepairer
10+
11+
__all__ = ["LinuxWheelRepairer"]
12+
13+
14+
class LinuxWheelRepairer(WheelRepairer):
15+
"""
16+
Adjust the RPATH with $ORIGIN.
17+
"""
18+
19+
_platform = "Linux"
20+
21+
def repair_wheel(self) -> None:
22+
raise NotImplementedError
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
"""
2+
Repair Windows dll path
3+
"""
4+
5+
from __future__ import annotations
6+
7+
import pefile # noqa: F401
8+
9+
from . import WheelRepairer
10+
11+
__all__ = ["WindowsWheelRepairer"]
12+
13+
14+
class WindowsWheelRepairer(WheelRepairer):
15+
"""
16+
Do some windows specific magic.
17+
"""
18+
19+
_platform = "Windows"
20+
21+
def repair_wheel(self) -> None:
22+
raise NotImplementedError

0 commit comments

Comments
 (0)