parent
71291e082f
commit
527734c9cf
@ -0,0 +1,378 @@
|
||||
From 3c866c32ec9135731d29066a980ca4edb692201d Mon Sep 17 00:00:00 2001
|
||||
From: Fabio Valentini <decathorpe@gmail.com>
|
||||
Date: Mon, 30 Sep 2024 14:55:09 +0200
|
||||
Subject: [PATCH] backport support for clap v4
|
||||
|
||||
---
|
||||
src/bindgen/builder.rs | 2 +-
|
||||
src/bindgen/cargo/cargo.rs | 2 +-
|
||||
src/main.rs | 120 ++++++++++++++++++++-----------------
|
||||
tests/depfile.rs | 12 +++-
|
||||
4 files changed, 76 insertions(+), 60 deletions(-)
|
||||
|
||||
diff --git a/src/bindgen/builder.rs b/src/bindgen/builder.rs
|
||||
index a0328b4..4d2eee1 100644
|
||||
--- a/src/bindgen/builder.rs
|
||||
+++ b/src/bindgen/builder.rs
|
||||
@@ -375,7 +375,7 @@ impl Builder {
|
||||
}
|
||||
|
||||
if let Some((lib_dir, binding_lib_name)) = self.lib.clone() {
|
||||
- let lockfile = self.lockfile.as_ref().and_then(|p| p.to_str());
|
||||
+ let lockfile = self.lockfile.as_deref();
|
||||
|
||||
let cargo = Cargo::load(
|
||||
&lib_dir,
|
||||
diff --git a/src/bindgen/cargo/cargo.rs b/src/bindgen/cargo/cargo.rs
|
||||
index 69cf938..542f8e3 100644
|
||||
--- a/src/bindgen/cargo/cargo.rs
|
||||
+++ b/src/bindgen/cargo/cargo.rs
|
||||
@@ -36,7 +36,7 @@ impl Cargo {
|
||||
/// need to be parsed.
|
||||
pub(crate) fn load(
|
||||
crate_dir: &Path,
|
||||
- lock_file: Option<&str>,
|
||||
+ lock_file: Option<&Path>,
|
||||
binding_crate_name: Option<&str>,
|
||||
use_cargo_lock: bool,
|
||||
clean: bool,
|
||||
diff --git a/src/main.rs b/src/main.rs
|
||||
index eb78a08..cd4f271 100644
|
||||
--- a/src/main.rs
|
||||
+++ b/src/main.rs
|
||||
@@ -20,60 +20,58 @@ extern crate quote;
|
||||
extern crate syn;
|
||||
extern crate toml;
|
||||
|
||||
-use clap::{Arg, ArgMatches, Command};
|
||||
+use clap::{value_parser, Arg, ArgAction, ArgMatches, Command};
|
||||
|
||||
mod bindgen;
|
||||
mod logging;
|
||||
|
||||
-use crate::bindgen::{Bindings, Builder, Cargo, Config, Error, Profile, Style};
|
||||
+use bindgen::{Bindings, Builder, Cargo, Config, Error};
|
||||
|
||||
fn apply_config_overrides(config: &mut Config, matches: &ArgMatches) {
|
||||
// We allow specifying a language to override the config default. This is
|
||||
// used by compile-tests.
|
||||
- if let Some(lang) = matches.value_of("lang") {
|
||||
- config.language = match lang.parse() {
|
||||
- Ok(lang) => lang,
|
||||
- Err(reason) => {
|
||||
- error!("{}", reason);
|
||||
- return;
|
||||
- }
|
||||
+ match matches.try_get_one::<String>("lang") {
|
||||
+ Ok(Some(lang)) => {
|
||||
+ config.language = bindgen::Language::from_str(lang).unwrap();
|
||||
+ }
|
||||
+ Err(reason) => {
|
||||
+ error!("{}", reason);
|
||||
+ return;
|
||||
}
|
||||
+ _ => (),
|
||||
}
|
||||
|
||||
- if matches.is_present("cpp-compat") {
|
||||
+ if matches.get_flag("cpp-compat") {
|
||||
config.cpp_compat = true;
|
||||
}
|
||||
|
||||
- if matches.is_present("only-target-dependencies") {
|
||||
+ if matches.get_flag("only-target-dependencies") {
|
||||
config.only_target_dependencies = true;
|
||||
}
|
||||
|
||||
- if let Some(style) = matches.value_of("style") {
|
||||
- config.style = match style {
|
||||
- "Both" => Style::Both,
|
||||
- "both" => Style::Both,
|
||||
- "Tag" => Style::Tag,
|
||||
- "tag" => Style::Tag,
|
||||
- "Type" => Style::Type,
|
||||
- "type" => Style::Type,
|
||||
- _ => {
|
||||
- error!("Unknown style specified.");
|
||||
- return;
|
||||
- }
|
||||
+ match matches.try_get_one::<String>("style") {
|
||||
+ Ok(Some(style)) => {
|
||||
+ config.style = bindgen::Style::from_str(style).unwrap();
|
||||
+ }
|
||||
+ Err(_) => {
|
||||
+ error!("Unknown style specified.");
|
||||
+ return;
|
||||
}
|
||||
+ _ => (),
|
||||
}
|
||||
|
||||
- if let Some(profile) = matches.value_of("profile") {
|
||||
- config.parse.expand.profile = match Profile::from_str(profile) {
|
||||
- Ok(p) => p,
|
||||
- Err(e) => {
|
||||
- error!("{}", e);
|
||||
- return;
|
||||
- }
|
||||
+ match matches.try_get_one::<String>("profile") {
|
||||
+ Ok(Some(profile)) => {
|
||||
+ config.parse.expand.profile = bindgen::Profile::from_str(profile).unwrap();
|
||||
+ }
|
||||
+ Err(e) => {
|
||||
+ error!("{}", e);
|
||||
+ return;
|
||||
}
|
||||
+ _ => (),
|
||||
}
|
||||
|
||||
- if matches.is_present("d") {
|
||||
+ if matches.get_flag("d") {
|
||||
config.parse.parse_deps = true;
|
||||
}
|
||||
}
|
||||
@@ -82,7 +80,7 @@ fn load_bindings(input: &Path, matches: &ArgMatches) -> Result<Bindings, Error>
|
||||
// If a file is specified then we load it as a single source
|
||||
if !input.is_dir() {
|
||||
// Load any config specified or search in the input directory
|
||||
- let mut config = match matches.value_of("config") {
|
||||
+ let mut config = match matches.get_one::<PathBuf>("config") {
|
||||
Some(c) => Config::from_file(c).unwrap(),
|
||||
None => Config::from_root_or_default(
|
||||
input
|
||||
@@ -102,16 +100,16 @@ fn load_bindings(input: &Path, matches: &ArgMatches) -> Result<Bindings, Error>
|
||||
// We have to load a whole crate, so we use cargo to gather metadata
|
||||
let lib = Cargo::load(
|
||||
input,
|
||||
- matches.value_of("lockfile"),
|
||||
- matches.value_of("crate"),
|
||||
+ matches.get_one::<PathBuf>("lockfile").map(|s| s.as_path()),
|
||||
+ matches.get_one::<String>("crate").map(|s| s.as_str()),
|
||||
true,
|
||||
- matches.is_present("clean"),
|
||||
- matches.is_present("only-target-dependencies"),
|
||||
- matches.value_of("metadata").map(Path::new),
|
||||
+ matches.get_flag("clean"),
|
||||
+ matches.get_flag("only-target-dependencies"),
|
||||
+ matches.get_one::<PathBuf>("metadata").map(Path::new),
|
||||
)?;
|
||||
|
||||
// Load any config specified or search in the binding crate directory
|
||||
- let mut config = match matches.value_of("config") {
|
||||
+ let mut config = match matches.get_one::<String>("config") {
|
||||
Some(c) => Config::from_file(c).unwrap(),
|
||||
None => {
|
||||
let binding_crate_dir = lib.find_crate_dir(&lib.binding_crate_ref());
|
||||
@@ -140,12 +138,13 @@ fn main() {
|
||||
.arg(
|
||||
Arg::new("v")
|
||||
.short('v')
|
||||
- .multiple_occurrences(true)
|
||||
+ .action(ArgAction::Count)
|
||||
.help("Enable verbose logging"),
|
||||
)
|
||||
.arg(
|
||||
Arg::new("verify")
|
||||
.long("verify")
|
||||
+ .action(ArgAction::SetTrue)
|
||||
.help("Generate bindings and compare it to the existing bindings file and error if they are different"),
|
||||
)
|
||||
.arg(
|
||||
@@ -153,6 +152,7 @@ fn main() {
|
||||
.short('c')
|
||||
.long("config")
|
||||
.value_name("PATH")
|
||||
+ .value_parser(value_parser!(PathBuf))
|
||||
.help("Specify path to a `cbindgen.toml` config to use"),
|
||||
)
|
||||
.arg(
|
||||
@@ -161,16 +161,18 @@ fn main() {
|
||||
.long("lang")
|
||||
.value_name("LANGUAGE")
|
||||
.help("Specify the language to output bindings in")
|
||||
- .possible_values(["c++", "C++", "c", "C", "cython", "Cython"]),
|
||||
+ .value_parser(["c++", "C++", "c", "C", "cython", "Cython"]),
|
||||
)
|
||||
.arg(
|
||||
Arg::new("cpp-compat")
|
||||
.long("cpp-compat")
|
||||
+ .action(ArgAction::SetTrue)
|
||||
.help("Whether to add C++ compatibility to generated C bindings")
|
||||
)
|
||||
.arg(
|
||||
Arg::new("only-target-dependencies")
|
||||
.long("only-target-dependencies")
|
||||
+ .action(ArgAction::SetTrue)
|
||||
.help("Only fetch dependencies needed by the target platform. \
|
||||
The target platform defaults to the host platform; set TARGET to override.")
|
||||
)
|
||||
@@ -180,17 +182,19 @@ fn main() {
|
||||
.long("style")
|
||||
.value_name("STYLE")
|
||||
.help("Specify the declaration style to use for bindings")
|
||||
- .possible_values(["Both", "both", "Tag", "tag", "Type", "type"]),
|
||||
+ .value_parser(["Both", "both", "Tag", "tag", "Type", "type"]),
|
||||
)
|
||||
.arg(
|
||||
Arg::new("d")
|
||||
.short('d')
|
||||
.long("parse-dependencies")
|
||||
+ .action(ArgAction::SetTrue)
|
||||
.help("Whether to parse dependencies when generating bindings"),
|
||||
)
|
||||
.arg(
|
||||
Arg::new("clean")
|
||||
.long("clean")
|
||||
+ .action(ArgAction::SetTrue)
|
||||
.help(
|
||||
"Whether to use a new temporary directory for expanding macros. \
|
||||
Affects performance, but might be required in certain build processes.")
|
||||
@@ -203,6 +207,7 @@ fn main() {
|
||||
In general this is the folder where the Cargo.toml file of \
|
||||
source Rust library resides.")
|
||||
.required(false)
|
||||
+ .value_parser(value_parser!(PathBuf))
|
||||
.index(1),
|
||||
)
|
||||
.arg(
|
||||
@@ -221,6 +226,7 @@ fn main() {
|
||||
.long("output")
|
||||
.value_name("PATH")
|
||||
.help("The file to output the bindings to")
|
||||
+ .value_parser(value_parser!(PathBuf))
|
||||
.required(false),
|
||||
)
|
||||
.arg(
|
||||
@@ -232,6 +238,7 @@ fn main() {
|
||||
is not specified, the Cargo.lock file is searched for in the \
|
||||
same folder as the Cargo.toml file. This option is useful for \
|
||||
projects that use workspaces.")
|
||||
+ .value_parser(value_parser!(PathBuf))
|
||||
.required(false),
|
||||
)
|
||||
.arg(
|
||||
@@ -247,6 +254,7 @@ fn main() {
|
||||
`cargo metadata --all-features --format-version 1 \
|
||||
--manifest-path <path/to/crate/Cargo.toml>"
|
||||
)
|
||||
+ .value_parser(value_parser!(PathBuf))
|
||||
.required(false),
|
||||
)
|
||||
.arg(
|
||||
@@ -257,12 +265,13 @@ fn main() {
|
||||
"Specify the profile to use when expanding macros. \
|
||||
Has no effect otherwise."
|
||||
)
|
||||
- .possible_values(["Debug", "debug", "Release", "release"]),
|
||||
+ .value_parser(["Debug", "debug", "Release", "release"]),
|
||||
)
|
||||
.arg(
|
||||
Arg::new("quiet")
|
||||
.short('q')
|
||||
.long("quiet")
|
||||
+ .action(ArgAction::SetTrue)
|
||||
.help("Report errors only (overrides verbosity options).")
|
||||
.required(false),
|
||||
)
|
||||
@@ -270,10 +279,9 @@ fn main() {
|
||||
Arg::new("depfile")
|
||||
.value_name("PATH")
|
||||
.long("depfile")
|
||||
- .takes_value(true)
|
||||
- .min_values(1)
|
||||
- .max_values(1)
|
||||
+ .num_args(1)
|
||||
.required(false)
|
||||
+ .value_parser(value_parser!(PathBuf))
|
||||
.help("Generate a depfile at the given Path listing the source files \
|
||||
cbindgen traversed when generating the bindings. Useful when \
|
||||
integrating cbindgen into 3rd party build-systems. \
|
||||
@@ -282,7 +290,7 @@ fn main() {
|
||||
)
|
||||
.get_matches();
|
||||
|
||||
- if !matches.is_present("out") && matches.is_present("verify") {
|
||||
+ if matches.get_flag("verify") && !matches.contains_id("out") {
|
||||
error!(
|
||||
"Cannot verify bindings against `stdout`, please specify a file to compare against."
|
||||
);
|
||||
@@ -290,10 +298,10 @@ fn main() {
|
||||
}
|
||||
|
||||
// Initialize logging
|
||||
- if matches.is_present("quiet") {
|
||||
+ if matches.get_flag("quiet") {
|
||||
logging::ErrorLogger::init().unwrap();
|
||||
} else {
|
||||
- match matches.occurrences_of("v") {
|
||||
+ match matches.get_count("v") {
|
||||
0 => logging::WarnLogger::init().unwrap(),
|
||||
1 => logging::InfoLogger::init().unwrap(),
|
||||
_ => logging::TraceLogger::init().unwrap(),
|
||||
@@ -301,10 +309,10 @@ fn main() {
|
||||
}
|
||||
|
||||
// Find the input directory
|
||||
- let input = match matches.value_of("INPUT") {
|
||||
- Some(input) => PathBuf::from(input),
|
||||
- None => env::current_dir().unwrap(),
|
||||
- };
|
||||
+ let input: PathBuf = matches
|
||||
+ .get_one("INPUT")
|
||||
+ .cloned()
|
||||
+ .unwrap_or_else(|| env::current_dir().unwrap());
|
||||
|
||||
let bindings = match load_bindings(&input, &matches) {
|
||||
Ok(bindings) => bindings,
|
||||
@@ -316,15 +324,15 @@ fn main() {
|
||||
};
|
||||
|
||||
// Write the bindings file
|
||||
- match matches.value_of("out") {
|
||||
+ match matches.get_one::<PathBuf>("out") {
|
||||
Some(file) => {
|
||||
let changed = bindings.write_to_file(file);
|
||||
|
||||
- if matches.is_present("verify") && changed {
|
||||
- error!("Bindings changed: {}", file);
|
||||
+ if matches.get_flag("verify") && changed {
|
||||
+ error!("Bindings changed: {}", file.display());
|
||||
std::process::exit(2);
|
||||
}
|
||||
- if let Some(depfile) = matches.value_of("depfile") {
|
||||
+ if let Some(depfile) = matches.get_one("depfile") {
|
||||
bindings.generate_depfile(file, depfile)
|
||||
}
|
||||
}
|
||||
diff --git a/tests/depfile.rs b/tests/depfile.rs
|
||||
index 7d629f3..512f69b 100644
|
||||
--- a/tests/depfile.rs
|
||||
+++ b/tests/depfile.rs
|
||||
@@ -44,7 +44,11 @@ fn test_project(project_path: &str) {
|
||||
let mut cmake_build = Command::new("cmake");
|
||||
cmake_build.arg("--build").arg(&build_dir);
|
||||
let output = cmake_build.output().expect("Failed to execute process");
|
||||
- assert!(output.status.success(), "Building test project failed");
|
||||
+ assert!(
|
||||
+ output.status.success(),
|
||||
+ "Building test project failed: {:?}",
|
||||
+ output
|
||||
+ );
|
||||
let out_str = String::from_utf8(output.stdout).unwrap();
|
||||
assert!(
|
||||
out_str.contains("Running cbindgen"),
|
||||
@@ -85,7 +89,11 @@ fn test_project(project_path: &str) {
|
||||
assert_eq!(dep_list, expected_dep_list);
|
||||
|
||||
let output = cmake_build.output().expect("Failed to execute process");
|
||||
- assert!(output.status.success(), "Building test project failed");
|
||||
+ assert!(
|
||||
+ output.status.success(),
|
||||
+ "Building test project failed: {:?}",
|
||||
+ output
|
||||
+ );
|
||||
let out_str = String::from_utf8(output.stdout).unwrap();
|
||||
assert!(
|
||||
!out_str.contains("Running cbindgen"),
|
||||
--
|
||||
2.46.2
|
||||
|
@ -0,0 +1,25 @@
|
||||
--- cbindgen-0.26.0/Cargo.toml 1970-01-01T00:00:01+00:00
|
||||
+++ cbindgen-0.26.0/Cargo.toml 2024-09-30T12:12:30.660048+00:00
|
||||
@@ -46,11 +46,11 @@
|
||||
required-features = ["clap"]
|
||||
|
||||
[dependencies.clap]
|
||||
-version = "3.1"
|
||||
+version = "4"
|
||||
optional = true
|
||||
|
||||
[dependencies.heck]
|
||||
-version = "0.4"
|
||||
+version = "0.5"
|
||||
|
||||
[dependencies.indexmap]
|
||||
version = "1"
|
||||
@@ -91,7 +91,7 @@
|
||||
version = "0.5"
|
||||
|
||||
[dev-dependencies.serial_test]
|
||||
-version = "0.5.0"
|
||||
+version = "3.1"
|
||||
|
||||
[features]
|
||||
default = ["clap"]
|
Loading…
Reference in new issue