Skip to content

Commit 130438f

Browse files
authored
Add a bindings subcommand. (#366)
Add a `bindings` subcommand, which just generates the bindings.rs file. And make the `new` subcommand auto-generate the bindings.rs file too, so that the tree is fully set up after a `new`. Fixes #362.
1 parent 7749434 commit 130438f

File tree

4 files changed

+61
-3
lines changed

4 files changed

+61
-3
lines changed

src/bin/cargo-component.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use std::path::PathBuf;
22

33
use anyhow::{bail, Result};
44
use cargo_component::{
5-
commands::{AddCommand, NewCommand, PublishCommand, UpdateCommand},
5+
commands::{AddCommand, BindingsCommand, NewCommand, PublishCommand, UpdateCommand},
66
config::{CargoArguments, Config},
77
load_component_metadata, load_metadata, run_cargo_command,
88
};
@@ -19,6 +19,7 @@ fn version() -> &'static str {
1919
/// The list of commands that are built-in to `cargo-component`.
2020
const BUILTIN_COMMANDS: &[&str] = &[
2121
"add",
22+
"bindings",
2223
"component", // for indirection via `cargo component`
2324
"help",
2425
"init",
@@ -71,6 +72,7 @@ enum CargoComponent {
7172
#[derive(Parser)]
7273
enum Command {
7374
Add(AddCommand),
75+
Bindings(BindingsCommand),
7476
// TODO: Init(InitCommand),
7577
New(NewCommand),
7678
// TODO: Remove(RemoveCommand),
@@ -115,6 +117,7 @@ async fn main() -> Result<()> {
115117
if let Err(e) = match CargoComponent::parse() {
116118
CargoComponent::Component(cmd) | CargoComponent::Command(cmd) => match cmd {
117119
Command::Add(cmd) => cmd.exec().await,
120+
Command::Bindings(cmd) => cmd.exec().await,
118121
Command::New(cmd) => cmd.exec().await,
119122
Command::Update(cmd) => cmd.exec().await,
120123
Command::Publish(cmd) => cmd.exec().await,

src/commands.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
//! Commands for the `cargo-component` CLI.
22
33
mod add;
4+
mod bindings;
45
mod new;
56
mod publish;
67
mod update;
78

89
pub use self::add::*;
10+
pub use self::bindings::*;
911
pub use self::new::*;
1012
pub use self::publish::*;
1113
pub use self::update::*;

src/commands/bindings.rs

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
use anyhow::Result;
2+
use cargo_component_core::command::CommonOptions;
3+
use clap::Args;
4+
5+
use crate::{
6+
config::Config, generate_bindings, load_component_metadata, load_metadata, CargoArguments,
7+
};
8+
9+
/// Just update the generated bindings.
10+
///
11+
/// The generated bindings are generated automatically by subcommands like
12+
/// `cargo component build`; `cargo component bindings` is for when one wishes
13+
/// to just generate the bindings without doing any other work.
14+
#[derive(Args)]
15+
#[clap(disable_version_flag = true)]
16+
pub struct BindingsCommand {
17+
/// The common command options.
18+
#[clap(flatten)]
19+
pub common: CommonOptions,
20+
}
21+
22+
impl BindingsCommand {
23+
/// Executes the command.
24+
pub async fn exec(self) -> Result<()> {
25+
log::debug!("generating bindings");
26+
27+
let config = Config::new(self.common.new_terminal(), self.common.config.clone()).await?;
28+
29+
let client = config.client(self.common.cache_dir.clone(), false).await?;
30+
31+
let cargo_args = CargoArguments::parse()?;
32+
let metadata = load_metadata(None)?;
33+
let packages =
34+
load_component_metadata(&metadata, cargo_args.packages.iter(), cargo_args.workspace)?;
35+
let _import_name_map =
36+
generate_bindings(client, &config, &metadata, &packages, &cargo_args).await?;
37+
38+
Ok(())
39+
}
40+
}

src/commands/new.rs

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,10 @@ use semver::VersionReq;
1717
use toml_edit::{table, value, DocumentMut, Item, Table, Value};
1818
use wasm_pkg_client::caching::{CachingClient, FileCache};
1919

20-
use crate::{config::Config, generator::SourceGenerator, metadata, metadata::DEFAULT_WIT_DIR};
20+
use crate::{
21+
config::Config, generate_bindings, generator::SourceGenerator, load_component_metadata,
22+
load_metadata, metadata, metadata::DEFAULT_WIT_DIR, CargoArguments,
23+
};
2124

2225
const WIT_BINDGEN_RT_CRATE: &str = "wit-bindgen-rt";
2326

@@ -159,7 +162,7 @@ impl NewCommand {
159162
None => None,
160163
};
161164
let client = config.client(self.common.cache_dir.clone(), false).await?;
162-
let target = self.resolve_target(client, target).await?;
165+
let target = self.resolve_target(Arc::clone(&client), target).await?;
163166
let source = self.generate_source(&target).await?;
164167

165168
let mut command = self.new_command();
@@ -187,6 +190,16 @@ impl NewCommand {
187190
self.create_targets_file(&name, &out_dir)?;
188191
self.create_editor_settings_file(&out_dir)?;
189192

193+
// Now that we've created the project, generate the bindings so that
194+
// users can start looking at code with an IDE and not see red squiggles.
195+
let cargo_args = CargoArguments::parse()?;
196+
let manifest_path = out_dir.join("Cargo.toml");
197+
let metadata = load_metadata(Some(&manifest_path))?;
198+
let packages =
199+
load_component_metadata(&metadata, cargo_args.packages.iter(), cargo_args.workspace)?;
200+
let _import_name_map =
201+
generate_bindings(client, &config, &metadata, &packages, &cargo_args).await?;
202+
190203
Ok(())
191204
}
192205

0 commit comments

Comments
 (0)