compiletest/directives/
auxiliary.rs

1//! Code for dealing with test directives that request an "auxiliary" crate to
2//! be built and made available to the test in some way.
3
4use std::iter;
5
6use camino::Utf8Path;
7
8use super::directives::{AUX_BIN, AUX_BUILD, AUX_CODEGEN_BACKEND, AUX_CRATE, PROC_MACRO};
9use crate::common::Config;
10
11/// Properties parsed from `aux-*` test directives.
12#[derive(Clone, Debug, Default)]
13pub(crate) struct AuxProps {
14    /// Other crates that should be built and made available to this test.
15    /// These are filenames relative to `./auxiliary/` in the test's directory.
16    pub(crate) builds: Vec<String>,
17    /// Auxiliary crates that should be compiled as `#![crate_type = "bin"]`.
18    pub(crate) bins: Vec<String>,
19    /// Similar to `builds`, but a list of NAME=somelib.rs of dependencies
20    /// to build and pass with the `--extern` flag.
21    pub(crate) crates: Vec<(String, String)>,
22    /// Same as `builds`, but for proc-macros.
23    pub(crate) proc_macros: Vec<String>,
24    /// Similar to `builds`, but also uses the resulting dylib as a
25    /// `-Zcodegen-backend` when compiling the test file.
26    pub(crate) codegen_backend: Option<String>,
27}
28
29impl AuxProps {
30    /// Yields all of the paths (relative to `./auxiliary/`) that have been
31    /// specified in `aux-*` directives for this test.
32    pub(crate) fn all_aux_path_strings(&self) -> impl Iterator<Item = &str> {
33        let Self { builds, bins, crates, proc_macros, codegen_backend } = self;
34
35        iter::empty()
36            .chain(builds.iter().map(String::as_str))
37            .chain(bins.iter().map(String::as_str))
38            .chain(crates.iter().map(|(_, path)| path.as_str()))
39            .chain(proc_macros.iter().map(String::as_str))
40            .chain(codegen_backend.iter().map(String::as_str))
41    }
42}
43
44/// If the given test directive line contains an `aux-*` directive, parse it
45/// and update [`AuxProps`] accordingly.
46pub(super) fn parse_and_update_aux(
47    config: &Config,
48    ln: &str,
49    testfile: &Utf8Path,
50    line_number: usize,
51    aux: &mut AuxProps,
52) {
53    if !(ln.starts_with("aux-") || ln.starts_with("proc-macro")) {
54        return;
55    }
56
57    config.push_name_value_directive(ln, AUX_BUILD, testfile, line_number, &mut aux.builds, |r| {
58        r.trim().to_string()
59    });
60    config.push_name_value_directive(ln, AUX_BIN, testfile, line_number, &mut aux.bins, |r| {
61        r.trim().to_string()
62    });
63    config.push_name_value_directive(
64        ln,
65        AUX_CRATE,
66        testfile,
67        line_number,
68        &mut aux.crates,
69        parse_aux_crate,
70    );
71    config.push_name_value_directive(
72        ln,
73        PROC_MACRO,
74        testfile,
75        line_number,
76        &mut aux.proc_macros,
77        |r| r.trim().to_string(),
78    );
79    if let Some(r) =
80        config.parse_name_value_directive(ln, AUX_CODEGEN_BACKEND, testfile, line_number)
81    {
82        aux.codegen_backend = Some(r.trim().to_owned());
83    }
84}
85
86fn parse_aux_crate(r: String) -> (String, String) {
87    let mut parts = r.trim().splitn(2, '=');
88    (
89        parts.next().expect("missing aux-crate name (e.g. log=log.rs)").to_string(),
90        parts.next().expect("missing aux-crate value (e.g. log=log.rs)").to_string(),
91    )
92}