Skip to content

Commit 1daa7e3

Browse files
Introduce strongly-typed strings, starting with TargetTriple
As discussed, for the price of having to think about `TargetTriple` (like `String`) vs `&TargetTripleRef` (like `&str`), we get: * No accidentally passing some other kind of string to a thing expecting a `TargetTriple` * Serialization/deserialization is still transparent, no schema changes or anything * We can add methods to it (like `is_windows()` in this PR - note that I dream of a `ParsedTargetTriple` in a separate PR) * Those methods are the only place where we check properties of the string (before this commit, we have `.contains("windows")` and `.contains("pc-windows")` for example) * We can "find all references" to the type itself ("where do we care about targets?") * We can "find all references" to `TargetTriple::new` ("where do we build targets from strings?") * We can "find all references" to `TargetTripleRef::as_str` ("where do we coerce it back into a string to pass it to a tool like cargo/wix/etc.) That kind of change is invaluable for me when working on cross-compilation support, and I suspect it will be invaluable for any current and future maintainers of cargo-dist as well (I've used it with great success in other large codebases). You can still treat `TargetTriple` as a string, but it'll be uglier (on purpose). There is however, some ugliness that isn't on purpose. In this changeset I discovered some annoyances around `.iter()` (which returns an `Iterator<Item = &TargetTriple>` instead of an `Iterator<Item = &TargetTripleRef>`. I've added `.as_explicit_ref` to work around those cases. Similarly, calling `Vec<TargetTriple>::contains()` with a `&TargetTripleRef` doesn't work (and you cannot convert a `&TargetTripleRef` into a `&TargetTriple`, the same way you cannot convert a `&str` back into a `&String` - you don't know where it's allocated from!). Finally, I ran into <rust-lang/rfcs#1445> while making this change: there was a big `match` for converting target triples to their display names, and although that works with `&str` constants, it doesn't work with `&TargetTripleRef` constants, due to Rust limitations right now. That explains the lazy_static (which we already depended on transitively, so at least that). I would've used `LazyLock` but our MSRV is currently 1.79 and LazyLock is since 1.80 :(
1 parent 78ccc65 commit 1daa7e3

32 files changed

+873
-432
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ schemars = "0.8.21"
6565
serde_yml = "0.0.10"
6666
spdx = "0.10.6"
6767
base64 = "0.22.1"
68+
lazy_static = "1.4.0"
6869

6970
[workspace.metadata.release]
7071
shared-version = true

axoproject/src/lib.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@ pub mod generic;
2626
#[cfg(feature = "npm-projects")]
2727
pub mod javascript;
2828
pub mod local_repo;
29-
pub mod platforms;
3029
mod repo;
3130
#[cfg(feature = "cargo-projects")]
3231
pub mod rust;

axoproject/src/platforms.rs

Lines changed: 0 additions & 241 deletions
This file was deleted.

cargo-dist-schema/src/lib.rs

Lines changed: 59 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,69 @@
88
//!
99
//! The root type of the schema is [`DistManifest`][].
1010
11+
pub mod macros;
12+
1113
use std::collections::BTreeMap;
1214

1315
use schemars::JsonSchema;
1416
use semver::Version;
1517
use serde::{Deserialize, Serialize};
1618

19+
declare_strongly_typed_string! {
20+
/// A rust target-triple (e.g. "x86_64-pc-windows-msvc")
21+
pub struct TargetTriple => &TargetTripleRef;
22+
}
23+
24+
impl TargetTripleRef {
25+
/// Returns true if this target triple refers to a musl target
26+
pub fn is_musl(&self) -> bool {
27+
self.0.contains("musl")
28+
}
29+
30+
/// Returns true if this target triple refers to a Linux target
31+
pub fn is_linux(&self) -> bool {
32+
self.0.contains("linux")
33+
}
34+
35+
/// Returns true if this target triple refers to an Apple target
36+
pub fn is_apple(&self) -> bool {
37+
self.0.contains("apple")
38+
}
39+
40+
/// Returns true if this target triple refers to a Darwin target
41+
pub fn is_darwin(&self) -> bool {
42+
self.0.contains("darwin")
43+
}
44+
45+
/// Returns true if this target triple refers to a Windows target
46+
pub fn is_windows(&self) -> bool {
47+
self.0.contains("windows")
48+
}
49+
50+
/// Returns true if this target triple refers to an Intel Apple target
51+
pub fn is_x86_64(&self) -> bool {
52+
self.0.contains("x86_64")
53+
}
54+
55+
/// Returns true if this target triple refers to an ARM target
56+
pub fn is_aarch64(&self) -> bool {
57+
self.0.contains("aarch64")
58+
}
59+
60+
//---------------------------
61+
// common combinations
62+
63+
/// Returns true if this target triple refers to a Linux target with MUSL libc
64+
pub fn is_linux_musl(&self) -> bool {
65+
self.0.contains("linux-musl")
66+
}
67+
68+
/// Returns true if this target triple refers to a Windows target with MSVC CRT
69+
pub fn is_windows_msvc(&self) -> bool {
70+
self.0.contains("windows-msvc")
71+
}
72+
}
73+
1774
/// A local system path on the machine cargo-dist was run.
1875
///
1976
/// This is a String because when deserializing this may be a path format from a different OS!
@@ -176,7 +233,7 @@ pub struct AssetInfo {
176233
/// * length 0: not a meaningful question, maybe some static file
177234
/// * length 1: typical of binaries
178235
/// * length 2+: some kind of universal binary
179-
pub target_triples: Vec<String>,
236+
pub target_triples: Vec<TargetTriple>,
180237
/// the linkage of this Asset
181238
pub linkage: Option<Linkage>,
182239
}
@@ -346,7 +403,7 @@ pub struct Artifact {
346403
/// The target triple of the bundle
347404
#[serde(skip_serializing_if = "Vec::is_empty")]
348405
#[serde(default)]
349-
pub target_triples: Vec<String>,
406+
pub target_triples: Vec<TargetTriple>,
350407
/// The location of the artifact on the local system
351408
#[serde(skip_serializing_if = "Option::is_none")]
352409
#[serde(default)]

0 commit comments

Comments
 (0)