3.1 KiB
Integrating Local Binary Extensions with uv
This guide explains how we packaged the local pyzed binary extension (originally from a system installation) so that uv can manage it as a project dependency.
The Problem
The ZED SDK installs its Python wrapper (pyzed) as a system-level package (often in /usr/local/lib/...). It consists of compiled extensions (.so or .sl files) and Python bindings.
uv strictly manages virtual environments and dependencies. It cannot directly "see" or import packages from the global system site-packages unless explicitly configured to use system site-packages (which reduces isolation). Furthermore, a raw .so file or a bare directory without metadata isn't a valid package source for uv.
The Solution: A Local Package Wrapper
To make pyzed compatible with uv, we wrapped the raw library files into a proper, minimally compliant Python package located at libs/pyzed_pkg.
1. Directory Structure
We organized the files into a standard package layout:
libs/pyzed_pkg/
├── pyproject.toml # Package metadata (CRITICAL)
└── pyzed/ # The actual importable package
├── __init__.py
├── sl.cpython-312-x86_64-linux-gnu.so # The compiled extension
└── ...
2. The Local pyproject.toml
We created a pyproject.toml inside libs/pyzed_pkg to tell build tools how to handle the files.
Key configuration points:
- Build System: Uses
setuptoolsto bundle the files. - Package Discovery: Explicitly lists
pyzed. - Package Data: Crucially, configures
setuptoolsto include binary files (*.so,*.pyi) which are usually ignored by default.
[project]
name = "pyzed"
version = "0.1.0"
description = "Wrapper for ZED SDK"
requires-python = ">=3.12"
dependencies = []
[build-system]
requires = ["setuptools", "wheel"]
build-backend = "setuptools.build_meta"
[tool.setuptools]
packages = ["pyzed"]
# IMPORTANT: Ensure the binary extension is included in the build
[tool.setuptools.package-data]
pyzed = ["*.so", "*.pyi"]
Configuring the Main Project
In the root pyproject.toml of your application, we used [tool.uv.sources] to redirect the pyzed dependency to our local path.
[project]
dependencies = [
"pyzed", # Declared as a normal dependency
"cupy-cuda12x",
"numpy",
]
# uv-specific configuration
[tool.uv.sources]
pyzed = { path = "libs/pyzed_pkg" }
How uv Processes This
- Resolution: When you run
uv syncoruv run,uvseespyzedin the dependencies. - Source Lookup: It checks
tool.uv.sourcesand finds the local pathlibs/pyzed_pkg. - Build/Install:
uvtreats the directory as a source distribution.- It uses the
build-systemdefined inlibs/pyzed_pkg/pyproject.tomlto build a temporary wheel. - This wheel (containing the
.sofile) is installed into the project's virtual environment (.venv).
This ensures that your application works seamlessly with import pyzed.sl while maintaining a clean, isolated, and reproducible environment managed by uv.