diff --git a/CHANGES.md b/CHANGES.md
index c0bdb64..f5a6f89 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -1,5 +1,9 @@
# Release Notes
+## 0.2.0
+
+Add support for injecting `--layout packed` PEXes.
+
## 0.1.0
Initial release.
diff --git a/Cargo.lock b/Cargo.lock
index 86af8aa..e5c9e22 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -199,6 +199,32 @@ dependencies = [
"serde",
]
+[[package]]
+name = "build-system"
+version = "0.0.0"
+dependencies = [
+ "anyhow",
+ "bstr",
+ "const_format",
+ "dirs",
+ "flate2",
+ "fs-err",
+ "hex",
+ "itertools 0.14.0",
+ "reqwest",
+ "serde",
+ "sha2",
+ "strum",
+ "strum_macros",
+ "tar",
+ "target-lexicon",
+ "tempfile",
+ "toml",
+ "which",
+ "xz2",
+ "zip",
+]
+
[[package]]
name = "build-target"
version = "0.8.0"
@@ -1128,9 +1154,9 @@ dependencies = [
"pep440_rs",
"pep508_rs",
"platform",
- "resources",
"rstest",
"same-file",
+ "scripts",
"serde",
"serde_json",
"target-lexicon",
@@ -1466,6 +1492,7 @@ version = "0.0.0"
dependencies = [
"anstream 1.0.0",
"anyhow",
+ "build-system",
"cache",
"clap",
"clap-verbosity-flag",
@@ -1473,7 +1500,6 @@ dependencies = [
"env_logger",
"fs-err",
"owo-colors",
- "pexrc-build-system",
"platform",
"sha2",
]
@@ -1541,10 +1567,12 @@ dependencies = [
"pep508_rs",
"python-pkginfo",
"rayon",
- "resources",
"rstest",
+ "scripts",
"serde",
"serde_json",
+ "strum",
+ "strum_macros",
"tempfile",
"testing",
"url",
@@ -1553,12 +1581,13 @@ dependencies = [
[[package]]
name = "pexrc"
-version = "0.1.0"
+version = "0.2.0"
dependencies = [
"anstream 1.0.0",
"anyhow",
"boot",
"bstr",
+ "build-system",
"cache",
"clap",
"clap-verbosity-flag",
@@ -1572,49 +1601,24 @@ dependencies = [
"log",
"owo-colors",
"pex",
- "pexrc-build-system",
"pexrs",
"platform",
- "resources",
+ "scripts",
"sha2",
"strum",
"tempfile",
+ "walkdir",
"zip",
"zstd",
]
-[[package]]
-name = "pexrc-build-system"
-version = "0.0.0"
-dependencies = [
- "anyhow",
- "bstr",
- "const_format",
- "dirs",
- "flate2",
- "fs-err",
- "hex",
- "itertools 0.14.0",
- "reqwest",
- "serde",
- "sha2",
- "strum",
- "strum_macros",
- "tar",
- "target-lexicon",
- "tempfile",
- "toml",
- "which",
- "xz2",
- "zip",
-]
-
[[package]]
name = "pexrs"
version = "0.0.0"
dependencies = [
"anyhow",
"cache",
+ "fs-err",
"interpreter",
"itertools 0.14.0",
"log",
@@ -1996,18 +2000,6 @@ dependencies = [
"web-sys",
]
-[[package]]
-name = "resources"
-version = "0.0.0"
-dependencies = [
- "anyhow",
- "env_logger",
- "pexrc-build-system",
- "strum",
- "strum_macros",
- "zip",
-]
-
[[package]]
name = "rfc2047-decoder"
version = "1.1.0"
@@ -2192,6 +2184,19 @@ dependencies = [
"windows-sys 0.61.2",
]
+[[package]]
+name = "scripts"
+version = "0.0.0"
+dependencies = [
+ "anyhow",
+ "build-system",
+ "env_logger",
+ "fs-err",
+ "strum",
+ "strum_macros",
+ "zip",
+]
+
[[package]]
name = "security-framework"
version = "3.7.0"
@@ -2477,8 +2482,8 @@ dependencies = [
"cache",
"ctor",
"fs-err",
- "resources",
"rstest",
+ "scripts",
"target-lexicon",
"tempfile",
]
@@ -2836,11 +2841,12 @@ dependencies = [
"pex",
"platform",
"rayon",
- "resources",
"rstest",
+ "scripts",
"target-lexicon",
"tempfile",
"testing",
+ "walkdir",
"zip",
]
diff --git a/Cargo.toml b/Cargo.toml
index 6f4ee8f..3c36b74 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,12 @@
# Copyright 2026 Pex project contributors.
# SPDX-License-Identifier: Apache-2.0
+[package]
+name = "pexrc"
+version = "0.2.0"
+edition = "2024"
+publish = false
+
[workspace]
members = [
".",
@@ -10,20 +16,14 @@ members = [
"crates/interpreter",
"crates/package",
"crates/pex",
- "crates/pexrc-build-system",
+ "crates/build-system",
"crates/pexrs",
"crates/platform",
- "crates/resources",
+ "crates/scripts",
"crates/testing",
"crates/venv",
]
-[package]
-name = "pexrc"
-version = "0.1.0"
-edition = "2024"
-publish = false
-
[package.metadata.build]
zig_version = "0.15.2"
@@ -140,6 +140,7 @@ textwrap = "0.16"
time = "0.3"
toml = "1.0"
url = "2.5"
+walkdir = "2.5"
which = "8.0"
xz2 = "0.1"
zip = { version = "8.1", default-features = false, features = ["deflate", "zstd"] }
@@ -147,9 +148,9 @@ zstd = "0.13"
[build-dependencies]
anyhow = { workspace = true }
+build-system = { path = "crates/build-system" }
bstr = { workspace = true }
fs-err = { workspace = true }
-pexrc-build-system = { path = "crates/pexrc-build-system" }
env_logger = { workspace = true }
itertools = { workspace = true }
zstd = { workspace = true }
@@ -173,9 +174,10 @@ owo-colors = { workspace = true }
pex = { path = "crates/pex" }
pexrs = { path = "crates/pexrs" }
platform = { path = "crates/platform" }
-resources = { path = "crates/resources", features = ["embedded"] }
+scripts = { path = "crates/scripts", features = ["embedded"] }
sha2 = { workspace = true }
strum = { workspace = true }
tempfile = { workspace = true }
+walkdir = { workspace = true }
zip = { workspace = true }
zstd = { workspace = true }
diff --git a/build.rs b/build.rs
index f2584be..742320d 100644
--- a/build.rs
+++ b/build.rs
@@ -4,13 +4,11 @@
use std::ffi::OsStr;
use std::path::{Path, PathBuf};
use std::process::{Command, Stdio};
-use std::{env, fs, io, iter};
+use std::{env, io, iter};
use anyhow::{anyhow, bail};
use bstr::ByteSlice;
-use fs_err::File;
-use itertools::Itertools;
-use pexrc_build_system::{
+use build_system::{
ClassifiedTargets,
ClibConfiguration,
FoundTool,
@@ -18,6 +16,9 @@ use pexrc_build_system::{
classify_targets,
ensure_tools_installed,
};
+use fs_err as fs;
+use fs_err::File;
+use itertools::Itertools;
fn main() -> anyhow::Result<()> {
println!("cargo::rerun-if-changed=crates");
diff --git a/crates/boot/src/boot.py b/crates/boot/src/boot.py
index 6e00b95..a603c40 100644
--- a/crates/boot/src/boot.py
+++ b/crates/boot/src/boot.py
@@ -1,6 +1,6 @@
+# -*- coding: utf-8 -*-
# Copyright 2026 Pex project contributors.
# SPDX-License-Identifier: Apache-2.0
-# -*- coding: utf-8 -*-
from __future__ import print_function
@@ -437,22 +437,38 @@ def boot(
def _load_pexrc():
# type: () -> Pexrc
- dll = None # type: Optional[Pexrc]
+ prefix = ".clib" if __name__ == "__pex__" else os.path.join("__pex__", ".clib")
target_triple = CURRENT_OS.target_triple(arch=CURRENT_ARCH, abi=CURRENT_ABI)
library_file_name = CURRENT_OS.library_file_name(lib_name="pexrc")
+ library_file_relpath = os.path.join(
+ prefix,
+ "{target_triple}.{library_file_name}".format(
+ target_triple=target_triple, library_file_name=library_file_name
+ ),
+ )
+ if __file__ and os.path.isfile(__file__):
+ # We're in a either a loose or packed PEX.
+ library_file_path = os.path.join(os.path.dirname(__file__), library_file_relpath)
+ if not os.path.exists(library_file_path):
+ raise RuntimeError(
+ "Pexrc is not supported on {target_triple}: no pexrc library found.".format(
+ target_triple=target_triple,
+ )
+ )
+ try:
+ return cdll.LoadLibrary(library_file_path) # type: Pexrc
+ except OSError as e:
+ raise RuntimeError(
+ "Failed to load pexrc library from {library_file_path}: {err}".format(
+ library_file_path=library_file_path, err=e
+ )
+ )
+
+ dll = None # type: Optional[Pexrc]
tmp_dir = tempfile.mkdtemp()
- library_file_path = os.path.join(tmp_dir, os.path.basename(library_file_name))
+ library_file_path = os.path.join(tmp_dir, library_file_name)
try:
- prefix = ".clib" if __name__ == "__pex__" else os.path.join("__pex__", ".clib")
- pexrc_data = pkgutil.get_data(
- __name__,
- os.path.join(
- prefix,
- "{target_triple}.{library_file_name}".format(
- target_triple=target_triple, library_file_name=library_file_name
- ),
- ),
- )
+ pexrc_data = pkgutil.get_data(__name__, library_file_relpath)
if pexrc_data is None:
raise RuntimeError(
"Pexrc is not supported on {target_triple}: no pexrc library found.".format(
diff --git a/crates/boot/src/boot.sh b/crates/boot/src/boot.sh
index dba9d88..f12e1b8 100644
--- a/crates/boot/src/boot.sh
+++ b/crates/boot/src/boot.sh
@@ -1,15 +1,19 @@
#!/bin/sh
+# -*- coding: utf-8 -*-
+# Copyright 2026 Pex project contributors.
+# SPDX-License-Identifier: Apache-2.0
+# --- split --- #
# N.B.: This script should stick to syntax defined for POSIX `sh` and avoid non-builtins.
# See: https://pubs.opengroup.org/onlinepubs/9699919799/idx/shell.html
set -eu
-# --- vars --- #
+# --- split --- #
# N.B.: These vars are templated in by pexrc when it injects a PEX with its runtime.
RAW_DEFAULT_PEXRC_ROOT="{pexrc_root}"
VENV_RELPATH="{venv_relpath}"
PYTHONS="{pythons}"
-# --- vars --- #
+# --- split --- #
# N.B.: The SC2116 warning suppressions below are in place to ensure tilde-expansion of the
# DEFAULT_PEX_ROOT value which is necessary for the -x check of the venv pex to succeed when it
diff --git a/crates/boot/src/lib.rs b/crates/boot/src/lib.rs
index b96fa30..da99d10 100644
--- a/crates/boot/src/lib.rs
+++ b/crates/boot/src/lib.rs
@@ -7,6 +7,7 @@ use std::path::Path;
use anyhow::{anyhow, bail};
use cache::CacheDir;
use const_format::str_split;
+use fs_err as fs;
use fs_err::File;
use interpreter::{InterpreterConstraints, SearchPath, SelectionStrategy};
use pex::{Pex, PexPath};
@@ -16,11 +17,13 @@ use zip::ZipWriter;
use zip::write::{FileOptionExtension, FileOptions};
const SH_BOOT_SHEBANG: &[u8] = b"#!/bin/sh\n";
-const SH_BOOT_PARTS: [&str; 3] = str_split!(include_str!("boot.sh"), "# --- vars --- #\n");
+const SH_BOOT_PARTS: [&str; 4] = str_split!(include_str!("boot.sh"), "# --- split --- #\n");
+
+pub fn sh_boot_shebang(pex: &Path, escaped: bool) -> anyhow::Result