Extract dependency WITs during build#3378
Extract dependency WITs during build#3378itowlson wants to merge 6 commits intospinframework:mainfrom
Conversation
|
I think I do determine the exported interfaces by looking at worlds, but I believe it's safe to ignore I am not sure if there is some edge case when a component exports interfaces from other packages but that seems like a potential issue regardless of |
de01fea to
09cf63d
Compare
4dbe62d to
ed40fa4
Compare
crates/build/src/lib.rs
Outdated
| terminal::warn!("One or more components specified dependencies for which Spin couldn't generate import bindings."); | ||
| eprintln!( | ||
| "If these components rely on Spin-generated bindings they may fail to build." | ||
| ); | ||
| eprintln!("Otherwise, to skip binding generation, use the --skip-generate-wits flag."); |
There was a problem hiding this comment.
is it accurate to call it bindngs? I am not really sure how to articulate it but to me it feels like bindings are what the language toolchain will generate based on the importized wit. This is a very loosely held opinion, so feel free to ignore.
There was a problem hiding this comment.
Yeah I was trying to find a wording that didn't presume intimate knowledge of Component Model internals. "Bindings" was the least worst one I could think of (because the effect in your program is that yay you have bindings or boo you don't) but I agree it's technically incorrect (the worst kind of incorrect). I'm very open to suggestions for this!
There was a problem hiding this comment.
If I squint bindings feels ok to me. I might just replace "bindings" with "interfaces". I'm sympathetic to not wanting to presuppose too much CM knowledge but interfaces in this context, at least to me, transcends the WIT specifics.
Signed-off-by: itowlson <ivan.towlson@fermyon.com>
Signed-off-by: itowlson <ivan.towlson@fermyon.com>
Signed-off-by: itowlson <ivan.towlson@fermyon.com>
Signed-off-by: itowlson <ivan.towlson@fermyon.com>
Signed-off-by: itowlson <ivan.towlson@fermyon.com>
ed40fa4 to
1d9d03b
Compare
crates/dependency-wit/src/lib.rs
Outdated
| (DecodedWasm::Component(resolve, world), None) => (resolve, world), | ||
| (DecodedWasm::Component(..), Some(_)) => { | ||
| anyhow::bail!( | ||
| "the `--importize-world` flag is not compatible with a \ |
There was a problem hiding this comment.
We probably don't want to surface this error back to the user.
I think what we can do here IIUC is what is done in the following case-block:
(DecodedWasm::Component(resolve, id), world) => {
let world = resolve.select_world(&[id], world)?;
(resolve, world)
}
There was a problem hiding this comment.
Good catch - I had to copy a bunch of stuff from wasm-tools because it was in the CLI but not the library, and was just too darn diligent about preserving it. Well, that's my story and I'm sticking to it.
There was a problem hiding this comment.
@fibonacci1729 The proposed fix doesn't work because id is a WorldId and select_world requires a PackageId, and I'm not sure how to address that. Can you expand on your intention here?
There was a problem hiding this comment.
Yeah definitely confusing.
I might rewrite importize here to be as minimal for what we actually need at this time. AFAICT importize is only ever called with world=None.
fn importize(
decoded: DecodedWasm,
out_world_name: Option<&String>,
) -> anyhow::Result<DecodedWasm> {
let (mut resolve, world_id) = match decoded {
DecodedWasm::Component(resolve, world) => (resolve, world),
DecodedWasm::WitPackage(resolve, id) => {
let world = resolve.select_world(&[id], None)?;
(resolve, world)
}
};
resolve
.importize(world_id, out_world_name.cloned())
.context("failed to move world exports to imports")?;
Ok(DecodedWasm::Component(resolve, world_id))
}
wit-bindgen has a few knobs i don't fully understand.
crates/dependency-wit/src/lib.rs
Outdated
| if wasm.is_none() { | ||
| anyhow::bail!( | ||
| "input is a core wasm module with no `component-type*` \ | ||
| custom sections meaning that there is not WIT information; \ |
There was a problem hiding this comment.
nit:
| custom sections meaning that there is not WIT information; \ | |
| custom sections meaning that there is no WIT information; \ |
crates/dependency-wit/src/lib.rs
Outdated
| }; | ||
|
|
||
| // Capture WITs for all packages used in the importised thing. | ||
| // Things like WASI packages may be depended on my multiple packages |
There was a problem hiding this comment.
nit:
| // Things like WASI packages may be depended on my multiple packages | |
| // Things like WASI packages may be depended on by multiple packages |
crates/dependency-wit/src/lib.rs
Outdated
| stability: wit_parser::Stability::Unknown, | ||
| span: Span::default(), | ||
| }; | ||
| aggregating_resolve |
There was a problem hiding this comment.
If two different dependencies import the same interface (e.g. both depend on wasi:http/types), this code inserts into [aggregating_resolve.worlds[...].imports with the same WorldKey. If the map already contains that key, the second insert silently overwrites it. This works by coincidence (both values should be equivalent), but i think it would be wise to debug-assert that the existing value matches the new one which would guard against subtle breakage.
crates/dependency-wit/src/lib.rs
Outdated
| } | ||
| } | ||
|
|
||
| fn one_import(wasm: &DecodedWasm, name: &str) -> Vec<wit_parser::InterfaceId> { |
There was a problem hiding this comment.
I can't quite convince myself this can't happen but if the interface name here doesn't match anything, the dependency is silently skipped. I think we should consider returning an error or logging a warning here that no import was added since this seems to indicate a misconfiguration at the manifest level.
There was a problem hiding this comment.
Confirmed that it can happen (e.g. "foo:bar/interface-that-doesnt-exist@1.0.0" = { ... }) and turned it into an error.
Crossing my fingers for no false positives...
crates/dependency-wit/src/lib.rs
Outdated
| export: &str, | ||
| new_name: &DependencyName, | ||
| ) -> anyhow::Result<DecodedWasm> { | ||
| // TODO: I am not sure how `export` is meant to work if you are |
There was a problem hiding this comment.
This can't actually happen given the validation here:
spin/crates/manifest/src/schema/v2.rs
Line 471 in 13a2a35
There was a problem hiding this comment.
VINDICATI-- uh I mean thanks for the pointer (and for having already dealt to it)
crates/dependency-wit/Cargo.toml
Outdated
|
|
||
| [dev-dependencies] | ||
| tempfile = { workspace = true } | ||
| wasm-pkg-common = { workspace = true } |
There was a problem hiding this comment.
I think this is a dead dependency
Signed-off-by: itowlson <ivan.towlson@fermyon.com>
1d9d03b to
ccb7fb1
Compare
Fixes #3376.
WIP. Current status: 1.
contains gross, gross hacksreplaced with BEAUTIFUL AND ELEGANT hacks, and 2. incomplete.Work needed:
HandleexportTest thatI think this works but a second tester would be very welcomeincludeis handled correctlyProvide a way to invoke it outside of build(can be deferred if naming is hard, which it always is)