工具链路线图#

使用 SciPy 库需要(或可选地依赖于)其他几个库才能运行,主要依赖项是 Python 和 NumPy。为了构建库或构建文档,它需要更大范围的库和工具。

当然,工具和库本身并不是静态的。本文档旨在提供一个指南,说明SciPy如何随着时间的推移处理这些动态依赖关系。

SciPy 旨在与其依赖的库和工具的多个版本兼容。强制用户每次发布时升级其他组件将大大降低 SciPy 的价值。然而,与非常旧的工具/库保持向后兼容性会对可以纳入的新功能和能力施加限制。SciPy 采取了一种较为保守的方法,在主要平台上保持与 Python 和 NumPy 的几个主要版本的兼容性。(这本身可能会施加进一步的限制。例如,请参阅 C 编译器部分。)

  • 首先,SciPy 是一个 Python 项目,因此它需要一个 Python 环境。

  • 需要安装 BLAS 和 LAPACK 数值库。

  • 需要 C、C++、Fortran 代码的编译器,以及 Cython 和 Pythran 的编译器(后者目前是可选的)

  • Python 环境需要安装 numpy 包。

  • 测试需要 pytesthypothesis Python 包。

  • 构建文档需要 matplotlib、Sphinx 和 MyST-NB 包,以及 PyData 主题。

用于构建 CPython 的工具对用于构建 SciPy 的工具有一定影响。它还对文档中使用的示例(例如,函数的文档字符串)有影响,因为这些示例只能使用所有支持的配置中都存在的功能。

构建 SciPy#

Python 版本#

SciPy 兼容多个版本的 Python。当放弃对旧版本 Python 的支持时,SciPy 会参考 [NEP29]。通常,最旧的 Python 版本的支持会在原始发布后的 42 个月后被放弃。随着 PEP 602 的接受,这主要发生在四月,并由 SciPy 年中发布的版本采纳。

Python 版本支持随时间变化

从 SciPy 1.3 开始,Python 2.7 的支持已被放弃。

日期

支持的Python版本

2024

Py3.10+

2023

Py3.9+

2022

Py3.8+

2021

Py3.7+

2020

Py3.6+

2019

Py3.5+

2018

Py2.7, Py3.4+

NumPy#

SciPy 依赖于 NumPy,但 SciPy 的发布并不与 NumPy 的发布绑定。SciPy 试图与至少前 4 个版本的 NumPy 兼容。特别是,SciPy 不能仅仅依赖于最新 NumPy 的功能,而是需要使用这 4 个 NumPy 版本 中的共同功能来编写。

每个 SciPy 版本支持的 Python 和 NumPy 版本

该表显示了适用于每个主要 Python 版本的 NumPy 版本。此表不区分 SciPy 补丁版本(例如,当发布新的 Python 版本时,SciPy 通常会发布兼容的补丁版本)。

SciPy 版本

Python 版本

NumPy 版本

1.13

>=3.9, <3.13

>=1.22.4, <2.3.0

1.12

>=3.9, <3.13

>=1.22.4, <2.0.0

1.11

>=3.9, <3.13

>=1.21.6, <1.27.0

1.10

>=3.8, <3.12

>=1.19.5, <1.26.0

1.9

>=3.8, <3.12

>=1.18.5, <1.26.0

1.8

>=3.8, <3.11

>=1.17.3, <1.24.0

1.7

>=3.7, <3.11

>=1.16.5, <1.23.0

1.6

>=3.7, <3.10

>=1.16.5, <1.21.0

1.5

>=3.6, <3.10

>=1.14.5, <1.20.0

1.4

>=3.5, <3.9

>=1.13.3, <1.18.0

1.2

2.7, >=3.4, <3.8

>=1.8.2, <1.17.0

在特定情况下,例如特定的架构,这些要求可能会有所不同。请查看 发布说明 和元包 oldest-supported-numpy 以获取更多信息 [OSN]

编译器#

构建 SciPy 需要 C、C++、Fortran 的编译器,以及 Python 的转译器 Cython 和 Pythran(后者从版本 1.7.0 开始是可选依赖)。

为了保持与大量平台和设置的兼容性,特别是在无法使用官方轮子(或其他分发渠道如Anaconda或conda-forge)的情况下,SciPy努力保持与旧编译器的兼容性,这些平台尚未达到其官方生命周期的终点。

如下文更详细地解释,当前的最小编译器版本是:

编译器

默认平台(已测试)

次级平台(未测试)

最小版本

GCC

Linux

AIX, Alpine Linux, OSX

GCC 9.x

LLVM

OSX

Linux, FreeBSD, Windows

LLVM 12.x

MSVC

Windows

Visual Studio 2019 (vc142)

请注意,目前没有专门的 CI 任务来测试最低支持的 LLVM/Clang 版本。只要它们支持核心(非标准库)C++17,比 SciPy CI 中使用的更旧的版本应该也能工作。如果在编译过程中遇到问题,请提交一个 issue。

官方构建#

目前,SciPy 轮子正在以下列方式构建:

平台

CI Base Images

编译器

评论

Linux x86

ubuntu-22.04

GCC 10.2.1

cibuildwheel

Linux arm

docker-builder-arm64

GCC 11.3.0

cibuildwheel

OSX x86_64 (OpenBLAS)

macos-12

Apple clang 13.1.6/gfortran 11.3.0

cibuildwheel

OSX x86_64 (加速)

macos-13

Apple clang 15.0.0/gfortran 13.2.0

cibuildwheel

OSX arm64 (OpenBLAS)

macos-14

Apple clang 15.0.0/gfortran 12.1.0

cibuildwheel

OSX arm64 (加速)

macos-14

Apple clang 15.0.0/gfortran 13.2.0

cibuildwheel

Windows

windows-2019

GCC 10.3.0 (rtools)

cibuildwheel

请注意,OSX 轮子额外包含了为 x86_64 编译的 gfortran 11.3.0,以及为 arm64 编译的 gfortran 12.1.0。请参见 tools/wheels/cibw_before_build_macos.sh

C 编译器#

SciPy 兼容大多数现代 C 编译器(特别是 clang)。如今,所有相关编译器对最新 C 语言标准的支持都相当合理,尽管这与过去的情况大不相同。以下段落主要讨论这些约束的演变;不关心历史背景的读者可以跳到最后的表格。

关于 ABI 与编译器支持与 C 标准的历史背景

在过去,在相关平台上对C语言支持最严格的编译器是微软的Visual C++编译器和工具集(统称为MSVC;它有一个复杂的`版本方案`_)[MSVC]_。直到Visual Studio 2013,每个MSVC版本都附带了一个更新的C运行时(CRT)库,该库与之前的版本不兼容。

应用程序二进制接口(ABI)的不兼容性意味着所有希望通过此接口进行通信的项目(例如,从共享库调用函数)都需要使用相同的MSVC版本进行(重新)编译。CPython 2.7的长期支持意味着Python本身长时间停留在VS 2008上(以避免在补丁发布中破坏ABI),因此SciPy也被困在了那个版本。

使用 VS 2008(不支持 C99)来编译 CPython 2.7 的构建意味着 SciPy 中的 C 代码长期以来必须符合早期的 C90 语言和标准库标准。在 SciPy 1.3.x 中放弃对 CPython 2.7 的支持后,这一限制终于被解除(尽管起初只是逐步解除)。

随着Visual Studio 2015发布以来引入的“通用C运行时” [UCRT],C运行时的ABI已经稳定,这意味着不再需要SciPy与底层CPython版本使用相同编译器版本的限制。然而,这种稳定性并非无限期:微软计划了跨编译器/C/C++标准库的ABI破坏性发布(暂称为“vNext”)已经有一段时间了,但目前尚不清楚何时会到来。一旦发生这种情况,SciPy将再次被限制在最多最后一个ABI兼容的Visual Studio版本(目前为VS 2022),直到根据NEP29支持的所有CPython版本都已在上游使用vNext兼容的编译器构建。

更具体地说,微软Visual Studio版本和目标“toolset”版本之间存在区别,后者被定义为“微软C++编译器、链接器、标准库及相关实用工具”。每个Visual Studio版本都附带一个默认的MSVC工具集版本(例如VS2017附带vc141,VS2019附带vc142),但在较新版本的Visual Studio中也可以针对较旧的工具集。由于编译器的性质(即分为前端和后端),支持某一特性(例如在C语言中)的限制因素取决于Visual Studio版本还是工具集,但通常后者是更难逾越的障碍,因此是实际的下限。

这是由于以下事实:尽管ABI在工具集版本之间保持兼容(直到vNext),所有链接操作必须使用至少与用于构建任何相关工件的工具集一样新的工具集,这意味着工具集版本升级往往具有“传染性”,即:要求所有使用的库也升级其工具集(可能还有编译器)版本。这对于NumPy来说比SciPy更为问题,因为后者只有一个小型的C API,并且被编译的项目远少于NumPy。此外,使用较新的工具集意味着编译C++代码(如SciPy所做的)的库的用户可能也需要一个较新的Microsoft Visual C++ Redistributable,这可能需要分发给他们。

总之,MSVC 编译器或工具集对 SciPy 版本的最低要求主要由当时支持的最旧 CPython 版本决定。第一个提高最低要求的 SciPy 版本是 SciPy 1.9,这是由于包含了 HiGHS 子模块,该子模块无法使用 vc141 编译(并且在公共 CI 中积极移除 VS2017,使得确保所有内容在非默认工具集版本下都能正常工作变得不可行)。

SciPy 版本

CPython 支持

MS Visual C++

工具集版本

直到1.2

2.7 和 3.4 及以上

VS 2008 (9.0)

vc90

1.3, 1.4

3.5+

VS 2010 (10.0)

vc100

1.5

3.6+

VS 2015 (14.0)

vc140

1.6, 1.7

3.7+

VS 2017 (14.1)

vc141

1.8

3.8+

VS 2017 (14.1)

vc141

1.9

3.8+

VS 2019 (14.20)

vc142

在C语言标准方面,值得注意的是C11有 `可选特性`_(例如原子操作、线程),其中一些(如可变长度数组和复数类型)在C99标准中是强制性的。C17(偶尔称为C18)可以被视为C11的错误修复,因此通常情况下,C11可能会被完全跳过。

SciPy 由于可用编译器的支持,在使用更高级的语言特性方面受到了限制,特别是微软花了很长时间才实现了对 C99/C11/C17 的兼容性,然而从 Visual Studio 16.8 开始,C11/C17 得到了支持(尽管不包括 C11 的可选特性)。C99 的 <complex.h> 支持 对 SciPy 来说尤其有趣。不过,在 Windows 上仍然可以使用复数类型,前提是使用 特定于 Windows 的类型

因此,使用超出 C90 标准的 C 语言特性只有在 Windows 上有支持的情况下才可能实现;然而,截至 2021 年底,已经使用了足够新的编译器。这是因为 GCC 和 LLVM 支持所有相关的 C11 特性,并且如上所述,C17 只是对 C11 的错误修复。简而言之:

日期

C 标准

<= 2018

C90

2019

旧代码使用C90,新代码可考虑使用C99

2020

C99 (不包括 <complex.h>, <stdatomic.h>, <threads.h> 和可变长度数组)

2021

C17 (不包含 <complex.h>, <stdatomic.h>, <threads.h> 和 VLAs)

toctree 是一个 reStructuredText 指令 ,这是一个非常多功能的标记。指令可以有参数、选项和内容。

C23, <complex.h>, <stdatomic.h>, …

C++ 语言标准#

SciPy 的 C++ 语言标准通常是指导方针而非官方决定。这在尝试预测新标准的采用时间表时尤其如此。

日期

C++ 标准

<= 2019

C++03

2020

C++11

2021

C++14

2022

C++17(核心语言 + 普遍可用的标准库特性)

toctree 是一个 reStructuredText 指令 ,这是一个非常多功能的标记。指令可以有参数、选项和内容。

C++17(含完整标准库),C++20,C++23,C++26

由于 manylinux 的编译器约束的历史背景

自从放弃对 Python 2.7 的支持后,C++11 可以被普遍使用,并且自从放弃 Python 3.6 后,Visual Studio 版本(之前由于与 CPython 的 ABI 兼容性而固定在 14.0)已经足够新,甚至支持 C++17。

由于官方构建(见上文)使用了相当新的 LLVM 版本,因此 C++ 支持的瓶颈是目前支持的最旧的 GCC 版本,SciPy 主要受限于最旧支持的 manylinux 版本和镜像 [MANY]

在2021年底(随着 manylinux1 轮子的最终移除),GCC 的最低要求提升到了 6.3,该版本完全支持 C++14 [CPP]。这对应于相关 manylinux 版本中最低的 GCC 版本,尽管这仍然考虑了基于 Debian 的“异常值” manylinux_2_24,它与基于 RHEL 衍生 CentOS 的先前 manylinux 镜像不同,后者可以从“RHEL 开发工具集”中的 ABI 兼容 GCC 回传中受益,而 manylinux_2_24 则停留在 GCC 6.3。该镜像未能起飞,部分原因在于那些 过时的编译器,并在2022年年中达到了其生命周期结束。由于不同原因,manylinux2010 也在 同一时间 左右达到了其生命周期结束。

剩余的镜像 manylinux2014manylinux_2_28 目前分别支持 GCC 10 和 12。后者将继续接收更新,因为新的 GCC 版本可用作回溯移植,但前者可能不会改变,因为 CentOS 项目不再响应关于发布 aarch64 回溯移植 的 GCC 11。

这使得所有主要平台及其编译器都保留了相对较新的版本。然而,SciPy 历史上也一直致力于支持不太常见的平台——即使没有二进制工件(即 wheel),至少也要保持可以从源代码编译——这包括例如 AIX、Alpine Linux 和 FreeBSD。

平台支持和其他编译器约束

对于 AIX 7.2 和 7.3,默认编译器是 GCC 10(AIX 7.1 已于 2023 年结束生命周期),但 GCC 11/12 可以 并行 安装,同样,AIX 也有基于 LLVM 17 的 Open XL

目前支持的最旧 Alpine Linux 版本是 3.16,并且已经 自带 GCC 11。对于 FreeBSD,目前支持的最旧 13.x 版本 自带 LLVM 14(并且 GCC 13 作为 freebsd-port 可用)。

最后,还有一个问题是哪些机器被需要从源代码编译SciPy的人们广泛使用(例如,SciPy开发者,或出于性能原因想要自行编译的人)。最老的相关发行版(没有RHEL风格的回溯)是Ubuntu 20.04 LTS(它有GCC 9,但也有GCC 10的回溯;Ubuntu 22.04 LTS有GCC 11)和Debian Bullseye(有GCC 10;Bookworm有GCC 12)。这是确定编译器支持下限的最弱限制(可以预期高级用户和开发者至少会保持他们的系统在一定程度上更新,或者在可用的地方使用回溯),并且随着旧发行版的使用数量逐渐减少,其重要性逐渐降低。

所有当前最低支持的编译器版本(GCC 9、LLVM 14、VS2019 使用 vc142)都完全支持 C++17 核心语言,因此可以无条件使用。然而,截至 2024 年年中,所有编译器对 C++17 标准库的全面支持尚未完成,特别是 LLVM。因此,在使用 SciPy 中的某个 stdlib 功能之前,有必要检查所有编译器是否支持该功能。

C++20 的支持正在非常缓慢地稳定下来,即使不考虑模块、协程和几个尚未普遍支持的标准库特性。鉴于 C++20 标准是一个非常大的发布版本,预计还需要 一段时间 我们才能开始考虑调整我们的基准。C++23 和 C++26 的编译器支持仍在积极开发中 [CPP]

Fortran 编译器#

通常,任何维护良好的编译器都可能适合并可用于构建 SciPy。尽管如此,我们并不测试旧版本的 gfortran,这就是为什么我们将下限与上述GCC的下限相匹配。

工具

版本

gfortran

>= 9.x

ifort/ifx

一个最近的版本(未在CI中测试)

flang (LLVM)

>= 17.x

Cython & Pythran#

SciPy 总是需要一个最新的 Cython 编译器。自 1.7 版本起,Pythran 成为了构建依赖项(目前可以选择退出)。

OpenMP 支持#

由于 各种原因 ,SciPy 不能随内置的 OpenMP 支持一起分发。当使用可选的 Pythran 支持时,从源代码构建时可以生成启用 OpenMP 的并行代码。

其他库#

任何符合 BLAS/LAPACK 接口的库都可以使用。已知 OpenBLAS、ATLAS、MKL、BLIS 和参考 Netlib 库可以正常工作。

最低版本

LAPACK

3.7.1

BLAS

最新版本的 OpenBLAS、MKL 或 ATLAS。Accelerate BLAS 库不再受支持。

有一些额外的可选依赖项。

版本

URL

mpmath

最近

http://mpmath.org/

scikit-umfpack

最近

https://pypi.org/project/scikit-umfpack/

pooch

最近

https://pypi.org/project/pooch/

此外,SciPy 支持与其他库的交互。当这些库安装时,测试套件会运行额外的兼容性测试:

工具

版本

URL

pydata/sparse

最近

pydata/sparse

测试与基准测试#

测试和基准测试需要以下最新版本:

工具

版本

URL

pytest

最近

https://docs.pytest.org/en/latest/

假设

最近

https://hypothesis.readthedocs.io/

asv (空速)

最近

https://asv.readthedocs.io/

构建文档#

工具

版本

Sphinx

无论最近版本如何,>= 5.0。

PyData Sphinx 主题

任何最近版本都适用。>= 0.15.2。

Sphinx-设计

任何最近版本都适用。>= 0.4.0。

numpydoc

任何最近版本都适用。>= 1.5.0。

matplotlib

一般建议 >= 3.5。

MyST-NB

任何最近版本都适用。>= 0.17.1

jupyterlite-sphinx

无论最近的版本是什么,只要 >= 0.12.0 即可。

备注

开发者注记:所需的 numpymatplotlib 版本对 Python 文档字符串中的示例有影响。示例必须能够在用于构建文档的环境中执行,以及用户可能在此 SciPy 版本中使用的任何受支持的 numpy/matplotlib 版本中执行。

打包#

一个最近的版本:

工具

版本

URL

setuptools

最近

https://pypi.org/project/setuptools/

轮子

最近

https://pythonwheels.com

多构建

最近

matthew-brett/multibuild

制作 SciPy 版本分发 包含关于制作和分发 SciPy 版本的信息。

参考文献#