# 3. 配置 Python

## 3.1. 配置选项

用以下方式列出 `./configure` 脚本的所有选项:

    ./configure --help

参阅 Python 源代码中的 `Misc/SpecialBuilds.txt` 。

### 3.1.1. 通用选项

`--enable-loadable-sqlite-extensions```

  支持 `_sqlite` 扩展模块中的可加载扩展（默认为否）。

  参见 `sqlite3.Connection.enable_load_extension()` 方法的 `sqlite3` 模块。

  3.6 版新加入.

`--disable-ipv6```

  禁用 IPv6 支持（若开启支持则默认启用），见 `socket` 模块。

`--enable-big-digits``=[15|30]`

  定义 Python `int` 数字的比特大小：15或30比特

  默认情况下，比特数取决于 `sizeof(void*)`。如果 `void*` 大小为 64 位以上，则比特数为 30 位，否则为 15 位。

  將 `PYLONG_BITS_IN_DIGIT` 定義為 `15` 或 `30`。

  參閱 `sys.int_info.bits_per_digit`。

`--with-cxx-main```

`--with-cxx-main``=COMPILER`

  编译 Python `main()` 函数，用 C++ 编译器链接 Python 可执行文件： $CXX` 或 COMPILER。

`--with-suffix``=SUFFIX`

  将 Python 的可执行文件后缀设置为 SUFFIX。

  在 Windows 和 macOS 上的默认后缀为 `.exe``（ ``python.exe` 为可执行文件），在其他平台上为空字符串（ `python` 可执行）。

`--with-tzpath``=<list of absolute paths separated by pathsep>`

  为 `zoneinfo.TZPATH` 选择默认的时区搜索路径。 参见 `zoneinfo` 模块的 编译时配置。

  默认：`/usr/share/zoneinfo:/usr/lib/zoneinfo:/usr/share/lib/zoneinfo:/etc/zoneinfo`

  参阅 `os.pathsep` 路径分隔符。

  3.9 版新加入.

`--without-decimal-contextvar```

  编译 `_decimal` 扩展模块时使用线程本地上下文，而不是协程本地上下文（默认），参见 `decimal` 模块。

  参见 `decimal.HAVE_CONTEXTVAR` 和 `contextvars` 模块。

  3.9 版新加入.

`--with-dbmliborder``=db1:db2:...`

  覆盖 `dbm` 模块的 db 后端检查顺序。

  合法值是用冒号（`:`）分隔的字符串，包含后端名称。

  - `ndbm` ；

  - `gdbm` ；

  - `bdb` 。

`--without-c-locale-coercion```

  禁用 C 语言对 UTF-8 的强制要求（默认为启用）。

  不定义 `PY_COERCE_C_LOCALE` 宏。

  請見 `PYTHONCOERCECLOCALE` 與 PEP 538。

`--with-platlibdir``=DIRNAME`

  Python 库目录名（默认为 `lib`）。

  Fedora 和 SuSE 在64 位平台用 `lib64` 。

  參閱 `sys.platlibdir`。

  3.9 版新加入.

`--with-wheel-pkg-dir``=PATH`

  `ensurepip` 模块用到的 wheel 包目录（默认为无）。

  某些 Linux 发行版的打包策略建议不要捆绑依赖关系。如 Fedora 在 `/usr/share/python-wheels/` 目录下安装 wheel 包，而不安装 `ensurepip._bundled` 包。

  3.10 版新加入.

### 3.1.2. 安装时的选项

`--prefix``=PREFIX`

  在 PREFIX 中安装架构无关的文件。 在 Unix 上，它默认为 `/usr/local`。

  该值可使用 `sys.prefix` 在运行时获取。

  作为示例，用户可以使用 `--prefix="$HOME/.local/"` 在其家目录中安装 Python。

`--exec-prefix``=EPREFIX`

  在 EPREFIX 中安装架构无关的文件，默认为 `--prefix`。

  该值可使用 `sys.exec_prefix` 在运行时获取。

`--disable-test-modules```

  不编译和安装 test 模块，如 `test` 包或 `_testcapi` 扩展模块（默认会编译并安装）。

  3.10 版新加入.

`--with-ensurepip``=[upgrade|install|no]`

  选择 Python 安装时运行的 `ensurepip` 命令。

  - `upgrade` （默认）：运行 `python -m ensurepip --altinstall --upgrade` 命令。

  - `install` ：运行 `python -m ensurepip --altinstall` 命令。

  - `no` ：不运行 ensurepip。

  3.6 版新加入.

### 3.1.3. 性能选项

建议用 `--enable-optimizations --with-lto` （PGO + LTO）配置 Python，以便实现最佳性能。

`--enable-optimizations```

  用 `PROFILE_TASK` 启用以配置文件主导的优化（PGO）（默认为禁用）。

  C 编译器 Clang 需要用到 `llvm-profdata` 程序进行 PGO。在 macOS 上，GCC 也需要用到它：在 macOS 上 GCC 只是 Clang 的别名而已。

  如果使用 `--enable-shared` 和 GCC ，还可以禁用 libpython 中的语义插值：在编译器和链接器的标志中加入 `-fno-semantic-interposition` 。

  3.6 版新加入.

  3.10 版更變: 在 GCC 上使用 `-fno-semantic-interposition` 。

`PROFILE_TASK`

  Makefile 用到的环境变量：PGO 用到的 Python 命令行参数。

  默认为：`-m test --pgo --timeout=$(TESTTIMEOUT)` 。

  3.8 版新加入.

`--with-lto```

  在编译过程中启用链接时间优化（LTO）（默认为禁用）。

  LTO 时 C 编译器 Clang 需要用到 `llvm-ar` 参数（在 macOS 则为 `ar`），以及支持 LTO 的链接器（`ld.gold` 或 `lld`）。

  3.6 版新加入.

`--with-computed-gotos```

  在求值环节启用 goto 计数（在支持的编译器上默认启用）。

`--without-pymalloc```

  禁用特定的 Python 内存分配器 pymalloc （默认为启用）。

  另請參閱 `PYTHONMALLOC` 環境變數。

`--without-doc-strings```

  禁用静态文档字符串以减少内存占用（默认启用）。Python 中定义的文档字符串不受影响。

  不定义 `PY_COERCE_C_LOCALE` 宏。

  参阅宏 `PyDoc_STRVAR()` 。

`--enable-profiling```

  用 `gprof` 启用 C 语言级的代码评估（默认为禁用）。

### 3.1.4. Python 调试级编译

调试版本 Python 是指带有 `--with-pydebug` 参数的编译。

调试版本的效果：

- 默认显示所有警告：在 `warnings` 模块中，默认警告过滤器的列表是空的。

- 在 `sys.abiflags` 中加入 `d` 标记。

- 加入 `sys.gettotalrefcount()` 函数。

- 命令行参数加入 `-X showrefcount` 。

- 环境变量加入 `PYTHONTHREADDEBUG` 。

- 加入对 `__ltrace__` 变量的支持：如果定义了该变量，在计算字节码环节启用底层跟踪。

- 安装 内存分配调试钩子 ，以便检测缓冲区溢出和其他内存错误。

- 定义宏 `Py_DEBUG` 和 `Py_REF_DEBUG` 。

- 加入运行时检查：针对 `#ifdef Py_DEBUG` 和 `#endif` 包裹的代码。启用 `assert(...)` 和 `_PyObject_ASSERT(...)` 断言：不设置 `NDEBUG` 宏（参阅 `--with-assertions` 参数）。主要的运行检查包括：

  - 增加了对函数参数的合理性检查。

  - 创建 Unicode 和 int 对象时，内存按某种模式进行了填充，用于检测是否使用了未初始化的对象。

  - 确保有能力清除或替换当前异常的函数在调用时不会引发异常。

  - 垃圾收集器（`gc.collect()` 函数）对对象的一致性进行一些基本检查。

  - 从较宽类型转换到较窄类型时，`Py_SAFE_DOWNCAST()` 宏会检查整数下溢和上溢的情况。

参见 Python 开发模式 和配置参数 `--with-trace-refs` 。

3.8 版更變: 发布版和调试版的编译现在是 ABI 兼容的：定义了 `Py_DEBUG` 宏不再意味着同时定义了 `Py_TRACE_REFS` 宏（参见 `--with-trace-refs` 参数），这引入了唯一一处不是 ABI 兼容的地方。

### 3.1.5. 调试选项

`--with-pydebug```

  在调试模式下编译 Python: 定义宏 `Py_DEBUG` (默认为禁用)。

`--with-trace-refs```

  为了调试而启用引用的跟踪（默认为禁用）。

  效果如下：

  - 定义 `Py_TRACE_REFS` 宏。

  - 加入 `sys.getobjects()` 函数。

  - 环境变量加入 `PYTHONDUMPREFS` 。

  此版本与发布模式（默认编译模式）或调试模式（`Py_DEBUG` 和 `Py_REF_DEBUG` 宏）不具备 ABI 兼容性。

  3.8 版新加入.

`--with-assertions```

  编译时启用 C 断言：`assert(...);` 和 `_PyObject_ASSERT(...);` （默认不启用）。

  如果设置此参数，则在 `OPT` 编译器变量中不定义 `NDEBUG` 宏。

  参阅 `--with-pydebug` 选项（调试编译模式），它也可以启用断言。

  3.6 版新加入.

`--with-valgrind```

  启用 Valgrind （默认禁用）。

`--with-dtrace```

  启用 DTrace（默认禁用）。

  参阅 用 DTrace 和 SystemTap 测试 CPython。

  3.6 版新加入.

`--with-address-sanitizer```

  启用 AddressSanitizer 内存错误检测 `asan`，（默认为禁用）。

  3.6 版新加入.

`--with-memory-sanitizer```

  启用 MemorySanitizer 内存错误检测 `msan`，（默认为禁用）。

  3.6 版新加入.

`--with-undefined-behavior-sanitizer```

  启用 undefinedBehaviorSanitizer 未定义行为检测 `ubsan`，（默认为禁用）。

  3.6 版新加入.

### 3.1.6. 链接器选项

`--enable-shared```

  启用共享 Python 库 `libpython` 的编译（默认为禁用）。

`--without-static-libpython```

  不编译 `libpythonMAJOR.MINOR.a`，也不安装 `python.o` (默认会编译并安装)。

  3.10 版新加入.

### 3.1.7. 库选项

`--with-libs``='lib1 ...'`

  链接附加库（默认不会）。

`--with-system-expat```

  用已安装的 `expat` 库编译 `pyexpat` 模块（默认为否）。

`--with-system-ffi```

  用已安装的 `ffi` 库编译 `_ctypes` 扩展模块，参见 `ctypes` 模块（默认情况视系统而定）。

`--with-system-libmpdec```

  用已安装的 `mpdec` 库编译 `_decimal` 扩展模块，参见 `decimal` 模块（默认为否）。

  3.3 版新加入.

`--with-readline``=editline`

  用 `editline` 库作为 `readline` 模块的后端。

  定义 `WITH_EDITLINE` 宏。

  3.10 版新加入.

`--without-readline```

  不编译 `readline` 模块（默认会）。

  不定义 `HAVE_LIBREADLINE` 宏。

  3.10 版新加入.

`--with-tcltk-includes``='-I...'`

  覆盖 Tcl 和 Tk 包含文件的搜索路径。

`--with-tcltk-libs``='-L...'`

  覆盖 Tcl 和 Tk 库的搜索路径。

`--with-libm``=STRING`

  将 `libm` 数学库覆盖为 STRING (默认情况视系统而定)。

`--with-libc``=STRING`

  将 `libc` C 库覆盖为 STRING (默认情况视系统而定)。

`--with-openssl``=DIR`

  OpenSSL 的根目录。

  3.7 版新加入.

`--with-openssl-rpath``=[no|auto|DIR]`

  设置 OpenSSL 库的运行时库目录（rpath）。

  - `no` (默认): 不设置 rpath。

  - `auto`：根据 `--with-openssl` 和 `pkg-config` 自动检测 rpath。

  - DIR ：直接设置 rpath。

  3.10 版新加入.

### 3.1.8. 安全性选项

`--with-hash-algorithm``=[fnv|siphash24]`

  选择 `Python/pyhash.c` 采用的哈希算法。

  - `siphash24` (默认)。

  - `fnv`。

  3.4 版新加入.

`--with-builtin-hashlib-hashes``=md5,sha1,sha256,sha512,sha3,blake2`

  内置哈希模块：

  - `md5`。

  - `sha1`。

  - `sha256`。

  - `sha512`。

  - `sha3` (带 shake)。

  - `blake2`。

  3.9 版新加入.

`--with-ssl-default-suites``=[python|openssl|STRING]`

  覆盖 OpenSSL 默认的密码套件字符串。

  - `python` (默认值): 采用 Python 推荐选择。

  - `openssl`：保留 OpenSSL 默认值不动。

  - STRING ：采用自定义字符串。

  参见 `ssl` 模块。

  3.7 版新加入.

  3.10 版更變: 设置 `python` 和 STRING 也会把 TLS 1.2 设为最低版本的协议。

### 3.1.9. macOS 选项

參閱 `Mac/README.rst`。

`--enable-universalsdk```

`--enable-universalsdk``=SDKDIR`

  创建通用的二进制版本。SDKDIR 指定应采用的 macOS SDK （默认为否）。

`--enable-framework```

`--enable-framework``=INSTALLDIR`

  创建 Python.framework ，而不是传统的 Unix 安装版。可选参数 INSTALLDIR 指定了安装路径（(默认为否）。

`--with-universal-archs``=ARCH`

  指定应创建何种通用二进制文件。该选项仅当设置了 `--enable-universalsdk` 时才有效。

  可选项：

  - `universal2`。

  - `32-bit`。

  - `64-bit`。

  - `3-way`。

  - `intel`。

  - `intel-32`。

  - `intel-64`。

  - `all`。

`--with-framework-name``=FRAMEWORK`

  为 macOS 中的 python 框架指定名称，仅当设置了 `--enable-framework` 时有效（默认：`Python`）。

## 3.2. Python 构建系统

### 3.2.1. 构建系统的主要文件

- `configure.ac` => `configure`；

- `Makefile.pre.in` => `Makefile` (由 `configure` 创建);

- `pyconfig.h` (created by `configure`)；

- `Modules/Setup`: 由Makefile 使用 `Module/makesetup` shell 脚本构建的 C 扩展;

- `setup.py`: 使用 `distutils` 模块构建的 C 扩展。

### 3.2.2. 主要构建步骤

- C文件（ `.c` ）是作为对象文件（ `.o` ）构建的。

- 一个静态库 `libpython` （ `.a` ）是由对象文件创建的。

- `python.o` 和静态库 `libpython` 被链接到最终程序 `python` 中。

- C 扩展由 Makefile （参见 `Modules/Setup` ） 和 `python setup.py build` 构建。

### 3.2.3. 主要 Makefile 目标

- `make` ：用标准库构建Python。

- `make platform:` ：构建 `python` 程序，但不构建标准库扩展模块。

- `make profile-opt` ：使用 Profile Guided Optimization (PGO) 构建 Python 。你可以使用 configure 的 `--enable-optimizations` 选项来使其成为 `make` 命令的默认目标（ `make all` 或只是 `make` ）。

- `make buildbottest` ：构建 Python 并运行 Python 测试套件，与 buildbots 测试 Python 的方式相同。设置变量 `TESTTIMEOUT` （单位：秒）来改变测试超时时间（默认为 1200 即 20 分钟）。

- `make install`：构建并安装 Python 。

- `make regen-all` ：重新生成（几乎）所有生成的文件； `make regen-stdlib-module-names` 和 `autoconf` 必须对其余生成的文件单独运行。

- `make clean` ：移除构建的文件。

- `make distclean` ：与 `make clean` 相同，但也删除由配置脚本创建的文件。

### 3.2.4. C 扩展

一些 C 扩展是作为内置模块构建的，比如模块 `sys` 。它们是在定义了宏 `Py_BUILD_CORE_BUILTIN` 的情况下构建的。内置模块没有 `__file__` 属性:

    >>> import sys
    >>> sys
    <module 'sys' (built-in)>
    >>> sys.__file__
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    AttributeError: module 'sys' has no attribute '__file__'

其他的 C 扩展是作为动态库构建的，就像 `_asyncio` 模块一样。 它们是在定义了 `Py_BUILD_CORE_MODULE` 宏的情况下构建的。 在 Linux x86-64 上的例子:

    >>> import _asyncio
    >>> _asyncio
    <module '_asyncio' from '/usr/lib64/python3.9/lib-dynload/_asyncio.cpython-39-x86_64-linux-gnu.so'>
    >>> _asyncio.__file__
    '/usr/lib64/python3.9/lib-dynload/_asyncio.cpython-39-x86_64-linux-gnu.so'

`Modules/Setup` 用于生成 Makefile 目标，以构建 C 扩展。在文件的开头， C 被构建为内置模块。在标记 `*shared*` 之后定义的扩展被构建为动态库。

`setup.py` 脚本只使用 `distutils` 模块将 C 构建为共享库。

宏 `PyAPI_FUNC()` ， `PyAPI_API()` 和 `PyMODINIT_FUNC()` 在 `Include/pyport.h` 中的定义不同，取决于是否定义宏 `Py_BUILD_CORE_MODULE` 。

- 如果 `Py_BUILD_CORE_MODULE` 定义了，使用 `Py_EXPORTED_SYMBOL` 。

- 否则使用 `Py_IMPORTED_SYMBOL` 。

如果宏 `Py_BUILD_CORE_BUILTIN` 被错误地用在作为共享库构建的 C 扩展上，它的函数 `PyInit_xxx()` 就不会被导出，导致导入时出现 `ImportError` 。

## 3.3. 编译器和链接器的标志

脚本 `./configure` 和环境变量设置的选项，并被 `Makefile` 使用。

### 3.3.1. 预处理器的标志

`CONFIGURE_CPPFLAGS`

  变量 `CPPFLAGS` 的值被传递给 `./configure` 脚本。

  3.6 版新加入.

`CPPFLAGS`

  （ Objective ） C/C++ 预处理器标志，例如，使用 `-I<include dir>` 如果你的头文件在一个非标准的目录 `<include dir>` 中 、

  `CPPFLAGS` 和 `LDFLAGS` 都需要包含shell的值，以便 setup.py 能够使用环境变量中指定的目录构建扩展模块。

`BASECPPFLAGS`

  3.4 版新加入.

`PY_CPPFLAGS`

  为构建解释器对象文件增加了额外的预处理器标志。

  默认为： `$(BASECPPFLAGS) -I. -I$(srcdir)/Include $(CONFIGURE_CPPFLAGS) $(CPPFLAGS)` 。

  3.2 版新加入.

### 3.3.2. 编译器标志

`CC`

  C 编译器指令。

  例如： `gcc -pthread` 。

`MAINCC`

  C编译器命令用于构建像 `python` 这样的程序的 `main()` 函数。

  由配置脚本的 `--with-cxx-main` 选项设置的变量。

  默认为： `$(CC)` 。

`CXX`

  C++ 编译器指令。

  如果使用了 `--with-cxx-main` 选项，则使用。

  例如： `g++ -pthread` 。

`CFLAGS`

  C 编译器标志。

`CFLAGS_NODIST`

  `CFLAGS_NODIST` 用于构建解释器和 stdlib C 扩展。当 Python 安装后，编译器标志 不 应该成为 distutils `CFLAGS` 的一部分时，可以使用它 （ bpo-21121 ）。

  特别地， `CFLAGS` 不应当包含:

  - 编译器旗标 `-I` (用于为包括文件设置搜索路径)。 `-I` 旗标将按从左到右的顺序处理，并且 `CFLAGS` 中的任何旗标都将优先于 user- 和 package- 层级所提供的 `-I` 旗标。

  - 加固旗标如 `-Werror` 因为分发版无法控制由用户安装的包是否符合这样的高标准。

  3.5 版新加入.

`EXTRA_CFLAGS`

  而外的 C 编译器指令。

`CONFIGURE_CFLAGS`

  变量 `CFLAGS` 的值传递给 `./configure` 脚本。

  3.2 版新加入.

`CONFIGURE_CFLAGS_NODIST`

  变量 `CFLAGS_NODIST` 的值传递给 `./configure` 脚本。

  3.5 版新加入.

`BASECFLAGS`

  基础编译器标志。

`OPT`

  优化标志。

`CFLAGS_ALIASING`

  严格或不严格的别名标志，用于编译 `Python/dtoa.c` 、

  3.7 版新加入.

`CCSHARED`

  用于构建共享库的编译器标志。

  例如說 `-fPIC` 被使用於 Linux 與 BSD 上。

`CFLAGSFORSHARED`

  为构建解释器对象文件增加了额外的 C 标志。

  ，默认为： `$(CCSHARED)` ，当 `--enable-shared` 被使用时，则为空字符串

`PY_CFLAGS`

  默认为： `$(BASECFLAGS) $(OPT) $(CONFIGURE_CFLAGS) $(CFLAGS) $(EXTRA_CFLAGS)` 。

`PY_CFLAGS_NODIST`

  默认为： `$(CONFIGURE_CFLAGS_NODIST) $(CFLAGS_NODIST) -I$(srcdir)/Include/internal` 。

  3.5 版新加入.

`PY_STDMODULE_CFLAGS`

  用于构建解释器对象文件的 C 标志。

  默认为： `$(PY_CFLAGS) $(PY_CFLAGS_NODIST) $(PY_CPPFLAGS) $(CFLAGSFORSHARED)`。

  3.7 版新加入.

`PY_CORE_CFLAGS`

  默认为 `$(PY_STDMODULE_CFLAGS) -DPy_BUILD_CORE` 。

  3.2 版新加入.

`PY_BUILTIN_MODULE_CFLAGS`

  编译器标志，将标准库的扩展模块作为内置模块来构建，如 `posix` 模块

  默认为： `$(PY_STDMODULE_CFLAGS) -DPy_BUILD_CORE_BUILTIN` 。

  3.8 版新加入.

`PURIFY`

  Purify 命令。 Purify 是一个内存调试程序。

  默认为：空字符串（不使用）。

### 3.3.3. 链接器标志位

`LINKCC`

  用于构建如 `python` 和 `_testembed` 的程序的链接器命令。

  默认为： `$(PURIFY) $(MAINCC)` 。

`CONFIGURE_LDFLAGS`

  变量 `LDFLAGS` 的值被传递给 `./configure` 脚本。

  避免指定 `CFLAGS` ， `LDFLAGS` 等，这样用户就可以在命令行上使用它们来追加这些值，而不用触碰到预设的值。

  3.2 版新加入.

`LDFLAGS_NODIST`

  `LDFLAGS_NODIST` 的使用方式与 `CFLAGS_NODIST` 相同。当 Python 安装后，链接器标志 不 应该成为 distutils `LDFLAGS` 的一部分时，可以使用它（ bpo-35257 ）。

  特别地， `LDFLAGS` 不应当包含:

  - 编译器旗标 `-L` (用于为库设置搜索路径)。 `-L` 旗标将按从左到右的顺序处理，并且 `LDFLAGS` 中的任何旗标都将优先于 user- 和 package 层级所提供的 `-L` 旗标。

`CONFIGURE_LDFLAGS_NODIST`

  变量 `LDFLAGS_NODIST` 的值传递给 `./configure` 脚本。

  3.8 版新加入.

`LDFLAGS`

  链接器标志，例如，如果你的库在一个非标准的目录 `<lib dir>` 中，则使用 `-L<lib dir>` 。

  `CPPFLAGS` 和 `LDFLAGS` 都需要包含shell的值，以便 setup.py 能够使用环境变量中指定的目录构建扩展模块。

`LIBS`

  链接器标志，在链接 Python 可执行文件时将库传递给链接器。

  例如： `-lrt` 。

`LDSHARED`

  构建一个共享库的命令。

  默认为： `@LDSHARED@ $(PY_LDFLAGS)` 。

`BLDSHARED`

  构建共享库 `libpython` 的命令。

  默认为： `@BLDSHARED@ $(PY_CORE_LDFLAGS)` 。

`PY_LDFLAGS`

  默认为： `$(CONFIGURE_LDFLAGS) $(LDFLAGS)` 。

`PY_LDFLAGS_NODIST`

  默认为： `$(CONFIGURE_LDFLAGS_NODIST) $(LDFLAGS_NODIST)` 。

  3.8 版新加入.

`PY_CORE_LDFLAGS`

  用于构建解释器对象文件的链接器标志。

  3.8 版新加入.