Skip to content

Commit

Permalink
Add rustc folder to dynamic linker search path
Browse files Browse the repository at this point in the history
... so that we can run cargo-nextest with proc-macro projects on
Windows.

This commit also adds integration tests for running cargo-nextest for
proc-macro projects.
  • Loading branch information
06393993 committed May 13, 2024
1 parent 1cee49b commit 9890eff
Show file tree
Hide file tree
Showing 21 changed files with 336 additions and 38 deletions.
36 changes: 35 additions & 1 deletion cargo-nextest/src/dispatch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ use std::{
collections::BTreeSet,
env::VarError,
io::{Cursor, Write},
path::PathBuf,
sync::Arc,
};
use swrite::{swrite, SWrite};
Expand Down Expand Up @@ -1009,7 +1010,31 @@ impl BaseApp {
None => {
let target_triple =
discover_target_triple(&cargo_configs, cargo_opts.target.as_deref());
BuildPlatforms::new(target_triple)?
let mut args = vec!["--print", "sysroot"];
if let Some(target_triple) = &target_triple {
args.extend(["--target", target_triple.platform.triple_str()]);
}
let output = duct::cmd(rustc_path().as_str(), args)
.stdout_capture()
.unchecked()
.run()
.ok()
.and_then(|output| {
if output.status.success() {
Some(Cursor::new(output.stdout))
} else {
log::debug!(
"failed to execute sysroot discover command: {}",
output.status
);
log::debug!("stdout:");
log::debug!("{}", String::from_utf8_lossy(&output.stdout));
log::debug!("stderr:");
log::debug!("{}", String::from_utf8_lossy(&output.stderr));
None
}
});
BuildPlatforms::new(output, target_triple)?
}
};

Expand Down Expand Up @@ -2012,6 +2037,15 @@ fn warn_on_err(thing: &str, err: &(dyn std::error::Error)) {
log::warn!("{}", s);
}

fn rustc_path() -> Utf8PathBuf {
match std::env::var_os("RUSTC") {
Some(rustc_path) => PathBuf::from(rustc_path)
.try_into()
.expect("RUSTC env var is not valid UTF-8"),
None => Utf8PathBuf::from("rustc"),
}
}

#[cfg(test)]
mod tests {
use super::*;
Expand Down
4 changes: 4 additions & 0 deletions fixtures/nextest-tests/Cargo.lock

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

1 change: 1 addition & 0 deletions fixtures/nextest-tests/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ members = [
"derive",
"dylib-test",
"with-build-script",
"proc-macro-test"
]

[dependencies]
Expand Down
7 changes: 7 additions & 0 deletions fixtures/nextest-tests/proc-macro-test/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
[package]
name = "proc-macro-test"
version = "0.1.0"
edition = "2021"

[lib]
proc-macro = true
1 change: 1 addition & 0 deletions fixtures/nextest-tests/proc-macro-test/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

16 changes: 15 additions & 1 deletion integration-tests/tests/integration/fixtures.rs
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,7 @@ pub static EXPECTED_LIST: Lazy<Vec<TestInfo>> = Lazy::new(|| {
BuildPlatform::Target,
vec![("tests::test_out_dir_present", false)],
),
TestInfo::new("proc-macro-test", BuildPlatform::Host, vec![]),
]
});

Expand Down Expand Up @@ -379,7 +380,20 @@ pub fn check_list_binaries_output(stdout: &[u8]) {
let result: BinaryListSummary = serde_json::from_slice(stdout).unwrap();

let test_suite = &*EXPECTED_LIST;
assert_eq!(test_suite.len(), result.rust_binaries.len());
let mut expected_binary_ids = test_suite
.iter()
.map(|test_info| test_info.id.clone())
.collect::<Vec<_>>();
expected_binary_ids.sort();
let mut actual_binary_ids = result.rust_binaries.keys().collect::<Vec<_>>();
actual_binary_ids.sort();
assert_eq!(
test_suite.len(),
result.rust_binaries.len(),
"expected rust binaries:\n{:?}\nactual rust binaries\n{:?}",
expected_binary_ids,
actual_binary_ids
);

for test in test_suite {
let entry = result
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
source: integration-tests/tests/integration/main.rs
expression: output.stderr_as_str()
---
Archiving 16 binaries (including 2 non-test binaries), 2 build script output directories, 2 linked paths, and 7 extra paths to <archive-file>
Archiving 17 binaries (including 2 non-test binaries), 2 build script output directories, 2 linked paths, and 7 extra paths to <archive-file>
Warning ignoring extra path `<target-dir>/excluded-dir` because it does not exist
Warning ignoring extra path `<target-dir>/depth-0-dir` specified with depth 0 since it is a directory
Warning ignoring extra path `<target-dir>/file_that_does_not_exist.txt` because it does not exist
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
source: integration-tests/tests/integration/main.rs
expression: output.stderr_as_str()
---
Archiving 16 binaries (including 2 non-test binaries), 2 build script output directories, 2 linked paths, and 7 extra paths to <archive-file>
Archiving 17 binaries (including 2 non-test binaries), 2 build script output directories, 2 linked paths, and 7 extra paths to <archive-file>
Warning ignoring extra path `<target-dir>/excluded-dir` because it does not exist
Warning ignoring extra path `<target-dir>/depth-0-dir` specified with depth 0 since it is a directory
Warning ignoring extra path `<target-dir>/file_that_does_not_exist.txt` because it does not exist
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
source: integration-tests/tests/integration/main.rs
expression: output.stderr_as_str()
---
Archiving 16 binaries (including 2 non-test binaries), 2 build script output directories, 2 linked paths, and 1 extra path to <archive-file>
Archiving 17 binaries (including 2 non-test binaries), 2 build script output directories, 2 linked paths, and 1 extra path to <archive-file>
error: error creating archive `<archive-file>`

Caused by:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
source: integration-tests/tests/integration/main.rs
expression: output.stderr_as_str()
---
Archiving 16 binaries (including 2 non-test binaries), 2 build script output directories, and 2 linked paths to <archive-file>
Archiving 17 binaries (including 2 non-test binaries), 2 build script output directories, and 2 linked paths to <archive-file>
Warning linked path `<target-dir>/debug/build/<cdylib-link-hash>/does-not-exist` not found, requested by: cdylib-link v0.1.0
(this is a bug in this crate that should be fixed)
Archived <file-count> files to <archive-file> in <duration>
6 changes: 6 additions & 0 deletions nextest-metadata/src/test_list.rs
Original file line number Diff line number Diff line change
Expand Up @@ -519,6 +519,12 @@ pub struct BuildPlatformsSummary {
/// In the future, this will become a list of target triples once multiple `--target` arguments
/// are supported.
pub target: PlatformSummary,

/// The sysroot for the target platform.
///
/// Empty if fialed to discover.
#[serde(default)]
pub sysroot: Option<Utf8PathBuf>,
}

/// Information about the kind of a Rust non-test binary.
Expand Down
12 changes: 8 additions & 4 deletions nextest-runner/src/config/test_helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,14 +84,18 @@ pub(super) fn binary_query<'a>(
}

pub(super) fn build_platforms() -> BuildPlatforms {
BuildPlatforms::new_with_host(
Platform::new("x86_64-unknown-linux-gnu", TargetFeatures::Unknown).unwrap(),
Some(TargetTriple {
BuildPlatforms {
host: Platform::new("x86_64-unknown-linux-gnu", TargetFeatures::Unknown).unwrap(),
target: Some(TargetTriple {
platform: Platform::new("aarch64-apple-darwin", TargetFeatures::Unknown).unwrap(),
source: TargetTripleSource::Env,
location: TargetDefinitionLocation::Builtin,
}),
)
sysroot: Some(
Utf8PathBuf::from("/home/fake/.rustup/toolchains/stable-x86_64-unknown-linux-gnu")
.into_boxed_path(),
),
}
}

pub(super) fn test_group(name: &str) -> TestGroup {
Expand Down
8 changes: 6 additions & 2 deletions nextest-runner/src/list/binary_list.rs
Original file line number Diff line number Diff line change
Expand Up @@ -398,6 +398,7 @@ mod tests {
use indoc::indoc;
use maplit::btreeset;
use pretty_assertions::assert_eq;
use std::io::Cursor;
use target_spec::{Platform, TargetFeatures};

#[test]
Expand Down Expand Up @@ -426,7 +427,9 @@ mod tests {
source: TargetTripleSource::CliOption,
location: TargetDefinitionLocation::Builtin,
};
let build_platforms = BuildPlatforms::new(Some(fake_triple)).unwrap();
let fake_sysroot = "/home/fake/.rustup/toolchains/stable-x86_64-unknown-linux-gnu";
let build_platforms =
BuildPlatforms::new(Some(Cursor::new(fake_sysroot)), Some(fake_triple)).unwrap();

let mut rust_build_meta = RustBuildMeta::new("/fake/target", build_platforms);
rust_build_meta
Expand Down Expand Up @@ -504,7 +507,8 @@ mod tests {
"target": {
"triple": "x86_64-unknown-linux-gnu",
"target-features": "unknown"
}
},
"sysroot": "/home/fake/.rustup/toolchains/stable-x86_64-unknown-linux-gnu"
}
],
"target-platform": "x86_64-unknown-linux-gnu"
Expand Down
65 changes: 65 additions & 0 deletions nextest-runner/src/list/rust_build_meta.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use crate::{
reuse_build::PathMapper,
};
use camino::Utf8PathBuf;
use itertools::Itertools;
use nextest_metadata::{RustBuildMetaSummary, RustNonTestBinarySummary};
use std::{
collections::{BTreeMap, BTreeSet},
Expand Down Expand Up @@ -95,6 +96,7 @@ impl RustBuildMeta<TestListState> {
build_platforms: BuildPlatforms {
host: Platform::current().unwrap(),
target: None,
sysroot: None,
},
}
}
Expand All @@ -109,6 +111,9 @@ impl RustBuildMeta<TestListState> {
// FIXME/HELP WANTED: get the rustc sysroot library path here.
// See https://github.com/nextest-rs/nextest/issues/267.

if self.build_platforms.sysroot.is_none() {
log::warn!("failed to detect the rustc sysroot, may fail to list or run tests");
}
// Cargo puts linked paths before base output directories.
self.linked_paths
.keys()
Expand All @@ -127,6 +132,15 @@ impl RustBuildMeta<TestListState> {
// This is the order paths are added in by Cargo.
[with_deps, abs_base]
}))
// Add the rustc path to the search paths to run procudure macro binaries. See
// details in https://github.com/nextest-rs/nextest/issues/1493.
.chain(
self.build_platforms
.sysroot
.as_ref()
.map(|sysroot| sysroot.to_path_buf().join("bin")),
)
.unique()
.collect()
}
}
Expand Down Expand Up @@ -169,3 +183,54 @@ impl<State> RustBuildMeta<State> {
}
}
}

#[cfg(test)]
mod tests {
use super::*;
use std::{fs, io::Cursor};

#[test]
fn test_dylib_paths_should_include_rustc_dir() {
let rust_sysroot = Utf8PathBuf::from("/fake/rustc/sysroot");
let rustc_dir = rust_sysroot.join("bin");

let rust_build_meta = RustBuildMeta {
build_platforms: BuildPlatforms::new(Some(Cursor::new(rust_sysroot.as_str())), None)
.expect("Should create BuildPlatforms with fake sysroot successfully"),
..RustBuildMeta::empty()
};
let dylib_paths = rust_build_meta.dylib_paths();

assert!(
dylib_paths.contains(&rustc_dir),
"{:?} should contain {}",
dylib_paths,
rustc_dir
);
}

#[test]
fn test_dylib_paths_should_not_contain_duplicate_paths() {
let tmpdir = camino_tempfile::tempdir().expect("should create temp dir successfully");
let rust_sysroot = tmpdir.path().to_path_buf();
let rustc_dir = rust_sysroot.join("bin");
fs::create_dir(&rustc_dir)
.expect("should create bin directory in the tmp folder successfully");

let rust_build_meta = RustBuildMeta {
target_directory: rust_sysroot.clone(),
linked_paths: [(Utf8PathBuf::from("bin"), Default::default())].into(),
base_output_directories: [Utf8PathBuf::from("bin")].into(),
build_platforms: BuildPlatforms::new(Some(Cursor::new(rust_sysroot.as_str())), None)
.expect("Should create BuildPlatforms with fake sysroot successfully"),
..RustBuildMeta::empty()
};
let dylib_paths = rust_build_meta.dylib_paths();

assert!(
dylib_paths.clone().into_iter().all_unique(),
"{:?} should not contain duplicate paths",
dylib_paths
);
}
}
9 changes: 6 additions & 3 deletions nextest-runner/src/list/test_list.rs
Original file line number Diff line number Diff line change
Expand Up @@ -968,7 +968,7 @@ mod tests {
use nextest_filtering::FilteringExpr;
use nextest_metadata::{FilterMatch, MismatchReason};
use pretty_assertions::assert_eq;
use std::iter;
use std::{io::Cursor, iter};
use target_spec::Platform;

#[test]
Expand Down Expand Up @@ -1033,7 +1033,9 @@ mod tests {
source: TargetTripleSource::CliOption,
location: TargetDefinitionLocation::Builtin,
};
let build_platforms = BuildPlatforms::new(Some(fake_triple)).unwrap();
let fake_sysroot = "/home/fake/.rustup/toolchains/stable-x86_64-unknown-linux-gnu";
let build_platforms =
BuildPlatforms::new(Some(Cursor::new(fake_sysroot)), Some(fake_triple)).unwrap();
let fake_env = EnvironmentMap::empty();
let rust_build_meta =
RustBuildMeta::new("/fake", build_platforms).map_paths(&PathMapper::noop());
Expand Down Expand Up @@ -1144,7 +1146,8 @@ mod tests {
"target": {
"triple": "aarch64-unknown-linux-gnu",
"target-features": "unknown"
}
},
"sysroot": "/home/fake/.rustup/toolchains/stable-x86_64-unknown-linux-gnu"
}
],
"target-platform": "aarch64-unknown-linux-gnu"
Expand Down
Loading

0 comments on commit 9890eff

Please sign in to comment.