Skip to content

Commit

Permalink
Add a bindings subcommand. (#366)
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
sunfishcode authored Jan 6, 2025
1 parent 7749434 commit 130438f
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 3 deletions.
5 changes: 4 additions & 1 deletion src/bin/cargo-component.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use std::path::PathBuf;

use anyhow::{bail, Result};
use cargo_component::{
commands::{AddCommand, NewCommand, PublishCommand, UpdateCommand},
commands::{AddCommand, BindingsCommand, NewCommand, PublishCommand, UpdateCommand},
config::{CargoArguments, Config},
load_component_metadata, load_metadata, run_cargo_command,
};
Expand All @@ -19,6 +19,7 @@ fn version() -> &'static str {
/// The list of commands that are built-in to `cargo-component`.
const BUILTIN_COMMANDS: &[&str] = &[
"add",
"bindings",
"component", // for indirection via `cargo component`
"help",
"init",
Expand Down Expand Up @@ -71,6 +72,7 @@ enum CargoComponent {
#[derive(Parser)]
enum Command {
Add(AddCommand),
Bindings(BindingsCommand),
// TODO: Init(InitCommand),
New(NewCommand),
// TODO: Remove(RemoveCommand),
Expand Down Expand Up @@ -115,6 +117,7 @@ async fn main() -> Result<()> {
if let Err(e) = match CargoComponent::parse() {
CargoComponent::Component(cmd) | CargoComponent::Command(cmd) => match cmd {
Command::Add(cmd) => cmd.exec().await,
Command::Bindings(cmd) => cmd.exec().await,
Command::New(cmd) => cmd.exec().await,
Command::Update(cmd) => cmd.exec().await,
Command::Publish(cmd) => cmd.exec().await,
Expand Down
2 changes: 2 additions & 0 deletions src/commands.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
//! Commands for the `cargo-component` CLI.
mod add;
mod bindings;
mod new;
mod publish;
mod update;

pub use self::add::*;
pub use self::bindings::*;
pub use self::new::*;
pub use self::publish::*;
pub use self::update::*;
40 changes: 40 additions & 0 deletions src/commands/bindings.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
use anyhow::Result;
use cargo_component_core::command::CommonOptions;
use clap::Args;

use crate::{
config::Config, generate_bindings, load_component_metadata, load_metadata, CargoArguments,
};

/// Just update the generated bindings.
///
/// The generated bindings are generated automatically by subcommands like
/// `cargo component build`; `cargo component bindings` is for when one wishes
/// to just generate the bindings without doing any other work.
#[derive(Args)]
#[clap(disable_version_flag = true)]
pub struct BindingsCommand {
/// The common command options.
#[clap(flatten)]
pub common: CommonOptions,
}

impl BindingsCommand {
/// Executes the command.
pub async fn exec(self) -> Result<()> {
log::debug!("generating bindings");

let config = Config::new(self.common.new_terminal(), self.common.config.clone()).await?;

let client = config.client(self.common.cache_dir.clone(), false).await?;

let cargo_args = CargoArguments::parse()?;
let metadata = load_metadata(None)?;
let packages =
load_component_metadata(&metadata, cargo_args.packages.iter(), cargo_args.workspace)?;
let _import_name_map =
generate_bindings(client, &config, &metadata, &packages, &cargo_args).await?;

Ok(())
}
}
17 changes: 15 additions & 2 deletions src/commands/new.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,10 @@ use semver::VersionReq;
use toml_edit::{table, value, DocumentMut, Item, Table, Value};
use wasm_pkg_client::caching::{CachingClient, FileCache};

use crate::{config::Config, generator::SourceGenerator, metadata, metadata::DEFAULT_WIT_DIR};
use crate::{
config::Config, generate_bindings, generator::SourceGenerator, load_component_metadata,
load_metadata, metadata, metadata::DEFAULT_WIT_DIR, CargoArguments,
};

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

Expand Down Expand Up @@ -159,7 +162,7 @@ impl NewCommand {
None => None,
};
let client = config.client(self.common.cache_dir.clone(), false).await?;
let target = self.resolve_target(client, target).await?;
let target = self.resolve_target(Arc::clone(&client), target).await?;
let source = self.generate_source(&target).await?;

let mut command = self.new_command();
Expand Down Expand Up @@ -187,6 +190,16 @@ impl NewCommand {
self.create_targets_file(&name, &out_dir)?;
self.create_editor_settings_file(&out_dir)?;

// Now that we've created the project, generate the bindings so that
// users can start looking at code with an IDE and not see red squiggles.
let cargo_args = CargoArguments::parse()?;
let manifest_path = out_dir.join("Cargo.toml");
let metadata = load_metadata(Some(&manifest_path))?;
let packages =
load_component_metadata(&metadata, cargo_args.packages.iter(), cargo_args.workspace)?;
let _import_name_map =
generate_bindings(client, &config, &metadata, &packages, &cargo_args).await?;

Ok(())
}

Expand Down

0 comments on commit 130438f

Please sign in to comment.