Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: support run, test and bench cargo commands #143

Merged

Conversation

eduardomourar
Copy link
Contributor

@eduardomourar eduardomourar commented Sep 22, 2023

This will take a similar approach as used by cargo-wasi (source code here) in order to expose the following cargo commands: run, test and bench.

The following steps will be done per action:

  • run: execute build command, componentize the output, and then feed what it componentized to the configured runner.
  • test and bench: execute test/bench with --no-run argument, componentize the output, and then feed componentized wasm to the configured runner.

Related to: #94.

@eduardomourar eduardomourar marked this pull request as ready for review September 22, 2023 02:11
@eduardomourar eduardomourar force-pushed the feat/cargo-component-test branch 3 times, most recently from dc08b18 to 075e5a9 Compare September 22, 2023 17:42
@eduardomourar
Copy link
Contributor Author

@peterhuene, does this approach makes sense to you?

@peterhuene
Copy link
Member

peterhuene commented Sep 25, 2023

Hi @eduardomourar, thanks for the PR!

Unfortunately, it isn't quite as simple as copying what cargo wasi does for using a runner to properly implement cargo component run.

The first problem is that componentization is expected to occur between the "build" and "run" stages of the "run" command; right now if you pass through to cargo run without a prior build, only a core module will get built before passing it to the runner. This may appear to work for things like WASI commands because the core module is using WASI preview 1, which Wasmtime still supports from the CLI.

If we assume the first problem is solved, we run into the second problem: the component produced by cargo-component has (intentionally) abstract instance imports for any of its dependencies. To make the component suitable for running, we need to compose it with its dependencies prior to giving it to the runner. There's been work to automatically compose a component with its dependencies based on registry information and I'm currently working on a proper text format for wasm-compose to define custom compositions, but cargo-component will need to integrate with these before it produces runnable components.

To solve the first problem, cargo component run (and friends) will need to be implemented as proper subcommands rather than pass-throughs to cargo to allow for it to first spawn a build, componentize the output from rustc, and then spawn the runner.

Solving the second problem is much more involved and one of the reasons I've been holding off implementing these commands until a proper design is put in place.

@eduardomourar
Copy link
Contributor Author

eduardomourar commented Sep 26, 2023

@peterhuene, my particular use case is only to speed the development cycle while building individual components. You can find a sample GitHub run here. There you will see that I am running the test using this branch and the WASI Preview 2 functions are actually being invoked. It probably works because I don't have a composed component.

Is there anything I can change in this PR to get us in the expected direction? Maybe scope it down to include only the test subcommand.

@peterhuene
Copy link
Member

peterhuene commented Sep 26, 2023

Your test is running aws-cli as a core module and not as a component, and this is only working because the Wasmtime CLI, until 5 days ago, supported wasi:http from a core module.

I suspect if you update your CI to use the latest Wasmtime, you'll get an error: Cannot enable wasi-http for core wasm modules.

As I mentioned earlier, the reason for this is that componentization of the build output occurs after a build command. As a test or run command implicitly executes the build command, there's no componentization occurring and you'll always get a core module being executed.

In addition to the problems I outlined above, cargo test will feed an output from deps dir to the runner (in your CI example, that would be /home/runner/work/wasm-web-shell/wasm-web-shell/target/wasm32-wasi/debug/deps/aws_cli-b90a0d2c7dc6f98b.wasm), which cargo component currently does not attempt to componentize; cargo component only componentizes the target directory output (e.g. target/wasm32-wasi/debug/foo.wasm), which is a hardlink except on macOS afaik.

@peterhuene
Copy link
Member

peterhuene commented Sep 26, 2023

That said, it is possible to implement a first-class test and run subcommand in cargo-component that does not delegate to cargo test or cargo run.

Those commands would do a build (cargo test --no-run probably for the test subcommand), componentize the output, and then feed what it componentized to a configured runner.

That would probably be the first step in implementing this, upon which we can add an integration of a composition step prior to executing the runner.

@eduardomourar
Copy link
Contributor Author

Thanks for the explanation. Apologies for the confusion on my part. I always forget that wasmtime will follow the component/core module path based on its content and not the arguments passed. I will check how complex it is to have the logic you suggested in this PR.

@eduardomourar
Copy link
Contributor Author

Ok, so finally got it working on unix. Just need to remove the hack to get the executable file.

@eduardomourar
Copy link
Contributor Author

@peterhuene , this is ready for review now.

@eduardomourar eduardomourar force-pushed the feat/cargo-component-test branch 4 times, most recently from 15bfdfd to 759c477 Compare October 3, 2023 08:33
@peterhuene
Copy link
Member

@eduardomourar thanks for all the work on this! I was away at a conference this week so haven't yet had time to review yet.

I'm still clawing my way out of a backlog, but I plan on reviewing this in full this coming Monday.

Copy link
Member

@peterhuene peterhuene left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @eduardomourar, sorry for the delay.

I have some general comments about the implementation before going deeper into the review.

Generally, I do like the approach of using the JSON messages to detect what got built, which is much more robust than the current implementation.

But we simply cannot buffer cargo's output like this implementation, as it really hurts DX.

Would it be possible to explore using a pipe for stdout and process the JSON messages as they arrive?

tests/bench.rs Show resolved Hide resolved
src/lib.rs Outdated Show resolved Hide resolved
@peterhuene
Copy link
Member

peterhuene commented Oct 11, 2023

I will mention that using --message-format is exactly how cargo-component should have been detecting Rust toolchain outputs in the first place, so I really appreciate that you pushed forward with that approach.

I'm also really grateful that you're driving this forward and we'll have a functioning cargo component run experience soon!

@eduardomourar
Copy link
Contributor Author

eduardomourar commented Oct 11, 2023

By the way, I could not figure out how to ensure that only the current package is executed in a cargo workspace context.

src/lib.rs Outdated Show resolved Hide resolved
Copy link
Member

@peterhuene peterhuene left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@eduardomourar thank you very much for your work on implementing these features!

I kept your approach mostly intact with my additional commits, except I piped stdout (when needed) and inherited stderr so that cargo both handles colors appropriately and output is displayed to users in "real time" (i.e. not buffering it).

The tests were modified slightly to rely on the cli world from the adapter, where applicable. This helped solve the conflicting run implementations.

@peterhuene peterhuene merged commit 8794955 into bytecodealliance:main Dec 4, 2023
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants