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