#!/usr/bin/env bash # Generate one platform's pyconfig.h for the vendored CPython 2.7.18 (docs/PORT-PLAN.md 批次 2P step 1). # pyconfig.h is the result of probing a platform's type sizes and system calls, so every platform keeps # its own copy under extension/third_party/cpython-2.7.18/config//. The source list and the # built-in module table (config/config.c) are shared and only regenerated from the macos run. # # tools/py_embed/gen_pyconfig.sh macos|android|ios|linux # # Build trees go to $MT_PY_CONFIG_DIR (default build/py_embed/). set -euo pipefail cd "$(dirname "$0")/../.." REPO="$PWD" SRC="$REPO/extension/third_party/cpython-2.7.18" PLAT="${1:?usage: gen_pyconfig.sh macos|android|ios|linux}" # config.sub in 2.7.18 predates arm64; the build triple only names the machine running configure. BUILD="$(uname -m | sed 's/^arm64$/aarch64/')-$(uname -s | tr 'A-Z' 'a-z')" W="${MT_PY_CONFIG_DIR:-$REPO/build/py_embed/$PLAT}" # The static module list, shared by every platform: the C modules the 40250 scripts and their stdlib # imports need. Keep it in sync with config/Setup.static. MODULES="array math _struct time operator _random _collections _heapq itertools strop _functools datetime _bisect _locale binascii cStringIO cPickle select fcntl" # In-place edit that works with both BSD and GNU sed. sedi() { local e="$1" f="$2"; sed -E "$e" "$f" > "$f.tmp" && mv "$f.tmp" "$f"; } case "$PLAT" in macos) HOST="" ;; linux) HOST="" [ "$(uname -s)" = Linux ] || { echo "gen_pyconfig: run this on a Linux host" >&2; exit 1; } ;; android) NDK="${ANDROID_NDK_HOME:-${ANDROID_NDK_ROOT:-$(ls -d "$HOME/Library/Android/sdk/ndk/"* | sort -V | tail -1)}}" TC="$NDK/toolchains/llvm/prebuilt/$(ls "$NDK/toolchains/llvm/prebuilt" | head -1)/bin" API=24 export CC="$TC/aarch64-linux-android$API-clang" AR="$TC/llvm-ar" RANLIB="$TC/llvm-ranlib" READELF="$TC/llvm-readelf" HOST="--host=aarch64-linux-android --build=$BUILD" ;; ios) # 2.7.18's configure refuses a darwin cross build ("cross build not supported for aarch64-apple-darwin"), # so iOS starts from the macOS probe — same arm64 Darwin ABI, same type sizes and headers — and only # drops the process-control calls the iOS sandbox forbids. The result is compiled for iphoneos by the # gate, which is what proves it. [ -f "$SRC/config/macos/pyconfig.h" ] || { echo "gen_pyconfig: run 'gen_pyconfig.sh macos' first" >&2; exit 1; } mkdir -p "$SRC/config/ios" "$W" cp "$SRC/config/macos/pyconfig.h" "$SRC/config/ios/pyconfig.h" sedi 's|^#define USE_TOOLBOX_OBJECT_GLUE 1|/* #undef USE_TOOLBOX_OBJECT_GLUE (Carbon is macOS-only) */|' \ "$SRC/config/ios/pyconfig.h" # HAVE_GETGROUPS stays defined: getgroups is allowed on iOS, and posixmodule.c only defines # MAX_GROUPS — which its HAVE_SETGROUPS path uses too — inside the #ifdef HAVE_GETGROUPS block. # The calls posixmodule.c hard-defines for "all other compilers" (system/fork/execv/wait/popen) # ignore pyconfig.h entirely; the vendored file's iOS guard drops those (see docs/THIRD-PARTY.md). for d in HAVE_SYSTEM HAVE_FORK HAVE_FORK1 HAVE_FORKPTY HAVE_EXECV HAVE_SPAWNV HAVE_WAIT HAVE_WAIT3 \ HAVE_WAIT4 HAVE_WAITPID HAVE_SETPGRP HAVE_KILLPG; do sedi "s|^#define $d 1|/* #undef $d (not usable on iOS) */|" "$SRC/config/ios/pyconfig.h" done # The iphoneos SDK has no ; Python/random.c then reads /dev/urandom, as it does on Linux. for d in HAVE_SYS_RANDOM_H HAVE_GETENTROPY; do sedi "s|^#define $d 1|/* #undef $d (not in the iphoneos SDK) */|" "$SRC/config/ios/pyconfig.h" done echo "wrote config/ios/pyconfig.h (derived from config/macos/pyconfig.h)" exit 0 ;; *) echo "gen_pyconfig: unknown platform $PLAT" >&2; exit 1 ;; esac mkdir -p "$W" && cd "$W" # Cross builds cannot run the host pgen; the tarball already ships these generated files. touch "$SRC/Include/graminit.h" "$SRC/Python/graminit.c" "$SRC/Include/Python-ast.h" "$SRC/Python/Python-ast.c" env -u CPPFLAGS -u LDFLAGS -u CFLAGS -u LIBS CONFIG_SITE=/dev/null \ "$SRC/configure" $HOST --disable-ipv6 --without-ensurepip --disable-shared \ ac_cv_file__dev_ptmx=no ac_cv_file__dev_ptc=no > configure.log if [ "$PLAT" = android ]; then # bionic declares nl_langinfo only from API 26 sedi 's|^#define HAVE_LANGINFO_H 1|/* #undef HAVE_LANGINFO_H (nl_langinfo needs API 26) */|' pyconfig.h fi # Enable the shared static-module list, then let makesetup regenerate the built-in table. for m in $MODULES; do sedi "s/^#($m )/\1/" Modules/Setup done sedi 's/^(math mathmodule.c _math.c) # -lm/\1/; s/^(time timemodule.c) # -lm/\1/; s/^(_locale _localemodule.c) # -lintl/\1/' Modules/Setup rm -f Modules/config.c make Modules/config.c > makesetup.log 2>&1 || make Makefile > makesetup.log 2>&1 || true [ -f Modules/config.c ] || { echo "gen_pyconfig: makesetup did not produce Modules/config.c" >&2; exit 1; } mkdir -p "$SRC/config/$PLAT" cp pyconfig.h "$SRC/config/$PLAT/pyconfig.h" if [ "$PLAT" = macos ]; then # the shared pieces come from the host build cp Modules/config.c "$SRC/config/config.c" cp Modules/Setup "$SRC/config/Setup.static" else # every platform must agree on the built-in table if ! diff -q Modules/config.c "$SRC/config/config.c" >/dev/null; then echo "gen_pyconfig: $PLAT built-in module table differs from config/config.c" >&2 diff "$SRC/config/config.c" Modules/config.c >&2 || true exit 1 fi fi echo "wrote config/$PLAT/pyconfig.h (built-in table matches config/config.c)"