Delocate macOS Dynamic Library Bundler
delocate is a Python library and command-line tool designed to move macOS dynamic libraries into Python packages, particularly for wheels. It helps bundle native dependencies directly into a wheel, making it self-contained and distributable across macOS systems. Currently at version 0.13.0, it maintains an active release cadence with regular updates.
Warnings
- breaking The command-line tool `delocate-fuse` was removed in version 0.12.0. Its functionality for merging wheels is now provided by the `delocate-merge` command.
- breaking Starting with version 0.12.0, the `--sanitize-rpaths` behavior is enabled by default for `delocate-wheel` and `delocate_wheel`. This means RPATHs in bundled binaries will be automatically sanitized, which might alter the resulting wheel compared to previous versions.
- breaking The `patch_wheel` function (internally used by `delocate_wheel` and `delocate-wheel`) now raises `FileNotFoundError` instead of `ValueError` when required patch files are missing. This change impacts error handling for missing dependencies within the wheel.
- deprecated Functions `get_rpaths`, `get_install_id`, and `unique_by_index` are deprecated as of version 0.13.0. These functions are being phased out, particularly due to their lack of comprehensive multi-architecture support.
Install
-
pip install delocate
Imports
- delocate_wheel
from delocate.delocating import delocate_wheel
- fuse_trees
from delocate.fuse import fuse_trees
- merge_wheels
from delocate.merge import merge_wheels
Quickstart
import os
import shutil
from pathlib import Path
from delocate.delocating import delocate_wheel
# This quickstart demonstrates how to programmatically call delocate_wheel.
# For a real use case, 'input_wheel_path' would be a path to a built .whl file
# that contains macOS dynamic libraries.
# Define paths for a dummy scenario
output_dir = Path("delocated_wheels_output")
dummy_wheel_name = "my_package-1.0-py3-none-any.whl" # Placeholder
input_wheel_path = Path(dummy_wheel_name) # This path needs to exist for real operation
output_wheel_path = output_dir / dummy_wheel_name
# Ensure output directory exists for illustration, and remove if run multiple times
if output_dir.exists():
shutil.rmtree(output_dir)
output_dir.mkdir(parents=True, exist_ok=True)
print(f"Attempting to delocate a dummy wheel '{input_wheel_path}'\n"
f"and save processed output to '{output_wheel_path}'.\n"
f"NOTE: This will fail unless '{input_wheel_path}' is a real .whl file.")
try:
# In a real scenario, input_wheel_path would point to an existing .whl.
# delocate_wheel will attempt to read, modify, and write the wheel.
# Using a non-existent path here illustrates the function call pattern.
delocate_wheel(
str(input_wheel_path),
str(output_wheel_path),
lib_sdir='.dylibs', # Default is 'delocate'
check_archs=True,
require_archs=None,
check_libs=True,
always_copy_libs=False,
signed_libs=False,
repair_libs=True,
fix_rpaths=True, # Default to True since 0.12.0
strip_executables=True,
ignore_missing_libraries=False,
verbose=1
)
print(f"Successfully called delocate_wheel (output to: {output_wheel_path}).")
except Exception as e:
# delocate_wheel will raise an error if input_wheel_path does not exist
print(f"Caught expected error (input wheel not found for dummy example): {type(e).__name__}: {e}")
# Cleanup dummy output directory
if output_dir.exists():
shutil.rmtree(output_dir)