Skip to content

Commit 4a1b4e1

Browse files
committed
Document wheel repair feature
Signed-off-by: Cristian Le <[email protected]>
1 parent 2e5f0e8 commit 4a1b4e1

File tree

3 files changed

+108
-1
lines changed

3 files changed

+108
-1
lines changed

docs/conf.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@
9090

9191

9292
intersphinx_mapping = {
93+
"cmake": ("https://cmake.org/cmake/help/latest/", None),
9394
"python": ("https://docs.python.org/3", None),
9495
"packaging": ("https://packaging.pypa.io/en/stable", None),
9596
"setuptools": ("https://setuptools.pypa.io/en/latest", None),
@@ -99,7 +100,7 @@
99100
val[0]
100101
for key, val in intersphinx_mapping.items()
101102
# Only works with RTD hosted intersphinx
102-
if key not in ("hatchling", "python")
103+
if key not in ("hatchling", "python", "cmake")
103104
]
104105

105106
nitpick_ignore = [

docs/guide/dynamic_link.md

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
# Dynamic linking
2+
3+
If you want to support dynamic linkages between python projects or system
4+
libraries, you will likely encounter some issues in making sure the compiled
5+
libraries/python bindings work after the wheel is created and the python project
6+
is installed on the system. The most common issue are the missing hints pointing
7+
to where the runtime libraries are located, specifically `RPATH` on Linux and
8+
MacOS systems, and `PATH`/`os.add_dll_directory` on Windows systems. Here are
9+
some recommendations on how to address them.
10+
11+
## Link to the static libraries
12+
13+
The easiest solution is to make sure you link to the static libraries
14+
counterparts during the CMake build. How to achieve this depends on the specific
15+
dependency, how it is imported in the CMake project and how the dependency is
16+
packaged in each ecosystem.
17+
18+
For example for [Boost][FindBoost] this is controlled via the variable
19+
`Boost_USE_STATIC_LIBS`.
20+
21+
[FindBoost]: inv:cmake:cmake:module#module:FindBoost
22+
23+
## Wheel repair tools
24+
25+
There are wheel repair tools for each operating system that bundle any dynamic
26+
libraries used and patch the libraries/python bindings to point to prioritize
27+
those libraries. The most common tools for these are [auditwheel] for Linux,
28+
[delocate] for MacOS and [delvewheel] for Windows. [cibuildwheel] incorporates
29+
these tools in its [repair wheel] feature.
30+
31+
One downside of these tools is that all dependencies are duplicated and bundled
32+
in each project.
33+
34+
[auditwheel]: https://pypi.org/project/auditwheel/
35+
[delocate]: https://pypi.org/project/delocate/
36+
[delvewheel]: https://pypi.org/project/delvewheel/
37+
[cibuildwheel]: https://cibuildwheel.pypa.io/en/stable/
38+
[repair wheel]:
39+
https://cibuildwheel.pypa.io/en/stable/options/#repair-wheel-command
40+
41+
## scikit-build-core wheel repair
42+
43+
:::{note}
44+
45+
This is an experimental feature currently under development.
46+
47+
:::
48+
49+
The wheel repair provided by scikit-build-core works in a similar way to the
50+
[wheel repair tools], but for any dependency that is provided in the
51+
`build-system.requires`, the libraries are linked to the dynamic libraries
52+
provided in the dependency's wheel.
53+
54+
To enable this feature set `wheel.repair` flag
55+
56+
```toml
57+
[tool.scikit-build]
58+
wheel.repair = true
59+
```
60+
61+
:::{note}
62+
63+
Bundling of dynamic libraries is not yet supported.
64+
65+
:::
66+
67+
:::{note}
68+
69+
For packagers, this feature may need to be disabled in order for the system
70+
packages to be used as the default.
71+
72+
:::
73+
74+
[wheel repair tools]: #wheel-repair-tools
75+
76+
## Manual patching
77+
78+
For maximum control, you can do the equivalent patching inside CMake manually.
79+
This is not recommended because it does not have access to the python
80+
environment metadata.
81+
82+
The `RPATH` patching can be done as
83+
84+
```cmake
85+
if(APPLE)
86+
set(origin_token "@loader_path")
87+
else()
88+
set(origin_token "$ORIGIN")
89+
endif()
90+
set_property(TARGET <target> PROPERTY INSTALL_RPATH
91+
"${origin_token}/install_path/to/dynamic_library"
92+
)
93+
```
94+
95+
For Windows patching, this has to be done at the python files using
96+
`os.add_dll_directory` at the top-most package `__init__.py` file or top-level
97+
python module files.
98+
99+
```python
100+
import os
101+
from pathlib import Path
102+
103+
dependency_dll_path = Path(__file__).parent / "install_path/to/dynamic_library"
104+
os.add_dll_directory(str(dependency_dll_path))
105+
```

docs/index.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ first Friday of every month at the same time. Our past meeting minutes are
2929
3030
guide/getting_started
3131
guide/cmakelists
32+
guide/dynamic_link
3233
guide/crosscompile
3334
guide/migration_guide
3435
guide/build

0 commit comments

Comments
 (0)