Skip to content

Commit f68b451

Browse files
Marius1311claude
andauthored
Make uv resolve gpcca-fast without compiling PETSc (#86)
petsc4py/slepc4py compute their metadata dynamically at build time, so any bare `uv sync`/`uv run`/`uv lock` compiled PETSc from source just to resolve the dependency universe — and that source build fails on machines without a system BLAS on the linker path (e.g. isolated CI/uv build envs), where PETSc configure errors with "Could not find a functional BLAS". Add [[tool.uv.dependency-metadata]] entries mirroring the deps petsc4py/ slepc4py inject at build time, so uv resolves them from static metadata without ever building (resolves in ~5s). PETSc/SLEPc now compile only when the gpcca-fast group is actually installed. Also correct the (copied-from-CellRank) source-build recipe in the group comment: the documented options provide no BLAS and fail here; document the pre-built conda-forge/pixi path as the recommended install and a shared-BLAS source build as the fallback. uv.lock stays gitignored (library convention; hatch does not use it) — the static metadata is what unblocks resolution, so no lockfile is required. Local checks remain petsc-free via `hatch test` (features dev+test), which never pulls this dependency group. Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent 54aff95 commit f68b451

1 file changed

Lines changed: 34 additions & 5 deletions

File tree

pyproject.toml

Lines changed: 34 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -94,11 +94,27 @@ urls.Source = "https://github.com/quadbio/cellmapper"
9494
# correctly, so petsc needs no such workaround.) Drop this once slepc4py — or
9595
# cellrank's petsc extra — declares slepc.
9696
#
97-
# The build needs a C compiler only (no Fortran/MPI/system libs) IF you pass
98-
# PETSC_CONFIGURE_OPTIONS. Do NOT set SLEPC_CONFIGURE_OPTIONS — SLEPc inherits
99-
# config from the built PETSc. Install (one-time source build, ~4 min, cached):
100-
# PETSC_CONFIGURE_OPTIONS="--with-fc=0 --with-mpi=0 --with-debugging=0 --with-shared-libraries=1" \
101-
# uv sync --all-extras --group gpcca-fast
97+
# petsc4py/slepc4py compute their metadata dynamically at build time. Without help,
98+
# uv would therefore compile PETSc from source just to *resolve* — breaking every
99+
# bare `uv sync` / `uv run` / `uv lock`, even when this group is NOT requested. The
100+
# [[tool.uv.dependency-metadata]] entries under [tool.uv] give uv that metadata
101+
# statically, so resolution/locking never builds anything; PETSc/SLEPc compile only
102+
# when the group is actually installed. Keep those entries in sync with this group.
103+
#
104+
# INSTALLING the group is the fragile part. The recommended route is pre-built
105+
# conda-forge binaries (no compiler, no BLAS hunting), e.g. with pixi/mamba:
106+
# mamba install -c conda-forge petsc4py slepc4py # or: pixi add petsc4py slepc4py
107+
# Building from PyPI source instead needs a C compiler AND a BLAS/LAPACK. The
108+
# CellRank-documented options alone (--with-fc=0 --with-mpi=0 --with-debugging=0
109+
# --with-shared-libraries=1) only work on machines that already expose a system
110+
# BLAS on the linker path; on others PETSc configure fails with "Could not find a
111+
# functional BLAS". Adding --download-f2cblaslapack=1 gets PETSc to build but then
112+
# SLEPc fails to link it (`cannot find -lf2cblas`), so for a source build point
113+
# PETSc at a real shared BLAS instead, e.g.:
114+
# PETSC_CONFIGURE_OPTIONS="--with-fc=0 --with-mpi=0 --with-debugging=0 \
115+
# --with-shared-libraries=1 --with-blaslapack-dir=$OPENBLAS_ROOT" \
116+
# uv sync --all-extras --group gpcca-fast
117+
# Do NOT set SLEPC_CONFIGURE_OPTIONS — SLEPc inherits config from the built PETSc.
102118
# NB: a plain `uv sync --all-extras` (without --group gpcca-fast) will UNINSTALL
103119
# petsc/slepc if present — re-include the group on every refresh to keep them.
104120
[dependency-groups]
@@ -133,6 +149,19 @@ envs.hatch-test.overrides.matrix.deps.env-vars = [
133149
# jinja2==3.0.3, which conflicts with sphinx (doc extra). Override until a
134150
# pygpcca release relaxes it. jinja2>=3.1 is known-safe (cellrank does the same).
135151
override-dependencies = [ "jinja2>=3.1" ]
152+
# Static metadata for the gpcca-fast source-only packages so uv can resolve/lock
153+
# WITHOUT compiling PETSc (see the note above [dependency-groups]). These mirror
154+
# the deps each package injects dynamically at build time: petsc4py -> petsc,
155+
# slepc4py -> petsc4py + slepc (slepc4py's own sdist omits slepc). The `petsc`/
156+
# `slepc` library packages have no Python dependencies. Version omitted -> applies
157+
# to all versions; petsc & petsc4py (and slepc & slepc4py) are always co-released
158+
# at matching versions, so uv resolves them in lockstep.
159+
dependency-metadata = [
160+
{ name = "petsc", requires-dist = [] },
161+
{ name = "slepc", requires-dist = [] },
162+
{ name = "petsc4py", requires-dist = [ "numpy", "petsc" ] },
163+
{ name = "slepc4py", requires-dist = [ "numpy", "petsc4py", "slepc" ] },
164+
]
136165

137166
[tool.ruff]
138167
line-length = 120

0 commit comments

Comments
 (0)