Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update argument parser to clap 4 #1105

Merged
merged 1 commit into from Sep 28, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion gen/cmd/Cargo.toml
Expand Up @@ -21,7 +21,7 @@ path = "src/main.rs"
experimental-async-fn = []

[dependencies]
clap = { version = "3.2", default-features = false, features = ["std", "suggestions"] }
clap = { version = "4", default-features = false, features = ["error-context", "help", "std", "suggestions", "usage"] }
codespan-reporting = "0.11"
proc-macro2 = { version = "1.0.39", default-features = false, features = ["span-locations"] }
quote = { version = "1.0", default-features = false }
Expand Down
68 changes: 43 additions & 25 deletions gen/cmd/src/app.rs
Expand Up @@ -10,6 +10,7 @@ use clap::builder::{ArgAction, ValueParser};
use clap::{Arg, Command};
use std::collections::{BTreeMap as Map, BTreeSet as Set};
use std::path::PathBuf;
use std::process;
use std::sync::{Arc, Mutex, PoisonError};
use syn::parse::Parser;

Expand All @@ -24,51 +25,54 @@ const TEMPLATE: &str = "\
David Tolnay <dtolnay@gmail.com>
https://github.com/dtolnay/cxx

USAGE:
{usage-heading}
{usage}

ARGS:
{positionals}

OPTIONS:
{options}\
{all-args}\
";

fn app() -> Command<'static> {
fn app() -> Command {
let mut app = Command::new("cxxbridge")
.override_usage(USAGE)
.help_template(TEMPLATE)
.next_line_help(true)
.disable_help_flag(true)
.disable_version_flag(true)
.arg(arg_input())
.arg(arg_cfg())
.arg(arg_cxx_impl_annotations())
.arg(arg_header())
.arg(arg_help())
.arg(arg_include())
.arg(arg_output())
.mut_arg("help", |a| a.help("Print help information."));
.arg(arg_output());
if let Some(version) = option_env!("CARGO_PKG_VERSION") {
app = app
.version(version)
.mut_arg("version", |a| a.help("Print version information."));
app = app.arg(arg_version()).version(version);
}
app
}

const INPUT: &str = "input";
const CFG: &str = "cfg";
const CXX_IMPL_ANNOTATIONS: &str = "cxx-impl-annotations";
const HELP: &str = "help";
const HEADER: &str = "header";
const INCLUDE: &str = "include";
const OUTPUT: &str = "output";
const VERSION: &str = "version";

pub(super) fn from_args() -> Opt {
let matches = app().get_matches();

if matches.get_flag(HELP) {
let _ = app().print_long_help();
process::exit(0);
}

let input = matches.get_one::<PathBuf>(INPUT).cloned();
let cxx_impl_annotations = matches
.get_one::<String>(CXX_IMPL_ANNOTATIONS)
.map(String::clone);
let header = matches.contains_id(HEADER);
let header = matches.get_flag(HEADER);
let include = matches
.get_many::<String>(INCLUDE)
.unwrap_or_default()
Expand Down Expand Up @@ -115,21 +119,21 @@ pub(super) fn from_args() -> Opt {
}
}

fn arg_input() -> Arg<'static> {
fn arg_input() -> Arg {
Arg::new(INPUT)
.help("Input Rust source file containing #[cxx::bridge].")
.required_unless_present(HEADER)
.required_unless_present_any(&[HEADER, HELP])
.value_parser(ValueParser::path_buf())
}

fn arg_cfg() -> Arg<'static> {
fn arg_cfg() -> Arg {
const HELP: &str = "\
Compilation configuration matching what will be used to build
the Rust side of the bridge.";
let bool_cfgs = Arc::new(Mutex::new(Map::<String, bool>::new()));
Arg::new(CFG)
.long(CFG)
.takes_value(true)
.num_args(1)
.value_name("name=\"value\" | name[=true] | name=false")
.action(ArgAction::Append)
.value_parser(move |arg: &str| match cfg::parse.parse_str(arg) {
Expand All @@ -149,7 +153,7 @@ the Rust side of the bridge.";
.help(HELP)
}

fn arg_cxx_impl_annotations() -> Arg<'static> {
fn arg_cxx_impl_annotations() -> Arg {
const HELP: &str = "\
Optional annotation for implementations of C++ function wrappers
that may be exposed to Rust. You may for example need to provide
Expand All @@ -158,42 +162,56 @@ if Rust code from one shared object or executable depends on
these C++ functions in another.";
Arg::new(CXX_IMPL_ANNOTATIONS)
.long(CXX_IMPL_ANNOTATIONS)
.takes_value(true)
.num_args(1)
.value_name("annotation")
.value_parser(ValueParser::string())
.help(HELP)
}

fn arg_header() -> Arg<'static> {
fn arg_header() -> Arg {
const HELP: &str = "\
Emit header with declarations only. Optional if using `-o` with
a path ending in `.h`.";
Arg::new(HEADER).long(HEADER).help(HELP)
Arg::new(HEADER).long(HEADER).num_args(0).help(HELP)
}

fn arg_include() -> Arg<'static> {
fn arg_help() -> Arg {
Arg::new(HELP)
.long(HELP)
.help("Print help information.")
.num_args(0)
}

fn arg_include() -> Arg {
const HELP: &str = "\
Any additional headers to #include. The cxxbridge tool does not
parse or even require the given paths to exist; they simply go
into the generated C++ code as #include lines.";
Arg::new(INCLUDE)
.long(INCLUDE)
.short('i')
.takes_value(true)
.num_args(1)
.action(ArgAction::Append)
.value_parser(ValueParser::string())
.help(HELP)
}

fn arg_output() -> Arg<'static> {
fn arg_output() -> Arg {
const HELP: &str = "\
Path of file to write as output. Output goes to stdout if -o is
not specified.";
Arg::new(OUTPUT)
.long(OUTPUT)
.short('o')
.takes_value(true)
.num_args(1)
.action(ArgAction::Append)
.value_parser(ValueParser::path_buf())
.help(HELP)
}

fn arg_version() -> Arg {
Arg::new(VERSION)
.long(VERSION)
.help("Print version information.")
.action(ArgAction::Version)
}
56 changes: 28 additions & 28 deletions gen/cmd/src/test.rs
Expand Up @@ -3,45 +3,45 @@ cxxbridge $VERSION
David Tolnay <dtolnay@gmail.com>
https://github.com/dtolnay/cxx

USAGE:
Usage:
cxxbridge <input>.rs Emit .cc file for bridge to stdout
cxxbridge <input>.rs --header Emit .h file for bridge to stdout
cxxbridge --header Emit \"rust/cxx.h\" header to stdout

ARGS:
<input>
Input Rust source file containing #[cxx::bridge].
Arguments:
[input]
Input Rust source file containing #[cxx::bridge].

OPTIONS:
--cfg <name=\"value\" | name[=true] | name=false>
Compilation configuration matching what will be used to build
the Rust side of the bridge.
Options:
--cfg <name=\"value\" | name[=true] | name=false>
Compilation configuration matching what will be used to build
the Rust side of the bridge.

--cxx-impl-annotations <annotation>
Optional annotation for implementations of C++ function wrappers
that may be exposed to Rust. You may for example need to provide
__declspec(dllexport) or __attribute__((visibility(\"default\")))
if Rust code from one shared object or executable depends on
these C++ functions in another.
--cxx-impl-annotations <annotation>
Optional annotation for implementations of C++ function wrappers
that may be exposed to Rust. You may for example need to provide
__declspec(dllexport) or __attribute__((visibility(\"default\")))
if Rust code from one shared object or executable depends on
these C++ functions in another.

-h, --help
Print help information.
--header
Emit header with declarations only. Optional if using `-o` with
a path ending in `.h`.

--header
Emit header with declarations only. Optional if using `-o` with
a path ending in `.h`.
--help
Print help information.

-i, --include <include>
Any additional headers to #include. The cxxbridge tool does not
parse or even require the given paths to exist; they simply go
into the generated C++ code as #include lines.
-i, --include <include>
Any additional headers to #include. The cxxbridge tool does not
parse or even require the given paths to exist; they simply go
into the generated C++ code as #include lines.

-o, --output <output>
Path of file to write as output. Output goes to stdout if -o is
not specified.
-o, --output <output>
Path of file to write as output. Output goes to stdout if -o is
not specified.

-V, --version
Print version information.
--version
Print version information.
";

#[test]
Expand Down
40 changes: 10 additions & 30 deletions third-party/BUCK
Expand Up @@ -17,24 +17,27 @@ rust_library(

rust_library(
name = "clap",
srcs = glob(["vendor/clap-3.2.22/src/**/*.rs"]) + [
"vendor/clap-3.2.22/examples/demo.md",
"vendor/clap-3.2.22/examples/demo.rs",
srcs = glob(["vendor/clap-4.0.2/src/**/*.rs"]) + [
"vendor/clap-4.0.2/examples/demo.md",
"vendor/clap-4.0.2/examples/demo.rs",
],
edition = "2021",
features = ["std"],
features = [
"error-context",
"help",
"std",
"usage",
],
visibility = ["PUBLIC"],
deps = [
":bitflags",
":clap_lex",
":indexmap",
":textwrap",
],
)

rust_library(
name = "clap_lex",
srcs = glob(["vendor/clap_lex-0.2.4/src/**/*.rs"]),
srcs = glob(["vendor/clap_lex-0.3.0/src/**/*.rs"]),
edition = "2021",
deps = [
":os_str_bytes",
Expand All @@ -52,22 +55,6 @@ rust_library(
],
)

rust_library(
name = "hashbrown",
srcs = glob(["vendor/hashbrown-0.12.3/src/**/*.rs"]),
edition = "2021",
features = ["raw"],
)

rust_library(
name = "indexmap",
srcs = glob(["vendor/indexmap-1.9.1/src/**/*.rs"]),
edition = "2021",
features = ["std"],
rustc_flags = ["--cfg=has_std"],
deps = [":hashbrown"],
)

rust_library(
name = "once_cell",
srcs = glob(["vendor/once_cell-1.15.0/src/**/*.rs"]),
Expand Down Expand Up @@ -146,13 +133,6 @@ rust_library(
edition = "2018",
)

rust_library(
name = "textwrap",
srcs = glob(["vendor/textwrap-0.15.1/src/**/*.rs"]),
edition = "2018",
deps = [":unicode-width"],
)

rust_library(
name = "unicode-ident",
srcs = glob(["vendor/unicode-ident-1.0.4/src/**/*.rs"]),
Expand Down
38 changes: 9 additions & 29 deletions third-party/BUILD
Expand Up @@ -20,22 +20,25 @@ rust_library(

rust_library(
name = "clap",
srcs = glob(["vendor/clap-3.2.22/src/**/*.rs"]) + ["vendor/clap-3.2.22/examples/demo.rs"],
crate_features = ["std"],
data = ["vendor/clap-3.2.22/examples/demo.md"],
srcs = glob(["vendor/clap-4.0.2/src/**/*.rs"]) + ["vendor/clap-4.0.2/examples/demo.rs"],
crate_features = [
"error-context",
"help",
"std",
"usage",
],
data = ["vendor/clap-4.0.2/examples/demo.md"],
edition = "2021",
visibility = ["//visibility:public"],
deps = [
":bitflags",
":clap_lex",
":indexmap",
":textwrap",
],
)

rust_library(
name = "clap_lex",
srcs = glob(["vendor/clap_lex-0.2.4/src/**/*.rs"]),
srcs = glob(["vendor/clap_lex-0.3.0/src/**/*.rs"]),
edition = "2021",
deps = [
":os_str_bytes",
Expand All @@ -53,22 +56,6 @@ rust_library(
],
)

rust_library(
name = "hashbrown",
srcs = glob(["vendor/hashbrown-0.12.3/src/**/*.rs"]),
crate_features = ["raw"],
edition = "2021",
)

rust_library(
name = "indexmap",
srcs = glob(["vendor/indexmap-1.9.1/src/**/*.rs"]),
crate_features = ["std"],
edition = "2021",
rustc_flags = ["--cfg=has_std"],
deps = [":hashbrown"],
)

rust_library(
name = "once_cell",
srcs = glob(["vendor/once_cell-1.15.0/src/**/*.rs"]),
Expand Down Expand Up @@ -185,13 +172,6 @@ rust_library(
edition = "2018",
)

rust_library(
name = "textwrap",
srcs = glob(["vendor/textwrap-0.15.1/src/**/*.rs"]),
edition = "2018",
deps = [":unicode-width"],
)

rust_library(
name = "unicode-ident",
srcs = glob(["vendor/unicode-ident-1.0.4/src/**/*.rs"]),
Expand Down