Skip to content

feat(embed): self-compiled pyscriptc bundle that runs with no Python installed - #794

Draft
espetro wants to merge 14 commits into
work/planesplitfrom
work/selfbin
Draft

espetro wants to merge 14 commits into
work/planesplitfrom
work/selfbin

Conversation

@espetro

@espetro espetro commented Oct 30, 2026 •

Copy link
Copy Markdown
Contributor

pyscriptc compiled to a relocatable bundle that needs no Python, uv or pip, stacked on #793. Recipe (mise run selfbin wraps it plus the slow tests):

pyscriptc compile src/pyscriptc --program --skip-check --island --emit bin --embed-python bundle --embed-headers --bundle-exclude mypy -o dist/selfbin

Results (VPS, warm cache, median):

  • Runs under env -i PATH=/nonexistent: no Python on the machine. With only clang on PATH it also compiles programs.
  • Byte-for-byte parity with the uv-installed pyscriptc on 16 example programs (compile --skip-check --island, check, assess, coverage, run, config, imports).
  • --version 313 ms vs 187 ms installed; hello-world compile --emit bin 1,274 ms vs 525 ms. The island pipeline has the same shape on both.

Changes: --embed-headers stages the pack's CPython headers into a bundle so the self binary can compile island programs; --bundle-exclude ROOT declares an import root extern (needed for lazily imported mypy); the runtime lock file is staged into a program-island compile; embed.self_pack_dir() lets a bundle that carries libpython and headers act as its own pack; a missing pyrefly in a self-compiled compiler now names the remedy instead of relaunching the compiler.

Honest gaps against "single binary":

  • The artifact is a 60 MB directory (bin/selfbin is 2.8 MB), not one file: libpython is a shared library and the stdlib is a zip, both must sit beside the executable.
  • Still needed at run time: a C toolchain (clang or zig) for --emit bin and run, and pyrefly for check, infer and preflight. Nothing else.
  • verify and build are untested against the uv install; CI does not run the slow test; the boxed ledger was not re-measured.

Agent added 3 commits October 30, 2026 17:44
…ntime

The bundle compile of a program now stages the runtime pack's CPython
headers (--embed-headers), the runtime lock file and the pack's own stdlib
zip, so the compiled binary can compile island programs at run time with no
Python install, no runtime pack cache and no network. A bundle dependency
root can be declared extern (--bundle-exclude), and a missing header
directory names the remedy.
tests/test_selfbin.py (marked slow) builds the self-compiled pyscriptc
through the cli and runs a hello world compile with no Python on PATH, and
mise run selfbin wraps the same build. The runtime-pack reference documents
the two-file bundle layout and the external tools the binary still needs.
…emedy

The -m pyrefly fallback in a self-compiled binary launches the compiler
itself, so the failure surfaced as an argparse usage error. The failure now
names PYREFLY_BIN, pip install pyrefly or --skip-check, and the doubled
Install one of: in PS0001 is deduplicated.
@espetro espetro added this to the v0.8.0 milestone Oct 30, 2026
@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Nov 2, 2026 •

Copy link
Copy Markdown

Deploying pyscriptc with  Cloudflare Pages  Cloudflare Pages

Latest commit: 4df6966
Status: ✅  Deploy successful!
Preview URL: https://7a445c56.pyscriptc.pages.dev
Branch Preview URL: https://work-selfbin.pyscriptc.pages.dev

View logs

Agent added 10 commits November 2, 2026 05:51
…o the self-compiled bundle

The self-compiled bundle keeps its own carried_modules helper (a pack
whose stdlib travels as a zip carries the zip's names), so the merge
keeps it and adds the runtime set on top: the check answers the runtime
the bundle links, not the compiler host's build.
The --bundle-exclude and --embed-headers flags landed without a docs
regeneration, so the generated-docs seam reported the CLI reference as
out of date.
…compiled bundle

The runtime-linked stdlib manifest check adds 7 self-host fences in
stdlibzip.py, so the bundle branch's census pin (3278) is stale on the
merged tree. The merged tree measures 3285 fences and the same package
sum; the pin moves with a comment that names both deltas.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Todo

Development

Successfully merging this pull request may close these issues.

1 participant