从源代码构建 PyPy

为了构建 PyPy,我们建议首先安装预构建的 PyPy(参见 下载和安装 PyPy)。可以使用 CPython 构建 PyPy,但运行时间会长得多——根据您的架构,运行时间会是两到三倍。

即使使用 PyPy 构建 PyPy,翻译也是很耗时的——在快速机器上需要 20 分钟——而且很占内存。您需要在 32 位机器上至少有 3 GB 的内存,在 64 位机器上至少有 6 GB 的内存。

开始之前

我们通常的开发工作流程通过使用测试驱动开发来避免完全翻译。您可以阅读更多关于如何开发 PyPy 的信息 这里,最新的翻译(希望是功能性的)二进制包可以在我们的 buildbot 的 每日构建 上获得。

您需要以下构建依赖项才能运行测试。

克隆仓库

如果您希望编译自己的 PyPy,或者如果您想修改它,您需要获取源代码的副本。这可以通过 从下载页面下载 或使用 git 从仓库中检出源代码来完成。如果您想访问当前开发版本,我们建议使用 git。

您必须在命令行、DOS 框或终端中发出以下命令

git clone https://github.com/pypy/pypy.git

这将克隆仓库并将其放置到名为 pypy 的目录中,并将为您提供位于 pypy/pypy 中的 PyPy 源代码和位于 pypy/pypy/doc 中的文档文件。我们努力确保顶端始终稳定,但它偶尔可能会出现故障。您可能需要查看 我们的每日测试:找到一个通过了至少 {linux32} 测试(对应于 success 行上的 + 符号)的修订版(12 个字符的字母数字字符串,例如“963e808156b3”),然后在您克隆的仓库中,使用以下命令切换到此修订版

hg up -r XXXXX

其中 XXXXX 是修订版 ID。

安装构建时依赖项

(注意:有关如何在 Windows 下翻译 Python 解释器的提示,请参见 windows 文档

主机 Python 需要安装 CFFI。如果在 PyPy 上进行翻译,则 CFFI 已经安装。如果在 CPython 上进行翻译,则需要安装它,例如使用 python -mpip install cffi

要在 Unix 上使用 C 翻译后端构建 PyPy,您至少需要安装 C 编译器和 make。此外,一些可选模块有额外的依赖项

cffi、ctypes
libffi、pkg-config
zlib
libz
bz2
libbz2
pyexpat
libexpat1
_vmprof
libunwind(可选,在运行时动态加载)

在构建 PyPy 之前,请确保已安装这些库(以及开发头文件),否则生成的二进制文件将不包含这些模块。此外,在构建 PyPy 后,以下库应该存在,否则相应的 CFFI 模块将不会被构建(您可以运行或重新运行 lib_pypy/pypy_tools/build_cffi_imports.py 来构建它们;您不需要重新翻译整个 PyPy)

sqlite3
libsqlite3
_ssl, _hashlib
libssl
curses
libncurses-dev(适用于 PyPy2) libncursesw-dev(适用于 PyPy3)
gdbm
libgdbm-dev
tk
tk-dev
lzma(仅限 PyPy3)
liblzma 或 libxz,版本 5 及以上

要运行未翻译的测试,您需要 Boehm 垃圾收集器 libgc,版本 7.4 及以上

在 Debian 和 Ubuntu(16.04 及更高版本)上,这是安装所有构建时依赖项的命令

apt-get install gcc make libffi-dev pkg-config zlib1g-dev libbz2-dev \
libsqlite3-dev libncurses5-dev libexpat1-dev libssl-dev libgdbm-dev \
tk-dev libgc-dev python-cffi \
liblzma-dev libncursesw5-dev     # these two only needed on PyPy3

在 Fedora 上

dnf install gcc make libffi-devel pkgconfig zlib-devel bzip2-devel \
sqlite-devel ncurses-devel expat-devel openssl-devel tk-devel \
gdbm-devel python-cffi gc-devel\
xz-devel  # For lzma on PyPy3.

在 SLES11 上

zypper install gcc make python-devel pkg-config \
zlib-devel libopenssl-devel libbz2-devel sqlite3-devel \
libexpat-devel libffi-devel python-curses python-cffi \
xz-devel # For lzma on PyPy3.
(XXX plus the SLES11 version of libgdbm-dev and tk-dev)

在 Mac OS X 上

目前 PyPy 支持在 Apple Silicon(M1,Arm64)和 X86_64 上构建。您必须使用适当的工具链进行构建:arm64x86_64。“胖”通用 2 构建不受支持。

大多数构建时依赖项与开发者工具一起安装。 libx11tkinter 所需的。 openssl 需要安装用于测试,并且 brew 提供的 pypy 将加速翻译。请注意,您必须使用架构适当的 x86_64 或 arm64 brew 命令

xcode-select --install
    brew install openssl pypy pkg-config libx11

设置完这些后,翻译(接下来描述)将通过 pkg-config 按预期找到库。

设置将影响翻译的环境变量

以下环境变量可用于调整结果

结果
CC 要使用的编译器
PYPY_MULTIARCH pypy 3.7+:最终出现在 posix 上的 sys.platform._multiarch 中,默认为 x86_64-linux-gnu
PYPY_USESSION_DIR 临时文件的基目录,通常为 $TMP
PYPY_USESSION_BASENAME 每次调用 from rpython.tools import udir 将获得一个临时目录 $PYPY_USESSION_DIR/usession-$PYPY_USESSION_BASENAME-N,其中 N 在每次调用时递增
PYPY_USESSION_KEEP 要保留多少个旧的临时目录,任何更旧的目录都将被删除。默认为 3

运行翻译

我们通常在 pypy/goal 目录中进行翻译,因此以下所有命令都假设您的 $pwd 在那里。

使用 JIT 进行翻译

pypy ../../rpython/bin/rpython --opt=jit

不使用 JIT 进行翻译

pypy ../../rpython/bin/rpython --opt=2

请注意,这通过 targetpypystandalone.py 文件翻译 pypy,因此这些是以下内容的简写

pypy ../../rpython/bin/rpython <rpython options> targetpypystandalone.py <pypy options>

更多帮助可以通过 --help 在任一选项位置获得,更多信息可以在 PyPy 的配置选项 部分找到。

(您可以在此处使用 python 而不是 pypy,这将花费更长时间,但也能正常工作。)

如果一切正常,这将

  1. 运行 rpython 翻译链,生成整个 pypy 解释器的数据库。此步骤目前是单线程的,并且占用大量内存。作为此步骤的一部分,该链将在由 PYPY_USESSION_DIR 环境变量控制的目录中创建大量 C 代码文件和一个 Makefile 来编译它们。
  2. 通过运行 Makefile 创建可执行文件 pypy-c。此步骤可以利用机器上所有可能的内核。
  3. 将所需的二进制文件复制到当前目录。
  4. 为任何基于 cffi 的标准库模块生成 c-扩展模块。

生成的执行文件在很大程度上与正常的 Python 解释器类似(参见 PyPy 与 CPython 之间的差异),并已准备好进行测试,用作新 virtualenv 的基础解释器,或打包成适合在与构建机器运行相同操作系统的另一台机器上安装的二进制文件。

请注意,步骤 4 仅仅是为了方便,任何步骤都可以重新运行,而无需重新运行之前的步骤。

创建 PyPy 的调试版本

使用 make lldebugmake lldebug0 目标重新运行 Makefile,这将以一种在调试器下运行有意义的方式进行构建。将添加适当的编译标志以添加调试信息,并且对于 lldebug0,编译器优化将完全禁用。如果您在调试器中停止,您将看到来自 rpython 翻译步骤的非常冗长的机器生成的 C 代码,这需要一些阅读才能与 rpython 代码相关联。

为标准库构建 cffi 导入库

各种标准库模块需要一个单独的构建步骤来在 行外 API 模式 中创建 cffi 导入库。这是通过以下命令完成的

cd pypy/goal
PYTHONPATH=../.. ./pypy-c ../../lib_pypy/pypy_tools/build_cffi_imports.py

打包(准备安装)

如果您想将 PyPy 安装到系统范围内,即使是在同一台机器上安装,也需要打包。原因是这样做会准备一些额外的功能,这些功能不能在根安装的 PyPy 上延迟完成,因为普通用户没有写入权限。这主要涉及在第一次导入时通常会编译的库。

python pypy/tool/release/package.py --archive-name=pypy-VER-PLATFORM

这将创建一个干净且准备好的层次结构,以及一个具有相同内容的 .tar.bz2;将打印出找到这些文件的目录。然后,您可以将文件层次结构移动或在正确的位置解压缩 .tar.bz2

建议使用 package.py,因为自定义脚本不可避免地会过时。如果您仍然想编写自定义脚本,请注意一个容易被忽略的点:一些模块是用 CFFI 编写的,需要一些编译。如果您以 root 身份安装 PyPy 而不预先编译它们,普通用户将收到错误。

安装

PyPy 根据可执行文件的位置动态查找其库的位置。典型 PyPy2 安装的目录层次结构如下所示

./bin/pypy
./include/
./lib_pypy/
./lib-python/2.7
./site-packages/

PyPy3.8+ 安装将匹配 CPython 布局

./bin/
./include/pypy3.8/include
./lib/pypy3.8

上面显示的层次结构相对于 PREFIX 目录。PREFIX 是通过从可执行文件所在的目录开始,并“向上”遍历文件系统,直到找到包含 lib_pypylib-python/2.7(在 pypy2 上)的目录来计算的。

要在类 Unix 系统上将 PyPy 安装到系统范围内,建议将整个层次结构单独放置(例如,在 /opt/pypy 中),并将指向 pypy 可执行文件的符号链接放入 /usr/bin/usr/local/bin 中。

如果可执行文件无法找到合适的库,它将报告 debug: WARNING: library path not found, using compiled-in sys.path,然后尝试正常继续。如果默认路径可用,大多数代码将正常工作。但是,sys.prefix 将被取消设置,并且一些现有库假设这种情况永远不会发生。