Skip to content

Commit 626797b

Browse files
authored
Merge pull request #2302 from ferrous-systems/clonable-builder
Implement `Clone` for `Builder`
2 parents d241e95 + 46cd3af commit 626797b

File tree

4 files changed

+38
-44
lines changed

4 files changed

+38
-44
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,7 @@
159159
* new feature: `--merge-extern-blocks` flag to merge several `extern` blocks
160160
that have the same ABI.
161161
* new feature: `--no-size_t-is-usize` flag to not bind `size_t` as `usize`.
162+
* new feature: `Builder` implements `Clone`.
162163

163164
## Changed
164165

bindgen/clang.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1823,7 +1823,7 @@ pub struct UnsavedFile {
18231823

18241824
impl UnsavedFile {
18251825
/// Construct a new unsaved file with the given `name` and `contents`.
1826-
pub fn new(name: &str, contents: &str) -> UnsavedFile {
1826+
pub fn new(name: String, contents: String) -> UnsavedFile {
18271827
let name = CString::new(name).unwrap();
18281828
let contents = CString::new(contents).unwrap();
18291829
let x = CXUnsavedFile {

bindgen/ir/context.rs

+1-5
Original file line numberDiff line numberDiff line change
@@ -541,11 +541,7 @@ If you encounter an error missing from this list, please file an issue or a PR!"
541541
let root_module_id = root_module.id().as_module_id_unchecked();
542542

543543
// depfiles need to include the explicitly listed headers too
544-
let mut deps = BTreeSet::default();
545-
if let Some(filename) = &options.input_header {
546-
deps.insert(filename.clone());
547-
}
548-
deps.extend(options.extra_input_headers.iter().cloned());
544+
let deps = options.input_headers.iter().cloned().collect();
549545

550546
BindgenContext {
551547
items: vec![Some(root_module)],

bindgen/lib.rs

+35-38
Original file line numberDiff line numberDiff line change
@@ -79,12 +79,12 @@ use crate::parse::{ClangItemParser, ParseError};
7979
use crate::regex_set::RegexSet;
8080

8181
use std::borrow::Cow;
82+
use std::env;
8283
use std::fs::{File, OpenOptions};
8384
use std::io::{self, Write};
8485
use std::path::{Path, PathBuf};
8586
use std::process::{Command, Stdio};
8687
use std::rc::Rc;
87-
use std::{env, iter};
8888

8989
// Some convenient typedefs for a fast hash map and hash set.
9090
type HashMap<K, V> = ::rustc_hash::FxHashMap<K, V>;
@@ -222,12 +222,9 @@ impl Default for CodegenConfig {
222222
/// End-users of the crate may need to set the `BINDGEN_EXTRA_CLANG_ARGS` environment variable to
223223
/// add additional arguments. For example, to build against a different sysroot a user could set
224224
/// `BINDGEN_EXTRA_CLANG_ARGS` to `--sysroot=/path/to/sysroot`.
225-
#[derive(Debug, Default)]
225+
#[derive(Debug, Default, Clone)]
226226
pub struct Builder {
227227
options: BindgenOptions,
228-
input_headers: Vec<String>,
229-
// Tuples of unsaved file contents of the form (name, contents).
230-
input_header_contents: Vec<(String, String)>,
231228
}
232229

233230
/// Construct a new [`Builder`](./struct.Builder.html).
@@ -254,7 +251,7 @@ impl Builder {
254251
pub fn command_line_flags(&self) -> Vec<String> {
255252
let mut output_vector: Vec<String> = Vec::new();
256253

257-
if let Some(header) = self.input_headers.last().cloned() {
254+
if let Some(header) = self.options.input_headers.last().cloned() {
258255
// Positional argument 'header'
259256
output_vector.push(header);
260257
}
@@ -627,13 +624,13 @@ impl Builder {
627624
output_vector.extend(self.options.clang_args.iter().cloned());
628625
}
629626

630-
if self.input_headers.len() > 1 {
631-
// To pass more than one header, we need to pass all but the last
632-
// header via the `-include` clang arg
633-
for header in &self.input_headers[..self.input_headers.len() - 1] {
634-
output_vector.push("-include".to_string());
635-
output_vector.push(header.clone());
636-
}
627+
// To pass more than one header, we need to pass all but the last
628+
// header via the `-include` clang arg
629+
for header in &self.options.input_headers
630+
[..self.options.input_headers.len().saturating_sub(1)]
631+
{
632+
output_vector.push("-include".to_string());
633+
output_vector.push(header.clone());
637634
}
638635

639636
output_vector
@@ -662,7 +659,7 @@ impl Builder {
662659
/// .unwrap();
663660
/// ```
664661
pub fn header<T: Into<String>>(mut self, header: T) -> Builder {
665-
self.input_headers.push(header.into());
662+
self.options.input_headers.push(header.into());
666663
self
667664
}
668665

@@ -691,7 +688,8 @@ impl Builder {
691688
.to_str()
692689
.expect("Cannot convert current directory name to string")
693690
.to_owned();
694-
self.input_header_contents
691+
self.options
692+
.input_header_contents
695693
.push((absolute_path, contents.into()));
696694
self
697695
}
@@ -1566,20 +1564,18 @@ impl Builder {
15661564
self.options.clang_args.extend(get_extra_clang_args());
15671565

15681566
// Transform input headers to arguments on the clang command line.
1569-
self.options.input_header = self.input_headers.pop();
1570-
self.options.extra_input_headers = self.input_headers;
15711567
self.options.clang_args.extend(
1572-
self.options.extra_input_headers.iter().flat_map(|header| {
1573-
iter::once("-include".into())
1574-
.chain(iter::once(header.to_string()))
1575-
}),
1568+
self.options.input_headers
1569+
[..self.options.input_headers.len().saturating_sub(1)]
1570+
.iter()
1571+
.flat_map(|header| ["-include".into(), header.to_string()]),
15761572
);
15771573

1578-
let input_unsaved_files = self
1579-
.input_header_contents
1580-
.into_iter()
1581-
.map(|(name, contents)| clang::UnsavedFile::new(&name, &contents))
1582-
.collect::<Vec<_>>();
1574+
let input_unsaved_files =
1575+
std::mem::take(&mut self.options.input_header_contents)
1576+
.into_iter()
1577+
.map(|(name, contents)| clang::UnsavedFile::new(name, contents))
1578+
.collect::<Vec<_>>();
15831579

15841580
Bindings::generate(self.options, input_unsaved_files)
15851581
}
@@ -1606,7 +1602,7 @@ impl Builder {
16061602
let mut is_cpp = args_are_cpp(&self.options.clang_args);
16071603

16081604
// For each input header, add `#include "$header"`.
1609-
for header in &self.input_headers {
1605+
for header in &self.options.input_headers {
16101606
is_cpp |= file_is_cpp(header);
16111607

16121608
wrapper_contents.push_str("#include \"");
@@ -1616,7 +1612,7 @@ impl Builder {
16161612

16171613
// For each input header content, add a prefix line of `#line 0 "$name"`
16181614
// followed by the contents.
1619-
for &(ref name, ref contents) in &self.input_header_contents {
1615+
for &(ref name, ref contents) in &self.options.input_header_contents {
16201616
is_cpp |= file_is_cpp(name);
16211617

16221618
wrapper_contents.push_str("#line 0 \"");
@@ -1970,11 +1966,11 @@ struct BindgenOptions {
19701966
/// The set of arguments to pass straight through to Clang.
19711967
clang_args: Vec<String>,
19721968

1973-
/// The input header file.
1974-
input_header: Option<String>,
1969+
/// The input header files.
1970+
input_headers: Vec<String>,
19751971

1976-
/// Any additional input header files.
1977-
extra_input_headers: Vec<String>,
1972+
/// Tuples of unsaved file contents of the form (name, contents).
1973+
input_header_contents: Vec<(String, String)>,
19781974

19791975
/// A user-provided visitor to allow customizing different kinds of
19801976
/// situations.
@@ -2224,8 +2220,8 @@ impl Default for BindgenOptions {
22242220
raw_lines: vec![],
22252221
module_lines: HashMap::default(),
22262222
clang_args: vec![],
2227-
input_header: None,
2228-
extra_input_headers: vec![],
2223+
input_headers: vec![],
2224+
input_header_contents: Default::default(),
22292225
parse_callbacks: None,
22302226
codegen_config: CodegenConfig::all(),
22312227
conservative_inline_namespaces: false,
@@ -2470,7 +2466,7 @@ impl Bindings {
24702466

24712467
// Whether we are working with C or C++ inputs.
24722468
let is_cpp = args_are_cpp(&options.clang_args) ||
2473-
options.input_header.as_deref().map_or(false, file_is_cpp);
2469+
options.input_headers.iter().any(|h| file_is_cpp(h));
24742470

24752471
let search_paths = if is_cpp {
24762472
clang.cpp_search_paths
@@ -2501,7 +2497,7 @@ impl Bindings {
25012497
true
25022498
}
25032499

2504-
if let Some(h) = options.input_header.as_ref() {
2500+
if let Some(h) = options.input_headers.last() {
25052501
let path = Path::new(h);
25062502
if let Ok(md) = std::fs::metadata(path) {
25072503
if md.is_dir() {
@@ -2512,14 +2508,15 @@ impl Bindings {
25122508
path.into(),
25132509
));
25142510
}
2515-
options.clang_args.push(h.clone())
2511+
let h = h.clone();
2512+
options.clang_args.push(h);
25162513
} else {
25172514
return Err(BindgenError::NotExist(path.into()));
25182515
}
25192516
}
25202517

25212518
for (idx, f) in input_unsaved_files.iter().enumerate() {
2522-
if idx != 0 || options.input_header.is_some() {
2519+
if idx != 0 || !options.input_headers.is_empty() {
25232520
options.clang_args.push("-include".to_owned());
25242521
}
25252522
options.clang_args.push(f.name.to_str().unwrap().to_owned())

0 commit comments

Comments
 (0)