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 camino::Utf8PathBuf;
6 use clap::{Parser, Subcommand};
7 use uniffi_bindgen::bindings::TargetLanguage;
8 use uniffi_bindgen::BindingGeneratorDefault;
9
10 // Structs to help our cmdline parsing. Note that docstrings below form part
11 // of the "help" output.
12
13 /// Scaffolding and bindings generator for Rust
14 #[derive(Parser)]
15 #[clap(name = "uniffi-bindgen")]
16 #[clap(version = clap::crate_version!())]
17 #[clap(propagate_version = true)]
18 struct Cli {
19 #[clap(subcommand)]
20 command: Commands,
21 }
22
23 #[derive(Subcommand)]
24 enum Commands {
25 /// Generate foreign language bindings
26 Generate {
27 /// Foreign language(s) for which to build bindings.
28 #[clap(long, short, value_enum)]
29 language: Vec<TargetLanguage>,
30
31 /// Directory in which to write generated files. Default is same folder as .udl file.
32 #[clap(long, short)]
33 out_dir: Option<Utf8PathBuf>,
34
35 /// Do not try to format the generated bindings.
36 #[clap(long, short)]
37 no_format: bool,
38
39 /// Path to optional uniffi config file. This config is merged with the `uniffi.toml` config present in each crate, with its values taking precedence.
40 #[clap(long, short)]
41 config: Option<Utf8PathBuf>,
42
43 /// Extract proc-macro metadata from a native lib (cdylib or staticlib) for this crate.
44 #[clap(long)]
45 lib_file: Option<Utf8PathBuf>,
46
47 /// Pass in a cdylib path rather than a UDL file
48 #[clap(long = "library")]
49 library_mode: bool,
50
51 /// When `--library` is passed, only generate bindings for one crate.
52 /// When `--library` is not passed, use this as the crate name instead of attempting to
53 /// locate and parse Cargo.toml.
54 #[clap(long = "crate")]
55 crate_name: Option<String>,
56
57 /// Path to the UDL file, or cdylib if `library-mode` is specified
58 source: Utf8PathBuf,
59 },
60
61 /// Generate Rust scaffolding code
62 Scaffolding {
63 /// Directory in which to write generated files. Default is same folder as .udl file.
64 #[clap(long, short)]
65 out_dir: Option<Utf8PathBuf>,
66
67 /// Do not try to format the generated bindings.
68 #[clap(long, short)]
69 no_format: bool,
70
71 /// Path to the UDL file.
72 udl_file: Utf8PathBuf,
73 },
74
75 /// Print a debug representation of the interface from a dynamic library
76 PrintRepr {
77 /// Path to the library file (.so, .dll, .dylib, or .a)
78 path: Utf8PathBuf,
79 },
80 }
81
run_main() -> anyhow::Result<()>82 pub fn run_main() -> anyhow::Result<()> {
83 let cli = Cli::parse();
84 match cli.command {
85 Commands::Generate {
86 language,
87 out_dir,
88 no_format,
89 config,
90 lib_file,
91 source,
92 crate_name,
93 library_mode,
94 } => {
95 if library_mode {
96 if lib_file.is_some() {
97 panic!("--lib-file is not compatible with --library.")
98 }
99 let out_dir = out_dir.expect("--out-dir is required when using --library");
100 if language.is_empty() {
101 panic!("please specify at least one language with --language")
102 }
103 uniffi_bindgen::library_mode::generate_bindings(
104 &source,
105 crate_name,
106 &BindingGeneratorDefault {
107 target_languages: language,
108 try_format_code: !no_format,
109 },
110 config.as_deref(),
111 &out_dir,
112 !no_format,
113 )?;
114 } else {
115 uniffi_bindgen::generate_bindings(
116 &source,
117 config.as_deref(),
118 BindingGeneratorDefault {
119 target_languages: language,
120 try_format_code: !no_format,
121 },
122 out_dir.as_deref(),
123 lib_file.as_deref(),
124 crate_name.as_deref(),
125 !no_format,
126 )?;
127 }
128 }
129 Commands::Scaffolding {
130 out_dir,
131 no_format,
132 udl_file,
133 } => {
134 uniffi_bindgen::generate_component_scaffolding(
135 &udl_file,
136 out_dir.as_deref(),
137 !no_format,
138 )?;
139 }
140 Commands::PrintRepr { path } => {
141 uniffi_bindgen::print_repr(&path)?;
142 }
143 };
144 Ok(())
145 }
146