Skip to content

Commit 4e9e6ca

Browse files
committed
output configured targets
1 parent bb3df1b commit 4e9e6ca

File tree

7 files changed

+156
-4
lines changed

7 files changed

+156
-4
lines changed

src/bin/commands/list_targets.rs

+131
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
use std::str::FromStr;
2+
3+
use clap::Args;
4+
use cross::docker;
5+
use cross::shell::MessageInfo;
6+
7+
#[derive(Args, Debug)]
8+
pub struct ListTargets {
9+
/// Format version
10+
#[clap(long)]
11+
format_version: Option<FormatVersion>,
12+
/// Coloring: auto, always, never
13+
#[clap(long)]
14+
pub color: Option<String>,
15+
}
16+
17+
#[derive(Debug, Clone, Copy, serde::Serialize)]
18+
pub enum FormatVersion {
19+
#[serde(rename = "1")]
20+
One,
21+
}
22+
23+
#[derive(Debug, thiserror::Error)]
24+
#[error("invalid format version")]
25+
pub struct FormatVersionError;
26+
27+
impl FromStr for FormatVersion {
28+
type Err = FormatVersionError;
29+
30+
fn from_str(s: &str) -> Result<Self, Self::Err> {
31+
match s {
32+
"1" => Ok(FormatVersion::One),
33+
_ => Err(FormatVersionError),
34+
}
35+
}
36+
}
37+
38+
#[derive(serde::Serialize)]
39+
pub struct Output {
40+
format_version: FormatVersion,
41+
#[serde(flatten)]
42+
other: serde_json::Value,
43+
}
44+
45+
impl ListTargets {
46+
pub fn verbose(&self) -> bool {
47+
false
48+
}
49+
50+
pub fn quiet(&self) -> bool {
51+
false
52+
}
53+
54+
pub fn color(&self) -> Option<&str> {
55+
self.color.as_deref()
56+
}
57+
58+
pub fn run(self, msg_info: &mut MessageInfo) -> cross::Result<()> {
59+
let toml = if let Some(metadata) = cross::cargo_metadata_with_args(None, None, msg_info)? {
60+
cross::toml(&metadata, msg_info)?
61+
} else {
62+
None
63+
};
64+
65+
let config = cross::config::Config::new(toml);
66+
let version = if let Some(version) = self.format_version {
67+
version
68+
} else {
69+
msg_info.warn(
70+
"please specify `--format-version` flag explicitly to avoid compatibility problems",
71+
)?;
72+
FormatVersion::One
73+
};
74+
let data = match version {
75+
FormatVersion::One => self.run_v1(&config, msg_info)?,
76+
};
77+
println!(
78+
"{}",
79+
serde_json::to_string_pretty(&Output {
80+
format_version: version,
81+
other: data,
82+
})?
83+
);
84+
Ok(())
85+
}
86+
87+
pub fn run_v1(
88+
self,
89+
config: &cross::config::Config,
90+
_msg_info: &mut MessageInfo,
91+
) -> cross::Result<serde_json::Value> {
92+
#[derive(serde::Serialize)]
93+
struct Target {
94+
triplet: String,
95+
platforms: Vec<String>,
96+
}
97+
let mut targets: Vec<_> = cross::docker::PROVIDED_IMAGES
98+
.iter()
99+
.filter_map(|i| {
100+
Some(Target {
101+
triplet: Some(i.name).filter(|i| *i != "zig")?.to_owned(),
102+
platforms: i.platforms.iter().map(ToString::to_string).collect(),
103+
})
104+
})
105+
.collect();
106+
if let Some(toml_targets) = config.targets() {
107+
for (target, config) in toml_targets {
108+
if targets.iter().any(|t| t.triplet == target.triple()) {
109+
continue;
110+
}
111+
targets.push(Target {
112+
triplet: target.triple().to_owned(),
113+
platforms: config
114+
.image
115+
.as_ref()
116+
.map(|i| {
117+
i.toolchain
118+
.iter()
119+
.map(ToString::to_string)
120+
.collect::<Vec<_>>()
121+
})
122+
.filter(|v| !v.is_empty())
123+
.unwrap_or_else(|| vec![docker::ImagePlatform::DEFAULT.to_string()]),
124+
})
125+
}
126+
}
127+
Ok(serde_json::json!({
128+
"targets": targets,
129+
}))
130+
}
131+
}

src/bin/commands/mod.rs

+2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
mod clean;
22
mod containers;
33
mod images;
4+
mod list_targets;
45

56
pub use self::clean::*;
67
pub use self::containers::*;
78
pub use self::images::*;
9+
pub use self::list_targets::*;

src/bin/cross-util.rs

+6
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@ enum Commands {
3939
Containers(commands::Containers),
4040
/// Clean all cross data in local storage.
4141
Clean(commands::Clean),
42+
/// List all cross targets, including those specialized for the current project (if in one).
43+
ListTargets(commands::ListTargets),
4244
}
4345

4446
fn is_toolchain(toolchain: &str) -> cross::Result<Toolchain> {
@@ -103,6 +105,10 @@ pub fn main() -> cross::Result<()> {
103105
let engine = get_engine!(args, false, msg_info)?;
104106
args.run(engine, &mut msg_info)?;
105107
}
108+
Commands::ListTargets(args) => {
109+
let mut msg_info = get_msg_info!(args)?;
110+
args.run(&mut msg_info)?;
111+
}
106112
}
107113

108114
Ok(())

src/config.rs

+7
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,13 @@ impl Config {
212212
}
213213
}
214214

215+
/// Grabs all defined targets in toml
216+
pub fn targets(
217+
&self,
218+
) -> Option<impl Iterator<Item = (&Target, &crate::cross_toml::CrossTargetConfig)>> {
219+
self.toml.as_ref().map(|toml| toml.targets.iter())
220+
}
221+
215222
pub fn confusable_target(&self, target: &Target, msg_info: &mut MessageInfo) -> Result<()> {
216223
if let Some(keys) = self.toml.as_ref().map(|t| t.targets.keys()) {
217224
for mentioned_target in keys {

src/cross_toml.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ pub struct CrossTargetConfig {
4343
#[serde(default, deserialize_with = "opt_string_bool_or_struct")]
4444
zig: Option<CrossZigConfig>,
4545
#[serde(default, deserialize_with = "opt_string_or_struct")]
46-
image: Option<PossibleImage>,
46+
pub image: Option<PossibleImage>,
4747
#[serde(default, deserialize_with = "opt_string_or_struct")]
4848
dockerfile: Option<CrossTargetDockerfileConfig>,
4949
#[serde(default, deserialize_with = "opt_string_or_string_vec")]

src/docker/image.rs

+6
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,12 @@ impl Serialize for ImagePlatform {
155155
}
156156
}
157157

158+
impl std::fmt::Display for ImagePlatform {
159+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
160+
self.serialize(f)
161+
}
162+
}
163+
158164
impl std::str::FromStr for ImagePlatform {
159165
type Err = eyre::Report;
160166
// [os/arch[/variant]=]toolchain

src/lib.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -279,13 +279,13 @@ impl Target {
279279
triple: TargetTriple::DEFAULT,
280280
};
281281

282-
fn new_built_in(triple: &str) -> Self {
282+
pub fn new_built_in(triple: &str) -> Self {
283283
Target::BuiltIn {
284284
triple: triple.into(),
285285
}
286286
}
287287

288-
fn new_custom(triple: &str) -> Self {
288+
pub fn new_custom(triple: &str) -> Self {
289289
Target::Custom {
290290
triple: triple.into(),
291291
}
@@ -861,7 +861,7 @@ macro_rules! commit_info {
861861
///
862862
/// The values from `CROSS_CONFIG` or `Cross.toml` are concatenated with the package
863863
/// metadata in `Cargo.toml`, with `Cross.toml` having the highest priority.
864-
fn toml(metadata: &CargoMetadata, msg_info: &mut MessageInfo) -> Result<Option<CrossToml>> {
864+
pub fn toml(metadata: &CargoMetadata, msg_info: &mut MessageInfo) -> Result<Option<CrossToml>> {
865865
let root = &metadata.workspace_root;
866866
let cross_config_path = match env::var("CROSS_CONFIG") {
867867
Ok(var) => PathBuf::from(var),

0 commit comments

Comments
 (0)