Skip to content
Open
21 changes: 0 additions & 21 deletions src/bin_target.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,32 +7,11 @@ pub struct BinTarget<'p> {
/// The package containing the binary.
pub package: &'p Package,
/// The path to the directory in `target` which contains the binary.
// Only used with `web` feature, but cfg-ing it out adds too much boilerplate
#[allow(dead_code)]
pub artifact_directory: PathBuf,
/// The name of the binary (without any extensions).
// Only used with `web` feature, but cfg-ing it out adds too much boilerplate
#[allow(dead_code)]
pub bin_name: String,
}

impl BinTarget<'_> {
pub fn update_artifact_directory(
&mut self,
target_directory: impl Into<PathBuf>,
compile_target: Option<&str>,
compile_profile: &str,
is_example: bool,
) {
self.artifact_directory = get_artifact_directory(
target_directory,
compile_target,
compile_profile,
is_example,
);
}
}

/// Determine which binary target should be run.
///
/// The `--package` arg narrows down the search space to the given package,
Expand Down
1 change: 1 addition & 0 deletions src/commands/build/args.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ impl BuildArgs {
}

/// The profile used to compile the app.
#[cfg(feature = "web")]
pub(crate) fn profile(&self) -> &str {
self.cargo_args.compilation_args.profile(self.is_web())
}
Expand Down
34 changes: 13 additions & 21 deletions src/commands/build/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ pub use args::*;

#[cfg(feature = "web")]
use crate::web::build::build_web;
use crate::{bin_target::select_run_binary, config::CliConfig, external_cli::cargo};
use crate::{commands::get_package, config::CliConfig, external_cli::cargo};

mod args;

Expand All @@ -16,21 +16,20 @@ mod args;
pub fn build(args: &mut BuildArgs) -> anyhow::Result<()> {
let metadata = cargo::metadata::metadata()?;

let mut bin_target = select_run_binary(
let package = get_package(
&metadata,
args.cargo_args.package_args.package.as_deref(),
args.cargo_args.target_args.bin.as_deref(),
args.cargo_args.target_args.example.as_deref(),
args.target().as_deref(),
args.profile(),
args.cargo_args.package_args.package.as_ref(),
false,
)?;

let mut config = CliConfig::for_package(
&metadata,
bin_target.package,
args.is_web(),
args.is_release(),
)?;
// apply the package specific config, otherwise use the default config (this happens when
// `bevy build` was called from a workspace root with no package selection (we do not support
// workspace config at the moment).
let mut config = if let Some(package) = package {
CliConfig::for_package(&metadata, package, args.is_web(), args.is_release())?
} else {
CliConfig::default()
};

// Read config files hierarchically from the current directory, merge them,
// apply environment variables, and resolve relative paths.
Expand All @@ -39,17 +38,10 @@ pub fn build(args: &mut BuildArgs) -> anyhow::Result<()> {
config.append_cargo_config_rustflags(args.target(), &cargo_config)?;

args.apply_config(&config);
// Update the artifact directory based on the config, e.g. in case the `target` changed
bin_target.update_artifact_directory(
&metadata.target_directory,
args.target().as_deref(),
args.profile(),
args.cargo_args.target_args.example.is_some(),
);

#[cfg(feature = "web")]
if args.is_web() {
build_web(args, &metadata, &bin_target)?;
build_web(args, &metadata)?;
return Ok(());
}

Expand Down
5 changes: 0 additions & 5 deletions src/commands/lint/args.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,6 @@ impl LintArgs {
|| self.cargo_args.compilation_args.is_release
}

/// The profile used to compile the app.
pub(crate) fn profile(&self) -> &str {
self.cargo_args.compilation_args.profile(self.is_web())
}

/// The targeted platform.
pub(crate) fn target(&self) -> Option<String> {
self.cargo_args.compilation_args.target(self.is_web())
Expand Down
34 changes: 12 additions & 22 deletions src/commands/lint/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,7 @@ use tracing::error;
#[cfg(feature = "rustup")]
use crate::commands::lint::install::install_linter;
use crate::{
bin_target::select_run_binary,
commands::lint::install::list,
commands::{get_package, lint::install::list},
config::CliConfig,
external_cli::{
CommandExt,
Expand Down Expand Up @@ -105,21 +104,20 @@ fn build_lint_cmd(args: &mut LintArgs) -> anyhow::Result<CommandExt> {

let metadata = cargo::metadata::metadata()?;

let mut bin_target = select_run_binary(
let package = get_package(
&metadata,
args.cargo_args.package_args.package.as_deref(),
args.cargo_args.target_args.bin.as_deref(),
args.cargo_args.target_args.example.as_deref(),
args.target().as_deref(),
args.profile(),
args.cargo_args.package_args.package.as_ref(),
false,
)?;

let mut config = CliConfig::for_package(
&metadata,
bin_target.package,
args.is_web(),
args.is_release(),
)?;
// apply the package specific config, otherwise use the default config (this happens when
// `bevy build` was called from a workspace root with no package selection (we do not support
// workspace config at the moment).
let mut config = if let Some(package) = package {
CliConfig::for_package(&metadata, package, args.is_web(), args.is_release())?
} else {
CliConfig::default()
};

// Read config files hierarchically from the current directory, merge them,
// apply environment variables, and resolve relative paths.
Expand All @@ -128,14 +126,6 @@ fn build_lint_cmd(args: &mut LintArgs) -> anyhow::Result<CommandExt> {

args.apply_config(&config);

// Update the artifact directory based on the config, e.g. in case the `target` changed
bin_target.update_artifact_directory(
&metadata.target_directory,
args.target().as_deref(),
args.profile(),
args.cargo_args.target_args.example.is_some(),
);

#[cfg(feature = "web")]
if matches!(args.subcommand, Some(LintSubcommands::Web)) {
use tracing::info;
Expand Down
92 changes: 92 additions & 0 deletions src/commands/mod.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,99 @@
//! All available commands for the Bevy CLI.

use cargo_metadata::{Metadata, Package, TargetKind};

pub mod build;
pub mod completions;
pub mod lint;
pub mod new;
pub mod run;

/// Determine the package to pass to `cargo`.
///
/// Either returns the [`Package`] specified in `package_arg` or tries to resolve the default
/// package:
///
/// If the [`Package`] should be passed to `cargo run`: workspace_packages > default_packages >
/// "only one binary target" > `default-run`.
///
/// If the [`Package`] is not passed to `cargo run` and no `package_arg` is present, just check if
/// there is a [`Package`] in the current directory and return that if one is found.
fn get_package<'m>(
metadata: &'m Metadata,
package_arg: Option<&String>,
run_command: bool,
) -> anyhow::Result<Option<&'m Package>> {
// If the `--package` arg was passed, search for the given package, otherwise
// check if the current directory contains a package.
let package = if let Some(package_name) = package_arg {
metadata
.packages
.iter()
.find(|package| package.name.as_str() == package_name)
} else if run_command {
let workspace_packages = metadata.workspace_packages();
let default_packages = metadata.workspace_default_packages();
let packages = if default_packages.is_empty() {
workspace_packages
} else {
default_packages
};

// If there is only one binary, pick that one
let bins: Vec<_> = packages
.iter()
.flat_map(|package| {
package
.targets
.iter()
.filter(|target| target.kind.contains(&TargetKind::Bin))
.map(move |_| package)
})
.collect();

let bin_package = if bins.is_empty() {
anyhow::bail!("No binaries available!");
} else if bins.len() == 1 {
bins[0]
} else {
// Otherwise, check if there is a default run target defined
let default_runs: Vec<_> = packages
.iter()
.filter_map(|package| package.default_run.as_ref())
.collect();

if default_runs.is_empty() {
anyhow::bail!(
"There are multiple binaries available, try one of the following:
- add `--bin` or `--package` after `bevy run` to specify which binary or package to run,
- define `default-run` in the Cargo.toml to define the default binary that should be executed in a package,
- define `default-members` in the Cargo.toml of your workspace to define the default package to pick the binary from."
);
} else if default_runs.len() > 1 {
anyhow::bail!(
"Found multiple `default-run` definitions, I don't know which one to pick!"
);
}

let default_run = default_runs[0];
**bins
.iter()
.find(|bin| bin.name == *default_run)
.ok_or_else(|| anyhow::anyhow!("Didn't find `default-run` binary {default_run}"))?
};
Some(bin_package)
} else {
// Get the current directory
let current_dir = std::env::current_dir()?;

// Find the package whose manifest_path matches the current directory
metadata.packages.iter().find(|pkg| {
pkg.manifest_path
.parent()
.map(cargo_metadata::camino::Utf8Path::as_std_path)
== Some(&current_dir)
})
};

Ok(package)
}
5 changes: 0 additions & 5 deletions src/commands/run/args.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,11 +66,6 @@ impl RunArgs {
|| self.cargo_args.compilation_args.is_release
}

/// The profile used to compile the app.
pub(crate) fn profile(&self) -> &str {
self.cargo_args.compilation_args.profile(self.is_web())
}

/// The targeted platform.
pub(crate) fn target(&self) -> Option<String> {
self.cargo_args.compilation_args.target(self.is_web())
Expand Down
34 changes: 13 additions & 21 deletions src/commands/run/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
pub use self::args::*;
#[cfg(feature = "web")]
use crate::web::run::run_web;
use crate::{bin_target::select_run_binary, config::CliConfig, external_cli::cargo};
use crate::{commands::get_package, config::CliConfig, external_cli::cargo};

mod args;

Expand All @@ -15,39 +15,31 @@ mod args;
pub fn run(args: &mut RunArgs) -> anyhow::Result<()> {
let metadata = cargo::metadata::metadata()?;

let mut bin_target = select_run_binary(
let package = get_package(
&metadata,
args.cargo_args.package_args.package.as_deref(),
args.cargo_args.target_args.bin.as_deref(),
args.cargo_args.target_args.example.as_deref(),
args.target().as_deref(),
args.profile(),
args.cargo_args.package_args.package.as_ref(),
true,
)?;

let mut config = CliConfig::for_package(
&metadata,
bin_target.package,
args.is_web(),
args.is_release(),
)?;
// apply the package specific config, otherwise use the default config (this happens when
// `bevy build` was called from a workspace root with no package selection (we do not support
// workspace config at the moment).
let mut config = if let Some(package) = package {
CliConfig::for_package(&metadata, package, args.is_web(), args.is_release())?
} else {
CliConfig::default()
};

// Read config files hierarchically from the current directory, merge them,
// apply environment variables, and resolve relative paths.
let cargo_config = cargo_config2::Config::load()?;
config.append_cargo_config_rustflags(args.target(), &cargo_config)?;

args.apply_config(&config);
// Update the artifact directory based on the config, e.g. in case the `target` changed
bin_target.update_artifact_directory(
&metadata.target_directory,
args.target().as_deref(),
args.profile(),
args.cargo_args.target_args.example.is_some(),
);

#[cfg(feature = "web")]
if args.is_web() {
return run_web(args, &metadata, &bin_target);
return run_web(args, &metadata);
}

let cargo_args = args.cargo_args_builder();
Expand Down
1 change: 1 addition & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
//! The library backend for the prototype Bevy CLI.

#[cfg(feature = "web")]
pub(crate) mod bin_target;
pub mod commands;
pub(crate) mod config;
Expand Down
Loading