Erstellen verteilungsfähiger Binärdateien#

Die Zielgruppe für diesen Abschnitt sind alle, die SciPy erstellen und es auf anderen Rechnern als ihrem eigenen bereitstellen möchten – von Distributionspaketen bis hin zu Benutzern, die Wheels erstellen möchten, um sie in ihrer Produktionsumgebung bereitzustellen.

Wenn python -m build oder pip wheel verwendet wird, um ein SciPy-Wheel zu erstellen, hängt dieses Wheel von externen gemeinsam genutzten Bibliotheken ab (zumindest für BLAS/LAPACK und eine Fortran-Compiler-Laufzeitbibliothek, möglicherweise auch andere Bibliotheken). Solche Wheels laufen daher nur auf dem System, auf dem sie erstellt wurden. Weitere Informationen hierzu finden Sie in den pypackaging-native Inhalten unter „Building and installing or uploading artifacts“.

Ein solches Wheel ist daher ein Zwischenschritt zur Erzeugung einer Binärdatei, die verteilt werden kann. Diese endgültige Binärdatei kann ein Wheel sein – in diesem Fall führen Sie auditwheel (Linux), delocate (macOS), delvewheel (Windows) oder repairwheel (plattformunabhängig) aus, um die erforderlichen gemeinsam genutzten Bibliotheken in das Wheel einzubinden.

Die endgültige Binärdatei kann auch in einem anderen Paketformat vorliegen (z. B. einem .rpm, .deb oder .conda Paket). In diesem Fall gibt es spezifische Werkzeuge für das Paketökosystem, um zuerst das Wheel in einen Staging-Bereich zu installieren, dann die Erweiterungsmodule an diesem Installationsort verschiebbar zu machen (z. B. durch Umschreiben von RPATHs) und sie dann in das endgültige Paketformat zurückzuverpacken.

Build- und Laufzeitabhängigkeiten#

Die Python-Build- und Laufzeitabhängigkeiten, die zum Erstellen von SciPy benötigt werden, finden Sie in den Metadaten von pyproject.toml. Beachten Sie, dass für veröffentlichte Versionen von SciPy die Abhängigkeiten wahrscheinlich Obergrenzen haben. Jede Obergrenze hat Kommentare darüber; Paketierer können die Obergrenzen in den meisten Fällen entfernen oder lockern (außer für numpy). Z.B.

# The upper bound on pybind11 is preemptive only
"pybind11>=2.12.0,<2.13.0",

#   ...
#   3. The <2.3 upper bound is for matching the numpy deprecation policy,
#      it should not be loosened.
"numpy>=2.0.0rc1,<2.3",

Nicht-Python-Build-Anforderungen sind

  • C-, C++- und Fortran-Compiler

  • BLAS- und LAPACK-Bibliotheken

  • ninja

  • pkg-config

Minimale Versionen gängiger Compiler werden in der obersten Ebene von meson.build erzwungen. Die minimale LAPACK-Version ist derzeit 3.7.1. Detailliertere Informationen zu diesen Build-Abhängigkeiten finden Sie in Toolchain Roadmap.

Verwendung von Systemabhängigkeiten anstelle von gebündelten Quellen#

SciPy enthält *viel* Code, der aus in C, C++ und Fortran geschriebenen Bibliotheken gebündelt wurde. Dies geschieht aus einer Mischung aus historischen und Robustheitsgründen. Distributionspakete haben manchmal Gründe, diesen Code *entbündeln* zu wollen, um sicherzustellen, dass sie nur eine einzige Version einer bestimmten Bibliothek verwenden. Wir bieten eine Build-Option, -Duse-system-libraries, um ihnen dies erheblich zu erleichtern, als es durch manuelles Patchen von SciPy möglich wäre.

$ python -m build -wnx -Duse-system-libraries=boost.math

Diese Build-Option löst eine Abhängigkeitssuche *nach der exakten gleichen Version* aus, die in SciPy gebündelt ist. Eine andere Systemversion wird nicht akzeptiert, der Build wird dann auf die gebündelten Quellen zurückfallen oder fehlschlagen. Dies liegt daran, dass unterschiedliche Versionen leicht zu Fehlern zur Build-Zeit oder zur Laufzeit führen können und SciPy's CI nicht mit anderen Versionen testet. Dies kann sich in Zukunft ändern, aber derzeit erfordert die Verwendung einer anderen Version das Patchen der entsprechenden Versionsprüfung und wird dringend abgeraten.

Ratschläge für Paketierer

  1. Sie sollten diese Build-Option so betrachten: „Wenn ich eine Bibliothek aus zwingenden Gründen bereits entbinde, erleichtert diese Option dies erheblich.“

  2. Sie sollten nicht standardmäßig alles entbinden, da dies zu Diamant-Abhängigkeiten und mehr Build-Komplexität bei geringem Gewinn führt. Die meisten dieser Bibliotheken werden nicht so gut gewartet wie SciPy und/oder sind dafür bekannt, keine stabile API anzubieten. Effektiv würden Sie für jede entbundene Bibliothek eine zusätzliche == Abhängigkeit hinzufügen. Tun Sie dies nur aus gutem Grund. Z. B. können Sie Patches entfernen, Sie betrachten sowohl SciPy als auch die betreffende gebündelte Bibliothek als sicherheitskritisch, oder es ist ein großer Gewinn bei der Binärgröße.

Die Build-Option nimmt die folgenden Werte an

  • none: Verwendet den als Teil von SciPy mitgelieferten Quellcode, sucht nicht nach externen Abhängigkeiten (Standard).

  • all: Verwendet externe Bibliotheken für alle Komponenten, die von use-system-libraries gesteuert werden, und gibt einen Fehler aus, wenn sie nicht gefunden werden. Die Erkennung erfolgt durch Meson, typischerweise zuerst über die pkg-config und dann über die cmake Methode der dependency() Funktion.

  • auto: Versucht, externe Bibliotheken zu erkennen, und wenn sie nicht gefunden werden, greift es auf gebündelte Quellen zurück.

  • Eine durch Kommas getrennte Liste von Abhängigkeitsnamen (z. B. boost.math,qhull). Wenn angegeben, wird das all Verhalten für die benannten Abhängigkeiten (und none für den Rest) verwendet. Unterstützte Optionen sind

    • boost.math (seit 1.16.0)

    • qhull (seit 1.16.0)

Es ist auch gültig, die generischen und benannten Optionen oben zu kombinieren, z. B. wendet boost.math,auto das auto Verhalten auf alle Abhängigkeiten außer boost.math an.

Entfernen der Testsuite aus einem Wheel oder einem installierten Paket#

Standardmäßig enthält eine installierte Version von scipy die vollständige Testsuite. Diese Testsuite, einschließlich Datendateien und kompilierter Erweiterungsmodule, die nur für Tests bestimmt sind, nimmt etwa 4,5 MB in einem Wheel ein (für x86-64, ab v1.14.0) und mehr auf der Festplatte. In Fällen, in denen die Binärgröße wichtig ist, möchten Paketierer möglicherweise die Testsuite entfernen. Ab SciPy 1.14.0 gibt es eine bequeme Möglichkeit, dies zu tun, indem die Meson-Funktionalität für Installations-Tags genutzt wird. Es ist eine Einzeiler

$ python -m build -wnx -Cinstall-args=--tags=runtime,python-runtime,devel

Hinweis

Beachten Sie, dass in dem obigen Befehl -wnx für --wheel --no-isolation --skip-dependency-check steht. Es wird davon ausgegangen, dass der Paketierer die Build-Umgebung bereits eingerichtet hat, was für Distributionspakete üblich ist. Die Installations-Tags-Funktion funktioniert gleichermaßen gut mit isolierten Builds (z. B. pip install scipy --no-binary -Cinstall-args=--tags=runtime,python-runtime,devel).

Wenn Sie ein separates Paket für die Tests selbst erstellen möchten, z. B. unter dem Namen scipy-tests, bearbeiten Sie pyproject.toml, um den Projektnamen zu ändern

[project]
name = "scipy-tests"

Und bauen Sie dann mit

$ python -m build -wnx -Cinstall-args=--tags=tests

Das obige würde das gesamte Paket zweimal erstellen; um in einem gecachten Modus neu zu erstellen, verwenden Sie die Build-Option -Cbuild-dir=build

$     $ # apply patch to change the project name in pyproject.toml
$ python -m build -wnx -Cbuild-dir=build -Cinstall-args=--tags=tests

Das Endergebnis sieht dann etwa so aus

$ ls -lh dist/*.whl
...  20M  ...  dist/scipy-1.14.0-cp311-cp311-linux_x86_64.whl
...  4,5M ...  dist/scipy_tests-1.14.0-cp311-cp311-linux_x86_64.whl