1 /* This Source Code Form is subject to the terms of the Mozilla Public
2  * License, v. 2.0. If a copy of the MPL was not distributed with this
3  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4 
5 use std::path;
6 
7 use bindgen::bindings::Bindings;
8 use bindgen::cargo::Cargo;
9 use bindgen::config::{Braces, Config, Language};
10 use bindgen::error::Error;
11 use bindgen::library::Library;
12 use bindgen::parser::{self, Parse};
13 
14 /// A builder for generating a bindings header.
15 #[derive(Debug, Clone)]
16 pub struct Builder {
17     config: Config,
18     srcs: Vec<path::PathBuf>,
19     lib: Option<(path::PathBuf, Option<String>)>,
20     lib_cargo: Option<Cargo>,
21     std_types: bool,
22     lockfile: Option<path::PathBuf>,
23 }
24 
25 impl Builder {
new() -> Builder26     pub fn new() -> Builder {
27         Builder {
28             config: Config::default(),
29             srcs: Vec::new(),
30             lib: None,
31             lib_cargo: None,
32             std_types: true,
33             lockfile: None,
34         }
35     }
36 
37     #[allow(unused)]
with_header<S: AsRef<str>>(mut self, header: S) -> Builder38     pub fn with_header<S: AsRef<str>>(mut self, header: S) -> Builder {
39         self.config.header = Some(String::from(header.as_ref()));
40         self
41     }
42 
43     #[allow(unused)]
with_no_includes(mut self) -> Builder44     pub fn with_no_includes(mut self) -> Builder {
45         self.config.no_includes = true;
46         self
47     }
48 
49     #[allow(unused)]
with_include<S: AsRef<str>>(mut self, include: S) -> Builder50     pub fn with_include<S: AsRef<str>>(mut self, include: S) -> Builder {
51         self.config.includes.push(String::from(include.as_ref()));
52         self
53     }
54 
55     #[allow(unused)]
with_sys_include<S: AsRef<str>>(mut self, include: S) -> Builder56     pub fn with_sys_include<S: AsRef<str>>(mut self, include: S) -> Builder {
57         self.config
58             .sys_includes
59             .push(String::from(include.as_ref()));
60         self
61     }
62 
63     #[allow(unused)]
with_trailer<S: AsRef<str>>(mut self, trailer: S) -> Builder64     pub fn with_trailer<S: AsRef<str>>(mut self, trailer: S) -> Builder {
65         self.config.trailer = Some(String::from(trailer.as_ref()));
66         self
67     }
68 
69     #[allow(unused)]
with_include_guard<S: AsRef<str>>(mut self, include_guard: S) -> Builder70     pub fn with_include_guard<S: AsRef<str>>(mut self, include_guard: S) -> Builder {
71         self.config.include_guard = Some(String::from(include_guard.as_ref()));
72         self
73     }
74 
75     #[allow(unused)]
with_autogen_warning<S: AsRef<str>>(mut self, autogen_warning: S) -> Builder76     pub fn with_autogen_warning<S: AsRef<str>>(mut self, autogen_warning: S) -> Builder {
77         self.config.autogen_warning = Some(String::from(autogen_warning.as_ref()));
78         self
79     }
80 
81     #[allow(unused)]
with_include_version(mut self, include_version: bool) -> Builder82     pub fn with_include_version(mut self, include_version: bool) -> Builder {
83         self.config.include_version = include_version;
84         self
85     }
86 
87     #[allow(unused)]
with_namespace<S: AsRef<str>>(mut self, namespace: S) -> Builder88     pub fn with_namespace<S: AsRef<str>>(mut self, namespace: S) -> Builder {
89         self.config.namespace = Some(String::from(namespace.as_ref()));
90         self
91     }
92 
93     #[allow(unused)]
with_namespaces<S: AsRef<str>>(mut self, namespaces: &[S]) -> Builder94     pub fn with_namespaces<S: AsRef<str>>(mut self, namespaces: &[S]) -> Builder {
95         self.config.namespaces = Some(
96             namespaces
97                 .iter()
98                 .map(|x| String::from(x.as_ref()))
99                 .collect(),
100         );
101         self
102     }
103 
104     #[allow(unused)]
with_braces(mut self, braces: Braces) -> Builder105     pub fn with_braces(mut self, braces: Braces) -> Builder {
106         self.config.braces = braces;
107         self
108     }
109 
110     #[allow(unused)]
with_line_length(mut self, line_length: usize) -> Builder111     pub fn with_line_length(mut self, line_length: usize) -> Builder {
112         self.config.line_length = line_length;
113         self
114     }
115 
116     #[allow(unused)]
with_tab_width(mut self, tab_width: usize) -> Builder117     pub fn with_tab_width(mut self, tab_width: usize) -> Builder {
118         self.config.tab_width = tab_width;
119         self
120     }
121 
122     #[allow(unused)]
with_language(mut self, language: Language) -> Builder123     pub fn with_language(mut self, language: Language) -> Builder {
124         self.config.language = language;
125         self
126     }
127 
128     #[allow(unused)]
include_item<S: AsRef<str>>(mut self, item_name: S) -> Builder129     pub fn include_item<S: AsRef<str>>(mut self, item_name: S) -> Builder {
130         self.config
131             .export
132             .include
133             .push(String::from(item_name.as_ref()));
134         self
135     }
136 
137     #[allow(unused)]
exclude_item<S: AsRef<str>>(mut self, item_name: S) -> Builder138     pub fn exclude_item<S: AsRef<str>>(mut self, item_name: S) -> Builder {
139         self.config
140             .export
141             .exclude
142             .push(String::from(item_name.as_ref()));
143         self
144     }
145 
146     #[allow(unused)]
rename_item<S: AsRef<str>>(mut self, from: S, to: S) -> Builder147     pub fn rename_item<S: AsRef<str>>(mut self, from: S, to: S) -> Builder {
148         self.config
149             .export
150             .rename
151             .insert(String::from(from.as_ref()), String::from(to.as_ref()));
152         self
153     }
154 
155     #[allow(unused)]
with_item_prefix<S: AsRef<str>>(mut self, prefix: S) -> Builder156     pub fn with_item_prefix<S: AsRef<str>>(mut self, prefix: S) -> Builder {
157         self.config.export.prefix = Some(String::from(prefix.as_ref()));
158         self
159     }
160 
161     #[allow(unused)]
with_parse_deps(mut self, parse_deps: bool) -> Builder162     pub fn with_parse_deps(mut self, parse_deps: bool) -> Builder {
163         self.config.parse.parse_deps = parse_deps;
164         self
165     }
166 
167     #[allow(unused)]
with_parse_include<S: AsRef<str>>(mut self, include: &[S]) -> Builder168     pub fn with_parse_include<S: AsRef<str>>(mut self, include: &[S]) -> Builder {
169         self.config.parse.include =
170             Some(include.iter().map(|x| String::from(x.as_ref())).collect());
171         self
172     }
173 
174     #[allow(unused)]
with_parse_exclude<S: AsRef<str>>(mut self, exclude: &[S]) -> Builder175     pub fn with_parse_exclude<S: AsRef<str>>(mut self, exclude: &[S]) -> Builder {
176         self.config.parse.exclude = exclude.iter().map(|x| String::from(x.as_ref())).collect();
177         self
178     }
179 
180     #[allow(unused)]
with_parse_expand<S: AsRef<str>>(mut self, expand: &[S]) -> Builder181     pub fn with_parse_expand<S: AsRef<str>>(mut self, expand: &[S]) -> Builder {
182         self.config.parse.expand.crates = expand.iter().map(|x| String::from(x.as_ref())).collect();
183         self
184     }
185 
186     #[allow(unused)]
with_parse_expand_all_features(mut self, expand_all_features: bool) -> Builder187     pub fn with_parse_expand_all_features(mut self, expand_all_features: bool) -> Builder {
188         self.config.parse.expand.all_features = expand_all_features;
189         self
190     }
191 
192     #[allow(unused)]
with_parse_expand_default_features(mut self, expand_default_features: bool) -> Builder193     pub fn with_parse_expand_default_features(mut self, expand_default_features: bool) -> Builder {
194         self.config.parse.expand.default_features = expand_default_features;
195         self
196     }
197 
198     #[allow(unused)]
with_parse_expand_features<S: AsRef<str>>(mut self, expand_features: &[S]) -> Builder199     pub fn with_parse_expand_features<S: AsRef<str>>(mut self, expand_features: &[S]) -> Builder {
200         self.config.parse.expand.features = Some(
201             expand_features
202                 .iter()
203                 .map(|x| String::from(x.as_ref()))
204                 .collect(),
205         );
206         self
207     }
208 
209     #[allow(unused)]
with_documentation(mut self, documentation: bool) -> Builder210     pub fn with_documentation(mut self, documentation: bool) -> Builder {
211         self.config.documentation = documentation;
212         self
213     }
214 
215     #[allow(unused)]
with_target_os_define(mut self, platform: &str, preprocessor_define: &str) -> Builder216     pub fn with_target_os_define(mut self, platform: &str, preprocessor_define: &str) -> Builder {
217         self.config.defines.insert(
218             format!("target_os = {}", platform),
219             preprocessor_define.to_owned(),
220         );
221         self
222     }
223 
224     #[allow(unused)]
with_define(mut self, key: &str, value: &str, preprocessor_define: &str) -> Builder225     pub fn with_define(mut self, key: &str, value: &str, preprocessor_define: &str) -> Builder {
226         self.config.defines.insert(
227             format!("{} = {}", key, value),
228             preprocessor_define.to_owned(),
229         );
230         self
231     }
232 
233     #[allow(unused)]
with_config(mut self, config: Config) -> Builder234     pub fn with_config(mut self, config: Config) -> Builder {
235         self.config = config;
236         self
237     }
238 
239     #[allow(unused)]
with_std_types(mut self, std_types: bool) -> Builder240     pub fn with_std_types(mut self, std_types: bool) -> Builder {
241         self.std_types = std_types;
242         self
243     }
244 
245     #[allow(unused)]
with_src<P: AsRef<path::Path>>(mut self, src: P) -> Builder246     pub fn with_src<P: AsRef<path::Path>>(mut self, src: P) -> Builder {
247         self.srcs.push(src.as_ref().to_owned());
248         self
249     }
250 
251     #[allow(unused)]
with_crate<P: AsRef<path::Path>>(mut self, lib_dir: P) -> Builder252     pub fn with_crate<P: AsRef<path::Path>>(mut self, lib_dir: P) -> Builder {
253         debug_assert!(self.lib.is_none());
254         debug_assert!(self.lib_cargo.is_none());
255         self.lib = Some((path::PathBuf::from(lib_dir.as_ref()), None));
256         self
257     }
258 
259     #[allow(unused)]
with_crate_and_name<P: AsRef<path::Path>, S: AsRef<str>>( mut self, lib_dir: P, binding_lib_name: S, ) -> Builder260     pub fn with_crate_and_name<P: AsRef<path::Path>, S: AsRef<str>>(
261         mut self,
262         lib_dir: P,
263         binding_lib_name: S,
264     ) -> Builder {
265         debug_assert!(self.lib.is_none());
266         debug_assert!(self.lib_cargo.is_none());
267         self.lib = Some((
268             path::PathBuf::from(lib_dir.as_ref()),
269             Some(String::from(binding_lib_name.as_ref())),
270         ));
271         self
272     }
273 
274     #[allow(unused)]
with_cargo(mut self, lib: Cargo) -> Builder275     pub(crate) fn with_cargo(mut self, lib: Cargo) -> Builder {
276         debug_assert!(self.lib.is_none());
277         debug_assert!(self.lib_cargo.is_none());
278         self.lib_cargo = Some(lib);
279         self
280     }
281 
282     #[allow(unused)]
with_lockfile<P: AsRef<path::Path>>(mut self, lockfile: P) -> Builder283     pub fn with_lockfile<P: AsRef<path::Path>>(mut self, lockfile: P) -> Builder {
284         debug_assert!(self.lockfile.is_none());
285         debug_assert!(self.lib_cargo.is_none());
286         self.lockfile = Some(path::PathBuf::from(lockfile.as_ref()));
287         self
288     }
289 
generate(self) -> Result<Bindings, Error>290     pub fn generate(self) -> Result<Bindings, Error> {
291         let mut result = Parse::new();
292 
293         if self.std_types {
294             result.add_std_types();
295         }
296 
297         for x in &self.srcs {
298             result.extend_with(&parser::parse_src(x, &self.config.macro_expansion)?);
299         }
300 
301         if let Some((lib_dir, binding_lib_name)) = self.lib.clone() {
302             let lockfile = self.lockfile.as_ref().and_then(|p| p.to_str());
303 
304             let cargo = if let Some(binding_lib_name) = binding_lib_name {
305                 Cargo::load(
306                     &lib_dir,
307                     lockfile,
308                     Some(&binding_lib_name),
309                     self.config.parse.parse_deps,
310                     self.config.parse.clean,
311                 )?
312             } else {
313                 Cargo::load(
314                     &lib_dir,
315                     lockfile,
316                     None,
317                     self.config.parse.parse_deps,
318                     self.config.parse.clean,
319                 )?
320             };
321 
322             result.extend_with(&parser::parse_lib(
323                 cargo,
324                 &self.config.macro_expansion,
325                 &self.config.parse,
326             )?);
327         } else if let Some(cargo) = self.lib_cargo.clone() {
328             result.extend_with(&parser::parse_lib(
329                 cargo,
330                 &self.config.macro_expansion,
331                 &self.config.parse,
332             )?);
333         }
334 
335         Library::new(
336             self.config,
337             result.constants,
338             result.globals,
339             result.enums,
340             result.structs,
341             result.unions,
342             result.opaque_items,
343             result.typedefs,
344             result.functions,
345         )
346         .generate()
347     }
348 }
349