diff --git a/crates/guest-rust/macro/src/lib.rs b/crates/guest-rust/macro/src/lib.rs index ef23291f9..fb51eac59 100644 --- a/crates/guest-rust/macro/src/lib.rs +++ b/crates/guest-rust/macro/src/lib.rs @@ -9,6 +9,7 @@ use syn::spanned::Spanned; use syn::{braced, token, LitStr, Token}; use wit_bindgen_core::wit_parser::{PackageId, Resolve, UnresolvedPackageGroup, WorldId}; use wit_bindgen_core::AsyncFilterSet; +use wit_bindgen_core::WorldGenerator; use wit_bindgen_rust::{Opts, Ownership, WithOption}; #[proc_macro] diff --git a/crates/rust/src/lib.rs b/crates/rust/src/lib.rs index fd92b1953..3881a0b3d 100644 --- a/crates/rust/src/lib.rs +++ b/crates/rust/src/lib.rs @@ -3,9 +3,11 @@ use anyhow::{bail, Result}; use core::panic; use heck::*; use indexmap::{IndexMap, IndexSet}; +use std::borrow::Cow; use std::collections::{BTreeMap, HashMap, HashSet}; use std::fmt::{self, Write as _}; use std::mem; +use std::path::Path; use std::str::FromStr; use wit_bindgen_core::abi::{Bitcast, WasmType}; use wit_bindgen_core::{ @@ -26,7 +28,7 @@ struct InterfaceName { } #[derive(Default)] -struct RustWasm { +pub struct RustWasm { types: Types, src_preamble: Source, src: Source, @@ -277,15 +279,43 @@ pub struct Opts { } impl Opts { - pub fn build(self) -> Box { + pub fn build(self) -> RustWasm { let mut r = RustWasm::new(); r.skip = self.skip.iter().cloned().collect(); r.opts = self; - Box::new(r) + r } } +const GENERATED_FILE_NAME: &str = "wit_bindgen_generated.rs"; impl RustWasm { + pub fn generate_to_out_dir(self, world: Option<&str>) -> Result<()> { + self.generate_to_out_dir_modify(world, |s| Cow::Borrowed(s)) + } + + pub fn generate_to_out_dir_modify( + mut self, + world: Option<&str>, + modify: impl FnOnce(&[u8]) -> Cow<[u8]>, + ) -> Result<()> { + let mut resolve = Resolve::default(); + println!("cargo:rerun-if-changed=wit/"); + let (pkg, _files) = resolve.push_path("wit")?; + let main_packages = vec![pkg]; + let world = resolve.select_world(&main_packages, world)?; + let mut files = Files::default(); + self.generate(&resolve, world, &mut files)?; + let out_dir = std::env::var("OUT_DIR").expect("cargo sets OUT_DIR"); + let dst = Path::new(&out_dir).join(GENERATED_FILE_NAME); + let (_name, contents) = files + .iter() + .next() + .expect("exactly one file should be generated"); + let contents = modify(contents); + std::fs::write(&dst, contents)?; + Ok(()) + } + fn new() -> RustWasm { RustWasm::default() } diff --git a/src/bin/wit-bindgen.rs b/src/bin/wit-bindgen.rs index d1d3666a8..d2cbac67c 100644 --- a/src/bin/wit-bindgen.rs +++ b/src/bin/wit-bindgen.rs @@ -143,7 +143,7 @@ fn main() -> Result<()> { #[cfg(feature = "cpp")] Opt::Cpp { opts, args } => (opts.build(args.out_dir.as_ref()), args), #[cfg(feature = "rust")] - Opt::Rust { opts, args } => (opts.build(), args), + Opt::Rust { opts, args } => (Box::new(opts.build()) as Box, args), #[cfg(feature = "go")] Opt::TinyGo { args: _ } => { bail!("Go bindgen has been moved to a separate repository. Please visit https://github.com/bytecodealliance/go-modules for the new Go bindings generator `wit-bindgen-go`.")