最近想看看 Python 3.10 的模式匹配新特性,刚好也了解了一些编译相关的基础知识,于是尝试下在平时使用的测试机上编译一份最新的 Python。
测试机的操作系统是 Ubuntu 20.10,已安装有 gcc
、git
等基础的开发工具。经验证以下步骤同样适用于 macOS 11。
1
2
| uname -a
Linux waynerv-woqutech 5.8.0-48-generic #54-Ubuntu SMP Fri Mar 19 14:25:20 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux
|
从 CPython 的官方仓库 https://github.com/python/cpython 克隆源码:
1
| git clone https://github.com/python/cpython.git
|
这个仓库的文件体积很大,如果克隆时遇到网络问题,可尝试使用 Gitee 的「同步 GitHub 仓库」功能。
核心的 CPython 编译器只需要一个基本的 C 编译器就可以编译,但一些扩展模块会需要开发头文件来提供一些额外的库(如压缩功能需要的zlib
库),这也是为什么我们用操作系统提供的包管理器(如apt
)安装 Python 时会需要 python3-dev
等等一大堆依赖。
由于我并不打算将自行编译的 Python 用于开发或生产,因此将跳过安装依赖这一步。
首先进入我们所克隆的仓库目录:
然后需要进行配置:
1
| ./configure --prefix=/root/build-python
|
默认情况下,后续的 make install
命令会将编译得到的文件安装到 /usr/local/bin
或 /usr/local/lib
,这可能会覆盖系统已有的安装文件,为了不和系统已安装的 Python 版本产生冲突,我们通过指定 --prefix
选项将其安装到一个自定义的目录。
配置结束后运行编译:
执行编译时可通过 -j
选项指定并行的任务数量来加快速度,通常我们将其设置为编译机器的 CPU 数量,可以结合 nproc
命令使用:
-s
选项意为 silence
,即不打印编译的过程日志,也可启用。
编译的过程可能会比较耗时,成功后的输出如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
| Python build finished successfully!
The necessary bits to build these optional modules were not found:
_bz2 _curses _curses_panel
_dbm _gdbm _hashlib
_lzma _sqlite3 _ssl
_tkinter _uuid readline
To find the necessary bits, look in setup.py in detect_modules() for the module's name.
The following modules found by detect_modules() in setup.py, have been
built by the Makefile instead, as configured by the Setup files:
_abc pwd time
Could not build the ssl module!
Python requires an OpenSSL 1.0.2 or 1.1 compatible libssl with X509_VERIFY_PARAM_set1_host().
LibreSSL 2.6.4 and earlier do not provide the necessary APIs, https://github.com/libressl-portable/portable/issues/381
|
由于我们没有安装依赖,所以提示有部分模块未找到,但不影响使用 Python 的基本功能。
编译成功后其实已经可以运行 Python 了。上述构建过程会在当前目录(非--prefix
指定的目录)生成一个名为 python
的二进制文件(macOS 下是 python.exe
),运行它即可启动 Python 解释器:
它会使用当前目录中编译生成的临时文件作为资源文件,现在我们将其安装到在配置步骤中指定的目录:
安装过程会进行大量的资源复制,并调用 Python 解释器将使用 Python 实现的标准库编译为字节码(.pyc
),此外默认还会安装 setuptools
和 pip
这两个 Python 包,因此当我们安装较新版本的 Python 版本时,基本不再需要手动安装 pip
。
安装完成后切换到 /root/build-python
目录下,并查看其目录结构:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
| cd /root/build-python
tree -L 2 .
.
├── bin
│ ├── 2to3 -> 2to3-3.10
│ ├── 2to3-3.10
│ ├── idle3 -> idle3.10
│ ├── idle3.10
│ ├── pip3
│ ├── pip3.10
│ ├── pydoc3 -> pydoc3.10
│ ├── pydoc3.10
│ ├── python3 -> python3.10
│ ├── python3.10 # Python 可执行文件
│ ├── python3.10-config
│ └── python3-config -> python3.10-config
├── include
│ └── python3.10 # 头文件目录
├── lib
│ ├── libpython3.10.a # 静态库文件
│ ├── pkgconfig
│ └── python3.10 # 标准库文件及 site-packages
└── share
└── man
|
现在执行 ./bin/python3
即可运行我们自己编译安装好的 Python:
1
2
3
| Python 3.10.0a6+ (heads/master:80017752ba, Apr 6 2021, 13:47:23) [GCC 10.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>>
|
大功告成!可以看到运行的 Python 版本是 3.10.0a6+
,一个尚未发布的开发中版本。
如果我们需要其他稳定版本的 Python,只需要在源码仓库中 git checkout
到指定的 release 标签,然后再重新运行配置-编译-安装 3 个步骤就可以了。