Skip to content

Commit 2818540

Browse files
committed
compiletest: Add support for //@ aux-bin: foo.rs
Which enables ui tests to use auxiliary binaries. See the added self-test for an example.
1 parent 55bba4f commit 2818540

File tree

4 files changed

+83
-20
lines changed

4 files changed

+83
-20
lines changed

src/tools/compiletest/src/header.rs

+15
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ impl HeadersCache {
3636
#[derive(Default)]
3737
pub struct EarlyProps {
3838
pub aux: Vec<String>,
39+
pub aux_bin: Vec<String>,
3940
pub aux_crate: Vec<(String, String)>,
4041
pub revisions: Vec<String>,
4142
}
@@ -59,6 +60,12 @@ impl EarlyProps {
5960
config.push_name_value_directive(ln, directives::AUX_BUILD, &mut props.aux, |r| {
6061
r.trim().to_string()
6162
});
63+
config.push_name_value_directive(
64+
ln,
65+
directives::AUX_BIN,
66+
&mut props.aux_bin,
67+
|r| r.trim().to_string(),
68+
);
6269
config.push_name_value_directive(
6370
ln,
6471
directives::AUX_CRATE,
@@ -95,6 +102,8 @@ pub struct TestProps {
95102
// directory as the test, but for backwards compatibility reasons
96103
// we also check the auxiliary directory)
97104
pub aux_builds: Vec<String>,
105+
// Auxiliary crates that should be compiled as `#![crate_type = "bin"]`.
106+
pub aux_bins: Vec<String>,
98107
// Similar to `aux_builds`, but a list of NAME=somelib.rs of dependencies
99108
// to build and pass with the `--extern` flag.
100109
pub aux_crates: Vec<(String, String)>,
@@ -217,6 +226,7 @@ mod directives {
217226
pub const PRETTY_EXPANDED: &'static str = "pretty-expanded";
218227
pub const PRETTY_MODE: &'static str = "pretty-mode";
219228
pub const PRETTY_COMPARE_ONLY: &'static str = "pretty-compare-only";
229+
pub const AUX_BIN: &'static str = "aux-bin";
220230
pub const AUX_BUILD: &'static str = "aux-build";
221231
pub const AUX_CRATE: &'static str = "aux-crate";
222232
pub const EXEC_ENV: &'static str = "exec-env";
@@ -252,6 +262,7 @@ impl TestProps {
252262
run_flags: None,
253263
pp_exact: None,
254264
aux_builds: vec![],
265+
aux_bins: vec![],
255266
aux_crates: vec![],
256267
revisions: vec![],
257268
rustc_env: vec![("RUSTC_ICE".to_string(), "0".to_string())],
@@ -417,6 +428,9 @@ impl TestProps {
417428
config.push_name_value_directive(ln, AUX_BUILD, &mut self.aux_builds, |r| {
418429
r.trim().to_string()
419430
});
431+
config.push_name_value_directive(ln, AUX_BIN, &mut self.aux_bins, |r| {
432+
r.trim().to_string()
433+
});
420434
config.push_name_value_directive(
421435
ln,
422436
AUX_CRATE,
@@ -683,6 +697,7 @@ pub fn line_directive<'line>(
683697
const KNOWN_DIRECTIVE_NAMES: &[&str] = &[
684698
// tidy-alphabetical-start
685699
"assembly-output",
700+
"aux-bin",
686701
"aux-build",
687702
"aux-crate",
688703
"build-aux-docs",

src/tools/compiletest/src/runtest.rs

+56-20
Original file line numberDiff line numberDiff line change
@@ -82,22 +82,21 @@ fn disable_error_reporting<F: FnOnce() -> R, R>(f: F) -> R {
8282
}
8383

8484
/// The platform-specific library name
85-
fn get_lib_name(lib: &str, aux_type: AuxType) -> String {
85+
fn get_lib_name(lib: &str, aux_type: AuxType) -> Option<String> {
8686
match aux_type {
87+
AuxType::Bin => None,
8788
// In some casess (e.g. MUSL), we build a static
8889
// library, rather than a dynamic library.
8990
// In this case, the only path we can pass
9091
// with '--extern-meta' is the '.rlib' file
91-
AuxType::Lib => format!("lib{}.rlib", lib),
92-
AuxType::Dylib => {
93-
if cfg!(windows) {
94-
format!("{}.dll", lib)
95-
} else if cfg!(target_os = "macos") {
96-
format!("lib{}.dylib", lib)
97-
} else {
98-
format!("lib{}.so", lib)
99-
}
100-
}
92+
AuxType::Lib => Some(format!("lib{}.rlib", lib)),
93+
AuxType::Dylib => Some(if cfg!(windows) {
94+
format!("{}.dll", lib)
95+
} else if cfg!(target_os = "macos") {
96+
format!("lib{}.dylib", lib)
97+
} else {
98+
format!("lib{}.so", lib)
99+
}),
101100
}
102101
}
103102

@@ -2099,19 +2098,36 @@ impl<'test> TestCx<'test> {
20992098
create_dir_all(&aux_dir).unwrap();
21002099
}
21012100

2101+
if !self.props.aux_bins.is_empty() {
2102+
let aux_bin_dir = self.aux_bin_output_dir_name();
2103+
let _ = fs::remove_dir_all(&aux_bin_dir);
2104+
create_dir_all(&aux_bin_dir).unwrap();
2105+
}
2106+
21022107
aux_dir
21032108
}
21042109

21052110
fn build_all_auxiliary(&self, of: &TestPaths, aux_dir: &Path, rustc: &mut Command) {
21062111
for rel_ab in &self.props.aux_builds {
2107-
self.build_auxiliary(of, rel_ab, &aux_dir);
2112+
self.build_auxiliary(of, rel_ab, &aux_dir, false /* is_bin */);
2113+
}
2114+
2115+
for rel_ab in &self.props.aux_bins {
2116+
self.build_auxiliary(of, rel_ab, &aux_dir, true /* is_bin */);
21082117
}
21092118

21102119
for (aux_name, aux_path) in &self.props.aux_crates {
2111-
let aux_type = self.build_auxiliary(of, &aux_path, &aux_dir);
2120+
let aux_type = self.build_auxiliary(of, &aux_path, &aux_dir, false /* is_bin */);
21122121
let lib_name =
21132122
get_lib_name(&aux_path.trim_end_matches(".rs").replace('-', "_"), aux_type);
2114-
rustc.arg("--extern").arg(format!("{}={}/{}", aux_name, aux_dir.display(), lib_name));
2123+
if let Some(lib_name) = lib_name {
2124+
rustc.arg("--extern").arg(format!(
2125+
"{}={}/{}",
2126+
aux_name,
2127+
aux_dir.display(),
2128+
lib_name
2129+
));
2130+
}
21152131
}
21162132
}
21172133

@@ -2130,12 +2146,23 @@ impl<'test> TestCx<'test> {
21302146
}
21312147

21322148
/// Builds an aux dependency.
2133-
///
2134-
/// Returns whether or not it is a dylib.
2135-
fn build_auxiliary(&self, of: &TestPaths, source_path: &str, aux_dir: &Path) -> AuxType {
2149+
fn build_auxiliary(
2150+
&self,
2151+
of: &TestPaths,
2152+
source_path: &str,
2153+
aux_dir: &Path,
2154+
is_bin: bool,
2155+
) -> AuxType {
21362156
let aux_testpaths = self.compute_aux_test_paths(of, source_path);
21372157
let aux_props = self.props.from_aux_file(&aux_testpaths.file, self.revision, self.config);
2138-
let aux_output = TargetLocation::ThisDirectory(aux_dir.to_path_buf());
2158+
let mut aux_dir = aux_dir.to_path_buf();
2159+
if is_bin {
2160+
// On unix, the binary of `auxiliary/foo.rs` will be named
2161+
// `auxiliary/foo` which clashes with the _dir_ `auxiliary/foo`, so
2162+
// put bins in a `bin` subfolder.
2163+
aux_dir.push("bin");
2164+
}
2165+
let aux_output = TargetLocation::ThisDirectory(aux_dir.clone());
21392166
let aux_cx = TestCx {
21402167
config: self.config,
21412168
props: &aux_props,
@@ -2153,14 +2180,16 @@ impl<'test> TestCx<'test> {
21532180
LinkToAux::No,
21542181
Vec::new(),
21552182
);
2156-
aux_cx.build_all_auxiliary(of, aux_dir, &mut aux_rustc);
2183+
aux_cx.build_all_auxiliary(of, &aux_dir, &mut aux_rustc);
21572184

21582185
for key in &aux_props.unset_rustc_env {
21592186
aux_rustc.env_remove(key);
21602187
}
21612188
aux_rustc.envs(aux_props.rustc_env.clone());
21622189

2163-
let (aux_type, crate_type) = if aux_props.no_prefer_dynamic {
2190+
let (aux_type, crate_type) = if is_bin {
2191+
(AuxType::Bin, Some("bin"))
2192+
} else if aux_props.no_prefer_dynamic {
21642193
(AuxType::Dylib, None)
21652194
} else if self.config.target.contains("emscripten")
21662195
|| (self.config.target.contains("musl")
@@ -2678,6 +2707,12 @@ impl<'test> TestCx<'test> {
26782707
.with_extra_extension(self.config.mode.aux_dir_disambiguator())
26792708
}
26802709

2710+
/// Gets the directory where auxiliary binaries are written.
2711+
/// E.g., `/.../testname.revision.mode/auxiliary/bin`.
2712+
fn aux_bin_output_dir_name(&self) -> PathBuf {
2713+
self.aux_output_dir_name().join("bin")
2714+
}
2715+
26812716
/// Generates a unique name for the test, such as `testname.revision.mode`.
26822717
fn output_testname_unique(&self) -> PathBuf {
26832718
output_testname_unique(self.config, self.testpaths, self.safe_revision())
@@ -4829,6 +4864,7 @@ enum LinkToAux {
48294864
}
48304865

48314866
enum AuxType {
4867+
Bin,
48324868
Lib,
48334869
Dylib,
48344870
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
fn main() {
2+
println!("it works");
3+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
//@ ignore-cross-compile because we run the compiled code
2+
//@ aux-bin: print-it-works.rs
3+
//@ run-pass
4+
5+
fn main() {
6+
let stdout =
7+
std::process::Command::new("auxiliary/bin/print-it-works").output().unwrap().stdout;
8+
assert_eq!(stdout, b"it works\n");
9+
}

0 commit comments

Comments
 (0)