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