run_make_support/external_deps/
llvm.rs

1use std::path::{Path, PathBuf};
2
3use crate::command::Command;
4use crate::env::env_var;
5
6/// Construct a new `llvm-readobj` invocation with the `GNU` output style.
7/// This assumes that `llvm-readobj` is available at `$LLVM_BIN_DIR/llvm-readobj`.
8#[track_caller]
9pub fn llvm_readobj() -> LlvmReadobj {
10    LlvmReadobj::new()
11}
12
13/// Construct a new `llvm-profdata` invocation. This assumes that `llvm-profdata` is available
14/// at `$LLVM_BIN_DIR/llvm-profdata`.
15#[track_caller]
16pub fn llvm_profdata() -> LlvmProfdata {
17    LlvmProfdata::new()
18}
19
20/// Construct a new `llvm-filecheck` invocation. This assumes that `llvm-filecheck` is available
21/// at `$LLVM_FILECHECK`.
22#[track_caller]
23pub fn llvm_filecheck() -> LlvmFilecheck {
24    LlvmFilecheck::new()
25}
26
27/// Construct a new `llvm-objdump` invocation. This assumes that `llvm-objdump` is available
28/// at `$LLVM_BIN_DIR/llvm-objdump`.
29pub fn llvm_objdump() -> LlvmObjdump {
30    LlvmObjdump::new()
31}
32
33/// Construct a new `llvm-ar` invocation. This assumes that `llvm-ar` is available
34/// at `$LLVM_BIN_DIR/llvm-ar`.
35pub fn llvm_ar() -> LlvmAr {
36    LlvmAr::new()
37}
38
39/// Construct a new `llvm-nm` invocation. This assumes that `llvm-nm` is available
40/// at `$LLVM_BIN_DIR/llvm-nm`.
41pub fn llvm_nm() -> LlvmNm {
42    LlvmNm::new()
43}
44
45/// Construct a new `llvm-bcanalyzer` invocation. This assumes that `llvm-bcanalyzer` is available
46/// at `$LLVM_BIN_DIR/llvm-bcanalyzer`.
47pub fn llvm_bcanalyzer() -> LlvmBcanalyzer {
48    LlvmBcanalyzer::new()
49}
50
51/// Construct a new `llvm-dwarfdump` invocation. This assumes that `llvm-dwarfdump` is available
52/// at `$LLVM_BIN_DIR/llvm-dwarfdump`.
53pub fn llvm_dwarfdump() -> LlvmDwarfdump {
54    LlvmDwarfdump::new()
55}
56
57/// Construct a new `llvm-pdbutil` invocation. This assumes that `llvm-pdbutil` is available
58/// at `$LLVM_BIN_DIR/llvm-pdbutil`.
59pub fn llvm_pdbutil() -> LlvmPdbutil {
60    LlvmPdbutil::new()
61}
62
63/// Construct a new `llvm-dis` invocation. This assumes that `llvm-dis` is available
64/// at `$LLVM_BIN_DIR/llvm-dis`.
65pub fn llvm_dis() -> LlvmDis {
66    LlvmDis::new()
67}
68
69/// Construct a new `llvm-objcopy` invocation. This assumes that `llvm-objcopy` is available
70/// at `$LLVM_BIN_DIR/llvm-objcopy`.
71pub fn llvm_objcopy() -> LlvmObjcopy {
72    LlvmObjcopy::new()
73}
74
75/// A `llvm-readobj` invocation builder.
76#[derive(Debug)]
77#[must_use]
78pub struct LlvmReadobj {
79    cmd: Command,
80}
81
82/// A `llvm-profdata` invocation builder.
83#[derive(Debug)]
84#[must_use]
85pub struct LlvmProfdata {
86    cmd: Command,
87}
88
89/// A `llvm-filecheck` invocation builder.
90#[derive(Debug)]
91#[must_use]
92pub struct LlvmFilecheck {
93    cmd: Command,
94}
95
96/// A `llvm-objdump` invocation builder.
97#[derive(Debug)]
98#[must_use]
99pub struct LlvmObjdump {
100    cmd: Command,
101}
102
103/// A `llvm-ar` invocation builder.
104#[derive(Debug)]
105#[must_use]
106pub struct LlvmAr {
107    cmd: Command,
108}
109
110/// A `llvm-nm` invocation builder.
111#[derive(Debug)]
112#[must_use]
113pub struct LlvmNm {
114    cmd: Command,
115}
116
117/// A `llvm-bcanalyzer` invocation builder.
118#[derive(Debug)]
119#[must_use]
120pub struct LlvmBcanalyzer {
121    cmd: Command,
122}
123
124/// A `llvm-dwarfdump` invocation builder.
125#[derive(Debug)]
126#[must_use]
127pub struct LlvmDwarfdump {
128    cmd: Command,
129}
130
131/// A `llvm-pdbutil` invocation builder.
132#[derive(Debug)]
133#[must_use]
134pub struct LlvmPdbutil {
135    cmd: Command,
136}
137
138/// A `llvm-dis` invocation builder.
139#[derive(Debug)]
140#[must_use]
141pub struct LlvmDis {
142    cmd: Command,
143}
144
145/// A `llvm-objcopy` invocation builder.
146#[derive(Debug)]
147#[must_use]
148pub struct LlvmObjcopy {
149    cmd: Command,
150}
151
152crate::macros::impl_common_helpers!(LlvmReadobj);
153crate::macros::impl_common_helpers!(LlvmProfdata);
154crate::macros::impl_common_helpers!(LlvmFilecheck);
155crate::macros::impl_common_helpers!(LlvmObjdump);
156crate::macros::impl_common_helpers!(LlvmAr);
157crate::macros::impl_common_helpers!(LlvmNm);
158crate::macros::impl_common_helpers!(LlvmBcanalyzer);
159crate::macros::impl_common_helpers!(LlvmDwarfdump);
160crate::macros::impl_common_helpers!(LlvmPdbutil);
161crate::macros::impl_common_helpers!(LlvmDis);
162crate::macros::impl_common_helpers!(LlvmObjcopy);
163
164/// Generate the path to the bin directory of LLVM.
165#[must_use]
166pub fn llvm_bin_dir() -> PathBuf {
167    let llvm_bin_dir = env_var("LLVM_BIN_DIR");
168    PathBuf::from(llvm_bin_dir)
169}
170
171impl LlvmReadobj {
172    /// Construct a new `llvm-readobj` invocation with the `GNU` output style.
173    /// This assumes that `llvm-readobj` is available at `$LLVM_BIN_DIR/llvm-readobj`.
174    #[track_caller]
175    pub fn new() -> Self {
176        let llvm_readobj = llvm_bin_dir().join("llvm-readobj");
177        let cmd = Command::new(llvm_readobj);
178        let mut readobj = Self { cmd };
179        readobj.elf_output_style("GNU");
180        readobj
181    }
182
183    /// Specify the format of the ELF information.
184    ///
185    /// Valid options are `LLVM` (default), `GNU`, and `JSON`.
186    pub fn elf_output_style(&mut self, style: &str) -> &mut Self {
187        self.cmd.arg("--elf-output-style");
188        self.cmd.arg(style);
189        self
190    }
191
192    /// Provide an input file.
193    pub fn input<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
194        self.cmd.arg(path.as_ref());
195        self
196    }
197
198    /// Pass `--file-header` to display file headers.
199    pub fn file_header(&mut self) -> &mut Self {
200        self.cmd.arg("--file-header");
201        self
202    }
203
204    /// Pass `--program-headers` to display program headers.
205    pub fn program_headers(&mut self) -> &mut Self {
206        self.cmd.arg("--program-headers");
207        self
208    }
209
210    /// Pass `--symbols` to display the symbol table, including both local
211    /// and global symbols.
212    pub fn symbols(&mut self) -> &mut Self {
213        self.cmd.arg("--symbols");
214        self
215    }
216
217    /// Pass `--dynamic-table` to display the dynamic symbol table.
218    pub fn dynamic_table(&mut self) -> &mut Self {
219        self.cmd.arg("--dynamic-table");
220        self
221    }
222
223    /// Specify the section to display.
224    pub fn section(&mut self, section: &str) -> &mut Self {
225        self.cmd.arg("--string-dump");
226        self.cmd.arg(section);
227        self
228    }
229}
230
231impl LlvmProfdata {
232    /// Construct a new `llvm-profdata` invocation. This assumes that `llvm-profdata` is available
233    /// at `$LLVM_BIN_DIR/llvm-profdata`.
234    #[track_caller]
235    pub fn new() -> Self {
236        let llvm_profdata = llvm_bin_dir().join("llvm-profdata");
237        let cmd = Command::new(llvm_profdata);
238        Self { cmd }
239    }
240
241    /// Provide an input file.
242    pub fn input<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
243        self.cmd.arg(path.as_ref());
244        self
245    }
246
247    /// Specify the output file path.
248    pub fn output<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
249        self.cmd.arg("-o");
250        self.cmd.arg(path.as_ref());
251        self
252    }
253
254    /// Take several profile data files generated by PGO instrumentation and merge them
255    /// together into a single indexed profile data file.
256    pub fn merge(&mut self) -> &mut Self {
257        self.cmd.arg("merge");
258        self
259    }
260}
261
262impl LlvmFilecheck {
263    /// Construct a new `llvm-filecheck` invocation. This assumes that `llvm-filecheck` is available
264    /// at `$LLVM_FILECHECK`.
265    #[track_caller]
266    pub fn new() -> Self {
267        let llvm_filecheck = env_var("LLVM_FILECHECK");
268        let cmd = Command::new(llvm_filecheck);
269        Self { cmd }
270    }
271
272    /// Provide a buffer representing standard input containing patterns that will be matched
273    /// against the `.patterns(path)` call.
274    pub fn stdin_buf<I: AsRef<[u8]>>(&mut self, input: I) -> &mut Self {
275        self.cmd.stdin_buf(input);
276        self
277    }
278
279    /// Provide the patterns that need to be matched.
280    pub fn patterns<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
281        self.cmd.arg(path.as_ref());
282        self
283    }
284
285    /// `--input-file` option.
286    pub fn input_file<P: AsRef<Path>>(&mut self, input_file: P) -> &mut Self {
287        self.cmd.arg("--input-file");
288        self.cmd.arg(input_file.as_ref());
289        self
290    }
291}
292
293impl LlvmObjdump {
294    /// Construct a new `llvm-objdump` invocation. This assumes that `llvm-objdump` is available
295    /// at `$LLVM_BIN_DIR/llvm-objdump`.
296    pub fn new() -> Self {
297        let llvm_objdump = llvm_bin_dir().join("llvm-objdump");
298        let cmd = Command::new(llvm_objdump);
299        Self { cmd }
300    }
301
302    /// Provide an input file.
303    pub fn input<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
304        self.cmd.arg(path.as_ref());
305        self
306    }
307
308    /// Disassemble all executable sections found in the input files.
309    pub fn disassemble(&mut self) -> &mut Self {
310        self.cmd.arg("-d");
311        self
312    }
313}
314
315impl LlvmAr {
316    /// Construct a new `llvm-ar` invocation. This assumes that `llvm-ar` is available
317    /// at `$LLVM_BIN_DIR/llvm-ar`.
318    pub fn new() -> Self {
319        let llvm_ar = llvm_bin_dir().join("llvm-ar");
320        let cmd = Command::new(llvm_ar);
321        Self { cmd }
322    }
323
324    /// Automatically pass the commonly used arguments `rcus`, used for combining one or more
325    /// input object files into one output static library file.
326    pub fn obj_to_ar(&mut self) -> &mut Self {
327        self.cmd.arg("rcus");
328        self
329    }
330
331    /// Like `obj_to_ar` except creating a thin archive.
332    pub fn obj_to_thin_ar(&mut self) -> &mut Self {
333        self.cmd.arg("rcus").arg("--thin");
334        self
335    }
336
337    /// Extract archive members back to files.
338    pub fn extract(&mut self) -> &mut Self {
339        self.cmd.arg("x");
340        self
341    }
342
343    /// Print the table of contents.
344    pub fn table_of_contents(&mut self) -> &mut Self {
345        self.cmd.arg("t");
346        self
347    }
348
349    /// Provide an output, then an input file. Bundled in one function, as llvm-ar has
350    /// no "--output"-style flag.
351    pub fn output_input(&mut self, out: impl AsRef<Path>, input: impl AsRef<Path>) -> &mut Self {
352        self.cmd.arg(out.as_ref());
353        self.cmd.arg(input.as_ref());
354        self
355    }
356}
357
358impl LlvmNm {
359    /// Construct a new `llvm-nm` invocation. This assumes that `llvm-nm` is available
360    /// at `$LLVM_BIN_DIR/llvm-nm`.
361    pub fn new() -> Self {
362        let llvm_nm = llvm_bin_dir().join("llvm-nm");
363        let cmd = Command::new(llvm_nm);
364        Self { cmd }
365    }
366
367    /// Provide an input file.
368    pub fn input<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
369        self.cmd.arg(path.as_ref());
370        self
371    }
372}
373
374impl LlvmBcanalyzer {
375    /// Construct a new `llvm-bcanalyzer` invocation. This assumes that `llvm-bcanalyzer` is available
376    /// at `$LLVM_BIN_DIR/llvm-bcanalyzer`.
377    pub fn new() -> Self {
378        let llvm_bcanalyzer = llvm_bin_dir().join("llvm-bcanalyzer");
379        let cmd = Command::new(llvm_bcanalyzer);
380        Self { cmd }
381    }
382
383    /// Provide an input file.
384    pub fn input<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
385        self.cmd.arg(path.as_ref());
386        self
387    }
388}
389
390impl LlvmDwarfdump {
391    /// Construct a new `llvm-dwarfdump` invocation. This assumes that `llvm-dwarfdump` is available
392    /// at `$LLVM_BIN_DIR/llvm-dwarfdump`.
393    pub fn new() -> Self {
394        let llvm_dwarfdump = llvm_bin_dir().join("llvm-dwarfdump");
395        let cmd = Command::new(llvm_dwarfdump);
396        Self { cmd }
397    }
398
399    /// Provide an input file.
400    pub fn input<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
401        self.cmd.arg(path.as_ref());
402        self
403    }
404}
405
406impl LlvmPdbutil {
407    /// Construct a new `llvm-pdbutil` invocation. This assumes that `llvm-pdbutil` is available
408    /// at `$LLVM_BIN_DIR/llvm-pdbutil`.
409    pub fn new() -> Self {
410        let llvm_pdbutil = llvm_bin_dir().join("llvm-pdbutil");
411        let cmd = Command::new(llvm_pdbutil);
412        Self { cmd }
413    }
414
415    /// Provide an input file.
416    pub fn input<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
417        self.cmd.arg(path.as_ref());
418        self
419    }
420}
421
422impl LlvmObjcopy {
423    /// Construct a new `llvm-objcopy` invocation. This assumes that `llvm-objcopy` is available
424    /// at `$LLVM_BIN_DIR/llvm-objcopy`.
425    pub fn new() -> Self {
426        let llvm_objcopy = llvm_bin_dir().join("llvm-objcopy");
427        let cmd = Command::new(llvm_objcopy);
428        Self { cmd }
429    }
430
431    /// Dump the contents of `section` into the file at `path`.
432    #[track_caller]
433    pub fn dump_section<S: AsRef<str>, P: AsRef<Path>>(
434        &mut self,
435        section_name: S,
436        path: P,
437    ) -> &mut Self {
438        self.cmd.arg("--dump-section");
439        self.cmd.arg(format!("{}={}", section_name.as_ref(), path.as_ref().to_str().unwrap()));
440        self
441    }
442}
443
444impl LlvmDis {
445    /// Construct a new `llvm-dis` invocation. This assumes that `llvm-dis` is available
446    /// at `$LLVM_BIN_DIR/llvm-dis`.
447    pub fn new() -> Self {
448        let llvm_dis = llvm_bin_dir().join("llvm-dis");
449        let cmd = Command::new(llvm_dis);
450        Self { cmd }
451    }
452
453    /// Provide an input file.
454    pub fn input<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
455        self.cmd.arg(path.as_ref());
456        self
457    }
458}