port(2P step 3a/3b): stdlib on sys.path + the pack module
step 3a — 标准库: tools/py_embed/make_stdlib_zip.py packs the vendored Lib/ into <build>/python27.zip (397 modules, 6876547 bytes, ZIP_STORED — the zlib module is trimmed out of our CPython, so zipimport cannot inflate). The mtpython_stdlib target builds it; py_embed_test and the launcher test both run against it. platform/ScriptLib/PythonHost sets the embedding flags before Py_Initialize and, after it, puts the zip on sys.path and re-registers encodings.search_function with codecs — 2.7 builds the codec registry once, at startup, so replacing sys.path afterwards needs it back. step 3b — pack 模块: UserInterface/PythonPackModule.cpp copied verbatim; packExist/packGet/ initpack read root/ and uiscript/ through CEterPackManager, i.e. through asset_io. The CHINA_CRYPT_KEY block in that unit is CAccountConnector's and is kept #if 0 until the login slice (2V1). UserInterface/StdAfx.h is a documented partial mirror — the original is the whole client's PCH. The launcher test now runs initpack() as RunMainScript does (its first line), reads system.py / uiscript / locale text back out of the packs, and confirms cp1252 decoding works off the zip. system.py still stops at "No module named app" — the C++ modules are the 2V0 slice. gates: port_map.py check 0 errors · key leak check 8/8 none · macOS ctest 27/27 · android + ios port_platform compile clean. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,59 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Pack the vendored CPython 2.7.18 Lib/ into the python27.zip the host puts on sys.path.
|
||||
|
||||
make_stdlib_zip.py <Lib dir> <out.zip>
|
||||
|
||||
40250 shipped a real python27 installation, so `import encodings` found Lib/ through the
|
||||
interpreter's prefix. The embedded interpreter has no prefix (Py_FrozenFlag, no site), so the host
|
||||
supplies the stdlib as this one file — the arrangement validated on the device by
|
||||
tools/py_embed_android/build-and-run.sh (PORT-PLAN 批次 2P step 3).
|
||||
|
||||
Entries are STORED, never deflated: the zlib module is not in the vendored Modules/ (see
|
||||
docs/THIRD-PARTY.md), so zipimport could not inflate them. Only .py goes in; zipimport reads
|
||||
source as happily as bytecode, and .pyc would pin the magic number to the build host's interpreter.
|
||||
Written deterministically (sorted, fixed timestamp) so the file's sha256 identifies its contents —
|
||||
3c checks that hash when staging the zip into a mobile sandbox.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import sys
|
||||
import zipfile
|
||||
from pathlib import Path
|
||||
|
||||
# Test suites, the Tk/2to3/bsddb/pip trees and the platform-specific stubs: none of the 40250 scripts
|
||||
# or their imports reach them, and they are most of the size.
|
||||
SKIP_DIRS = {"test", "tests", "lib-tk", "idlelib", "lib2to3", "bsddb", "ensurepip", "curses",
|
||||
"distutils", "unittest", "wsgiref", "multiprocessing", "compiler"}
|
||||
|
||||
|
||||
def main() -> int:
|
||||
if len(sys.argv) != 3:
|
||||
print(__doc__, file=sys.stderr)
|
||||
return 2
|
||||
lib, out = Path(sys.argv[1]), Path(sys.argv[2])
|
||||
if not (lib / "os.py").is_file():
|
||||
print(f"make_stdlib_zip: {lib} is not a CPython Lib/ directory", file=sys.stderr)
|
||||
return 1
|
||||
|
||||
members = []
|
||||
for path in sorted(lib.rglob("*.py")):
|
||||
rel = path.relative_to(lib)
|
||||
if rel.parts[0].startswith("plat-") or SKIP_DIRS.intersection(rel.parts[:-1]):
|
||||
continue
|
||||
members.append((rel, path))
|
||||
|
||||
out.parent.mkdir(parents=True, exist_ok=True)
|
||||
tmp = out.with_suffix(".zip.tmp")
|
||||
with zipfile.ZipFile(tmp, "w", zipfile.ZIP_STORED) as zf:
|
||||
for rel, path in members:
|
||||
info = zipfile.ZipInfo(rel.as_posix(), date_time=(1980, 1, 1, 0, 0, 0))
|
||||
info.external_attr = 0o644 << 16
|
||||
zf.writestr(info, path.read_bytes())
|
||||
tmp.replace(out)
|
||||
print(f"make_stdlib_zip: {out} ({len(members)} modules, {out.stat().st_size} bytes)")
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main())
|
||||
Reference in New Issue
Block a user