diff --git a/Cargo.lock b/Cargo.lock index 1998b2059..b1bec5c63 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -654,6 +654,17 @@ dependencies = [ "logos-codegen", ] +[[package]] +name = "macro-string" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59a9dbbfc75d2688ed057456ce8a3ee3f48d12eec09229f560f3643b9f275653" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "memchr" version = "2.7.6" @@ -1604,6 +1615,7 @@ name = "wit-bindgen-rust-macro" version = "0.54.0" dependencies = [ "anyhow", + "macro-string", "prettyplease", "proc-macro2", "quote", diff --git a/Cargo.toml b/Cargo.toml index dd0807dd0..4b9cd0bbf 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -45,6 +45,7 @@ indexmap = "2.0.0" prettyplease = "0.2.20" syn = { version = "2.0.89", features = ["printing"] } futures = "0.3.31" +macro-string = "0.2.0" wat = "1.245.1" wasmparser = "0.245.1" diff --git a/crates/guest-rust/Cargo.toml b/crates/guest-rust/Cargo.toml index 5014f9e90..c38a70e63 100644 --- a/crates/guest-rust/Cargo.toml +++ b/crates/guest-rust/Cargo.toml @@ -19,7 +19,7 @@ workspace = true all-features = true [dependencies] -wit-bindgen-rust-macro = { path = "./macro", optional = true, version = "0.54.0" } +wit-bindgen-rust-macro = { path = "./macro", optional = true, default-features = false, version = "0.54.0" } bitflags = { workspace = true, optional = true } futures = { version = "0.3.30", optional = true } @@ -28,13 +28,14 @@ core = { version = "1.0", optional = true, package = "rustc-std-workspace-core" alloc = { version = "1.0", optional = true, package = "rustc-std-workspace-alloc" } [features] -default = ["macros", "realloc", "async", "std", "bitflags"] +default = ["macros", "realloc", "async", "std", "bitflags", "macro-string"] macros = ["dep:wit-bindgen-rust-macro"] realloc = [] std = [] async = ["std", "wit-bindgen-rust-macro?/async"] bitflags = ["dep:bitflags"] async-spawn = ['async', 'dep:futures'] +macro-string = ["wit-bindgen-rust-macro?/macro-string"] # Unstable feature to support being a libstd dependency rustc-dep-of-std = ["dep:core", "dep:alloc"] diff --git a/crates/guest-rust/macro/Cargo.toml b/crates/guest-rust/macro/Cargo.toml index 5fb9c1ea6..4c3a5fb8a 100644 --- a/crates/guest-rust/macro/Cargo.toml +++ b/crates/guest-rust/macro/Cargo.toml @@ -23,6 +23,9 @@ wit-bindgen-rust = { workspace = true } anyhow = { workspace = true } syn = { workspace = true } prettyplease = { workspace = true } +macro-string = { workspace = true, optional = true } [features] +default = ["macro-string"] async = [] +macro-string = ["dep:macro-string"] diff --git a/crates/guest-rust/macro/src/lib.rs b/crates/guest-rust/macro/src/lib.rs index 91d4335dd..d8b4170bd 100644 --- a/crates/guest-rust/macro/src/lib.rs +++ b/crates/guest-rust/macro/src/lib.rs @@ -5,8 +5,7 @@ use std::path::{Path, PathBuf}; use std::sync::atomic::{AtomicUsize, Ordering::Relaxed}; use syn::parse::{Error, Parse, ParseStream, Result}; use syn::punctuated::Punctuated; -use syn::spanned::Spanned; -use syn::{LitStr, Token, braced, token}; +use syn::{Token, braced, token}; use wit_bindgen_core::AsyncFilterSet; use wit_bindgen_core::WorldGenerator; use wit_bindgen_core::wit_parser::{PackageId, Resolve, UnresolvedPackageGroup, WorldId}; @@ -76,7 +75,13 @@ impl Parse for Config { for field in fields.into_pairs() { match field.into_value() { Opt::Path(span, p) => { - let paths = p.into_iter().map(|f| PathBuf::from(f.value())).collect(); + let paths = p + .into_iter() + .map(|f| f.evaluate_string()) + .collect::>>()? + .into_iter() + .map(PathBuf::from) + .collect(); source = Some(match source { Some(Source::Paths(_)) | Some(Source::Inline(_, Some(_))) => { @@ -346,9 +351,32 @@ impl From for wit_bindgen_rust::ExportKey { } } +#[cfg(feature = "macro-string")] +type PathType = macro_string::MacroString; +#[cfg(not(feature = "macro-string"))] +type PathType = syn::LitStr; + +trait EvaluateString { + fn evaluate_string(&self) -> Result; +} + +#[cfg(feature = "macro-string")] +impl EvaluateString for macro_string::MacroString { + fn evaluate_string(&self) -> Result { + self.eval() + } +} + +#[cfg(not(feature = "macro-string"))] +impl EvaluateString for syn::LitStr { + fn evaluate_string(&self) -> Result { + Ok(self.value()) + } +} + enum Opt { World(syn::LitStr), - Path(Span, Vec), + Path(Span, Vec), Inline(syn::LitStr), UseStdFeature, RawStrings, @@ -387,11 +415,13 @@ impl Parse for Opt { if input.peek(token::Bracket) { let contents; syn::bracketed!(contents in input); - let list = Punctuated::<_, Token![,]>::parse_terminated(&contents)?; - Ok(Opt::Path(list.span(), list.into_iter().collect())) + let span = input.span(); + let list = Punctuated::::parse_terminated(&contents)?; + Ok(Opt::Path(span, list.into_iter().collect())) } else { - let path: LitStr = input.parse()?; - Ok(Opt::Path(path.span(), vec![path])) + let span = input.span(); + let path: PathType = input.parse()?; + Ok(Opt::Path(span, vec![path])) } } else if l.peek(kw::inline) { input.parse::()?; diff --git a/crates/guest-rust/src/examples.rs b/crates/guest-rust/src/examples.rs index a63996889..653cb717a 100644 --- a/crates/guest-rust/src/examples.rs +++ b/crates/guest-rust/src/examples.rs @@ -53,3 +53,12 @@ pub mod _3_world_exports; #[doc = include_str!("./examples/_4_exported_resources.rs")] /// ``` pub mod _4_exported_resources; + +/// An example of importing a compile-time directory of wit files. +/// +/// The code used to generate this module is: +/// +/// ```rust +#[doc = include_str!("./examples/_5_import_directory.rs")] +/// ``` +pub mod _5_import_directory; diff --git a/crates/guest-rust/src/examples/_5_import_directory.rs b/crates/guest-rust/src/examples/_5_import_directory.rs new file mode 100644 index 000000000..a6905e944 --- /dev/null +++ b/crates/guest-rust/src/examples/_5_import_directory.rs @@ -0,0 +1,6 @@ +crate::generate!({ + path: concat!( + env!("CARGO_MANIFEST_DIR"), + "/wit/" + ), +}); diff --git a/crates/guest-rust/wit/_5_import_directory.wit b/crates/guest-rust/wit/_5_import_directory.wit new file mode 100644 index 000000000..e43771793 --- /dev/null +++ b/crates/guest-rust/wit/_5_import_directory.wit @@ -0,0 +1,5 @@ +package example:import-directory; + +world import-directory { + import hello: func() -> string; +}