run_make_support/external_deps/c_cxx_compiler/
cc.rs

1use std::path::Path;
2
3use crate::command::Command;
4use crate::{env_var, is_msvc};
5
6/// Construct a new platform-specific C compiler invocation.
7///
8/// WARNING: This means that what flags are accepted by the underlying C compiler is
9/// platform- AND compiler-specific. Consult the relevant docs for `gcc`, `clang` and `mvsc`.
10#[track_caller]
11pub fn cc() -> Cc {
12    Cc::new()
13}
14
15/// Construct a new platform-specific CXX compiler invocation.
16/// CXX_DEFAULT_FLAGS is passed from compiletest.
17#[track_caller]
18pub fn cxx() -> Cc {
19    Cc::new_cxx()
20}
21
22/// A platform-specific C compiler invocation builder. The specific C compiler used is
23/// passed down from compiletest.
24#[derive(Debug)]
25#[must_use]
26pub struct Cc {
27    cmd: Command,
28}
29
30crate::macros::impl_common_helpers!(Cc);
31
32impl Cc {
33    /// Construct a new platform-specific C compiler invocation.
34    ///
35    /// WARNING: This means that what flags are accepted by the underlying C compile is
36    /// platform- AND compiler-specific. Consult the relevant docs for `gcc`, `clang` and `mvsc`.
37    #[track_caller]
38    pub fn new() -> Self {
39        let compiler = env_var("CC");
40
41        let mut cmd = Command::new(compiler);
42
43        let default_cflags = env_var("CC_DEFAULT_FLAGS");
44        for flag in default_cflags.split(char::is_whitespace) {
45            cmd.arg(flag);
46        }
47
48        Self { cmd }
49    }
50
51    /// Construct a new platform-specific CXX compiler invocation.
52    /// CXX_DEFAULT_FLAGS is passed from compiletest.
53    #[track_caller]
54    pub fn new_cxx() -> Self {
55        let compiler = env_var("CXX");
56
57        let mut cmd = Command::new(compiler);
58
59        let default_cflags = env_var("CXX_DEFAULT_FLAGS");
60        for flag in default_cflags.split(char::is_whitespace) {
61            cmd.arg(flag);
62        }
63
64        Self { cmd }
65    }
66
67    /// Specify path of the input file.
68    pub fn input<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
69        self.cmd.arg(path.as_ref());
70        self
71    }
72
73    /// Adds directories to the list that the linker searches for libraries.
74    /// Equivalent to `-L`.
75    pub fn library_search_path<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
76        self.cmd.arg("-L");
77        self.cmd.arg(path.as_ref());
78        self
79    }
80
81    /// Specify `-o` or `-Fe`/`-Fo` depending on platform/compiler.
82    pub fn out_exe(&mut self, name: &str) -> &mut Self {
83        let mut path = std::path::PathBuf::from(name);
84
85        if is_msvc() {
86            path.set_extension("exe");
87            let fe_path = path.clone();
88            path.set_extension("");
89            path.set_extension("obj");
90            let fo_path = path;
91            self.cmd.arg(format!("-Fe:{}", fe_path.to_str().unwrap()));
92            self.cmd.arg(format!("-Fo:{}", fo_path.to_str().unwrap()));
93        } else {
94            self.cmd.arg("-o");
95            self.cmd.arg(name);
96        }
97
98        self
99    }
100
101    /// Specify path of the output binary.
102    pub fn output<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
103        self.cmd.arg("-o");
104        self.cmd.arg(path.as_ref());
105        self
106    }
107
108    /// Optimize the output.
109    /// Equivalent to `-O3` for GNU-compatible linkers or `-O2` for MSVC linkers.
110    pub fn optimize(&mut self) -> &mut Self {
111        if is_msvc() {
112            self.cmd.arg("-O2");
113        } else {
114            self.cmd.arg("-O3");
115        }
116        self
117    }
118}