Skip to content

Commit 717fcef

Browse files
Add parse-bridges CLI subcommand (#274)
## What's this? A new `parse-bridges` subcommand. Also, an update to the documentation in the example showing this feature's preview. This is handy for usage in higher-level build systems. For example, in my case, I build both Rust and Swift with CMake, and having this CLI command implemented would allow generating the glue code from CMake as well, as a dependency step before building Rust/Swift targets (via `add_custom_target` API). ## Notes One caveat of the current implementation is that one would have to duplicate the crate name in the invocation line (the first argument). This is fine for cases like mine, where this would be taken from the build system anyway, but it may not be handy for other cases. The package name can be automatically deduced if one's running in the correct directory (the package root). In this case, we can parse the `cargo read-manifest` output and get the name from there. This would require a new dependency, though (`serde_json`), so I decided not to do this just yet, but if this sounds okay to you, I'll go ahead and implement this as well. ## Examples Single file: ```shell swift-bridge-cli parse-bridges --crate-name my-awesome-crate -f src/lib.rs -o generated ``` Multiple files: ```shell swift-bridge-cli parse-bridges --crate-name my-superb-crate \ -f src/lib.rs \ -f src/some_other_file.rs \ -o generated ```
1 parent ef01d21 commit 717fcef

File tree

4 files changed

+59
-25
lines changed

4 files changed

+59
-25
lines changed

book/src/building/swiftc-and-cargo/README.md

Lines changed: 7 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ func run() {
7070
```
7171

7272
```sh
73-
# briding-header.h
73+
# bridging-header.h
7474

7575
#ifndef BridgingHeader_h
7676
#define BridgingHeader_h
@@ -134,25 +134,13 @@ chmod +x build-swiftc-links-rust.sh
134134

135135
## Rust links to a Swift native library
136136

137-
Unlike the when we had `swiftc` in the Rust code, you do not need to set the `crate-type`
137+
Unlike when we had `swiftc` linking in the Rust code, you do not need to set the `crate-type`
138138
when you have `Cargo` linking in the Swift code.
139139

140140
```rust
141141
// build.rs
142-
use std::path::PathBuf;
143-
144142
fn main() {
145-
let out_dir = PathBuf::from("./generated");
146-
147-
let bridges = vec!["src/lib.rs"];
148-
for path in &bridges {
149-
println!("cargo:rerun-if-changed={}", path);
150-
}
151-
152-
swift_bridge_build::parse_bridges(bridges)
153-
.write_all_concatenated(out_dir, env!("CARGO_PKG_NAME"));
154-
155-
println!("cargo:rustc-link-lib=static=swiftc_link_rust");
143+
println!("cargo:rustc-link-lib=static=my_swift");
156144
println!("cargo:rustc-link-search=./");
157145
}
158146
```
@@ -163,9 +151,10 @@ fn main() {
163151
#!/bin/bash
164152
set -e
165153

166-
# The swift-bridge CLI does not exist yet. Open an issue if you need to use
167-
# this approach and I'll happily whip up the CLI.
168-
swift-bridge -f src/lib.rs > generated
154+
# Generate the bridging headers.
155+
# Multiple files can be supplied with "-f" flag, e.g. "-f file1 -f file2".
156+
# Substitute <package name> for the crate name in your Cargo.toml file.
157+
swift-bridge-cli parse-bridges --crate-name <package name> -f src/lib.rs -o generated
169158

170159
swiftc -emit-library -static -module-name my_swift -import-objc-header bridging-header.h \
171160
lib.swift ./generated/swift-and-rust/swift-and-rust.swift

crates/swift-bridge-cli/src/clap_app.rs

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use clap::{Arg, Command};
1+
use clap::{Arg, ArgAction, Command};
22

33
/// The CLI application
44
pub fn cli() -> Command<'static> {
@@ -7,6 +7,7 @@ pub fn cli() -> Command<'static> {
77
.version(env!("CARGO_PKG_VERSION"))
88
.subcommand_required(true)
99
.subcommand(create_package_command())
10+
.subcommand(create_bridges_command())
1011
}
1112

1213
/// The command for creating a Swift Package
@@ -101,3 +102,35 @@ fn create_package_command() -> Command<'static> {
101102
.help("The name for the Swift Package"),
102103
)
103104
}
105+
106+
fn create_bridges_command() -> Command<'static> {
107+
Command::new("parse-bridges")
108+
.about("Parse bridge library files and output generated headers")
109+
.arg(
110+
Arg::new("crate-name")
111+
.action(ArgAction::Set)
112+
.help(
113+
"Crate name for which the bridging headers are generated; \
114+
used as a part of header names",
115+
)
116+
.long("--crate-name")
117+
.required(true),
118+
)
119+
.arg(
120+
Arg::new("source-file")
121+
.action(ArgAction::Append)
122+
.help("source file(s) containing #[swift_bridge::bridge] macro")
123+
.long("file")
124+
.short('f')
125+
.required(true),
126+
)
127+
.arg(
128+
Arg::new("output")
129+
.action(ArgAction::Set)
130+
.help("Output destination folder")
131+
.long("output")
132+
.short('o')
133+
.value_name("PATH")
134+
.required(true),
135+
)
136+
}

crates/swift-bridge-cli/src/clap_exec.rs

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,16 @@
11
use clap::ArgMatches;
22
use std::collections::HashMap;
33
use std::path::{Path, PathBuf};
4-
use swift_bridge_build::{create_package, ApplePlatform, CreatePackageConfig};
4+
use swift_bridge_build::{create_package, parse_bridges, ApplePlatform, CreatePackageConfig};
55

66
/// Executes the correct function depending on the cli input
77
pub fn handle_matches(matches: ArgMatches) {
88
match matches.subcommand_name() {
9-
Some("create-package") => {
10-
handle_create_package(matches.subcommand_matches("create-package").unwrap())
9+
Some(cmd @ "create-package") => {
10+
handle_create_package(matches.subcommand_matches(cmd).unwrap())
11+
}
12+
Some(cmd @ "parse-bridges") => {
13+
handle_parse_bridges(matches.subcommand_matches(cmd).unwrap())
1114
}
1215
_ => unreachable!("No subcommand or unknown subcommand given"), // Shouldn't happen
1316
}
@@ -16,7 +19,7 @@ pub fn handle_matches(matches: ArgMatches) {
1619
/// Executes the `create-package` command
1720
fn handle_create_package(matches: &ArgMatches) {
1821
let bridges_dir = matches.value_of("bridges-dir").unwrap(); // required
19-
let out_dir = matches.value_of("out-dir").map(|p| Path::new(p)).unwrap(); // required
22+
let out_dir = matches.value_of("out-dir").map(Path::new).unwrap(); // required
2023
let name = matches.value_of("name").unwrap(); // required
2124

2225
let mut config = CreatePackageConfig {
@@ -34,3 +37,12 @@ fn handle_create_package(matches: &ArgMatches) {
3437

3538
create_package(config);
3639
}
40+
41+
/// Executes the `parse-bridges` command
42+
fn handle_parse_bridges(matches: &ArgMatches) {
43+
let crate_name = matches.get_one::<String>("crate-name").unwrap(); // required
44+
let source_files: Vec<&String> = matches.get_many("source-file").unwrap().collect(); // required
45+
let output = matches.get_one::<String>("output").map(Path::new).unwrap(); // required
46+
47+
parse_bridges(source_files.iter().map(Path::new)).write_all_concatenated(output, crate_name);
48+
}

crates/swift-bridge-macro/tests/ui/args-into-argument-not-found.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,12 @@ mod ffi {
1515
}
1616
}
1717

18-
fn some_function(arg: u8) {}
18+
fn some_function(_arg: u8) {}
1919

2020
struct SomeType;
2121

2222
impl SomeType {
23-
fn some_method(&self, foo: u8) {}
23+
fn some_method(&self, _foo: u8) {}
2424
}
2525

2626
fn main() {}

0 commit comments

Comments
 (0)