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 // Ref: tools.mk (irrelevant lines omitted):
84 //
85 // ```makefile
86 // ifdef IS_MSVC
87 // OUT_EXE=-Fe:`cygpath -w $(TMPDIR)/$(call BIN,$(1))` \
88 // -Fo:`cygpath -w $(TMPDIR)/$(1).obj`
89 // else
90 // OUT_EXE=-o $(TMPDIR)/$(1)
91 // endif
92 // ```
93
94 let mut path = std::path::PathBuf::from(name);
95
96 if is_msvc() {
97 path.set_extension("exe");
98 let fe_path = path.clone();
99 path.set_extension("");
100 path.set_extension("obj");
101 let fo_path = path;
102 self.cmd.arg(format!("-Fe:{}", fe_path.to_str().unwrap()));
103 self.cmd.arg(format!("-Fo:{}", fo_path.to_str().unwrap()));
104 } else {
105 self.cmd.arg("-o");
106 self.cmd.arg(name);
107 }
108
109 self
110 }
111
112 /// Specify path of the output binary.
113 pub fn output<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
114 self.cmd.arg("-o");
115 self.cmd.arg(path.as_ref());
116 self
117 }
118
119 /// Optimize the output.
120 /// Equivalent to `-O3` for GNU-compatible linkers or `-O2` for MSVC linkers.
121 pub fn optimize(&mut self) -> &mut Self {
122 if is_msvc() {
123 self.cmd.arg("-O2");
124 } else {
125 self.cmd.arg("-O3");
126 }
127 self
128 }
129}