use std::path::{Path, PathBuf};
use std::process::Command;
fn main() {
let manifest = PathBuf::from(std::env::var("CARGO_MANIFEST_DIR").unwrap());
let crates = manifest.parent().unwrap(); let plecto = crates.parent().unwrap(); let repo_root = plecto.parent().unwrap(); let wit = manifest.join("wit");
let filters = plecto.join("examples").join("filters");
let bench_filters = repo_root.join("bench").join("filters");
let out_dir = PathBuf::from(std::env::var("OUT_DIR").unwrap());
let cargo = std::env::var("CARGO").unwrap_or_else(|_| "cargo".to_string());
println!("cargo:rerun-if-changed={}", wit.display());
let test_support = std::env::var("CARGO_FEATURE_TEST_SUPPORT").is_ok();
if test_support {
build_component(
&cargo,
&filters.join("filter-hello"),
&out_dir,
"filter_hello",
"FILTER_HELLO_COMPONENT",
);
build_component(
&cargo,
&filters.join("filter-apikey"),
&out_dir,
"filter_apikey",
"FILTER_APIKEY_COMPONENT",
);
build_component(
&cargo,
&filters.join("filter-quickstart"),
&out_dir,
"filter_quickstart",
"FILTER_QUICKSTART_COMPONENT",
);
build_component(
&cargo,
&filters.join("filter-cors"),
&out_dir,
"filter_cors",
"FILTER_CORS_COMPONENT",
);
build_component(
&cargo,
&manifest.join("fixtures").join("filter-compat-v02"),
&out_dir,
"filter_compat_v02",
"FILTER_COMPAT_V02_COMPONENT",
);
build_component(
&cargo,
&bench_filters.join("filter-noop"),
&out_dir,
"filter_noop",
"FILTER_NOOP_COMPONENT",
);
build_component(
&cargo,
&bench_filters.join("filter-resp"),
&out_dir,
"filter_resp",
"FILTER_RESP_COMPONENT",
);
}
if test_support && std::env::var("CARGO_FEATURE_STREAMING_BODY").is_ok() {
build_wasip2_component(
&cargo,
&filters.join("filter-streaming"),
&out_dir,
"filter_streaming",
"FILTER_STREAMING_COMPONENT",
);
}
if test_support && std::env::var("CARGO_FEATURE_OUTBOUND_HTTP").is_ok() {
build_wasip2_component(
&cargo,
&filters.join("filter-extauthz"),
&out_dir,
"filter_extauthz",
"FILTER_EXTAUTHZ_COMPONENT",
);
build_wasip2_component(
&cargo,
&filters.join("filter-jwt"),
&out_dir,
"filter_jwt",
"FILTER_JWT_COMPONENT",
);
}
if test_support && std::env::var("CARGO_FEATURE_OUTBOUND_TCP").is_ok() {
build_wasip2_component(
&cargo,
&filters.join("filter-tcp-gate"),
&out_dir,
"filter_tcp_gate",
"FILTER_TCP_GATE_COMPONENT",
);
build_wasip2_component(
&cargo,
&filters.join("filter-ratelimit-redis"),
&out_dir,
"filter_ratelimit_redis",
"FILTER_RATELIMIT_REDIS_COMPONENT",
);
}
}
fn build_wasip2_component(cargo: &str, guest: &Path, out_dir: &Path, stem: &str, env_var: &str) {
println!("cargo:rerun-if-changed={}", guest.join("src").display());
println!(
"cargo:rerun-if-changed={}",
guest.join("Cargo.toml").display()
);
println!(
"cargo:rerun-if-changed={}",
guest.join("Cargo.lock").display()
);
let target_dir = guest.join("target");
let status = Command::new(cargo)
.current_dir(guest)
.env_remove("CARGO_TARGET_DIR")
.args([
"build",
"--target",
"wasm32-wasip2",
"--release",
"--target-dir",
])
.arg(&target_dir)
.status()
.unwrap_or_else(|e| panic!("failed to spawn cargo to build {}: {e}", guest.display()));
if !status.success() {
panic!(
"building {} for wasm32-wasip2 failed.\n\
The wasip2 fixture guests (streaming-body / outbound-http / outbound-tcp test\n\
fixtures) need the wasm32-wasip2 target:\n \
rustup target add wasm32-wasip2",
guest.display()
);
}
let component = target_dir.join(format!("wasm32-wasip2/release/{stem}.wasm"));
assert!(
component.exists(),
"guest component not found at {}",
component.display()
);
let published = out_dir.join(format!("{stem}-wasip2.wasm"));
std::fs::copy(&component, &published).unwrap_or_else(|e| {
panic!(
"copying {} to {} failed: {e}",
component.display(),
published.display()
)
});
println!("cargo:rustc-env={env_var}={}", published.display());
}
fn build_component(cargo: &str, guest: &Path, out_dir: &Path, stem: &str, env_var: &str) {
println!("cargo:rerun-if-changed={}", guest.join("src").display());
println!(
"cargo:rerun-if-changed={}",
guest.join("Cargo.toml").display()
);
println!(
"cargo:rerun-if-changed={}",
guest.join("Cargo.lock").display()
);
let target_dir = guest.join("target");
let status = Command::new(cargo)
.current_dir(guest)
.env_remove("CARGO_TARGET_DIR")
.args([
"build",
"--target",
"wasm32-unknown-unknown",
"--release",
"--target-dir",
])
.arg(&target_dir)
.status()
.unwrap_or_else(|e| panic!("failed to spawn cargo to build {}: {e}", guest.display()));
if !status.success() {
panic!(
"building {} for wasm32-unknown-unknown failed.\n\
The usual cause is a missing WASM target. It is installed automatically by \
plecto/rust-toolchain.toml; if you build outside that toolchain, run:\n \
rustup target add wasm32-unknown-unknown",
guest.display()
);
}
let core = target_dir.join(format!("wasm32-unknown-unknown/release/{stem}.wasm"));
assert!(
core.exists(),
"guest core module not found at {}",
core.display()
);
let core_bytes = std::fs::read(&core).expect("read guest core module");
let component_bytes = wit_component::ComponentEncoder::default()
.module(&core_bytes)
.expect("ComponentEncoder::module")
.validate(true)
.encode()
.unwrap_or_else(|e| panic!("encode {stem} component: {e}"));
let component = out_dir.join(format!("{stem}.component.wasm"));
std::fs::write(&component, &component_bytes).expect("write guest component");
println!("cargo:rustc-env={env_var}={}", component.display());
}