Skip to content

Commit ffbf78c

Browse files
authored
[rust] bindgen path supports env!() macro (#1569)
* [rust] bindgen path supports env!() macro This makes it possible to refer to a wit path by a path that includes things like OUT_DIR or CARGO_MANIFEST_DIR. Relative paths that navigate up, like `../wit/`, don't work well with cargo publish, and symlinks have difficulties between git and cargo. Using [macro-string](https://github.com/dtolnay/macro-string), this replaces the `path` option's `syn::LitStr` with MacroString. * add macro-string feature to wit-bindgen-rust-macro gates the macro-string dependency on the new default feature macro-string. * lift macro-string feature toggle to wit-bindgen
1 parent b858f8e commit ffbf78c

File tree

8 files changed

+77
-10
lines changed

8 files changed

+77
-10
lines changed

Cargo.lock

Lines changed: 12 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ indexmap = "2.0.0"
4545
prettyplease = "0.2.20"
4646
syn = { version = "2.0.89", features = ["printing"] }
4747
futures = "0.3.31"
48+
macro-string = "0.2.0"
4849

4950
wat = "1.245.1"
5051
wasmparser = "0.245.1"

crates/guest-rust/Cargo.toml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ workspace = true
1919
all-features = true
2020

2121
[dependencies]
22-
wit-bindgen-rust-macro = { path = "./macro", optional = true, version = "0.54.0" }
22+
wit-bindgen-rust-macro = { path = "./macro", optional = true, default-features = false, version = "0.54.0" }
2323
bitflags = { workspace = true, optional = true }
2424
futures = { version = "0.3.30", optional = true }
2525

@@ -28,13 +28,14 @@ core = { version = "1.0", optional = true, package = "rustc-std-workspace-core"
2828
alloc = { version = "1.0", optional = true, package = "rustc-std-workspace-alloc" }
2929

3030
[features]
31-
default = ["macros", "realloc", "async", "std", "bitflags"]
31+
default = ["macros", "realloc", "async", "std", "bitflags", "macro-string"]
3232
macros = ["dep:wit-bindgen-rust-macro"]
3333
realloc = []
3434
std = []
3535
async = ["std", "wit-bindgen-rust-macro?/async"]
3636
bitflags = ["dep:bitflags"]
3737
async-spawn = ['async', 'dep:futures']
38+
macro-string = ["wit-bindgen-rust-macro?/macro-string"]
3839

3940
# Unstable feature to support being a libstd dependency
4041
rustc-dep-of-std = ["dep:core", "dep:alloc"]

crates/guest-rust/macro/Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@ wit-bindgen-rust = { workspace = true }
2323
anyhow = { workspace = true }
2424
syn = { workspace = true }
2525
prettyplease = { workspace = true }
26+
macro-string = { workspace = true, optional = true }
2627

2728
[features]
29+
default = ["macro-string"]
2830
async = []
31+
macro-string = ["dep:macro-string"]

crates/guest-rust/macro/src/lib.rs

Lines changed: 38 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,7 @@ use std::path::{Path, PathBuf};
55
use std::sync::atomic::{AtomicUsize, Ordering::Relaxed};
66
use syn::parse::{Error, Parse, ParseStream, Result};
77
use syn::punctuated::Punctuated;
8-
use syn::spanned::Spanned;
9-
use syn::{LitStr, Token, braced, token};
8+
use syn::{Token, braced, token};
109
use wit_bindgen_core::AsyncFilterSet;
1110
use wit_bindgen_core::WorldGenerator;
1211
use wit_bindgen_core::wit_parser::{PackageId, Resolve, UnresolvedPackageGroup, WorldId};
@@ -76,7 +75,13 @@ impl Parse for Config {
7675
for field in fields.into_pairs() {
7776
match field.into_value() {
7877
Opt::Path(span, p) => {
79-
let paths = p.into_iter().map(|f| PathBuf::from(f.value())).collect();
78+
let paths = p
79+
.into_iter()
80+
.map(|f| f.evaluate_string())
81+
.collect::<Result<Vec<_>>>()?
82+
.into_iter()
83+
.map(PathBuf::from)
84+
.collect();
8085

8186
source = Some(match source {
8287
Some(Source::Paths(_)) | Some(Source::Inline(_, Some(_))) => {
@@ -346,9 +351,32 @@ impl From<ExportKey> for wit_bindgen_rust::ExportKey {
346351
}
347352
}
348353

354+
#[cfg(feature = "macro-string")]
355+
type PathType = macro_string::MacroString;
356+
#[cfg(not(feature = "macro-string"))]
357+
type PathType = syn::LitStr;
358+
359+
trait EvaluateString {
360+
fn evaluate_string(&self) -> Result<String>;
361+
}
362+
363+
#[cfg(feature = "macro-string")]
364+
impl EvaluateString for macro_string::MacroString {
365+
fn evaluate_string(&self) -> Result<String> {
366+
self.eval()
367+
}
368+
}
369+
370+
#[cfg(not(feature = "macro-string"))]
371+
impl EvaluateString for syn::LitStr {
372+
fn evaluate_string(&self) -> Result<String> {
373+
Ok(self.value())
374+
}
375+
}
376+
349377
enum Opt {
350378
World(syn::LitStr),
351-
Path(Span, Vec<syn::LitStr>),
379+
Path(Span, Vec<PathType>),
352380
Inline(syn::LitStr),
353381
UseStdFeature,
354382
RawStrings,
@@ -387,11 +415,13 @@ impl Parse for Opt {
387415
if input.peek(token::Bracket) {
388416
let contents;
389417
syn::bracketed!(contents in input);
390-
let list = Punctuated::<_, Token![,]>::parse_terminated(&contents)?;
391-
Ok(Opt::Path(list.span(), list.into_iter().collect()))
418+
let span = input.span();
419+
let list = Punctuated::<PathType, Token![,]>::parse_terminated(&contents)?;
420+
Ok(Opt::Path(span, list.into_iter().collect()))
392421
} else {
393-
let path: LitStr = input.parse()?;
394-
Ok(Opt::Path(path.span(), vec![path]))
422+
let span = input.span();
423+
let path: PathType = input.parse()?;
424+
Ok(Opt::Path(span, vec![path]))
395425
}
396426
} else if l.peek(kw::inline) {
397427
input.parse::<kw::inline>()?;

crates/guest-rust/src/examples.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,3 +53,12 @@ pub mod _3_world_exports;
5353
#[doc = include_str!("./examples/_4_exported_resources.rs")]
5454
/// ```
5555
pub mod _4_exported_resources;
56+
57+
/// An example of importing a compile-time directory of wit files.
58+
///
59+
/// The code used to generate this module is:
60+
///
61+
/// ```rust
62+
#[doc = include_str!("./examples/_5_import_directory.rs")]
63+
/// ```
64+
pub mod _5_import_directory;
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
crate::generate!({
2+
path: concat!(
3+
env!("CARGO_MANIFEST_DIR"),
4+
"/wit/"
5+
),
6+
});
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
package example:import-directory;
2+
3+
world import-directory {
4+
import hello: func() -> string;
5+
}

0 commit comments

Comments
 (0)