Skip to content

compiletest: Add support for //@ aux-bin: foo.rs #122634

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Mar 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions src/tools/compiletest/src/header.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ impl HeadersCache {
#[derive(Default)]
pub struct EarlyProps {
pub aux: Vec<String>,
pub aux_bin: Vec<String>,
pub aux_crate: Vec<(String, String)>,
pub revisions: Vec<String>,
}
Expand All @@ -59,6 +60,12 @@ impl EarlyProps {
config.push_name_value_directive(ln, directives::AUX_BUILD, &mut props.aux, |r| {
r.trim().to_string()
});
config.push_name_value_directive(
ln,
directives::AUX_BIN,
&mut props.aux_bin,
|r| r.trim().to_string(),
);
config.push_name_value_directive(
ln,
directives::AUX_CRATE,
Expand Down Expand Up @@ -95,6 +102,8 @@ pub struct TestProps {
// directory as the test, but for backwards compatibility reasons
// we also check the auxiliary directory)
pub aux_builds: Vec<String>,
// Auxiliary crates that should be compiled as `#![crate_type = "bin"]`.
pub aux_bins: Vec<String>,
// Similar to `aux_builds`, but a list of NAME=somelib.rs of dependencies
// to build and pass with the `--extern` flag.
pub aux_crates: Vec<(String, String)>,
Expand Down Expand Up @@ -217,6 +226,7 @@ mod directives {
pub const PRETTY_EXPANDED: &'static str = "pretty-expanded";
pub const PRETTY_MODE: &'static str = "pretty-mode";
pub const PRETTY_COMPARE_ONLY: &'static str = "pretty-compare-only";
pub const AUX_BIN: &'static str = "aux-bin";
pub const AUX_BUILD: &'static str = "aux-build";
pub const AUX_CRATE: &'static str = "aux-crate";
pub const EXEC_ENV: &'static str = "exec-env";
Expand Down Expand Up @@ -252,6 +262,7 @@ impl TestProps {
run_flags: None,
pp_exact: None,
aux_builds: vec![],
aux_bins: vec![],
aux_crates: vec![],
revisions: vec![],
rustc_env: vec![("RUSTC_ICE".to_string(), "0".to_string())],
Expand Down Expand Up @@ -417,6 +428,9 @@ impl TestProps {
config.push_name_value_directive(ln, AUX_BUILD, &mut self.aux_builds, |r| {
r.trim().to_string()
});
config.push_name_value_directive(ln, AUX_BIN, &mut self.aux_bins, |r| {
r.trim().to_string()
});
config.push_name_value_directive(
ln,
AUX_CRATE,
Expand Down Expand Up @@ -683,6 +697,7 @@ pub fn line_directive<'line>(
const KNOWN_DIRECTIVE_NAMES: &[&str] = &[
// tidy-alphabetical-start
"assembly-output",
"aux-bin",
"aux-build",
"aux-crate",
"build-aux-docs",
Expand Down
100 changes: 71 additions & 29 deletions src/tools/compiletest/src/runtest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,21 +82,21 @@ fn disable_error_reporting<F: FnOnce() -> R, R>(f: F) -> R {
}

/// The platform-specific library name
pub fn get_lib_name(lib: &str, dylib: bool) -> String {
// In some casess (e.g. MUSL), we build a static
// library, rather than a dynamic library.
// In this case, the only path we can pass
// with '--extern-meta' is the '.lib' file
if !dylib {
return format!("lib{}.rlib", lib);
}

if cfg!(windows) {
format!("{}.dll", lib)
} else if cfg!(target_os = "macos") {
format!("lib{}.dylib", lib)
} else {
format!("lib{}.so", lib)
fn get_lib_name(lib: &str, aux_type: AuxType) -> Option<String> {
match aux_type {
AuxType::Bin => None,
// In some cases (e.g. MUSL), we build a static
// library, rather than a dynamic library.
// In this case, the only path we can pass
// with '--extern-meta' is the '.rlib' file
AuxType::Lib => Some(format!("lib{}.rlib", lib)),
AuxType::Dylib => Some(if cfg!(windows) {
format!("{}.dll", lib)
} else if cfg!(target_os = "macos") {
format!("lib{}.dylib", lib)
} else {
format!("lib{}.so", lib)
}),
}
}

Expand Down Expand Up @@ -2098,19 +2098,36 @@ impl<'test> TestCx<'test> {
create_dir_all(&aux_dir).unwrap();
}

if !self.props.aux_bins.is_empty() {
let aux_bin_dir = self.aux_bin_output_dir_name();
let _ = fs::remove_dir_all(&aux_bin_dir);
create_dir_all(&aux_bin_dir).unwrap();
}

aux_dir
}

fn build_all_auxiliary(&self, of: &TestPaths, aux_dir: &Path, rustc: &mut Command) {
for rel_ab in &self.props.aux_builds {
self.build_auxiliary(of, rel_ab, &aux_dir);
self.build_auxiliary(of, rel_ab, &aux_dir, false /* is_bin */);
}

for rel_ab in &self.props.aux_bins {
self.build_auxiliary(of, rel_ab, &aux_dir, true /* is_bin */);
}

for (aux_name, aux_path) in &self.props.aux_crates {
let is_dylib = self.build_auxiliary(of, &aux_path, &aux_dir);
let aux_type = self.build_auxiliary(of, &aux_path, &aux_dir, false /* is_bin */);
let lib_name =
get_lib_name(&aux_path.trim_end_matches(".rs").replace('-', "_"), is_dylib);
rustc.arg("--extern").arg(format!("{}={}/{}", aux_name, aux_dir.display(), lib_name));
get_lib_name(&aux_path.trim_end_matches(".rs").replace('-', "_"), aux_type);
if let Some(lib_name) = lib_name {
rustc.arg("--extern").arg(format!(
"{}={}/{}",
aux_name,
aux_dir.display(),
lib_name
));
}
}
}

Expand All @@ -2129,12 +2146,23 @@ impl<'test> TestCx<'test> {
}

/// Builds an aux dependency.
///
/// Returns whether or not it is a dylib.
fn build_auxiliary(&self, of: &TestPaths, source_path: &str, aux_dir: &Path) -> bool {
fn build_auxiliary(
&self,
of: &TestPaths,
source_path: &str,
aux_dir: &Path,
is_bin: bool,
) -> AuxType {
let aux_testpaths = self.compute_aux_test_paths(of, source_path);
let aux_props = self.props.from_aux_file(&aux_testpaths.file, self.revision, self.config);
let aux_output = TargetLocation::ThisDirectory(aux_dir.to_path_buf());
let mut aux_dir = aux_dir.to_path_buf();
if is_bin {
// On unix, the binary of `auxiliary/foo.rs` will be named
// `auxiliary/foo` which clashes with the _dir_ `auxiliary/foo`, so
// put bins in a `bin` subfolder.
aux_dir.push("bin");
}
let aux_output = TargetLocation::ThisDirectory(aux_dir.clone());
let aux_cx = TestCx {
config: self.config,
props: &aux_props,
Expand All @@ -2152,15 +2180,17 @@ impl<'test> TestCx<'test> {
LinkToAux::No,
Vec::new(),
);
aux_cx.build_all_auxiliary(of, aux_dir, &mut aux_rustc);
aux_cx.build_all_auxiliary(of, &aux_dir, &mut aux_rustc);

for key in &aux_props.unset_rustc_env {
aux_rustc.env_remove(key);
}
aux_rustc.envs(aux_props.rustc_env.clone());

let (dylib, crate_type) = if aux_props.no_prefer_dynamic {
(true, None)
let (aux_type, crate_type) = if is_bin {
(AuxType::Bin, Some("bin"))
} else if aux_props.no_prefer_dynamic {
(AuxType::Dylib, None)
} else if self.config.target.contains("emscripten")
|| (self.config.target.contains("musl")
&& !aux_props.force_host
Expand All @@ -2185,9 +2215,9 @@ impl<'test> TestCx<'test> {
// Coverage tests want static linking by default so that coverage
// mappings in auxiliary libraries can be merged into the final
// executable.
(false, Some("lib"))
(AuxType::Lib, Some("lib"))
} else {
(true, Some("dylib"))
(AuxType::Dylib, Some("dylib"))
};

if let Some(crate_type) = crate_type {
Expand All @@ -2211,7 +2241,7 @@ impl<'test> TestCx<'test> {
&auxres,
);
}
dylib
aux_type
}

fn read2_abbreviated(&self, child: Child) -> (Output, Truncated) {
Expand Down Expand Up @@ -2677,6 +2707,12 @@ impl<'test> TestCx<'test> {
.with_extra_extension(self.config.mode.aux_dir_disambiguator())
}

/// Gets the directory where auxiliary binaries are written.
/// E.g., `/.../testname.revision.mode/auxiliary/bin`.
fn aux_bin_output_dir_name(&self) -> PathBuf {
self.aux_output_dir_name().join("bin")
}

/// Generates a unique name for the test, such as `testname.revision.mode`.
fn output_testname_unique(&self) -> PathBuf {
output_testname_unique(self.config, self.testpaths, self.safe_revision())
Expand Down Expand Up @@ -4826,3 +4862,9 @@ enum LinkToAux {
Yes,
No,
}

enum AuxType {
Bin,
Lib,
Dylib,
}
3 changes: 3 additions & 0 deletions tests/ui/compiletest-self-test/auxiliary/print-it-works.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
fn main() {
println!("it works");
}
9 changes: 9 additions & 0 deletions tests/ui/compiletest-self-test/test-aux-bin.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
//@ ignore-cross-compile because we run the compiled code
//@ aux-bin: print-it-works.rs
//@ run-pass

fn main() {
let stdout =
std::process::Command::new("auxiliary/bin/print-it-works").output().unwrap().stdout;
assert_eq!(stdout, b"it works\n");
}
Loading