Skip to content

Commit

Permalink
[nextest-runner] compute target triple eagerly
Browse files Browse the repository at this point in the history
We currently only parse the build platform once it gets to the target
runner. In the future, we'll want to use host and target platform in
more places. Parse the target triple and run it through target-spec
eagerly.

Also do some initial prep work for multiple `--target` support.
  • Loading branch information
sunshowers committed Oct 22, 2022
1 parent 28d0efb commit 555fa98
Show file tree
Hide file tree
Showing 16 changed files with 208 additions and 75 deletions.
4 changes: 3 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions cargo-nextest/src/dispatch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -974,7 +974,7 @@ impl BaseApp {
.map_err(|err| {
ExpectedError::argument_json_parse_error("binaries-metadata", path, err)
})?;
Arc::new(BinaryList::from_summary(binary_list))
Arc::new(BinaryList::from_summary(binary_list)?)
}
None => {
let target_triple =
Expand Down Expand Up @@ -1291,7 +1291,7 @@ fn discover_target_triple(
Ok(Some(triple)) => {
log::debug!(
"using target triple `{}` defined by `{}`",
triple.triple,
triple.platform.triple_str(),
triple.source
);
Some(triple)
Expand Down
10 changes: 10 additions & 0 deletions cargo-nextest/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,11 @@ pub enum ExpectedError {
#[source]
err: guppy::Error,
},
#[error("rust build meta parse error")]
RustBuildMetaParseError {
#[from]
err: RustBuildMetaParseError,
},
#[error("error parsing Cargo messages")]
FromMessagesError {
#[from]
Expand Down Expand Up @@ -297,6 +302,7 @@ impl ExpectedError {
| Self::ArgumentFileReadError { .. }
| Self::UnknownArchiveFormat { .. }
| Self::ArchiveExtractError { .. }
| Self::RustBuildMetaParseError { .. }
| Self::PathMapperConstructError { .. }
| Self::ArgumentJsonParseError { .. }
| Self::TestRunnerBuildError { .. }
Expand Down Expand Up @@ -440,6 +446,10 @@ impl ExpectedError {
);
Some(err as &dyn Error)
}
Self::RustBuildMetaParseError { err } => {
log::error!("error parsing Rust build metadata");
Some(err as &dyn Error)
}
Self::ArgumentJsonParseError {
arg_name,
file_name,
Expand Down
13 changes: 13 additions & 0 deletions nextest-metadata/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,18 @@
# Changelog

## Unreleased

### Added

- `RustBuildMetaSummary` has a new `target-platforms` field, which records information about a list
of cross-compilation target platforms. This is to prepare for future support for multiple
`--target` arguments ([#537]).

This field is optional, which means that the minimum supported nextest version hasn't been bumped
with this release.

[#537]: https://github.com/nextest-rs/nextest/issues/537

## [0.6.0] - 2022-08-17

### Added
Expand Down
1 change: 1 addition & 0 deletions nextest-metadata/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ rust-version = "1.62"
camino = { version = "1.1.1", features = ["serde1"] }
serde = { version = "1.0.146", features = ["derive"] }
serde_json = "1.0.86"
target-spec = { version = "1.2.0", features = ["summaries"] }
nextest-workspace-hack = { version = "0.1", path = "../workspace-hack" }

[dev-dependencies]
Expand Down
25 changes: 24 additions & 1 deletion nextest-metadata/src/test_list.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ use std::{
path::PathBuf,
process::Command,
};
use target_spec::summaries::PlatformSummary;

/// Command builder for `cargo nextest list`.
#[derive(Clone, Debug, Default)]
Expand Down Expand Up @@ -272,7 +273,14 @@ pub struct RustBuildMetaSummary {
/// Linked paths, relative to the target directory.
pub linked_paths: BTreeSet<Utf8PathBuf>,

/// The target platform used while compiling the Rust artifacts
/// The target platforms used while compiling the Rust artifacts.
#[serde(default)]
pub target_platforms: Vec<PlatformSummary>,

/// A deprecated form of the target platform used for cross-compilation, if any.
///
/// This is no longer used by nextest, but is maintained for compatibility with older versions
/// which used to generate this.
#[serde(default)]
pub target_platform: Option<String>,
}
Expand Down Expand Up @@ -485,7 +493,22 @@ mod tests {
non_test_binaries: BTreeMap::new(),
linked_paths: BTreeSet::new(),
target_platform: None,
target_platforms: vec![],
}; "no target platform")]
#[test_case(r#"{
"target-directory": "/foo",
"base-output-directories": [],
"non-test-binaries": {},
"linked-paths": [],
"target-platform": "x86_64-unknown-linux-gnu"
}"#, RustBuildMetaSummary {
target_directory: "/foo".into(),
base_output_directories: BTreeSet::new(),
non_test_binaries: BTreeMap::new(),
linked_paths: BTreeSet::new(),
target_platform: Some("x86_64-unknown-linux-gnu".to_owned()),
target_platforms: vec![],
}; "single target platform specified")]
fn test_deserialize_old_rust_build_meta(input: &str, expected: RustBuildMetaSummary) {
let build_meta: RustBuildMetaSummary =
serde_json::from_str(input).expect("input deserialized correctly");
Expand Down
2 changes: 1 addition & 1 deletion nextest-runner/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ shell-words = "1.1.0"
strip-ansi-escapes = "0.1.1"
tar = "0.4.38"
# For cfg expression evaluation for [target.'cfg()'] expressions
target-spec = "1.2.0"
target-spec = { version = "1.2.0", features = ["summaries"] }
tempfile = "3.3.0"
thiserror = "1.0.37"
# For parsing of .cargo/config.toml files
Expand Down
103 changes: 72 additions & 31 deletions nextest-runner/src/cargo_config/target_triple.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@ use crate::{
errors::TargetTripleError,
};
use std::fmt;
use target_spec::Platform;
use target_spec::{summaries::PlatformSummary, Platform, TargetFeatures};

/// Represents a target triple that's being cross-compiled against.
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct TargetTriple {
/// The target triple being built.
pub triple: String,
/// The target platform being built.
pub platform: Platform,

/// The source the triple came from.
pub source: TargetTripleSource,
Expand All @@ -23,12 +23,12 @@ impl TargetTriple {
/// cargo-nextest represents the host triple with `None` during runtime.
/// However the build-metadata might be used on a system with a different host triple.
/// Therefore the host triple is detected if `target_triple` is `None`
pub fn serialize(target_triple: Option<&TargetTriple>) -> Option<String> {
pub fn serialize(target_triple: Option<&TargetTriple>) -> Option<PlatformSummary> {
if let Some(target) = &target_triple {
Some(target.triple.clone())
Some(target.platform.to_summary())
} else {
match Platform::current() {
Ok(host) => Some(host.triple_str().to_owned()),
Ok(host) => Some(host.to_summary()),
Err(err) => {
log::warn!(
"failed to detect host target: {err}!\n cargo nextest may use the wrong test runner for this archive."
Expand All @@ -39,13 +39,33 @@ impl TargetTriple {
}
}

/// Converts a `String` that was output by `TargetTriple::serialize` back to a target triple.
/// This target triple is assumed to orginiate from a build-metadata config.
pub fn deserialize(target_triple: Option<String>) -> Option<TargetTriple> {
Some(TargetTriple {
triple: target_triple?,
source: TargetTripleSource::Metadata,
})
/// Converts a `PlatformSummary` that was output by `TargetTriple::serialize` back to a target triple.
/// This target triple is assumed to originate from a build-metadata config.
pub fn deserialize(
platform: Option<PlatformSummary>,
) -> Result<Option<TargetTriple>, target_spec::Error> {
platform
.map(|platform| {
Ok(TargetTriple {
platform: platform.to_platform()?,
source: TargetTripleSource::Metadata,
})
})
.transpose()
}

/// Converts a string that was output by older versions of nextest back to a target triple.
pub fn deserialize_str(
triple_str: Option<String>,
) -> Result<Option<TargetTriple>, target_spec::Error> {
triple_str
.map(|triple_str| {
Ok(TargetTriple {
platform: Platform::new(triple_str, TargetFeatures::Unknown)?,
source: TargetTripleSource::Metadata,
})
})
.transpose()
}

/// Find the target triple being built.
Expand All @@ -63,8 +83,16 @@ impl TargetTriple {
) -> Result<Option<Self>, TargetTripleError> {
// First, look at the CLI option passed in.
if let Some(triple) = target_cli_option {
let platform =
Platform::new(triple.to_owned(), TargetFeatures::Unknown).map_err(|error| {
TargetTripleError::TargetSpecError {
source: TargetTripleSource::CliOption,
error,
}
})?;
return Ok(Some(TargetTriple {
triple: triple.to_owned(),
// TODO: need to get the minimum set of target features from here
platform,
source: TargetTripleSource::CliOption,
}));
}
Expand All @@ -81,8 +109,14 @@ impl TargetTriple {
let triple = triple_val
.into_string()
.map_err(|_osstr| TargetTripleError::InvalidEnvironmentVar)?;
let platform = Platform::new(triple, TargetFeatures::Unknown).map_err(|error| {
TargetTripleError::TargetSpecError {
source: TargetTripleSource::Env,
error,
}
})?;
Ok(Some(Self {
triple,
platform,
source: TargetTripleSource::Env,
}))
} else {
Expand All @@ -95,13 +129,16 @@ impl TargetTriple {
match discovered_config {
DiscoveredConfig::CliOption { config, source }
| DiscoveredConfig::File { config, source } => {
let source = TargetTripleSource::CargoConfig {
source: source.clone(),
};
if let Some(triple) = &config.build.target {
return Ok(Some(TargetTriple {
triple: triple.to_owned(),
source: TargetTripleSource::CargoConfig {
source: source.clone(),
},
}));
match Platform::new(triple.clone(), TargetFeatures::Unknown) {
Ok(platform) => return Ok(Some(TargetTriple { platform, source })),
Err(error) => {
return Err(TargetTripleError::TargetSpecError { source, error })
}
}
}
}
DiscoveredConfig::Env => {
Expand Down Expand Up @@ -183,7 +220,7 @@ mod tests {
assert_eq!(
find_target_triple(&[], None, &dir_foo_bar_path, &dir_path),
Some(TargetTriple {
triple: "x86_64-unknown-linux-gnu".into(),
platform: platform("x86_64-unknown-linux-gnu"),
source: TargetTripleSource::CargoConfig {
source: CargoConfigSource::File(dir_path.join("foo/bar/.cargo/config.toml")),
},
Expand All @@ -193,7 +230,7 @@ mod tests {
assert_eq!(
find_target_triple(&[], None, &dir_foo_path, &dir_path),
Some(TargetTriple {
triple: "x86_64-pc-windows-msvc".into(),
platform: platform("x86_64-pc-windows-msvc"),
source: TargetTripleSource::CargoConfig {
source: CargoConfigSource::File(dir_path.join("foo/.cargo/config")),
},
Expand All @@ -208,7 +245,7 @@ mod tests {
&dir_path
),
Some(TargetTriple {
triple: "aarch64-unknown-linux-gnu".into(),
platform: platform("aarch64-unknown-linux-gnu"),
source: TargetTripleSource::CargoConfig {
source: CargoConfigSource::CliOption,
},
Expand All @@ -227,7 +264,7 @@ mod tests {
&dir_path
),
Some(TargetTriple {
triple: "aarch64-unknown-linux-gnu".into(),
platform: platform("aarch64-unknown-linux-gnu"),
source: TargetTripleSource::CargoConfig {
source: CargoConfigSource::CliOption,
},
Expand All @@ -243,7 +280,7 @@ mod tests {
&dir_path
),
Some(TargetTriple {
triple: "aarch64-unknown-linux-gnu".into(),
platform: platform("aarch64-unknown-linux-gnu"),
source: TargetTripleSource::CargoConfig {
source: CargoConfigSource::CliOption,
},
Expand All @@ -259,7 +296,7 @@ mod tests {
&dir_path
),
Some(TargetTriple {
triple: "aarch64-pc-windows-msvc".into(),
platform: platform("aarch64-pc-windows-msvc"),
source: TargetTripleSource::Env,
})
);
Expand All @@ -269,7 +306,7 @@ mod tests {
assert_eq!(
find_target_triple(&["extra-config.toml"], None, &dir_foo_path, &dir_path),
Some(TargetTriple {
triple: "aarch64-unknown-linux-gnu".into(),
platform: platform("aarch64-unknown-linux-gnu"),
source: TargetTripleSource::CargoConfig {
source: CargoConfigSource::File(dir_foo_path.join("extra-config.toml")),
},
Expand All @@ -283,7 +320,7 @@ mod tests {
&dir_path
),
Some(TargetTriple {
triple: "aarch64-pc-windows-msvc".into(),
platform: platform("aarch64-pc-windows-msvc"),
source: TargetTripleSource::Env,
})
);
Expand All @@ -298,7 +335,7 @@ mod tests {
&dir_path
),
Some(TargetTriple {
triple: "x86_64-unknown-linux-musl".into(),
platform: platform("x86_64-unknown-linux-musl"),
source: TargetTripleSource::CargoConfig {
source: CargoConfigSource::CliOption,
},
Expand All @@ -315,7 +352,7 @@ mod tests {
&dir_path
),
Some(TargetTriple {
triple: "x86_64-unknown-linux-musl".into(),
platform: platform("x86_64-unknown-linux-musl"),
source: TargetTripleSource::CargoConfig {
source: CargoConfigSource::CliOption,
},
Expand All @@ -341,4 +378,8 @@ mod tests {
std::env::remove_var("CARGO_BUILD_TARGET");
ret
}

fn platform(triple_str: &str) -> Platform {
Platform::new(triple_str.to_owned(), TargetFeatures::Unknown).expect("triple str is valid")
}
}
Loading

0 comments on commit 555fa98

Please sign in to comment.