aboutsummaryrefslogtreecommitdiff
path: root/options.rs
diff options
context:
space:
mode:
Diffstat (limited to 'options.rs')
-rw-r--r--options.rs202
1 files changed, 127 insertions, 75 deletions
diff --git a/options.rs b/options.rs
index 1e592ce..b4b22dc 100644
--- a/options.rs
+++ b/options.rs
@@ -1,23 +1,27 @@
use bindgen::callbacks::TypeKind;
use bindgen::{
- builder, AliasVariation, Builder, CodegenConfig, EnumVariation,
+ builder, Abi, AliasVariation, Builder, CodegenConfig, EnumVariation,
FieldVisibilityKind, Formatter, MacroTypeVariation, NonCopyUnionStyle,
RegexSet, RustTarget, DEFAULT_ANON_FIELDS_PREFIX, RUST_TARGET_STRINGS,
};
-use clap::Parser;
+use clap::error::{Error, ErrorKind};
+use clap::{CommandFactory, Parser};
use std::fs::File;
-use std::io::{self, Error, ErrorKind};
-use std::path::PathBuf;
+use std::io;
+use std::path::{Path, PathBuf};
+use std::process::exit;
fn rust_target_help() -> String {
format!(
- "Version of the Rust compiler to target. Valid options are: {:?}. Defaults to {:?}.",
+ "Version of the Rust compiler to target. Valid options are: {:?}. Defaults to {}.",
RUST_TARGET_STRINGS,
- String::from(RustTarget::default())
+ RustTarget::default()
)
}
-fn parse_codegen_config(what_to_generate: &str) -> io::Result<CodegenConfig> {
+fn parse_codegen_config(
+ what_to_generate: &str,
+) -> Result<CodegenConfig, Error> {
let mut config = CodegenConfig::empty();
for what in what_to_generate.split(',') {
match what {
@@ -28,9 +32,9 @@ fn parse_codegen_config(what_to_generate: &str) -> io::Result<CodegenConfig> {
"constructors" => config.insert(CodegenConfig::CONSTRUCTORS),
"destructors" => config.insert(CodegenConfig::DESTRUCTORS),
otherwise => {
- return Err(Error::new(
- ErrorKind::Other,
- format!("Unknown generate item: {}", otherwise),
+ return Err(Error::raw(
+ ErrorKind::InvalidValue,
+ format!("Unknown codegen item kind: {}", otherwise),
));
}
}
@@ -39,10 +43,54 @@ fn parse_codegen_config(what_to_generate: &str) -> io::Result<CodegenConfig> {
Ok(config)
}
+fn parse_rustfmt_config_path(path_str: &str) -> Result<PathBuf, Error> {
+ let path = Path::new(path_str);
+
+ if !path.is_absolute() {
+ return Err(Error::raw(
+ ErrorKind::InvalidValue,
+ "--rustfmt-configuration-file needs to be an absolute path!",
+ ));
+ }
+
+ if path.to_str().is_none() {
+ return Err(Error::raw(
+ ErrorKind::InvalidUtf8,
+ "--rustfmt-configuration-file contains non-valid UTF8 characters.",
+ ));
+ }
+
+ Ok(path.to_path_buf())
+}
+
+fn parse_abi_override(abi_override: &str) -> Result<(Abi, String), Error> {
+ let (regex, abi_str) = abi_override
+ .rsplit_once('=')
+ .ok_or_else(|| Error::raw(ErrorKind::InvalidValue, "Missing `=`"))?;
+
+ let abi = abi_str
+ .parse()
+ .map_err(|err| Error::raw(ErrorKind::InvalidValue, err))?;
+
+ Ok((abi, regex.to_owned()))
+}
+
+fn parse_custom_derive(
+ custom_derive: &str,
+) -> Result<(Vec<String>, String), Error> {
+ let (regex, derives) = custom_derive
+ .rsplit_once('=')
+ .ok_or_else(|| Error::raw(ErrorKind::InvalidValue, "Missing `=`"))?;
+
+ let derives = derives.split(',').map(|s| s.to_owned()).collect();
+
+ Ok((derives, regex.to_owned()))
+}
+
#[derive(Parser, Debug)]
#[clap(
about = "Generates Rust bindings from C/C++ headers.",
- override_usage = "bindgen [FLAGS] [OPTIONS] [HEADER] -- [CLANG_ARGS]...",
+ override_usage = "bindgen <FLAGS> <OPTIONS> <HEADER> -- <CLANG_ARGS>...",
trailing_var_arg = true
)]
struct BindgenCommand {
@@ -51,8 +99,8 @@ struct BindgenCommand {
/// Path to write depfile to.
#[arg(long)]
depfile: Option<String>,
- /// The default style of code used to generate enums.
- #[arg(long, value_name = "VARIANT")]
+ /// The default STYLE of code used to generate enums.
+ #[arg(long, value_name = "STYLE")]
default_enum_style: Option<EnumVariation>,
/// Mark any enum whose name matches REGEX as a set of bitfield flags.
#[arg(long, value_name = "REGEX")]
@@ -72,11 +120,11 @@ struct BindgenCommand {
/// Mark any enum whose name matches REGEX as a module of constants.
#[arg(long, value_name = "REGEX")]
constified_enum_module: Vec<String>,
- /// The default signed/unsigned type for C macro constants.
- #[arg(long, value_name = "VARIANT")]
+ /// The default signed/unsigned TYPE for C macro constants.
+ #[arg(long, value_name = "TYPE")]
default_macro_constant_type: Option<MacroTypeVariation>,
- /// The default style of code used to generate typedefs.
- #[arg(long, value_name = "VARIANT")]
+ /// The default STYLE of code used to generate typedefs.
+ #[arg(long, value_name = "STYLE")]
default_alias_style: Option<AliasVariation>,
/// Mark any typedef alias whose name matches REGEX to use normal type aliasing.
#[arg(long, value_name = "REGEX")]
@@ -87,7 +135,7 @@ struct BindgenCommand {
/// Mark any typedef alias whose name matches REGEX to have a new type with Deref and DerefMut to the inner type.
#[arg(long, value_name = "REGEX")]
new_type_alias_deref: Vec<String>,
- /// The default style of code used to generate unions with non-Copy members. Note that ManuallyDrop was first stabilized in Rust 1.20.0.
+ /// The default STYLE of code used to generate unions with non-Copy members. Note that ManuallyDrop was first stabilized in Rust 1.20.0.
#[arg(long, value_name = "STYLE")]
default_non_copy_union_style: Option<NonCopyUnionStyle>,
/// Mark any union whose name matches REGEX and who has a non-Copy member to use a bindgen-generated wrapper for fields.
@@ -156,6 +204,9 @@ struct BindgenCommand {
/// Generate block signatures instead of void pointers.
#[arg(long)]
generate_block: bool,
+ /// Generate string constants as `&CStr` instead of `&[u8]`.
+ #[arg(long)]
+ generate_cstr: bool,
/// Use extern crate instead of use for block.
#[arg(long)]
block_extern_crate: bool,
@@ -165,10 +216,10 @@ struct BindgenCommand {
/// Output bindings for builtin definitions, e.g. __builtin_va_list.
#[arg(long)]
builtins: bool,
- /// Use the given prefix before raw types instead of ::std::os::raw.
+ /// Use the given PREFIX before raw types instead of ::std::os::raw.
#[arg(long, value_name = "PREFIX")]
ctypes_prefix: Option<String>,
- /// Use the given prefix for anonymous fields.
+ /// Use the given PREFIX for anonymous fields.
#[arg(long, default_value = DEFAULT_ANON_FIELDS_PREFIX, value_name = "PREFIX")]
anon_fields_prefix: String,
/// Time the different bindgen phases and print to stderr
@@ -180,7 +231,7 @@ struct BindgenCommand {
/// Output our internal IR for debugging purposes.
#[arg(long)]
emit_ir: bool,
- /// Dump graphviz dot file.
+ /// Dump a graphviz dot file to PATH.
#[arg(long, value_name = "PATH")]
emit_ir_graphviz: Option<String>,
/// Enable support for C++ namespaces.
@@ -228,8 +279,8 @@ struct BindgenCommand {
/// Add a raw line of Rust code at the beginning of output.
#[arg(long)]
raw_line: Vec<String>,
- /// Add a raw line of Rust code to a given module.
- #[arg(long, number_of_values = 2, value_names = ["MODULE-NAME", "RAW-LINE"])]
+ /// Add a RAW_LINE of Rust code to a given module with name MODULE_NAME.
+ #[arg(long, number_of_values = 2, value_names = ["MODULE_NAME", "RAW_LINE"])]
module_raw_line: Vec<String>,
#[arg(long, help = rust_target_help())]
rust_target: Option<RustTarget>,
@@ -254,6 +305,9 @@ struct BindgenCommand {
/// Allowlist all contents of PATH.
#[arg(long, value_name = "PATH")]
allowlist_file: Vec<String>,
+ /// Allowlist all items matching REGEX. Other non-allowlisted items will not be generated.
+ #[arg(long, value_name = "REGEX")]
+ allowlist_item: Vec<String>,
/// Print verbose error messages.
#[arg(long)]
verbose: bool,
@@ -270,16 +324,16 @@ struct BindgenCommand {
/// `--formatter=none` instead.
#[arg(long)]
no_rustfmt_bindings: bool,
- /// Which tool should be used to format the bindings
+ /// Which FORMATTER should be used for the bindings
#[arg(
long,
value_name = "FORMATTER",
conflicts_with = "no_rustfmt_bindings"
)]
formatter: Option<Formatter>,
- /// The absolute path to the rustfmt configuration file. The configuration file will be used for formatting the bindings. This parameter sets `formatter` to `rustfmt`.
- #[arg(long, value_name = "PATH", conflicts_with = "no_rustfmt_bindings")]
- rustfmt_configuration_file: Option<String>,
+ /// The absolute PATH to the rustfmt configuration file. The configuration file will be used for formatting the bindings. This parameter sets `formatter` to `rustfmt`.
+ #[arg(long, value_name = "PATH", conflicts_with = "no_rustfmt_bindings", value_parser=parse_rustfmt_config_path)]
+ rustfmt_configuration_file: Option<PathBuf>,
/// Avoid deriving PartialEq for types matching REGEX.
#[arg(long, value_name = "REGEX")]
no_partialeq: Vec<String>,
@@ -304,10 +358,10 @@ struct BindgenCommand {
/// Use `*const [T; size]` instead of `*const T` for C arrays
#[arg(long)]
use_array_pointers_in_arguments: bool,
- /// The name to be used in a #[link(wasm_import_module = ...)] statement
+ /// The NAME to be used in a #[link(wasm_import_module = ...)] statement
#[arg(long, value_name = "NAME")]
wasm_import_module_name: Option<String>,
- /// Use dynamic loading mode with the given library name.
+ /// Use dynamic loading mode with the given library NAME.
#[arg(long, value_name = "NAME")]
dynamic_loading: Option<String>,
/// Require successful linkage to all functions in the library.
@@ -337,42 +391,45 @@ struct BindgenCommand {
/// Deduplicates extern blocks.
#[arg(long)]
merge_extern_blocks: bool,
- /// Overrides the ABI of functions matching REGEX. The OVERRIDE value must be of the shape REGEX=ABI where ABI can be one of C, stdcall, efiapi, fastcall, thiscall, aapcs, win64 or C-unwind.
- #[arg(long, value_name = "OVERRIDE")]
- override_abi: Vec<String>,
+ /// Overrides the ABI of functions matching REGEX. The OVERRIDE value must be of the shape REGEX=ABI where ABI can be one of C, stdcall, efiapi, fastcall, thiscall, aapcs, win64 or C-unwind<.>
+ #[arg(long, value_name = "OVERRIDE", value_parser = parse_abi_override)]
+ override_abi: Vec<(Abi, String)>,
/// Wrap unsafe operations in unsafe blocks.
#[arg(long)]
wrap_unsafe_ops: bool,
/// Derive custom traits on any kind of type. The CUSTOM value must be of the shape REGEX=DERIVE where DERIVE is a coma-separated list of derive macros.
- #[arg(long, value_name = "CUSTOM")]
- with_derive_custom: Vec<String>,
+ #[arg(long, value_name = "CUSTOM", value_parser = parse_custom_derive)]
+ with_derive_custom: Vec<(Vec<String>, String)>,
/// Derive custom traits on a `struct`. The CUSTOM value must be of the shape REGEX=DERIVE where DERIVE is a coma-separated list of derive macros.
- #[arg(long, value_name = "CUSTOM")]
- with_derive_custom_struct: Vec<String>,
+ #[arg(long, value_name = "CUSTOM", value_parser = parse_custom_derive)]
+ with_derive_custom_struct: Vec<(Vec<String>, String)>,
/// Derive custom traits on an `enum. The CUSTOM value must be of the shape REGEX=DERIVE where DERIVE is a coma-separated list of derive macros.
- #[arg(long, value_name = "CUSTOM")]
- with_derive_custom_enum: Vec<String>,
+ #[arg(long, value_name = "CUSTOM", value_parser = parse_custom_derive)]
+ with_derive_custom_enum: Vec<(Vec<String>, String)>,
/// Derive custom traits on a `union`. The CUSTOM value must be of the shape REGEX=DERIVE where DERIVE is a coma-separated list of derive macros.
- #[arg(long, value_name = "CUSTOM")]
- with_derive_custom_union: Vec<String>,
+ #[arg(long, value_name = "CUSTOM", value_parser = parse_custom_derive)]
+ with_derive_custom_union: Vec<(Vec<String>, String)>,
/// Generate wrappers for `static` and `static inline` functions.
#[arg(long, requires = "experimental")]
wrap_static_fns: bool,
- /// Sets the path for the source file that must be created due to the presence of `static` and
+ /// Sets the PATH for the source file that must be created due to the presence of `static` and
/// `static inline` functions.
#[arg(long, requires = "experimental", value_name = "PATH")]
wrap_static_fns_path: Option<PathBuf>,
- /// Sets the suffix added to the extern wrapper functions generated for `static` and `static
+ /// Sets the SUFFIX added to the extern wrapper functions generated for `static` and `static
/// inline` functions.
#[arg(long, requires = "experimental", value_name = "SUFFIX")]
wrap_static_fns_suffix: Option<String>,
- /// Set the default visibility of fields, including bitfields and accessor methods for
+ /// Set the default VISIBILITY of fields, including bitfields and accessor methods for
/// bitfields. This flag is ignored if the `--respect-cxx-access-specs` flag is used.
#[arg(long, value_name = "VISIBILITY")]
default_visibility: Option<FieldVisibilityKind>,
/// Whether to emit diagnostics or not.
#[arg(long, requires = "experimental")]
emit_diagnostics: bool,
+ /// Generates completions for the specified SHELL, sends them to `stdout` and exits.
+ #[arg(long, value_name = "SHELL")]
+ generate_shell_completions: Option<clap_complete::Shell>,
/// Enables experimental features.
#[arg(long)]
experimental: bool,
@@ -430,6 +487,7 @@ where
no_recursive_allowlist,
objc_extern_crate,
generate_block,
+ generate_cstr,
block_extern_crate,
distrust_clang_mangling,
builtins,
@@ -463,6 +521,7 @@ where
allowlist_type,
allowlist_var,
allowlist_file,
+ allowlist_item,
verbose,
dump_preprocessed_input,
no_record_matches,
@@ -500,15 +559,27 @@ where
wrap_static_fns_suffix,
default_visibility,
emit_diagnostics,
+ generate_shell_completions,
experimental: _,
version,
clang_args,
} = command;
+ if let Some(shell) = generate_shell_completions {
+ clap_complete::generate(
+ shell,
+ &mut BindgenCommand::command(),
+ "bindgen",
+ &mut std::io::stdout(),
+ );
+
+ exit(0);
+ }
+
if version {
println!(
"bindgen {}",
- Some("0.65.1").unwrap_or("unknown")
+ Some("0.69.1").unwrap_or("unknown")
);
if verbose {
println!("Clang: {}", bindgen::clang_version().full);
@@ -521,7 +592,7 @@ where
if let Some(header) = header {
builder = builder.header(header);
} else {
- return Err(Error::new(ErrorKind::Other, "Header not found"));
+ return Err(io::Error::new(io::ErrorKind::Other, "Header not found"));
}
if let Some(rust_target) = rust_target {
@@ -755,6 +826,10 @@ where
builder = builder.generate_block(true);
}
+ if generate_cstr {
+ builder = builder.generate_cstr(true);
+ }
+
if block_extern_crate {
builder = builder.block_extern_crate(true);
}
@@ -805,6 +880,10 @@ where
builder = builder.allowlist_file(file);
}
+ for item in allowlist_item {
+ builder = builder.allowlist_item(item);
+ }
+
for arg in clang_args {
builder = builder.clang_arg(arg);
}
@@ -842,23 +921,7 @@ where
builder = builder.formatter(formatter);
}
- if let Some(path_str) = rustfmt_configuration_file {
- let path = PathBuf::from(path_str);
-
- if !path.is_absolute() {
- return Err(Error::new(
- ErrorKind::Other,
- "--rustfmt-configuration--file needs to be an absolute path!",
- ));
- }
-
- if path.to_str().is_none() {
- return Err(Error::new(
- ErrorKind::Other,
- "--rustfmt-configuration-file contains non-valid UTF8 characters.",
- ));
- }
-
+ if let Some(path) = rustfmt_configuration_file {
builder = builder.rustfmt_configuration_file(Some(path));
}
@@ -944,13 +1007,7 @@ where
builder = builder.merge_extern_blocks(true);
}
- for abi_override in override_abi {
- let (regex, abi_str) = abi_override
- .rsplit_once('=')
- .expect("Invalid ABI override: Missing `=`");
- let abi = abi_str
- .parse()
- .unwrap_or_else(|err| panic!("Invalid ABI override: {}", err));
+ for (abi, regex) in override_abi {
builder = builder.override_abi(abi, regex);
}
@@ -1020,12 +1077,7 @@ where
),
] {
let name = emit_diagnostics.then_some(name);
- for custom_derive in custom_derives {
- let (regex, derives) = custom_derive
- .rsplit_once('=')
- .expect("Invalid custom derive argument: Missing `=`");
- let derives = derives.split(',').map(|s| s.to_owned()).collect();
-
+ for (derives, regex) in custom_derives {
let mut regex_set = RegexSet::new();
regex_set.insert(regex);
regex_set.build_with_diagnostics(false, name);