Skip to content

Commit 05249c3

Browse files
authored
Support lists of WIT directories on the CLI. (#1368)
Accept multiple WIT paths in the wit-bindgen CLI, using the same logic as the multiple WIT paths accepted by the `path` parameter in the Rust bindgen macro. Also, document that list-of-WIT interfaces, in the Rust macro and now the wit-bindgen CLI, have a topological ordering requirement which may be lifted in the future.
1 parent 90031e8 commit 05249c3

File tree

7 files changed

+76
-98
lines changed

7 files changed

+76
-98
lines changed

Cargo.lock

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

Cargo.toml

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -33,13 +33,13 @@ prettyplease = "0.2.20"
3333
syn = { version = "2.0.89", features = ["printing"] }
3434
futures = "0.3.31"
3535

36-
wat = "1.237.0"
37-
wasmparser = "0.237.0"
38-
wasm-encoder = "0.237.0"
39-
wasm-metadata = { version = "0.237.0", default-features = false }
40-
wit-parser = "0.237.0"
41-
wit-component = "0.237.0"
42-
wasm-compose = "0.237.0"
36+
wat = "1.238.0"
37+
wasmparser = "0.238.0"
38+
wasm-encoder = "0.238.0"
39+
wasm-metadata = { version = "0.238.0", default-features = false }
40+
wit-parser = "0.238.0"
41+
wit-component = "0.238.0"
42+
wasm-compose = "0.238.0"
4343

4444
wit-bindgen-core = { path = 'crates/core', version = '0.44.0' }
4545
wit-bindgen-c = { path = 'crates/c', version = '0.44.0' }

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

Lines changed: 4 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ struct Config {
5252

5353
/// The source of the wit package definition
5454
enum Source {
55-
/// A path to a wit directory
55+
/// A list of paths to wit directories
5656
Paths(Vec<PathBuf>),
5757
/// Inline sources have an optional path to a directory of their dependencies
5858
Inline(String, Option<Vec<PathBuf>>),
@@ -174,9 +174,10 @@ impl Parse for Config {
174174
)]));
175175
}
176176
}
177-
let (resolve, pkgs, files) =
177+
let (resolve, main_packages, files) =
178178
parse_source(&source, &features).map_err(|err| anyhow_to_syn(call_site, err))?;
179-
let world = select_world(&resolve, &pkgs, world.as_deref())
179+
let world = resolve
180+
.select_world(&main_packages, world.as_deref())
180181
.map_err(|e| anyhow_to_syn(call_site, e))?;
181182
Ok(Config {
182183
opts,
@@ -188,43 +189,6 @@ impl Parse for Config {
188189
}
189190
}
190191

191-
fn select_world(
192-
resolve: &Resolve,
193-
pkgs: &[PackageId],
194-
world: Option<&str>,
195-
) -> anyhow::Result<WorldId> {
196-
if pkgs.len() == 1 {
197-
resolve.select_world(pkgs[0], world)
198-
} else {
199-
assert!(!pkgs.is_empty());
200-
match world {
201-
Some(name) => {
202-
if !name.contains(":") {
203-
anyhow::bail!(
204-
"with multiple packages a fully qualified \
205-
world name must be specified"
206-
)
207-
}
208-
209-
// This will ignore the package argument due to the fully
210-
// qualified name being used.
211-
resolve.select_world(pkgs[0], world)
212-
}
213-
None => {
214-
let worlds = pkgs
215-
.iter()
216-
.filter_map(|p| resolve.select_world(*p, None).ok())
217-
.collect::<Vec<_>>();
218-
match &worlds[..] {
219-
[] => anyhow::bail!("no packages have a world"),
220-
[world] => Ok(*world),
221-
_ => anyhow::bail!("multiple packages have a world, must specify which to use"),
222-
}
223-
}
224-
}
225-
}
226-
}
227-
228192
/// Parse the source
229193
fn parse_source(
230194
source: &Option<Source>,

crates/guest-rust/src/lib.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -652,7 +652,9 @@
652652
/// // ["../path/to/wit1", "../path/to/wit2"]
653653
/// // Usually used in testing, our test suite may want to generate code
654654
/// // from wit files located in multiple paths within a single mod, and we
655-
/// // don't want to copy these files again.
655+
/// // don't want to copy these files again. Currently these locations must
656+
/// // be ordered, as later paths can't contain dependencies on earlier
657+
/// // paths. This restriction may be lifted in the future.
656658
/// path: "../path/to/wit",
657659
///
658660
/// // Enables passing "inline WIT". If specified this is the default

crates/test-helpers/src/lib.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -143,9 +143,9 @@ pub fn run_component_codegen_test(
143143
fn parse_wit(path: &Path) -> (Resolve, WorldId) {
144144
let mut resolve = Resolve::default();
145145
let (pkg, _files) = resolve.push_path(path).unwrap();
146-
let world = resolve.select_world(pkg, None).unwrap_or_else(|_| {
146+
let world = resolve.select_world(&[pkg], None).unwrap_or_else(|_| {
147147
// note: if there are multiples worlds in the wit package, we assume the "imports" world
148-
resolve.select_world(pkg, Some("imports")).unwrap()
148+
resolve.select_world(&[pkg], Some("imports")).unwrap()
149149
});
150150
(resolve, world)
151151
}

crates/test/src/lib.rs

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -342,7 +342,7 @@ impl Runner<'_> {
342342
let mut worlds = Vec::new();
343343

344344
let mut push_world = |kind: Kind, name: &str| -> Result<()> {
345-
let world = resolve.select_world(pkg, Some(name)).with_context(|| {
345+
let world = resolve.select_world(&[pkg], Some(name)).with_context(|| {
346346
format!("failed to find expected `{name}` world to generate bindings")
347347
})?;
348348
worlds.push((world, kind));
@@ -582,8 +582,12 @@ impl Runner<'_> {
582582
let mut resolve = wit_parser::Resolve::default();
583583
let (pkg, _) = resolve.push_path(test).context("failed to load WIT")?;
584584
let world = resolve
585-
.select_world(pkg, None)
586-
.or_else(|err| resolve.select_world(pkg, Some("imports")).map_err(|_| err))
585+
.select_world(&[pkg], None)
586+
.or_else(|err| {
587+
resolve
588+
.select_world(&[pkg], Some("imports"))
589+
.map_err(|_| err)
590+
})
587591
.context("failed to select a world for bindings generation")?;
588592
let world = resolve.worlds[world].name.clone();
589593

@@ -992,7 +996,7 @@ status: {}",
992996
let (pkg, _) = resolve
993997
.push_path(&compile.component.bindgen.wit_path)
994998
.context("failed to load WIT")?;
995-
let world = resolve.select_world(pkg, Some(&compile.component.bindgen.world))?;
999+
let world = resolve.select_world(&[pkg], Some(&compile.component.bindgen.world))?;
9961000
let mut module = fs::read(&p1).context("failed to read wasm file")?;
9971001
let encoded = wit_component::metadata::encode(&resolve, world, StringEncoding::UTF8, None)?;
9981002

src/bin/wit-bindgen.rs

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -85,14 +85,18 @@ struct Common {
8585
#[clap(long = "out-dir")]
8686
out_dir: Option<PathBuf>,
8787

88-
/// Location of WIT file(s) to generate bindings for.
88+
/// Locations of WIT file(s) to generate bindings for.
8989
///
90-
/// This path can be either a directory containing `*.wit` files, a `*.wit`
91-
/// file itself, or a `*.wasm` file which is a wasm-encoded WIT package.
92-
/// Most of the time it's likely to be a directory containing `*.wit` files
93-
/// with an optional `deps` folder inside of it.
90+
/// These paths can be either directories containing `*.wit` files, `*.wit`
91+
/// files themselves, or `*.wasm` files which are wasm-encoded WIT packages.
92+
/// Most of the time they're likely to be directories containing `*.wit`
93+
/// files with optional `deps` folders inside of them.
94+
///
95+
/// Currently these locations must be ordered, as later paths can't contain
96+
/// dependencies on earlier paths. This restriction may be lifted in the
97+
/// future.
9498
#[clap(value_name = "WIT", index = 1)]
95-
wit: PathBuf,
99+
wit: Vec<PathBuf>,
96100

97101
/// Optionally specified world that bindings are generated for.
98102
///
@@ -219,8 +223,12 @@ fn gen_world(
219223
resolve.features.insert(feature.to_string());
220224
}
221225
}
222-
let (pkg, _files) = resolve.push_path(&opts.wit)?;
223-
let world = resolve.select_world(pkg, opts.world.as_deref())?;
226+
let mut main_packages = Vec::new();
227+
for wit in &opts.wit {
228+
let (pkg, _files) = resolve.push_path(wit)?;
229+
main_packages.push(pkg);
230+
}
231+
let world = resolve.select_world(&main_packages, opts.world.as_deref())?;
224232
generator.generate(&resolve, world, files)?;
225233

226234
Ok(())

0 commit comments

Comments
 (0)