port 2P step 1: vendor CPython 2.7.18 as the mtpython static library
The embedded 40250 script layer needs its own interpreter on five platforms. 2.7 is end-of-life, so nothing can be fetched from the target SDKs and the source is vendored (official 2.7.18 tarball, trimmed to 25MB; Lib/ stays for step 3's python27.zip). cpython-2.7.18/CMakeLists.txt builds one `mtpython` static library from exactly the 133 objects the reference libpython2.7.a contains, off by default behind -DMTGODOT_EMBED_PYTHON=ON. The source list and the built-in module table (config/config.c, 39 entries) are shared; pyconfig.h is a probe result and is not, so each platform keeps its own under config/<platform>/, regenerated by tools/py_embed/gen_pyconfig.sh and checked against the shared table. Three vendor patches, documented in docs/THIRD-PARTY.md: configure/configure.ac learn arm64 on macOS, and posixmodule.c undefines the process-control calls it hard-defines past pyconfig.h when building for iOS. macOS (ctest python.embed: every builtin imports, codecs and pickle work off the vendored Lib/), Android arm64 and iOS arm64 build. Linux needs a Linux host and Windows needs a MinGW-vs-MSVC decision; both are noted for step 4. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Executable
+105
@@ -0,0 +1,105 @@
|
||||
#!/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/<platform>/. 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/<platform>).
|
||||
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 <sys/random.h>; 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)"
|
||||
Reference in New Issue
Block a user