Skip to content

Commit f592dd9

Browse files
committed
Compiletest: Add proc-macro header
This adds a proc-macro header to make it easier to depend on a proc-macro, and remove some of the boilerplate necessary.
1 parent 39cb338 commit f592dd9

File tree

4 files changed

+66
-23
lines changed

4 files changed

+66
-23
lines changed

src/tools/compiletest/src/directive-list.rs

+1
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,7 @@ const KNOWN_DIRECTIVE_NAMES: &[&str] = &[
215215
"pp-exact",
216216
"pretty-compare-only",
217217
"pretty-mode",
218+
"proc-macro",
218219
"reference",
219220
"regex-error-pattern",
220221
"remap-src-base",

src/tools/compiletest/src/header.rs

+1
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,7 @@ mod directives {
221221
pub const AUX_BIN: &'static str = "aux-bin";
222222
pub const AUX_BUILD: &'static str = "aux-build";
223223
pub const AUX_CRATE: &'static str = "aux-crate";
224+
pub const PROC_MACRO: &'static str = "proc-macro";
224225
pub const AUX_CODEGEN_BACKEND: &'static str = "aux-codegen-backend";
225226
pub const EXEC_ENV: &'static str = "exec-env";
226227
pub const RUSTC_ENV: &'static str = "rustc-env";

src/tools/compiletest/src/header/auxiliary.rs

+8-3
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
use std::iter;
55

66
use crate::common::Config;
7-
use crate::header::directives::{AUX_BIN, AUX_BUILD, AUX_CODEGEN_BACKEND, AUX_CRATE};
7+
use crate::header::directives::{AUX_BIN, AUX_BUILD, AUX_CODEGEN_BACKEND, AUX_CRATE, PROC_MACRO};
88

99
/// Properties parsed from `aux-*` test directives.
1010
#[derive(Clone, Debug, Default)]
@@ -17,6 +17,8 @@ pub(crate) struct AuxProps {
1717
/// Similar to `builds`, but a list of NAME=somelib.rs of dependencies
1818
/// to build and pass with the `--extern` flag.
1919
pub(crate) crates: Vec<(String, String)>,
20+
/// Same as `builds`, but for proc-macros.
21+
pub(crate) proc_macros: Vec<String>,
2022
/// Similar to `builds`, but also uses the resulting dylib as a
2123
/// `-Zcodegen-backend` when compiling the test file.
2224
pub(crate) codegen_backend: Option<String>,
@@ -26,26 +28,29 @@ impl AuxProps {
2628
/// Yields all of the paths (relative to `./auxiliary/`) that have been
2729
/// specified in `aux-*` directives for this test.
2830
pub(crate) fn all_aux_path_strings(&self) -> impl Iterator<Item = &str> {
29-
let Self { builds, bins, crates, codegen_backend } = self;
31+
let Self { builds, bins, crates, proc_macros, codegen_backend } = self;
3032

3133
iter::empty()
3234
.chain(builds.iter().map(String::as_str))
3335
.chain(bins.iter().map(String::as_str))
3436
.chain(crates.iter().map(|(_, path)| path.as_str()))
37+
.chain(proc_macros.iter().map(String::as_str))
3538
.chain(codegen_backend.iter().map(String::as_str))
3639
}
3740
}
3841

3942
/// If the given test directive line contains an `aux-*` directive, parse it
4043
/// and update [`AuxProps`] accordingly.
4144
pub(super) fn parse_and_update_aux(config: &Config, ln: &str, aux: &mut AuxProps) {
42-
if !ln.starts_with("aux-") {
45+
if !(ln.starts_with("aux-") || ln.starts_with("proc-macro")) {
4346
return;
4447
}
4548

4649
config.push_name_value_directive(ln, AUX_BUILD, &mut aux.builds, |r| r.trim().to_string());
4750
config.push_name_value_directive(ln, AUX_BIN, &mut aux.bins, |r| r.trim().to_string());
4851
config.push_name_value_directive(ln, AUX_CRATE, &mut aux.crates, parse_aux_crate);
52+
config
53+
.push_name_value_directive(ln, PROC_MACRO, &mut aux.proc_macros, |r| r.trim().to_string());
4954
if let Some(r) = config.parse_name_value_directive(ln, AUX_CODEGEN_BACKEND) {
5055
aux.codegen_backend = Some(r.trim().to_owned());
5156
}

src/tools/compiletest/src/runtest.rs

+56-20
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ fn get_lib_name(name: &str, aux_type: AuxType) -> Option<String> {
102102
// In this case, the only path we can pass
103103
// with '--extern-meta' is the '.rlib' file
104104
AuxType::Lib => Some(format!("lib{name}.rlib")),
105-
AuxType::Dylib => Some(dylib_name(name)),
105+
AuxType::Dylib | AuxType::ProcMacro => Some(dylib_name(name)),
106106
}
107107
}
108108

@@ -1097,7 +1097,9 @@ impl<'test> TestCx<'test> {
10971097
}
10981098

10991099
fn has_aux_dir(&self) -> bool {
1100-
!self.props.aux.builds.is_empty() || !self.props.aux.crates.is_empty()
1100+
!self.props.aux.builds.is_empty()
1101+
|| !self.props.aux.crates.is_empty()
1102+
|| !self.props.aux.proc_macros.is_empty()
11011103
}
11021104

11031105
fn aux_output_dir(&self) -> PathBuf {
@@ -1118,31 +1120,48 @@ impl<'test> TestCx<'test> {
11181120

11191121
fn build_all_auxiliary(&self, of: &TestPaths, aux_dir: &Path, rustc: &mut Command) {
11201122
for rel_ab in &self.props.aux.builds {
1121-
self.build_auxiliary(of, rel_ab, &aux_dir, false /* is_bin */);
1123+
self.build_auxiliary(of, rel_ab, &aux_dir, None);
11221124
}
11231125

11241126
for rel_ab in &self.props.aux.bins {
1125-
self.build_auxiliary(of, rel_ab, &aux_dir, true /* is_bin */);
1127+
self.build_auxiliary(of, rel_ab, &aux_dir, Some(AuxType::Bin));
11261128
}
11271129

1130+
let path_to_crate_name = |path: &str| -> String {
1131+
path.rsplit_once('/')
1132+
.map_or(path, |(_, tail)| tail)
1133+
.trim_end_matches(".rs")
1134+
.replace('-', "_")
1135+
};
1136+
1137+
let add_extern =
1138+
|rustc: &mut Command, aux_name: &str, aux_path: &str, aux_type: AuxType| {
1139+
let lib_name = get_lib_name(&path_to_crate_name(aux_path), aux_type);
1140+
if let Some(lib_name) = lib_name {
1141+
rustc.arg("--extern").arg(format!(
1142+
"{}={}/{}",
1143+
aux_name,
1144+
aux_dir.display(),
1145+
lib_name
1146+
));
1147+
}
1148+
};
1149+
11281150
for (aux_name, aux_path) in &self.props.aux.crates {
1129-
let aux_type = self.build_auxiliary(of, &aux_path, &aux_dir, false /* is_bin */);
1130-
let lib_name =
1131-
get_lib_name(&aux_path.trim_end_matches(".rs").replace('-', "_"), aux_type);
1132-
if let Some(lib_name) = lib_name {
1133-
rustc.arg("--extern").arg(format!(
1134-
"{}={}/{}",
1135-
aux_name,
1136-
aux_dir.display(),
1137-
lib_name
1138-
));
1139-
}
1151+
let aux_type = self.build_auxiliary(of, &aux_path, &aux_dir, None);
1152+
add_extern(rustc, aux_name, aux_path, aux_type);
1153+
}
1154+
1155+
for proc_macro in &self.props.aux.proc_macros {
1156+
self.build_auxiliary(of, proc_macro, &aux_dir, Some(AuxType::ProcMacro));
1157+
let crate_name = path_to_crate_name(proc_macro);
1158+
add_extern(rustc, &crate_name, proc_macro, AuxType::ProcMacro);
11401159
}
11411160

11421161
// Build any `//@ aux-codegen-backend`, and pass the resulting library
11431162
// to `-Zcodegen-backend` when compiling the test file.
11441163
if let Some(aux_file) = &self.props.aux.codegen_backend {
1145-
let aux_type = self.build_auxiliary(of, aux_file, aux_dir, false);
1164+
let aux_type = self.build_auxiliary(of, aux_file, aux_dir, None);
11461165
if let Some(lib_name) = get_lib_name(aux_file.trim_end_matches(".rs"), aux_type) {
11471166
let lib_path = aux_dir.join(&lib_name);
11481167
rustc.arg(format!("-Zcodegen-backend={}", lib_path.display()));
@@ -1209,17 +1228,23 @@ impl<'test> TestCx<'test> {
12091228
}
12101229

12111230
/// Builds an aux dependency.
1231+
///
1232+
/// If `aux_type` is `None`, then this will determine the aux-type automatically.
12121233
fn build_auxiliary(
12131234
&self,
12141235
of: &TestPaths,
12151236
source_path: &str,
12161237
aux_dir: &Path,
1217-
is_bin: bool,
1238+
aux_type: Option<AuxType>,
12181239
) -> AuxType {
12191240
let aux_testpaths = self.compute_aux_test_paths(of, source_path);
1220-
let aux_props = self.props.from_aux_file(&aux_testpaths.file, self.revision, self.config);
1241+
let mut aux_props =
1242+
self.props.from_aux_file(&aux_testpaths.file, self.revision, self.config);
1243+
if aux_type == Some(AuxType::ProcMacro) {
1244+
aux_props.force_host = true;
1245+
}
12211246
let mut aux_dir = aux_dir.to_path_buf();
1222-
if is_bin {
1247+
if aux_type == Some(AuxType::Bin) {
12231248
// On unix, the binary of `auxiliary/foo.rs` will be named
12241249
// `auxiliary/foo` which clashes with the _dir_ `auxiliary/foo`, so
12251250
// put bins in a `bin` subfolder.
@@ -1250,8 +1275,12 @@ impl<'test> TestCx<'test> {
12501275
aux_rustc.env_remove(key);
12511276
}
12521277

1253-
let (aux_type, crate_type) = if is_bin {
1278+
let (aux_type, crate_type) = if aux_type == Some(AuxType::Bin) {
12541279
(AuxType::Bin, Some("bin"))
1280+
} else if aux_type == Some(AuxType::ProcMacro) {
1281+
(AuxType::ProcMacro, Some("proc-macro"))
1282+
} else if aux_type.is_some() {
1283+
panic!("aux_type {aux_type:?} not expected");
12551284
} else if aux_props.no_prefer_dynamic {
12561285
(AuxType::Dylib, None)
12571286
} else if self.config.target.contains("emscripten")
@@ -1287,6 +1316,11 @@ impl<'test> TestCx<'test> {
12871316
aux_rustc.args(&["--crate-type", crate_type]);
12881317
}
12891318

1319+
if aux_type == AuxType::ProcMacro {
1320+
// For convenience, but this only works on 2018.
1321+
aux_rustc.args(&["--extern", "proc_macro"]);
1322+
}
1323+
12901324
aux_rustc.arg("-L").arg(&aux_dir);
12911325

12921326
let auxres = aux_cx.compose_and_run(
@@ -2768,8 +2802,10 @@ enum LinkToAux {
27682802
No,
27692803
}
27702804

2805+
#[derive(Debug, PartialEq)]
27712806
enum AuxType {
27722807
Bin,
27732808
Lib,
27742809
Dylib,
2810+
ProcMacro,
27752811
}

0 commit comments

Comments
 (0)