Skip to content

Commit 37c3554

Browse files
crusaderkyisuruflucascolley
authored
gh-143120: pixi builds for free-threading and TSAN (#142872)
Co-authored-by: Isuru Fernando <isuruf@gmail.com> Co-authored-by: Lucas Colley <lucas.colley8@gmail.com>
1 parent 9d0c743 commit 37c3554

File tree

15 files changed

+470
-121
lines changed

15 files changed

+470
-121
lines changed

Tools/pixi-packages/README.md

Lines changed: 32 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,56 @@
11
# CPython Pixi packages
22

3-
This directory contains definitions for [Pixi packages](https://pixi.sh/latest/reference/pixi_manifest/#the-package-section)
4-
which can be built from the CPython source code.
3+
This directory contains definitions for [Pixi
4+
packages](https://pixi.sh/latest/reference/pixi_manifest/#the-package-section) which can
5+
be built from the CPython source code.
56

6-
Downstream developers can make use of these packages by adding them as Git dependencies in a
7-
[Pixi workspace](https://pixi.sh/latest/first_workspace/), like:
7+
Downstream developers can make use of these packages by adding them as Git dependencies
8+
in a [Pixi workspace](https://pixi.sh/latest/first_workspace/), like:
89

910
```toml
1011
[dependencies]
11-
python = { git = "https://github.com/python/cpython", subdirectory = "Tools/pixi-packages/asan" }
12+
python.git = "https://github.com/python/cpython"
13+
python.subdirectory = "Tools/pixi-packages/asan"
1214
```
1315

1416
This is particularly useful when developers need to build CPython from source
15-
(for example, for an ASan-instrumented build), as it does not require any manual
17+
(for example, for an ASan or TSan-instrumented build), as it does not require any manual
1618
clone or build steps. Instead, Pixi will automatically handle both the build
1719
and installation of the package.
1820

1921
Each package definition is contained in a subdirectory, but they share the build script
2022
`build.sh` in this directory. Currently defined package variants:
2123

2224
- `default`
23-
- `asan`: ASan-instrumented build with `PYTHON_ASAN=1`
25+
- `freethreading`
26+
- `asan`: ASan-instrumented build
27+
- `tsan-freethreading`: TSan-instrumented free-threading build
2428

2529
## Maintenance
2630

27-
- Keep the `version` fields in each `recipe.yaml` up to date with the Python version
28-
- Keep the dependency requirements up to date in each `recipe.yaml`
31+
- Keep the `abi_tag` and `version` fields in each `variants.yaml` up to date with the
32+
Python version
2933
- Update `build.sh` for any breaking changes in the `configure` and `make` workflow
3034

3135
## Opportunities for future improvement
3236

33-
- More package variants (such as TSan, UBSan)
37+
- More package variants (such as UBSan)
3438
- Support for Windows
35-
- Using a single `pixi.toml` and `recipe.yaml` for all package variants is blocked on https://github.com/prefix-dev/pixi/issues/4599
36-
- A workaround can be removed from the build script once https://github.com/prefix-dev/rattler-build/issues/2012 is resolved
39+
- Using a single `pixi.toml` and `recipe.yaml` for all package variants is blocked on
40+
[pixi-build-backends#532](https://github.com/prefix-dev/pixi-build-backends/pull/532)
41+
and [pixi#5248](https://github.com/prefix-dev/pixi/issues/5248)
42+
43+
## Troubleshooting
44+
45+
TSan builds may crash on Linux with
46+
```
47+
FATAL: ThreadSanitizer: unexpected memory mapping 0x7977bd072000-0x7977bd500000
48+
```
49+
To fix it, try reducing `mmap_rnd_bits`:
50+
51+
```bash
52+
$ sudo sysctl vm.mmap_rnd_bits
53+
vm.mmap_rnd_bits = 32 # too high for TSan
54+
$ sudo sysctl vm.mmap_rnd_bits=28 # reduce it
55+
vm.mmap_rnd_bits = 28
56+
```

Tools/pixi-packages/asan/pixi.toml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
1+
# NOTE: Please always only modify default/pixi.toml and then run clone-recipe.sh to
2+
# propagate the changes to the other variants.
3+
14
[workspace]
25
channels = ["https://prefix.dev/conda-forge"]
3-
platforms = ["osx-arm64", "linux-64"]
6+
platforms = ["linux-64", "linux-aarch64", "osx-64", "osx-arm64"]
47
preview = ["pixi-build"]
58

69
[package.build.backend]

Tools/pixi-packages/asan/recipe.yaml

Lines changed: 80 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -1,61 +1,92 @@
1+
# NOTE: Please always only modify default/recipe.yaml and then run clone-recipe.sh to
2+
# propagate the changes to the other variants.
3+
14
context:
25
# Keep up to date
3-
version: "3.15"
6+
freethreading_tag: ${{ "t" if "freethreading" in variant else "" }}
47

5-
package:
8+
recipe:
69
name: python
7-
version: ${{ version }}
810

911
source:
1012
- path: ../../..
1113

12-
build:
13-
files:
14-
exclude:
15-
- "*.o"
16-
script:
17-
file: ../build.sh
18-
env:
19-
PYTHON_VARIANT: "asan"
20-
21-
# derived from https://github.com/conda-forge/python-feedstock/blob/main/recipe/meta.yaml
22-
requirements:
14+
outputs:
15+
- package:
16+
name: python_abi
17+
version: ${{ version }}
18+
build:
19+
string: "0_${{ abi_tag }}"
20+
requirements:
21+
run_constraints:
22+
- python ${{ version }}.* *_${{ abi_tag }}
23+
24+
- package:
25+
name: python
26+
version: ${{ version }}
2327
build:
24-
- ${{ compiler('c') }}
25-
- ${{ compiler('cxx') }}
26-
- make
27-
- pkg-config
28-
# configure script looks for llvm-ar for lto
29-
- if: osx
30-
then:
31-
- llvm-tools
32-
- if: linux
33-
then:
34-
- ld_impl_${{ target_platform }}
35-
- binutils_impl_${{ target_platform }}
36-
- clang-19
37-
- llvm-tools-19
38-
39-
host:
40-
- bzip2
41-
- sqlite
42-
- liblzma-devel
43-
- zlib
44-
- zstd
45-
- openssl
46-
- readline
47-
- tk
48-
# These two are just to get the headers needed for tk.h, but is unused
49-
- xorg-libx11
50-
- xorg-xorgproto
51-
- ncurses
52-
- libffi
53-
- if: linux
54-
then:
55-
- ld_impl_${{ target_platform }}
56-
- libuuid
57-
- libmpdec-devel
58-
- expat
28+
string: "0_${{ abi_tag }}"
29+
files:
30+
exclude:
31+
- "*.o"
32+
script:
33+
file: ../build.sh
34+
env:
35+
PYTHON_VARIANT: ${{ variant }}
36+
python:
37+
site_packages_path: "lib/python${{ version }}${{ freethreading_tag }}/site-packages"
38+
39+
# derived from https://github.com/conda-forge/python-feedstock/blob/main/recipe/meta.yaml
40+
requirements:
41+
build:
42+
- ${{ compiler('c') }}
43+
- ${{ compiler('cxx') }}
44+
# Note that we are not using stdlib arguments which means the packages
45+
# are built for the build settings and are not relocatable to a different
46+
# machine that has a older system version. (eg: macOS/glibc version)
47+
- make
48+
- pkg-config
49+
# configure script looks for llvm-ar for lto
50+
- if: osx
51+
then:
52+
- llvm-tools
53+
54+
host:
55+
- bzip2
56+
- sqlite
57+
- liblzma-devel
58+
- zlib
59+
- zstd
60+
- openssl
61+
- readline
62+
- tk
63+
# These two are just to get the headers needed for tk.h, but is unused
64+
- xorg-libx11
65+
- xorg-xorgproto
66+
- ncurses
67+
- libffi
68+
- if: linux
69+
then:
70+
- libuuid
71+
- libmpdec-devel
72+
- expat
73+
- if: linux and "san" in variant
74+
then:
75+
- libsanitizer
76+
- if: osx and "san" in variant
77+
then:
78+
- libcompiler-rt
79+
80+
ignore_run_exports:
81+
from_package:
82+
- xorg-libx11
83+
- xorg-xorgproto
84+
85+
run_exports:
86+
noarch:
87+
- python
88+
weak:
89+
- python_abi ${{ version }}.* *_${{ abi_tag }}
5990

6091
about:
6192
homepage: https://www.python.org/
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
variant:
2+
- asan
3+
abi_tag:
4+
- asan_cp315
5+
version:
6+
- 3.15

Tools/pixi-packages/build.sh

Lines changed: 27 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,36 @@
11
#!/bin/bash
22

3-
if [[ "${PYTHON_VARIANT}" == "asan" ]]; then
4-
echo "BUILD TYPE: ASAN"
5-
BUILD_DIR="../build_asan"
3+
echo "PYTHON_VARIANT: ${PYTHON_VARIANT}"
4+
5+
if [[ "${PYTHON_VARIANT}" == "freethreading" ]]; then
6+
CONFIGURE_EXTRA="--disable-gil"
7+
elif [[ "${PYTHON_VARIANT}" == "asan" ]]; then
68
CONFIGURE_EXTRA="--with-address-sanitizer"
7-
export PYTHON_ASAN="1"
89
export ASAN_OPTIONS="strict_init_order=true"
9-
else
10-
echo "BUILD TYPE: DEFAULT"
11-
BUILD_DIR="../build"
10+
elif [[ "${PYTHON_VARIANT}" == "tsan-freethreading" ]]; then
11+
CONFIGURE_EXTRA="--disable-gil --with-thread-sanitizer"
12+
export TSAN_OPTIONS="suppressions=${SRC_DIR}/Tools/tsan/suppressions_free_threading.txt"
13+
elif [[ "${PYTHON_VARIANT}" == "default" ]]; then
1214
CONFIGURE_EXTRA=""
15+
else
16+
echo "Unknown PYTHON_VARIANT: ${PYTHON_VARIANT}"
17+
exit 1
1318
fi
1419

20+
# rattler-build by default set a target of 10.9
21+
# override it to at least 10.12
22+
case ${MACOSX_DEPLOYMENT_TARGET:-10.12} in
23+
10.12|10.13|10.14|10.15|10.16)
24+
;;
25+
10.*)
26+
export CPPFLAGS=${CPPFLAGS/-mmacosx-version-min=${MACOSX_DEPLOYMENT_TARGET}/-mmacosx-version-min=10.12}
27+
export MACOSX_DEPLOYMENT_TARGET=10.12
28+
;;
29+
*)
30+
;;
31+
esac
32+
33+
BUILD_DIR="../build_${PYTHON_VARIANT}"
1534
mkdir -p "${BUILD_DIR}"
1635
cd "${BUILD_DIR}"
1736

@@ -23,15 +42,11 @@ else
2342
--oldincludedir="${BUILD_PREFIX}/${HOST}/sysroot/usr/include" \
2443
--enable-shared \
2544
--srcdir="${SRC_DIR}" \
45+
--with-system-expat \
2646
${CONFIGURE_EXTRA}
2747
fi
2848

2949
touch configure-done
3050

3151
make -j"${CPU_COUNT}" install
3252
ln -sf "${PREFIX}/bin/python3" "${PREFIX}/bin/python"
33-
34-
# https://github.com/prefix-dev/rattler-build/issues/2012
35-
if [[ ${OSTYPE} == "darwin"* ]]; then
36-
cp "${BUILD_PREFIX}/lib/clang/21/lib/darwin/libclang_rt.asan_osx_dynamic.dylib" "${PREFIX}/lib/libclang_rt.asan_osx_dynamic.dylib"
37-
fi
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
#!/bin/bash
2+
3+
# Please always only modify default/recipe.yaml and default/pixi.toml and then run this
4+
# script to propagate the changes to the other variants.
5+
set -o errexit
6+
cd "$(dirname "$0")"
7+
8+
for variant in asan freethreading tsan-freethreading; do
9+
cp -av default/recipe.yaml default/pixi.toml ${variant}/
10+
done

Tools/pixi-packages/default/pixi.toml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
1+
# NOTE: Please always only modify default/pixi.toml and then run clone-recipe.sh to
2+
# propagate the changes to the other variants.
3+
14
[workspace]
25
channels = ["https://prefix.dev/conda-forge"]
3-
platforms = ["osx-arm64", "linux-64"]
6+
platforms = ["linux-64", "linux-aarch64", "osx-64", "osx-arm64"]
47
preview = ["pixi-build"]
58

69
[package.build.backend]

0 commit comments

Comments
 (0)