Skip to content

Instantly share code, notes, and snippets.

@alexcrichton
Created June 11, 2026 13:52
Show Gist options
  • Select an option

  • Save alexcrichton/d34f2a54293eabee94e59e91bfcb143b to your computer and use it in GitHub Desktop.

Select an option

Save alexcrichton/d34f2a54293eabee94e59e91bfcb143b to your computer and use it in GitHub Desktop.
diff --git a/Cargo.lock b/Cargo.lock
index dd05b9a..66ae230 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1888,14 +1888,15 @@ dependencies = [
[[package]]
name = "pyo3"
-version = "0.26.0"
+version = "0.27.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7ba0117f4212101ee6544044dae45abe1083d30ce7b29c4b5cbdfa2354e07383"
+checksum = "ab53c047fcd1a1d2a8820fe84f05d6be69e9526be40cb03b73f86b6b03e6d87d"
dependencies = [
"indoc",
"libc",
"memoffset",
"num-bigint",
+ "num-traits",
"once_cell",
"portable-atomic",
"pyo3-build-config",
@@ -1906,18 +1907,18 @@ dependencies = [
[[package]]
name = "pyo3-build-config"
-version = "0.26.0"
+version = "0.27.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4fc6ddaf24947d12a9aa31ac65431fb1b851b8f4365426e182901eabfb87df5f"
+checksum = "b455933107de8642b4487ed26d912c2d899dec6114884214a0b3bb3be9261ea6"
dependencies = [
"target-lexicon",
]
[[package]]
name = "pyo3-ffi"
-version = "0.26.0"
+version = "0.27.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "025474d3928738efb38ac36d4744a74a400c901c7596199e20e45d98eb194105"
+checksum = "1c85c9cbfaddf651b1221594209aed57e9e5cff63c4d11d1feead529b872a089"
dependencies = [
"libc",
"pyo3-build-config",
@@ -1925,9 +1926,9 @@ dependencies = [
[[package]]
name = "pyo3-macros"
-version = "0.26.0"
+version = "0.27.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2e64eb489f22fe1c95911b77c44cc41e7c19f3082fc81cce90f657cdc42ffded"
+checksum = "0a5b10c9bf9888125d917fb4d2ca2d25c8df94c7ab5a52e13313a07e050a3b02"
dependencies = [
"proc-macro2",
"pyo3-macros-backend",
@@ -1937,9 +1938,9 @@ dependencies = [
[[package]]
name = "pyo3-macros-backend"
-version = "0.26.0"
+version = "0.27.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "100246c0ecf400b475341b8455a9213344569af29a3c841d29270e53102e0fcf"
+checksum = "03b51720d314836e53327f5871d4c0cfb4fb37cc2c4a11cc71907a86342c40f9"
dependencies = [
"heck",
"proc-macro2",
diff --git a/Cargo.toml b/Cargo.toml
index 2440d73..6adec61 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -22,7 +22,7 @@ wasmparser = "0.245.0"
indexmap = "2.6.0"
bincode = "1.3.3"
heck = "0.5.0"
-pyo3 = { version = "0.26.0", features = [
+pyo3 = { version = "0.27.0", features = [
"abi3-py39",
"extension-module",
], optional = true }
diff --git a/build.rs b/build.rs
index a6d9d6d..cd4b45e 100644
--- a/build.rs
+++ b/build.rs
@@ -1,7 +1,7 @@
#![deny(warnings)]
use {
- anyhow::{Context, Result, anyhow, bail},
+ anyhow::{anyhow, bail, Context, Result},
std::{
env,
fmt::Write as _,
@@ -191,20 +191,26 @@ fn package_all_the_things(out_dir: &Path) -> Result<()> {
"libwasi-emulated-process-clocks.so",
"libwasi-emulated-getpid.so",
"libwasi-emulated-signal.so",
- "libc++.so",
- "libc++abi.so",
+ "noeh/libc++.so",
+ "noeh/libc++abi.so",
];
for library in libraries {
- compress(
- &wasi_sdk.join("share/wasi-sysroot/lib/wasm32-wasip2"),
- library,
- out_dir,
- true,
- )?;
+ let lib = wasi_sdk
+ .join("share/wasi-sysroot/lib/wasm32-wasip2")
+ .join(library);
+ let dst = out_dir.join(format!(
+ "{}.zst",
+ lib.file_name().unwrap().to_str().unwrap()
+ ));
+ compress(&lib, &dst, true)?;
}
- compress(&cpython_wasi_dir, "libpython3.14.so", out_dir, true)?;
+ compress(
+ &cpython_wasi_dir.join("libpython3.14.so"),
+ &out_dir.join("libpython3.14.so.zst"),
+ true,
+ )?;
let path = repo_dir.join("cpython/builddir/wasi/install/lib/python3.14");
@@ -237,36 +243,32 @@ fn package_all_the_things(out_dir: &Path) -> Result<()> {
}
compress(
- &repo_dir.join("adapters/ab5a4484"),
- "wasi_snapshot_preview1.reactor.wasm",
- out_dir,
+ &repo_dir
+ .join("adapters/ab5a4484")
+ .join("wasi_snapshot_preview1.reactor.wasm"),
+ &out_dir.join("wasi_snapshot_preview1.reactor.wasm.zst"),
false,
)?;
Ok(())
}
-fn compress(src_dir: &Path, name: &str, dst_dir: &Path, rerun_if_changed: bool) -> Result<()> {
- let path = src_dir.join(name);
-
+fn compress(src: &Path, dst: &Path, rerun_if_changed: bool) -> Result<()> {
if rerun_if_changed {
- println!("cargo:rerun-if-changed={}", path.to_str().unwrap());
+ println!("cargo:rerun-if-changed={}", src.to_str().unwrap());
}
- if path.exists() {
- let mut encoder = Encoder::new(
- File::create(dst_dir.join(format!("{name}.zst")))?,
- ZSTD_COMPRESSION_LEVEL,
- )?;
- if STRIP_RUNTIME && name.ends_with(".so") {
- io::copy(&mut Cursor::new(strip(&fs::read(path)?)?), &mut encoder)?;
+ if src.exists() {
+ let mut encoder = Encoder::new(File::create(dst)?, ZSTD_COMPRESSION_LEVEL)?;
+ if STRIP_RUNTIME && src.extension().and_then(|s| s.to_str()) == Some("so") {
+ io::copy(&mut Cursor::new(strip(&fs::read(src)?)?), &mut encoder)?;
} else {
- io::copy(&mut File::open(path)?, &mut encoder)?;
+ io::copy(&mut File::open(src)?, &mut encoder)?;
}
encoder.do_finish()?;
Ok(())
} else {
- Err(anyhow!("no such file: {}", path.display()))
+ Err(anyhow!("no such file: {}", src.display()))
}
}
@@ -500,15 +502,15 @@ fn make_runtime(
async_: bool,
name: &str,
) -> Result<()> {
- let mut cmd = Command::new("rustup");
+ let mut cmd = Command::new("cargo");
cmd.current_dir("runtime")
- .arg("run")
- .arg("nightly")
- .arg("cargo")
+ // .arg("run")
+ // .arg("nightly")
+ // .arg("cargo")
.arg("build")
- .arg("-Z")
- .arg("build-std=panic_abort,std")
- .arg("--target=wasm32-wasip1");
+ // .arg("-Z")
+ // .arg("build-std=panic_abort,std")
+ .arg("--target=wasm32-wasip2");
if !DEBUG_RUNTIME {
cmd.arg("--release");
@@ -530,12 +532,9 @@ fn make_runtime(
let target = if async_ { "async" } else { "sync" };
- cmd.env(
- "RUSTFLAGS",
- "-C relocation-model=pic -Z default-visibility=hidden --cfg pyo3_disable_reference_pool",
- )
- .env("CARGO_TARGET_DIR", out_dir.join(target))
- .env("PYO3_CONFIG_FILE", out_dir.join("pyo3-config.txt"));
+ cmd.env("RUSTFLAGS", "--cfg pyo3_disable_reference_pool")
+ .env("CARGO_TARGET_DIR", out_dir.join(target))
+ .env("PYO3_CONFIG_FILE", out_dir.join("pyo3-config.txt"));
let status = cmd.status()?;
assert!(status.success());
@@ -543,7 +542,7 @@ fn make_runtime(
let build = if DEBUG_RUNTIME { "debug" } else { "release" };
let path = out_dir.join(target).join(format!(
- "wasm32-wasip1/{build}/libcomponentize_py_runtime.a"
+ "wasm32-wasip2/{build}/libcomponentize_py_runtime.a"
));
if path.exists() {
@@ -551,6 +550,7 @@ fn make_runtime(
if clang.exists() {
run(Command::new(clang)
.arg("-shared")
+ .arg("--target=wasm32-wasip2")
.arg("-o")
.arg(out_dir.join(name))
.arg("-Wl,--whole-archive")
@@ -559,7 +559,11 @@ fn make_runtime(
.arg(format!("-L{}", cpython_wasi_dir.to_str().unwrap()))
.arg("-lpython3.14"))?;
- compress(out_dir, name, out_dir, false)?;
+ compress(
+ &out_dir.join(&name),
+ &out_dir.join(&format!("{}.zst", name)),
+ false,
+ )?;
} else {
bail!("no such file: {}", clang.display())
}
@@ -579,19 +583,17 @@ fn fetch_extract(url: &str, out_dir: &Path) -> Result<()> {
}
fn add_compile_envs(wasi_sdk: &Path, command: &mut Command) {
- let sysroot = wasi_sdk.join("share/wasi-sysroot");
- let sysroot = sysroot.to_string_lossy();
command
.env("AR", wasi_sdk.join("bin/ar"))
.env("CC", wasi_sdk.join("bin/clang"))
.env("RANLIB", wasi_sdk.join("bin/ranlib"))
.env(
"CFLAGS",
- format!("--target=wasm32-wasi --sysroot={sysroot} -I{sysroot}/include/wasm32-wasip1 -D_WASI_EMULATED_SIGNAL -fPIC"),
+ format!("--target=wasm32-wasip2 -D_WASI_EMULATED_SIGNAL -fPIC"),
)
.env(
"LDFLAGS",
- format!("--target=wasm32-wasip2 --sysroot={sysroot} -L{sysroot}/lib -lwasi-emulated-signal")
+ format!("--target=wasm32-wasip2 -lwasi-emulated-signal"),
);
}
@@ -666,10 +668,6 @@ fn build_sqlite(wasi_sdk: &Path, install_dir: &Path) -> Result<()> {
fs::create_dir_all(install_dir.join("lib"))?;
fs::create_dir_all(install_dir.join("include"))?;
- let sysroot = wasi_sdk.join("share/wasi-sysroot");
- let sysroot_str = sysroot
- .to_str()
- .ok_or_else(|| anyhow!("non-UTF8 path: {}", sysroot.display()))?;
let install_dir_str = install_dir
.to_str()
.ok_or_else(|| anyhow!("non-UTF8 path: {}", install_dir.display()))?;
@@ -682,9 +680,7 @@ fn build_sqlite(wasi_sdk: &Path, install_dir: &Path) -> Result<()> {
// Note: Don't set SQLITE_THREADSAFE here - let --disable-threadsafe handle it
// to avoid macro redefinition warnings
let sqlite_cflags = format!(
- "--target=wasm32-wasi \
- --sysroot={sysroot_str} \
- -I{sysroot_str}/include/wasm32-wasip1 \
+ "--target=wasm32-wasip2 \
-D_WASI_EMULATED_SIGNAL \
-D_WASI_EMULATED_PROCESS_CLOCKS \
-fPIC \
@@ -704,10 +700,7 @@ fn build_sqlite(wasi_sdk: &Path, install_dir: &Path) -> Result<()> {
.env("CC", wasi_sdk.join("bin/clang"))
.env("RANLIB", wasi_sdk.join("bin/ranlib"))
.env("CFLAGS", &sqlite_cflags)
- .env(
- "LDFLAGS",
- format!("--target=wasm32-wasip2 --sysroot={sysroot_str} -L{sysroot_str}/lib",),
- )
+ .env("LDFLAGS", format!("--target=wasm32-wasip2"))
.arg("--host=wasm32-wasi")
.arg(format!("--prefix={install_dir_str}"))
.arg("--disable-shared")
diff --git a/runtime/Cargo.toml b/runtime/Cargo.toml
index c6d491f..e33179a 100644
--- a/runtime/Cargo.toml
+++ b/runtime/Cargo.toml
@@ -9,7 +9,7 @@ crate-type = ["staticlib"]
[dependencies]
anyhow = "1.0.91"
once_cell = "1.20.2"
-pyo3 = { version="0.26.0", features = ["abi3-py312", "num-bigint"] }
+pyo3 = { version="0.27.0", features = ["abi3-py312", "num-bigint"] }
num-bigint = "0.4.6"
wit-bindgen = { version = "0.52.0", default-features = false, features = ["macros", "realloc"] }
# TODO: switch to a release when available:
diff --git a/runtime/src/lib.rs b/runtime/src/lib.rs
index de9ad47..7a050bd 100644
--- a/runtime/src/lib.rs
+++ b/runtime/src/lib.rs
@@ -20,13 +20,13 @@ use {
num_bigint::BigUint,
once_cell::sync::OnceCell,
pyo3::{
- Bound, IntoPyObject, Py, PyAny, PyErr, PyResult, Python,
exceptions::PyAssertionError,
intern,
types::{
PyAnyMethods, PyBool, PyBytes, PyBytesMethods, PyDict, PyList, PyListMethods,
PyMapping, PyMappingMethods, PyModule, PyModuleMethods, PyString, PyTuple,
},
+ Bound, IntoPyObject, Py, PyAny, PyErr, PyResult, Python,
},
std::{
alloc::{self, Layout},
@@ -816,10 +816,10 @@ mod async_ {
ty.write()(handle, buffer.cast())
};
- let resources = call
- .resources
- .take()
- .and_then(|v| if v.is_empty() { None } else { Some(v) });
+ let resources =
+ call.resources
+ .take()
+ .and_then(|v| if v.is_empty() { None } else { Some(v) });
Ok(if code == RETURN_CODE_BLOCKED {
ERR_CONSTRUCTOR
@@ -1090,7 +1090,7 @@ fn do_init(app_name: String, symbols: Symbols, stub_wasi: bool) -> Result<(), St
let environ = py
.import("os")?
.getattr("environ")?
- .downcast_into::<PyMapping>()
+ .cast_into::<PyMapping>()
.unwrap();
let keys = environ.keys()?;
@@ -1152,7 +1152,7 @@ fn do_init(app_name: String, symbols: Symbols, stub_wasi: bool) -> Result<(), St
let argv = py
.import("sys")?
.getattr("argv")?
- .downcast_into::<PyList>()
+ .cast_into::<PyList>()
.unwrap();
for i in 0..argv.len() {
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment