Skip to content

Commit 97481bd

Browse files
committed
Support autobins and target renaming [lib] and [[bin]]
1 parent 28f5e91 commit 97481bd

File tree

7 files changed

+87
-19
lines changed

7 files changed

+87
-19
lines changed

Cargo.toml

+9
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,15 @@ edition = "2018"
66
description = "Library for creating cargo subcommands."
77
repository = "https://github.com/dvc94ch/cargo-subcommand"
88
license = "ISC"
9+
# autobins = false
10+
11+
[lib]
12+
name = "cargo_subcommand"
13+
# name = "foo"
14+
15+
[[bin]]
16+
name = "cargo-subcommand"
17+
path = "src/main.rs"
918

1019
[features]
1120
default = ["clap"]

README.md

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
# cargo-subcommand library for building subcommands
2-
Is used by `cargo-ndk` and `cargo-flutter`.
1+
# `cargo-subcommand` library for building subcommands
2+
3+
Is used by [`cargo-apk`](https://crates.io/crates/cargo-apk) and `cargo-flutter`.
34

45
# License
56
Copyright 2020 David Craven <david@craven.ch>

src/args.rs

+9
Original file line numberDiff line numberDiff line change
@@ -130,4 +130,13 @@ impl Args {
130130
Profile::Dev
131131
}
132132
}
133+
134+
/// Returns [`true`] when one or more target selection options are active.
135+
/// This is generally used to deduce whether to default to binary and
136+
/// library targets, in accordance with [`cargo build`].
137+
///
138+
/// [`cargo build`]: https://doc.rust-lang.org/cargo/commands/cargo-build.html#target-selection
139+
pub fn specific_target_selected(&self) -> bool {
140+
self.lib || self.bins || self.examples || !self.bin.is_empty() || !self.example.is_empty()
141+
}
133142
}

src/artifact.rs

+7-9
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,6 @@ pub enum Artifact {
66
Example(String),
77
}
88

9-
impl AsRef<Path> for Artifact {
10-
fn as_ref(&self) -> &Path {
11-
Path::new(match self {
12-
Self::Root(_) => "",
13-
Self::Example(_) => "examples",
14-
})
15-
}
16-
}
17-
189
impl Artifact {
1910
pub fn name(&self) -> &str {
2011
match self {
@@ -23,6 +14,13 @@ impl Artifact {
2314
}
2415
}
2516

17+
pub fn build_dir(&self) -> &'static Path {
18+
Path::new(match self {
19+
Self::Root(_) => "",
20+
Self::Example(_) => "examples",
21+
})
22+
}
23+
2624
pub fn file_name(&self, ty: CrateType, target: &str) -> String {
2725
match ty {
2826
CrateType::Bin => {

src/manifest.rs

+19
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@ use std::path::Path;
66
pub struct Manifest {
77
pub workspace: Option<Workspace>,
88
pub package: Option<Package>,
9+
pub lib: Option<Lib>,
10+
#[serde(default, rename = "bin")]
11+
pub bins: Vec<Bin>,
912
}
1013

1114
impl Manifest {
@@ -20,7 +23,23 @@ pub struct Workspace {
2023
pub members: Vec<String>,
2124
}
2225

26+
const fn default_true() -> bool {
27+
true
28+
}
29+
2330
#[derive(Debug, Deserialize)]
2431
pub struct Package {
2532
pub name: String,
33+
#[serde(default = "default_true")]
34+
pub autobins: bool,
35+
}
36+
37+
#[derive(Debug, Deserialize)]
38+
pub struct Lib {
39+
pub name: Option<String>,
40+
}
41+
42+
#[derive(Debug, Deserialize)]
43+
pub struct Bin {
44+
pub name: String,
2645
}

src/subcommand.rs

+39-7
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use crate::args::Args;
22
use crate::artifact::{Artifact, CrateType};
33
use crate::error::Error;
4+
use crate::manifest::Manifest;
45
use crate::profile::Profile;
56
use crate::{utils, LocalizedConfig};
67
use std::io::BufRead;
@@ -35,6 +36,7 @@ impl Subcommand {
3536
"`--exclude` is not supported yet by `cargo-subcommand`"
3637
);
3738
let (manifest_path, package) = utils::find_package(
39+
// TODO: This must be the path to the package already!
3840
&args
3941
.manifest_path
4042
.clone()
@@ -50,6 +52,8 @@ impl Subcommand {
5052
config.set_env_vars().unwrap();
5153
}
5254

55+
let parsed_manifest = Manifest::parse_from_toml(&manifest_path)?;
56+
5357
let target_dir = args
5458
.target_dir
5559
.clone()
@@ -75,6 +79,8 @@ impl Subcommand {
7579
.join(utils::get_target_dir_name(config.as_deref()).unwrap())
7680
});
7781

82+
// https://doc.rust-lang.org/cargo/reference/cargo-targets.html#target-auto-discovery
83+
7884
let mut artifacts = vec![];
7985
if args.examples {
8086
for file in utils::list_rust_files(&root_dir.join("examples"))? {
@@ -85,17 +91,41 @@ impl Subcommand {
8591
artifacts.push(Artifact::Example(example.into()));
8692
}
8793
}
88-
if args.bins {
89-
for file in utils::list_rust_files(&root_dir.join("src").join("bin"))? {
90-
artifacts.push(Artifact::Root(file));
94+
95+
let specific_target_selected = args.specific_target_selected();
96+
97+
// https://doc.rust-lang.org/cargo/reference/cargo-targets.html#binaries
98+
if args.bins || !specific_target_selected {
99+
// Parse all autobins
100+
if parsed_manifest.package.map_or(true, |p| p.autobins) {
101+
// TODO: Autobins can still be "configured" through [[bin]] in the manifest
102+
// and should then NOT end up in the artifacts list twice!
103+
// We should effectively merge those lists here.
104+
for file in utils::list_rust_files(&root_dir.join("src").join("bin"))? {
105+
artifacts.push(Artifact::Root(file));
106+
}
107+
if root_dir.join("src/main.rs").is_file() {
108+
artifacts.push(Artifact::Root(package.clone()));
109+
}
110+
}
111+
112+
// Add all explicitly configured binaries
113+
for bin in parsed_manifest.bins {
114+
artifacts.push(Artifact::Root(bin.name.clone()));
91115
}
92116
} else {
117+
// TODO: Use info from the above if body to validate that these bins exist?
93118
for bin in &args.bin {
94-
artifacts.push(Artifact::Root(bin.into()));
119+
artifacts.push(Artifact::Root(bin.clone()));
95120
}
96121
}
97-
if artifacts.is_empty() {
98-
artifacts.push(Artifact::Root(package.clone()));
122+
if args.lib || !specific_target_selected {
123+
// Add the one and only library target, if it exists
124+
let name = parsed_manifest
125+
.lib
126+
.and_then(|lib| lib.name)
127+
.unwrap_or_else(|| package.clone());
128+
artifacts.push(Artifact::Root(name));
99129
}
100130
let host_triple = Command::new("rustc")
101131
.arg("-vV")
@@ -178,6 +208,8 @@ impl Subcommand {
178208
) -> PathBuf {
179209
let triple = target.unwrap_or_else(|| self.host_triple());
180210
let file_name = artifact.file_name(crate_type, triple);
181-
self.build_dir(target).join(artifact).join(file_name)
211+
self.build_dir(target)
212+
.join(artifact.build_dir())
213+
.join(file_name)
182214
}
183215
}

src/utils.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ pub fn find_package(path: &Path, name: Option<&str>) -> Result<(PathBuf, String)
4040
for manifest_path in path
4141
.ancestors()
4242
.map(|dir| dir.join("Cargo.toml"))
43-
.filter(|dir| dir.exists())
43+
.filter(|manifest| manifest.exists())
4444
{
4545
let manifest = Manifest::parse_from_toml(&manifest_path)?;
4646
if let Some(p) = manifest.package.as_ref() {

0 commit comments

Comments
 (0)