在Windows上从源代码构建

概述

与OSX和Linux相比,在Windows上构建NumPy和SciPy更加困难,这在很大程度上是因为缺乏兼容的开源库,如 BLAS/LAPACK 以及开放源码编译器,它们是构建这两个库并使它们相对运行良好所必需的。不能像在其他平台上那样,只在命令提示符上调用一行程序,方法是 sudo apt install 机器。

本文档描述了一种从源代码构建OpenBLAS和SciPy的选项,该选项已针对SciPy 1.6.0进行了验证。不过,鉴于目前正在进行的所有工作,请 不要期望 从长远来看,这些说明是准确的,并且一定要检查提到的任何开放源码项目,以获得最新的信息。有关所有这些项目的更多信息,请参阅 Mingwpy 与本文档将提供的信息相比,网站是一个极好的深度信息来源。

构建已发布的SciPy

本节提供构建已发布的SciPy的分步过程。如果您想要完全从源代码构建,您应该估计至少需要三个小时来构建所有的库并编译SciPy。您可以随时停止并检查任何步骤,但在本节中,我们只会提到这些步骤,而不会对其背后的原因进行深入解释。如果您对我们正在做的事情有进一步的疑问,下面几节提供了更深入的文档。此外,在继续操作之前,请确保阅读本节内容,因为一般来说,错误消息的存在与否并不能很好地表明您是否正确完成了某个步骤。每一步都创建特定的文件,最终重要的是您是否构建了所需的文件,而不是错误消息是否出现在您的终端中。

构建OpenBLAS

First, we need to install the software required to build OpenBLAS, which is the BLAS library that we're going to use. Because the software to build OpenBLAS is different than that required to build SciPy and because OpenBLAS takes a long time to build, we're going to start building OpenBLAS first and then explain what to do next while the OpenBLAS build is running. Alternatively, if you'd rather download a pre-built OpenBLAS, download the one of the pre-built zip files and skip to the Installing OpenBLAS section below.. However it is also likely that your version of Windows and the compiler you wish to use won't be compatible with what these prebuilt binaries produced. This is still one of the main pain points of building for Windows. That's why we will attempt to build our own OpenBLAS.

我们首先安装MSYS2平台,OpenBLAS构建将在该平台上进行。首先,从下载MSYS2安装程序 msysintaller 通过选择32位或64位。确保为您要构建的SciPy安装正确的体系结构(例如,32位或64位)。如果您不确定要使用哪一个,请继续使用64位。请仔细按照安装说明进行操作,特别是步骤6和7,以更新所有组件。

注解

有时,在更新期间,终端可能会要求您关闭终端,但随后可能会拒绝关闭和挂起。如果发生这种情况,您可以通过任务管理器终止它,然后继续执行说明。

现在,下一步是安装更多我们需要的软件包。打开MSYS2 微型GW (64或32位)终端,并根据您选择的体系结构键入以下内容;对于常见的64位版本,运行以下命令

pacman -S --needed base-devel mingw-w64-x86_64-toolchain mingw-w64-x86_64-cmake git

而对于32位运行,

pacman -S --needed base-devel mingw-w64-i686-toolchain mingw-w64-i686-cmake git

同样,如果您不确定需要哪一个,请在每个步骤中选择64位选项。

它将提示是否安装这些软件包中的所有内容,您可以通过在每个步骤中按Enter键简单地接受所有内容,这也需要一些时间才能完成。安装完毕后,关闭并重新打开MSYS2 MinGW终端。

如果您已经有一个GitHub存储库文件夹来保存您自己的repos,那么最好使用该位置来保持事物的整洁,因为我们将克隆另一个存储库来获取源代码。它应该位于某个方便且具有写入权限的地方。如果这是您的第一次,那么您可以选择“DocumentsGitHub”作为一个可行的选项。我们将假设您在本文档的睡觉中选择了此文件夹。您可以使用Windows资源管理器在“我的文档”中创建文件夹。要确保我们已经准备好构建,请在终端中逐个键入以下内容:

make
gfortran
gcc
git

这些命令中的每一个都应该失败,因为我们没有向它们提供任何参数。但是,来自程序而不是来自命令提示符的显式故障意味着程序在路径上是可访问的,这正是我们要测试的。反过来,如果返回关于找不到命令的错误,则软件包的安装没有成功完成。如果其中任何一个丢失了,您就没有做好构建的准备。返回并确保MSYS2已正确安装并启用了所需的软件包。

现在是时候在方便的地方克隆OpenBLAS存储库了。单独逐行运行以下命令,并根据需要修改GitHub repo文件夹的路径。

cd C:\Users\<user name>\Documents\GitHub
git clone https://github.com/xianyi/OpenBLAS.git
cd OpenBLAS
git submodule update --init --recursive
git fetch --all --tags --prune

现在我们将切换到我们选择的版本。在撰写本文时,最新的OpenBLAS发布版本是0.3.7,因此我们将使用该版本。

git checkout tags/v0.3.7 -b v0.3.7

您可以通过以下方式查看所有可用选项

git tag

现在通过将目录更改为上一级 cd .. 要退出目录并创建名为的文件,请执行以下操作 build_openblas.sh 。最简单的方法是打字

touch build_openblas.sh

当然,您也可以使用Windows资源管理器在该位置创建新的txt文件,然后将其重命名。因此,最终得到的结构将是

my repo folder
    ├─── build_openblas.sh
    ├─── OpenBLAS
            ├─── ...

然后在任何文本编辑器(如Notepad++)中打开此文件,并将以下内容粘贴到此空文件中:

# You may adjust to your preferred output directory
OPENBLAS_ROOT=/c/opt

# Adjust to match the MSYS2 version you installed
BUILD_BITS=64

# Print some gcc info that MSYS2 discovered in the path
which gcc
gcc --version

# Get into the repository that we cloned
cd OpenBLAS

# The following two lines clean up in case we make a mistake and need
# to run the script again
git clean -fxd
git reset --hard
rm -rf $OPENBLAS_ROOT/$BUILD_BITS

# Set architecture flags
march="x86-64"
extra="-fno-asynchronous-unwind-tables"
vc_arch="X64"
cflags="-O2 -march=$march -mtune=generic $extra"
fflags="$cflags -frecursive -ffpe-summary=invalid,zero"

# Build name for output library from gcc version and OpenBLAS commit.
GCC_TAG="gcc_$(gcc -dumpversion | tr .- _)"
OPENBLAS_VERSION=$(git describe --tags)
# Build OpenBLAS
# Variable used in creating output libraries
export LIBNAMESUFFIX=${OPENBLAS_VERSION}-${GCC_TAG}
make BINARY=$BUILD_BITS DYNAMIC_ARCH=1 USE_THREAD=1 USE_OPENMP=0 \
    NO_WARMUP=1 BUILD_LAPACK_DEPRECATED=1 \
    COMMON_OPT="$cflags" FCOMMON_OPT="$fflags"
make install PREFIX=$OPENBLAS_ROOT/$BUILD_BITS

这是一个自动化脚本,它将确保在正确的位置使用正确的变量。Linux用户非常熟悉这样的脚本,但是对于Windows用户来说可能有点尴尬。你可以把这些想象成 .bat 文件。该脚本应作为64位MSYS2的AS-in使用,但您可以根据需要更改变量。在您创建了该文件,并且您是该文件的OpenBLAS存储库的上一个目录之后,使用以下命令开始OpenBLAS构建:

./build_openblas.sh

构建OpenBLAS具有挑战性且耗时。构建可能会在几小时后因错误而失败,但也可能以静默方式失败并生成不正确的二进制文件。拜托,如果你有什么问题, report them 这样我们就可以节省下一个人的时间。

以下是已知问题之一;如果您碰巧收到以下错误

<command-line>:0:4: error: expected identifier or '(' before numeric constant

这意味着您有一些头文件定义冲突,您必须降级某些项目。这与本科学计划无关,但让我们尝试提供一个解决方案。看这个 OpenBLASwiki 页面阅读哪些包要降级以及如何降级。基本上,它需要下载三个文件。然后,在MSYS终端中,将目录更改为您下载文件的位置,并运行wiki链接中给出的命令。然后返回到脚本目录,其中 /build_openblas.sh 活下去,再试一次。这应该足以让您构建OpenBLAS。

当您等待OpenBLAS完成构建时,请继续安装 build tools Microsoft提供的,因为这些程序需要一段时间才能安装,您稍后会用到它们。

在此之后 build_openblas.sh 脚本已完成,应该有一个 libopenblas.....a 作为最终的艺术品。如果 OPENBLAS_ROOT 设置为 C:\\opt ,那么您可能会在MSYS2终端中看到类似这样的行:

Copying the static library to /c/opt/64/lib

这是一个非常好的消息:您已经成功地构建了OpenBLAS!

安装OpenBLAS

查找 lib 您用作参数的文件夹中的 OPENBLAS_ROOT 。(这是 /c/opt/64/lib 如果您没有更改脚本中的任何内容。)你会发现三个 .a 文件,例如(名称可以不同):

libopenblas_v0.2.20-2-g5f998efd-gcc_9_2_0.a
libopenblas_v0.2.20-2-g5f998efd-gcc_9_2_0.dll.a
libopenblas_v0.2.20-2-g5f998efd-gcc_9_2_0.p-r0.2.20.a

从这三个方面,我们只对第一个感兴趣。只需复制一份并将其重命名为 openblas.a

如果没有该文件,则可能需要找出发生了什么情况,然后重新构建OpenBLAS。我们知道这是 very 很烦人,但不幸的是我们别无选择。首先要查找的位置是OpenBLAS目录内。如果构建成功,但(由于某种原因)自动将文件移动到 OPENBLAS_ROOT 失败,则工件将保留在OpenBLAS repo文件夹中。但是如果您有那个文件,那就太好了,我们将假定您已经正确地完成了这一步。在这个假设的基础上,让我们构建SciPy。

在继续之前,请确保您没有这两个副本中的任何一个的其他副本 openblas.alibopenblas.a 来自以前的尝试或通过以前的下载。多个副本可能会导致以后的生成错误,这些错误将很难调试。如果这是第一次尝试,您不需要担心这一步。

构建Science Py

一旦您构建了OpenBLAS,就可以构建SciPy了。在继续之前,请确保安装以下软件,以便在最新的Python版本上构建。有关在其他Python版本上构建的信息,请参阅 WindowsCompilers 佩奇。我们还假设您的Python位于系统路径上。也就是说,当你打字的时候 python 在Windows命令提示符下执行正确的Python。

安装Microsoft Visual Studio 2017或2019社区版(使用 build tools 来自微软)。如果您觉得它过于臃肿,无法安装该捆绑包中的所有内容(我们确实觉得有点臃肿),那么这里有一个子集,它们在构建SciPy 1.6.0和VS 2019期间进行了测试。您可以切换到顶部的单个项目视图,并仅选择以下选项

C++ Core Features
Windows Universal C Runtime
MSVC v142 - VS 2019 C++ x64/x86 build tools (...)
Windows 10 SDK (10.0.18362.0)
C++ 2019 Redistributable Update
C++ Clang-cl for 142 build tools (x64/x86)
C++ Clang Compiler for Windows (8.0.1)

就像以前一样,选择一个方便的位置来克隆SciPy。OpenBLAS旁边通常是一个方便的选项(注意:不在OpenBLAS文件夹中,而是在旁边)。继续上面的示例

my repo folder
    ├─── build_openblas.sh
    ├─── OpenBLAS
    ├─── SciPy
            ├─── ...

再次使用上面相同的通用示例文件夹

cd C:\Users\<user name>\Documents\GitHub
git clone https://github.com/scipy/scipy.git
cd scipy
git submodule update --init

现在我们需要复制 openblas.a 将我们先前构建的文件添加到正确的位置。如果您的Python安装在如下位置:

C:\Users\<user name>\AppData\Local\Programs\Python\Python38\python.exe

那么你就需要把 openblas.a 我们之前复制并重命名的文件,如下所示:

C:\Users\<user name>\AppData\Local\Programs\Python\Python38\Lib

根据位置相应调整位置 python.exe 已经找到了。

在这个阶段,我们已经完成了OpenBLAS部分,希望我们在短期内不需要构建OpenBLAS。但我们倾向于更频繁地构建SciPy,因为它的发布周期更快。因此,使用Windows是有意义的 cmd 或者用于构建的PowerShell,因为它是一个更本机的工具。这需要将MinGW编译器放在路径上。因此,请确保以下文件夹(或已安装MSYS的文件夹)位于系统PATH变量中足够靠近顶部的位置。

C:\MSYS64\MINGW64\BIN

要进行健全性检查,请重新启动 cmd 或Powershell,然后键入:

gfortran

如果您在上面看到缺少命令错误, gfortran 未正确安装或仍不在路径上。但是,我们假设它现在在路径上并且可以访问。

现在安装构建和测试SciPy所需的依赖项。

python -m pip install wheel setuptools numpy>=1.16.5 Cython>=0.29.18 pybind11>=2.4.3 pythran>=0.9.12 pytest pytest-xdist

注解

这些说明使用 pip 作为包裹经理。您还可以使用 conda 根据文件中的说明 开发环境快速入门指南(Ubuntu) 修改最少(例如,您不需要安装 gfortrangit 因为你已经拥有它们了)。

最后两个是用于使用SciPy的测试套件,如果您想要在本地测试一些新的更改,该套件非常方便。

请注意,这是一个比用于官方二进制文件的过程更简单的过程。 您的二进制文件只能与最新的NumPy一起使用 。有关基于较旧的NumPy版本进行构建的信息,请参见 Building Against an Older NumPy Version

假设您位于SciPy存储库目录的顶部,其中 setup.py 并且假设您已经正确设置了所有内容,那么您就可以构建了。运行以下命令:

python setup.py build

您可以通过在构建日志中查找以下内容来验证OpenBLAS库是否被正确提取:

FOUND:
   libraries = ['openblas']
   library_dirs = ['C:\...........\lib']
   language = f77
   define_macros = [('HAVE_CBLAS', None)]

请注意,将有多行类似于这些行。您只需要跟踪OpenBLAS One。

当一切顺利完成时,祝贺您!你已经建立了Science Py!

您可以通过进一步安装构建的SciPy

python setup.py install

只需确保您卸载了现有的其他SciPy安装(如果有)(按常规 pip uninstall scipy 机械)。

基于较旧的NumPy版本构建

如果您希望构建SciPy以使用较旧的NumPy版本,则需要使用最新NumPy中的文件夹替换NumPy“distutils”文件夹。以下Powershell代码段可以升级NumPy distutils,同时保留较旧的NumPy ABI.

$NumpyDir = $((python -c 'import os; import numpy; print(os.path.dirname(numpy.__file__))') | Out-String).Trim()
rm -r -Force "$NumpyDir\distutils"
$tmpdir = New-TemporaryFile | %{ rm $_; mkdir $_ }
git clone -q --depth=1 -b master https://github.com/numpy/numpy.git $tmpdir
mv $tmpdir\numpy\distutils $NumpyDir

其他资源

正如概述中所讨论的,本文档不打算就如何在Windows上构建NumPy和SciPy提供非常详细的解释。这在很大程度上是因为目前还没有单一的更好的方法来做到这一点,而且在Windows上构建这些库的过程还在开发中。很可能任何信息都会相对较快地过期。如果您希望获得更多帮助,请联系NumPy和SciPy邮件列表,可以找到 here 。现在有很多开发人员正在处理这个问题,他们肯定会很乐意帮助您解决这个问题!Google也是一个很好的资源,因为有很多人在Windows上使用NumPy和SciPy,所以如果你的问题已经得到解决也就不足为奇了。