Skip to content

Commit 574c75c

Browse files
committed
Add configure.py, replacing configure.ac.
Assisted-by: claude-opus-4-6
1 parent 6665115 commit 574c75c

40 files changed

+59237
-36165
lines changed

Tools/configure/CONFIG_USE.md

Lines changed: 233 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,233 @@
1+
# CPython CI Configure Usage Summary
2+
3+
This file documents how `./configure` is invoked across CPython's GitHub Actions
4+
CI workflows, to ensure the Python-based `configure.py` supports all required
5+
options.
6+
7+
## Testing Checklist
8+
9+
Each item tracks whether `configure.py` correctly handles that flag or scenario.
10+
11+
### Build variant flags
12+
- [x] `--with-pydebug` — enable debug build (Py_DEBUG)
13+
- [x] `--disable-gil` — free-threading build (no GIL)
14+
- [x] `--enable-shared` — build shared library
15+
- [x] `--without-pymalloc` — disable pymalloc allocator
16+
17+
### Optimization / safety flags
18+
- [x] `--enable-safety` — enable safety checks
19+
- [x] `--enable-slower-safety` — enable slower safety checks
20+
- [x] `--enable-bolt` — enable BOLT binary optimization
21+
- [x] `--config-cache` — read/write `config.cache` to speed up re-runs
22+
23+
### JIT / interpreter flags
24+
- [x] `--enable-experimental-jit` — enable the JIT compiler
25+
- [x] `--enable-experimental-jit=interpreter` — JIT interpreter-only mode
26+
- [x] `--with-tail-call-interp` — enable tail-call interpreter
27+
28+
### Cross-compilation / universal binary flags
29+
- [x] `--prefix=PATH` — installation prefix
30+
- [ ] `--with-build-python=PATH` — build-system Python for cross-compilation (needs two-stage build)
31+
- [x] `--enable-universalsdk` — build macOS universal binary (macOS only)
32+
- [x] `--with-universal-archs=universal2` — macOS arm64+x86_64 universal binary (macOS only)
33+
34+
### SSL / crypto flags
35+
- [x] `--with-openssl=PATH` — path to OpenSSL installation
36+
- [x] `--with-builtin-hashlib-hashes=blake2` — build blake2 into hashlib
37+
- [x] `--with-ssl-default-suites=openssl` — use OpenSSL default cipher suites
38+
39+
### Sanitizer flags
40+
- [x] `--with-address-sanitizer` — enable AddressSanitizer
41+
- [x] `--with-thread-sanitizer` — enable ThreadSanitizer
42+
- [x] `--with-undefined-behavior-sanitizer` — enable UBSan
43+
44+
### Environment variables passed to configure
45+
- [x] `CC=clang-N` — custom compiler (tail-call.yml, jit.yml)
46+
- [x] `CFLAGS="..."` — extra compiler flags (e.g. `-fdiagnostics-format=json`)
47+
- [x] `MACOSX_DEPLOYMENT_TARGET=10.15` — macOS min deployment target (macOS only)
48+
- [x] `GDBM_CFLAGS`, `GDBM_LIBS` — GDBM library paths (macOS only)
49+
- [x] `PROFILE_TASK=...` — PGO task override (reusable-ubuntu.yml)
50+
51+
### Invocation scenarios
52+
- [x] In-tree build: `./configure [flags]`
53+
- [x] Out-of-tree build: invoke as `../srcdir/configure` from a build directory
54+
- [ ] WASI wrapper passthrough: `python3 Platforms/WASI configure-build-python -- --config-cache --with-pydebug` (needs WASI SDK)
55+
56+
---
57+
58+
## Workflow Files with Configure Invocations
59+
60+
### build.yml (Tests)
61+
62+
**Platforms:** ubuntu-24.04, ubuntu-24.04-arm, macos-14, macos-15-intel, android, ios, wasi
63+
64+
```sh
65+
# check-generated-files
66+
./configure --config-cache --with-pydebug --enable-shared
67+
68+
# build-ubuntu-ssltests-openssl
69+
./configure CFLAGS="-fdiagnostics-format=json" \
70+
--config-cache --enable-slower-safety --with-pydebug \
71+
--with-openssl="$OPENSSL_DIR"
72+
73+
# build-ubuntu-ssltests-awslc
74+
./configure CFLAGS="-fdiagnostics-format=json" \
75+
--config-cache --enable-slower-safety --with-pydebug \
76+
--with-openssl="$OPENSSL_DIR" \
77+
--with-builtin-hashlib-hashes=blake2 \
78+
--with-ssl-default-suites=openssl
79+
80+
# test-hypothesis (out-of-tree build from $BUILD_DIR)
81+
../cpython-ro-srcdir/configure \
82+
--config-cache --with-pydebug --enable-slower-safety \
83+
--with-openssl="$OPENSSL_DIR"
84+
85+
# build-asan
86+
./configure --config-cache --with-address-sanitizer --without-pymalloc
87+
88+
# cross-build-linux (build host python, then cross-compile)
89+
./configure --prefix="$BUILD_DIR/host-python"
90+
./configure --prefix="$BUILD_DIR/cross-python" \
91+
--with-build-python="$BUILD_DIR/host-python/bin/python3"
92+
```
93+
94+
---
95+
96+
### jit.yml (JIT)
97+
98+
**Platforms:** ubuntu-24.04, ubuntu-24.04-arm, macos-14, macos-15-intel, windows-2022, windows-11-arm
99+
100+
```sh
101+
# interpreter job
102+
./configure --enable-experimental-jit=interpreter --with-pydebug
103+
104+
# jit - Linux (--with-pydebug conditional on debug matrix var)
105+
./configure --enable-experimental-jit [--with-pydebug]
106+
107+
# jit - macOS
108+
./configure --enable-experimental-jit \
109+
--enable-universalsdk --with-universal-archs=universal2 [--with-pydebug]
110+
111+
# jit-with-disabled-gil
112+
./configure --enable-experimental-jit --with-pydebug --disable-gil
113+
114+
# tail-call-jit (with explicit compiler)
115+
CC=clang-$LLVM ./configure --enable-experimental-jit \
116+
--with-tail-call-interp --with-pydebug
117+
```
118+
119+
---
120+
121+
### reusable-docs.yml (Docs)
122+
123+
**Platforms:** ubuntu-24.04
124+
125+
```sh
126+
./configure --with-pydebug
127+
```
128+
129+
---
130+
131+
### reusable-macos.yml
132+
133+
**Platforms:** macos-14, macos-15-intel
134+
135+
Environment: `MACOSX_DEPLOYMENT_TARGET=10.15`, `GDBM_CFLAGS`, `GDBM_LIBS`
136+
137+
```sh
138+
./configure \
139+
--config-cache \
140+
--with-pydebug \
141+
--enable-slower-safety \
142+
--enable-safety \
143+
[--disable-gil] \
144+
--prefix=/opt/python-dev \
145+
--with-openssl="$(brew --prefix openssl@3.0)"
146+
```
147+
148+
---
149+
150+
### reusable-san.yml (Sanitizers)
151+
152+
**Platforms:** ubuntu-24.04
153+
154+
```sh
155+
./configure \
156+
--config-cache \
157+
--with-pydebug \
158+
[--with-thread-sanitizer | --with-undefined-behavior-sanitizer] \
159+
[--disable-gil]
160+
```
161+
162+
---
163+
164+
### reusable-ubuntu.yml
165+
166+
**Platforms:** ubuntu-24.04, ubuntu-24.04-arm (out-of-tree build)
167+
168+
Environment: `PROFILE_TASK='-m test --pgo --ignore test_unpickle_module_race'`
169+
170+
```sh
171+
../cpython-ro-srcdir/configure \
172+
--config-cache \
173+
--with-pydebug \
174+
--enable-slower-safety \
175+
--enable-safety \
176+
--with-openssl="$OPENSSL_DIR" \
177+
[--disable-gil] \
178+
[--enable-bolt]
179+
```
180+
181+
---
182+
183+
### reusable-wasi.yml
184+
185+
**Platforms:** ubuntu-24.04-arm
186+
187+
Uses a Python wrapper rather than calling `./configure` directly:
188+
189+
```sh
190+
python3 Platforms/WASI configure-build-python -- --config-cache --with-pydebug
191+
python3 Platforms/WASI configure-host -- --config-cache
192+
```
193+
194+
---
195+
196+
### tail-call.yml (Tail-calling interpreter)
197+
198+
**Platforms:** ubuntu-24.04, ubuntu-24.04-arm, macos-14, macos-15-intel, windows-2022, windows-2025-vs2026, windows-11-arm
199+
200+
```sh
201+
# Linux
202+
CC=clang-20 ./configure --with-tail-call-interp --with-pydebug
203+
204+
# Linux free-threading
205+
CC=clang-20 ./configure --with-tail-call-interp --disable-gil
206+
207+
# macOS
208+
CC=clang-20 ./configure --with-tail-call-interp
209+
```
210+
211+
---
212+
213+
## Notes for configure.py Implementation
214+
215+
1. **Out-of-tree builds**: `configure` is invoked from a separate build directory
216+
with the source path as `../cpython-ro-srcdir/configure`. The `srcdir` must
217+
be correctly detected as distinct from the current directory.
218+
219+
2. **Environment variable passthrough**: `CC`, `CFLAGS`, and library-path variables
220+
(`GDBM_CFLAGS`, `GDBM_LIBS`) must be accepted and propagated into the build.
221+
222+
3. **`--config-cache`**: Used extensively; must read/write `config.cache` to
223+
speed up repeated configure runs.
224+
225+
4. **Conditional flags**: `--disable-gil`, `--with-pydebug`, etc. are passed
226+
conditionally based on matrix variables — all must be accepted gracefully.
227+
228+
5. **WASI**: Uses a wrapper script, not `./configure` directly. The wrapper
229+
passes `--config-cache` and `--with-pydebug` through, so those flags must
230+
work when configure is invoked as a sub-step.
231+
232+
6. **Windows**: JIT and tail-call workflows include Windows runners, but
233+
configure on Windows uses PCbuild/MSBuild — no `./configure` call is made.

Tools/configure/README.md

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
# configure.py, a replacement for configure.ac
2+
3+
CPython's build configuration is driven by `configure.ac` (8,344 lines, ~271
4+
KB), which uses autoconf/M4 macros to generate a 946 KB shell script
5+
(`configure`). This system is:
6+
- Opaque and hard to read/maintain (M4 macro language)
7+
- Inefficient (generates a giant shell script, then runs it)
8+
- Difficult to extend or debug
9+
10+
This replaces it with a Python-based build configuration system where
11+
`Tools/configure/configure.py` is a real Python script that imports a `pyconf`
12+
module. The `pyconf` functions generally match the autoconf behaviour, so that
13+
translation from the configure.ac file is mostly direct and mechanical.
14+
15+
There is also a transpiler that converts configure.py into POSIX AWK (wrapped
16+
in a small shell stub). The transpiler lives in `Tools/configure/transpiler/`
17+
and the pipeline is: Python AST → pysh_ast → awk_ast → AWK text. The sh and
18+
AWK code needs to be compatible with those tools on various Unix-like operating
19+
systems.
20+
21+
Note that configure.py needs to be cross platform. Implementation that only
22+
only works on the current OS is *not* okay. This configure script will run on
23+
many different Unix like platforms: Linux, FreeBSD, OpenBSD, NetBSD, MacOS,
24+
AIX. Avoid "baking in" Linux specific behaviour that is going to break on
25+
other platforms.
26+
27+
We compare output files, produced by the script, in order to ensure we
28+
faithfully re-implement the configure.ac script. When comparing output files,
29+
like Makefile, pyconfig.h, we generally don't care about whitespace changes.
30+
So `diff -u -bw` could be used to compare.
31+
32+
You can run the new configure.py script by running `./configure`. The autoconf
33+
script has been renamed to `./configure-old`.
34+
35+
When making code changes, you should use `ruff check Tools/configure/*.py` and
36+
`ruff format Tools/configure/*.py` to ensure code is formatted and lint clean.
37+
38+
There are unit tests for the pyconf module, test_pyconf.py. You can run these
39+
tests with `uv run <file>`. There are also unit tests for the transpiler, in
40+
test_transpile.py. To compare the output of the transpiled version, run
41+
`compare-transpile.sh`. You can compare outputs of the two configure
42+
implementations by running `./compare-conf.sh`.

0 commit comments

Comments
 (0)