https://github.com/python/prebuilt-cpython
# Plans
- [ ] [PBS patches](https://github.com/python/prebuilt-cpython/discussions/21) ([list](https://github.com/astral-sh/python-build-standalone/issues/886))
- [x] Ask AI to find a list of open source projects that build Python in a relocatable way
- [ ] Conda patches?
- [ ] Thomas patches?
- [ ] Homebrew patches?
- [ ] Spack patches?
- [ ] Salt patches?
# Every project that builds relocatable CPython
**At least 12 open-source projects produce relocatable CPython binaries**, each using a distinct strategy ranging from static linking and `$ORIGIN`-relative RPATHs to placeholder-prefix rewriting and single-file executables. The gold standard is **python-build-standalone** (now maintained by Astral), which combines static dependency linking with patched relative path resolution — and powers tools like `uv`, Rye, and Briefcase. Below is every significant project, the exact files implementing relocation, and how each approach works.
The techniques cluster into five categories: static linking (eliminate shared library dependencies entirely), RPATH patching (rewrite binary load paths to be relative), placeholder-prefix rewriting (build with a dummy path, replace at install time), framework/dylib fixups (macOS-specific `install_name_tool` rewrites), and single-file embedding (pack everything into one executable). Several projects combine multiple techniques.
---
## python-build-standalone is the ecosystem's foundation
**Repository:** [astral-sh/python-build-standalone](https://github.com/astral-sh/python-build-standalone) (transferred from indygreg/python-build-standalone)
Gregory Szorc created this project; Astral now maintains it. It produces the relocatable CPython distributions consumed by `uv`, Rye, Briefcase, mise, and pipx. [Astral](https://astral.sh/blog/python-build-standalone)
**Key files implementing relocation:**
- [`cpython-unix/build-cpython.sh`](https://github.com/astral-sh/python-build-standalone/blob/main/cpython-unix/build-cpython.sh) — main Unix build script that drives the CPython compilation with controlled flags
- [`cpython-unix/patches/`](https://github.com/astral-sh/python-build-standalone/tree/main/cpython-unix/patches) — patches applied to CPython source, including the critical `getpath.py` patch for relative path resolution
- [`pythonbuild/cpython.py`](https://github.com/astral-sh/python-build-standalone/blob/main/pythonbuild/cpython.py) — Python orchestration script coordinating the build
- [`cpython-unix/static-modules.*`](https://github.com/astral-sh/python-build-standalone/tree/main/cpython-unix) — files defining static compilation of extension modules, bypassing `setup.py` entirely
**Approach:** Two core techniques make it work. First, **all dependencies are statically linked** — OpenSSL, SQLite, ncurses, libedit, libffi, and others have their symbols inlined directly into extension `.so` files rather than linking against system shared libraries. Second, **CPython's `Modules/getpath.py` is patched** to locate the installation directory relative to the binary's own path (using `$ORIGIN` on Linux, `@executable_path` on macOS) rather than hardcoded absolute paths set at `./configure` time. [Astral](https://astral.sh/blog/python-build-standalone) The project also scrubs `_sysconfigdata_*.py` of build-time paths. Builds happen inside deterministic Docker containers with a custom-bootstrapped Clang toolchain, ensuring zero host system dependencies leak in. [GitHub](https://github.com/astral-sh/python-build-standalone/blob/main/docs/technotes.rst) The output "install_only" tarballs can be extracted anywhere and run immediately. [Astral](https://astral.sh/blog/python-build-standalone)
---
## conda-forge rewrites prefixes at install time
**Repository:** [conda-forge/python-feedstock](https://github.com/conda-forge/python-feedstock)
**Key files implementing relocation:**
- [`recipe/build_base.sh`](https://github.com/conda-forge/python-feedstock/blob/main/recipe/build_base.sh) — main Unix build script; injects `-Wl,-rpath,$PREFIX/lib` into LDFLAGS and cleans `_sysconfigdata`
- [`recipe/meta.yaml`](https://github.com/conda-forge/python-feedstock/blob/main/recipe/meta.yaml) — conda-build recipe controlling `binary_relocation` and `detect_binary_files_with_prefix` settings
- [`recipe/replace-word-pairs.py`](https://github.com/conda-forge/python-feedstock/blob/main/recipe/replace-word-pairs.py) — helper script that sanitizes `_sysconfigdata` files, replacing build-environment paths with install-time paths
- conda-build's relocation engine in [conda/conda-build](https://github.com/conda/conda-build) — handles post-build binary rewriting
**Approach:** conda-forge uses **placeholder-prefix rewriting**. During build, conda-build uses a long placeholder directory path (e.g., `_h_env_placeholder...`). When a package is installed, conda replaces these placeholder strings with the actual install prefix in both text and binary files. [Mamba](https://mamba.readthedocs.io/en/latest/advanced_usage/detailed_operations.html) On Linux, **patchelf** rewrites ELF RPATHs; on macOS, **install_name_tool** rewrites dylib load commands. The build script also explicitly strips absolute build paths from `_sysconfigdata_*.py` using `sed` replacements (e.g., removing `-fdebug-prefix-map=$SRC_DIR=...` entries). [GitHub](https://github.com/conda-forge/python-feedstock/blob/main/recipe/build_base.sh) Python is built with `--enable-shared`, and RPATH is injected via LDFLAGS during compilation.
---
## Homebrew's keg relocation infrastructure
**Repository:** [Homebrew/homebrew-core](https://github.com/Homebrew/homebrew-core) + [Homebrew/brew](https://github.com/Homebrew/brew)
**Key files implementing relocation:**
- [`Formula/p/
[email protected]`](https://github.com/Homebrew/homebrew-core/blob/master/Formula/p/
[email protected]) — Python formula with `inreplace` calls rewriting Cellar paths to `opt_prefix` in `_sysconfigdata`, `config/Makefile`, and `.pc` files
- [`Library/Homebrew/keg_relocate.rb`](https://github.com/Homebrew/brew/blob/master/Library/Homebrew/keg_relocate.rb) — core relocation logic implementing the `@@HOMEBREW_PREFIX@@` / `@@HOMEBREW_CELLAR@@` placeholder system for bottle distribution
- [`Library/Homebrew/extend/os/mac/keg_relocate.rb`](https://github.com/Homebrew/brew/blob/master/Library/Homebrew/extend/os/mac/keg_relocate.rb) — macOS-specific relocation using the **ruby-macho** library to rewrite `LC_ID_DYLIB`, `LC_LOAD_DYLIB`, and `LC_RPATH` entries without shelling out to `install_name_tool`
- [`Library/Homebrew/extend/os/linux/keg_relocate.rb`](https://github.com/Homebrew/brew/blob/master/Library/Homebrew/extend/os/linux/keg_relocate.rb) — Linux-specific relocation using **patchelf** to set ELF RPATH and interpreter paths
**Approach:** Homebrew uses a **Cellar → opt_prefix symlink + bottle placeholder** system. The Python formula's `inreplace` directives rewrite hardcoded Cellar versioned paths to stable `opt_prefix` paths in `_sysconfigdata` and pkg-config files. For distributing pre-built "bottles," `keg_relocate.rb` replaces installation-specific paths with placeholders like `@@HOMEBREW_PREFIX@@` at bottle-creation time, then substitutes actual paths when a bottle is poured. [GitHub](https://github.com/Homebrew/brew/blob/master/Library/Homebrew/keg_relocate.rb) On macOS, the `fix_dynamic_linkage` method uses ruby-macho to rewrite Mach-O load commands; on Linux, patchelf handles ELF RPATH patching. The formula also patches `ctypes/macholib/dyld.py` to add Homebrew's lib directory to the default library search path. [GitHub](https://github.com/Homebrew/homebrew-core/blob/master/Formula/p/
[email protected])
---
## Spack's relocate module handles binary caches
**Repository:** [spack/spack](https://github.com/spack/spack)
**Key files implementing relocation:**
- [`lib/spack/spack/relocate.py`](https://github.com/spack/spack/blob/develop/lib/spack/spack/relocate.py) — core relocation module with functions: `relocate_text()`, `relocate_text_bin()`, `relocate_macho_binaries()`, `fixup_macos_rpaths()`, and internal `_patchelf()` wrapper
- [`var/spack/repos/builtin/packages/python/package.py`](https://github.com/spack/spack/blob/develop/var/spack/repos/builtin/packages/python/package.py) — CPython build recipe using Spack's compiler wrappers
- [`lib/spack/spack/binary_distribution.py`](https://github.com/spack/spack/blob/develop/lib/spack/spack/binary_distribution.py) — binary cache creation/installation with prefix relocation
**Approach:** Spack's compiler wrappers automatically inject `-Wl,-rpath,<prefix>/lib` for every dependency at build time. [Betterscientificsoftware](https://betterscientificsoftware.github.io/python-for-hpc/python-packages-and-spack/) [GitHub](https://github.com/spack/spack/issues/640) For binary caches (buildcaches), `relocate.py` converts absolute RPATHs to **`$ORIGIN`-relative** form, records hardcoded prefix strings in text files, and performs full relocation when installing from cache. On Linux it uses **patchelf**; on macOS it uses **macholib** for Mach-O manipulation. [Readthedocs](https://spack.readthedocs.io/en/latest/_modules/spack/relocate.html) Spack uses padded install paths (`padded_length:128`) in CI to ensure new paths fit within original binary allocations. A known limitation: Python extensions built via pip/setuptools bypass Spack's compiler wrappers and may lack proper RPATHs — addressed by passing `build_ext --rpath=...` explicitly. [GitHub](https://github.com/spack/spack/pull/4545)
---
## saltstack/relenv builds relocatable Python for Salt
**Repository:** [saltstack/relenv](https://github.com/saltstack/relenv)
**Key files implementing relocation:**
- [`relenv/relocate.py`](https://github.com/saltstack/relenv/blob/main/relenv/relocate.py) — core relocation module with `handle_elf()`, `handle_macho()`, `patch_rpath()`, `is_elf()`, `is_macho()`, `parse_readelf()`, `parse_macho()`, and `main()` functions [Readthedocs](https://relenv.readthedocs.io/en/latest/developer/relocate.html)
- [`relenv/build.py`](https://github.com/saltstack/relenv/blob/main/relenv/build.py) — builds CPython from source with bundled OpenSSL, SQLite, libffi, and zlib
**Approach:** Relenv compiles CPython and all its dependencies from source into a single prefix, then **patches all ELF and Mach-O binaries to use `$ORIGIN`-relative RPATHs**. On Linux, `handle_elf()` parses and rewrites RPATH entries; on macOS, `handle_macho()` uses `otool`/`install_name_tool`. [Readthedocs](https://relenv.readthedocs.io/en/latest/developer/relocate.html) It also makes shebangs relative. [GitHub](https://github.com/saltstack/relenv/blob/main/CHANGELOG.md) Built specifically for the Salt Project's "onedir" packaging model, where the entire Python environment must be movable across filesystems and machines of the same architecture. Supports Linux (x86_64, aarch64), macOS (arm64, x86_64), and Windows.
---
## Four approaches to fully static or single-file Python
### codrsquad/portable-python: zero shared libraries
**Repository:** [codrsquad/portable-python](https://github.com/codrsquad/portable-python)
**Key files:**
- [`src/portable_python/cpython.py`](https://github.com/codrsquad/portable-python/blob/main/src/portable_python/cpython.py) — main CPython build logic with static compilation flags
- [`src/portable_python/inspector.py`](https://github.com/codrsquad/portable-python/blob/main/src/portable_python/inspector.py) — `PythonInspector` class that validates portability by checking for shared library dependencies via `otool -L` / `ldd` [GitHub](https://github.com/codrsquad/portable-python)
- [`portable-python.yml`](https://github.com/codrsquad/portable-python/blob/main/portable-python.yml) — build configuration
**Approach:** Compiles CPython with `--enable-shared=no` and all dependencies (xz, OpenSSL, gdbm) with `--enable-static=yes`. Uses **no patches** — relies solely on `./configure` flags. [GitHub](https://github.com/blog2i2j/codrsquad.._..portable-python) The `PythonInspector` class validates that the resulting binary has zero external shared library dependencies. [GitHub](https://github.com/codrsquad/portable-python) Supports Linux and macOS (Intel/Apple Silicon); Windows not supported. [GitHub](https://github.com/codrsquad/portable-python/blob/main/README.rst)
### Cosmopolitan Python: one binary, six operating systems
**Repository:** [jart/cosmopolitan](https://github.com/jart/cosmopolitan) + [ahgamut/cpython](https://github.com/ahgamut/cpython) (cosmo branches)
**Key files:**
- [`third_party/python/python.mk`](https://github.com/jart/cosmopolitan/blob/master/third_party/python/python.mk) — Makefile target building `python.com`
- [`third_party/python/`](https://github.com/jart/cosmopolitan/tree/master/third_party/python) — patched CPython 3.6.14 source with Cosmopolitan Libc integration [GitHub](https://github.com/jart/cosmopolitan/wiki/python.com)
- [`third_party/python/pyobj.c`](https://github.com/jart/cosmopolitan/blob/master/third_party/python/pyobj.c) — compiles Python code objects into linkable ELF objects
- Newer CPython 3.11 fork: [`ahgamut/cpython` (cosmo_py311 branch)](https://github.com/ahgamut/cpython/tree/cosmo_py311)
**Approach:** Compiles CPython using **Cosmopolitan Libc** to produce an "Actually Portable Executable" (APE) [GitHub](https://github.com/jart/cosmopolitan/releases/tag/2.0) — a single `python.com` file (~4.1 MB) [GitHub](https://github.com/jart/cosmopolitan/issues/141) that runs natively on Linux, macOS, Windows, FreeBSD, OpenBSD, and NetBSD [GitHub](https://github.com/jart/cosmopolitan/releases/tag/2.0) on both AMD64 and ARM64. The stdlib is embedded as a ZIP store within the executable. No dynamic linking whatsoever. No `./configure` step; build configuration is entirely in the Makefile. [GitHub](https://github.com/jart/cosmopolitan/wiki/python.com) Some stdlib modules (`_ssl`, `_ctypes`) are absent.
### PyOxidizer / pyoxy: Python embedded in Rust
**Repository:** [indygreg/PyOxidizer](https://github.com/indygreg/PyOxidizer)
**Key files:**
- [`pyembed/`](https://github.com/indygreg/PyOxidizer/tree/main/pyembed) — Rust crate managing the embedded Python interpreter
- [`pyoxy/`](https://github.com/indygreg/PyOxidizer/tree/main/pyoxy) — standalone `python`-like runner binary
- [`oxidized-importer/`](https://github.com/indygreg/PyOxidizer/tree/main/oxidized-importer) — custom Python importer loading modules from memory via zero-copy from a "Python Packed Resources" data blob
**Approach:** Embeds a **static libpython** and all Python resources (`.pyc` files, stdlib) directly into a single Rust-compiled binary. The `oxidized_importer` extension imports modules from memory without filesystem access. No RPATH manipulation needed since everything is statically linked into one executable. Project is in maintenance mode since ~2023. [GitHub](https://github.com/astral-sh/python-build-standalone/issues/221) [Gregoryszorc](https://gregoryszorc.com/blog/category/pyoxidizer/)
### niess/python-appimage: Linux AppImage packaging
**Repository:** [niess/python-appimage](https://github.com/niess/python-appimage)
**Key files:**
- [`python_appimage/`](https://github.com/niess/python-appimage/tree/master/python_appimage) — main package with relocation logic
- Related: [`niess/linuxdeploy-plugin-python`](https://github.com/niess/linuxdeploy-plugin-python/blob/master/linuxdeploy-plugin-python.sh) — shell script with `patch_binary()` function using patchelf with `--force-rpath` and `--set-rpath` for `$ORIGIN`-relative paths
**Approach:** Extracts Python runtimes from Manylinux Docker images, patches all binary RPATHs with **`$ORIGIN`-relative paths using patchelf**, and packages everything into a Linux AppImage. [GitHub](https://github.com/niess/python-appimage) [GitHub](https://github.com/xonsh/xonsh/pull/3362) The resulting AppImage is a single-file FUSE-mountable executable containing a complete Python installation. Linux-only; supports Python 3.8–3.14.
---
## Two macOS-focused relocation projects
### gregneagle/relocatable-python: framework patching for app bundles
**Repository:** [gregneagle/relocatable-python](https://github.com/gregneagle/relocatable-python)
**Key files:**
- [`make_relocatable_python_framework.py`](https://github.com/gregneagle/relocatable-python/blob/main/make_relocatable_python_framework.py) — single script that downloads and patches Python.framework
- [`research_notes.txt`](https://github.com/gregneagle/relocatable-python/blob/main/research_notes.txt) — detailed notes on macOS relocation techniques
**Approach:** Downloads Apple's official Python.framework from python.org, then converts absolute dylib paths to **`@rpath`-based paths** using `install_name_tool -id`, `-change`, `-add_rpath`, and `-delete_rpath`. Adds `@executable_path/../../../../` as rpath for executables. [GitHub](https://github.com/gregneagle/relocatable-python/blob/main/research_notes.txt) Removes or replaces invalidated code signatures with ad-hoc signatures. [GitHub](https://github.com/gregneagle/relocatable-python) Used by Munki, AutoPkg, and other macOS admin tools for embedding Python into `.app` bundles. [GitHub](https://github.com/gregneagle/relocatable-python) macOS-only.
### Infinidat/relocatable-python3: buildout-based multi-platform builds
**Repository:** [Infinidat/relocatable-python3](https://github.com/Infinidat/relocatable-python3)
**Key files:**
- [`buildout.cfg`](https://github.com/Infinidat/relocatable-python3/blob/develop/buildout.cfg) — main zc.buildout configuration
- [`buildout-build-ubuntu-22.04.cfg`](https://github.com/Infinidat/relocatable-python3/blob/develop/buildout-build-ubuntu-22.04.cfg) — Ubuntu-specific build config
- [`buildout-build-windows.cfg`](https://github.com/Infinidat/relocatable-python3/blob/develop/buildout-build-windows.cfg) — Windows build config using Visual Studio [GitHub](https://github.com/Infinidat/relocatable-python3/blob/develop/buildout-build-windows.cfg)
**Approach:** Uses the **zc.buildout** framework to download CPython source and all dependencies [GitHub](https://github.com/Infinidat/relocatable-python) (OpenSSL, SQLite, libffi, gnutls, libgcrypt), compiles everything from source into a single prefix. Validates portability with `otool -L` / `ldd` to ensure no system shared libraries leak in. [GitHub](https://github.com/Infinidat/relocatable-python3) Notable for its wide platform support: **Linux, macOS, Windows, Solaris, and AIX**. [GitHub](https://github.com/Infinidat/relocatable-python)
---
## bjia56/portable-python targets 15+ platform variants
**Repository:** [bjia56/portable-python](https://github.com/bjia56/portable-python)
This project stands out for its extraordinary platform coverage. Using GitHub Actions with QEMU for cross-compilation, it builds CPython 3.9–3.13 for **Linux** (x86_64, i386, aarch64, arm, riscv64, s390x, loongarch64, powerpc64le), **Windows** (x86_64, aarch64), **macOS** (universal2), **FreeBSD**, **Solaris**, and even **Cosmopolitan Libc**. Provides both "full" (with Tk) and "headless" variants. Distributions are available as GitHub release archives and as npm packages (e.g., `@bjia56/portable-python-3.12`), making them usable from Node.js projects.
---
## Projects that do NOT produce relocatable binaries
Three commonly mentioned projects build CPython but **hardcode absolute paths**, making the results non-relocatable:
- **pyenv** ([pyenv/pyenv](https://github.com/pyenv/pyenv)): The [`plugins/python-build/bin/python-build`](https://github.com/pyenv/pyenv/blob/master/plugins/python-build/bin/python-build) script sets `-Wl,-rpath,<absolute_install_prefix>/lib` in LDFLAGS. RPATHs point to fixed paths like `/home/user/.pyenv/versions/3.11.7/lib`. Moving the installation breaks library resolution. [GitHub](https://github.com/pyenv/pyenv/wiki)
- **Nix/nixpkgs** ([NixOS/nixpkgs](https://github.com/NixOS/nixpkgs)): The [`pkgs/development/interpreters/python/cpython/default.nix`](https://github.com/NixOS/nixpkgs/blob/master/pkgs/development/interpreters/python/cpython/default.nix) derivation produces binaries with hardcoded `/nix/store/<hash>-...` paths. Nix's stdenv runs `patchelf --shrink-rpath` in its fixup phase, but this optimizes RPATHs rather than making them relative. [GitHub](https://github.com/nixos/nixpkgs/issues/419942)