Skip to content

Commit e6985fb

Browse files
authored
Consider default-members when resolving the binary to run (#477)
# Objective Fixes #443. Cargo allows you to use `default-members` to define the default package to search for binaries in within a workspace. The Bevy CLI didn't consider this field, resulting in divergent behavior in comparison to `cargo`. To avoid confusion, we always want to behave like `cargo` where possible. # Solution Now that we use the `cargo_metadata` crate, we can use some helpers to pick the packages to search the binary in. We are now respecting the default workspace members. Note that this also now respects the location where you execute the command in. If you are located directly in a package, that package is now picked by default (same as `cargo`) and no longer the other defaults defined in the workspace. # Testing 1. Install the CLI from this branch: ``` cargo install --git https://github.com/TheBevyFlock/bevy_cli --branch 443-fix-binary-resulution --locked bevy_cli ``` 3. You can use <https://github.com/TimJentzsch/bevy_complex_repo> for testing, check the new `default_members` workspace. Compare which package `cargo run` and `bevy run` executes. They should now match up.
1 parent edb69bd commit e6985fb

File tree

1 file changed

+29
-20
lines changed

1 file changed

+29
-20
lines changed

src/bin_target.rs

Lines changed: 29 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@ pub struct BinTarget<'p> {
2121
/// The `--package` arg narrows down the search space to the given package,
2222
/// while the `--bin` and `--example` args determine the binary target within the selected packages.
2323
///
24-
/// If the search couldn't be narrowed down to a single binary,
25-
/// the `default_run` option is taken into account.
24+
/// From the `Cargo.toml`, the `default-members` workspace option
25+
/// and the `default-run` package option are taken into account.
2626
///
2727
/// The path to the compiled binary is determined via the compilation target and profile.
2828
pub(crate) fn select_run_binary<'p>(
@@ -33,29 +33,35 @@ pub(crate) fn select_run_binary<'p>(
3333
compile_target: Option<&str>,
3434
compile_profile: &str,
3535
) -> anyhow::Result<BinTarget<'p>> {
36-
// Determine which packages the binary could be in
36+
let workspace_packages = metadata.workspace_packages();
37+
38+
// Narrow down the packages that the binary could be contained in:
39+
// - If `--package=name` is specified, look for that specific package
40+
// - If `default-members` is defined in the workspace, consider only these packages
41+
// - Otherwise, consider all packages in the current workspace
3742
let packages = if let Some(package_name) = package_name {
38-
let package = metadata
39-
.packages
43+
let package = workspace_packages
4044
.iter()
41-
.find(|package| {
42-
// Only consider packages in the current workspace and with the correct name
43-
metadata.workspace_members.contains(&package.id)
44-
&& package.name.as_str() == package_name
45-
})
45+
.find(|package| package.name.as_str() == package_name)
4646
.ok_or_else(|| anyhow::anyhow!("Failed to find package {package_name}"))?;
47-
vec![package]
47+
vec![*package]
4848
} else {
49-
metadata
50-
.packages
51-
.iter()
52-
// Only consider packages in the current workspace
53-
.filter(|package| metadata.workspace_members.contains(&package.id))
54-
.collect()
49+
let default_packages = metadata.workspace_default_packages();
50+
51+
if default_packages.is_empty() {
52+
workspace_packages
53+
} else {
54+
default_packages
55+
}
5556
};
5657

5758
let mut is_example = false;
5859

60+
// Find the binary in the specified packages:
61+
// - If `--bin=name` is specified, look for that specific binary
62+
// - If `--example=name` is specified, look for that specific example
63+
// - If only one binary is available, take that one
64+
// - Otherwise, take the `default-run` binary, if specified
5965
let (target, package) = if let Some(bin_name) = bin_name {
6066
// The user specified a concrete binary
6167
let bins: Vec<_> = packages
@@ -137,19 +143,22 @@ pub(crate) fn select_run_binary<'p>(
137143

138144
if default_runs.is_empty() {
139145
anyhow::bail!(
140-
"There are multiple binaries available, try specifying one with --bin or define `default_run` in the Cargo.toml"
146+
"There are multiple binaries available, try one of the following:
147+
- add `--bin` or `--package` after `bevy run` to specify which binary or package to run,
148+
- define `default-run` in the Cargo.toml to define the default binary that should be executed in a package,
149+
- define `default-members` in the Cargo.toml of your workspace to define the default package to pick the binary from."
141150
);
142151
} else if default_runs.len() > 1 {
143152
anyhow::bail!(
144-
"Found multiple `default_run` definitions, I don't know which one to pick!"
153+
"Found multiple `default-run` definitions, I don't know which one to pick!"
145154
);
146155
}
147156

148157
let default_run = default_runs[0];
149158
*bins
150159
.iter()
151160
.find(|(bin, _)| bin.name == *default_run)
152-
.ok_or_else(|| anyhow::anyhow!("Didn't find `default_run` binary {default_run}"))?
161+
.ok_or_else(|| anyhow::anyhow!("Didn't find `default-run` binary {default_run}"))?
153162
}
154163
};
155164

0 commit comments

Comments
 (0)