Skip to content

Commit

Permalink
Add parse-bridges CLI subcommand (#274)
Browse files Browse the repository at this point in the history
## 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
```
  • Loading branch information
integer-overflown authored Jun 16, 2024
1 parent ef01d21 commit 717fcef
Show file tree
Hide file tree
Showing 4 changed files with 59 additions and 25 deletions.
25 changes: 7 additions & 18 deletions book/src/building/swiftc-and-cargo/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ func run() {
```

```sh
# briding-header.h
# bridging-header.h

#ifndef BridgingHeader_h
#define BridgingHeader_h
Expand Down Expand Up @@ -134,25 +134,13 @@ chmod +x build-swiftc-links-rust.sh

## Rust links to a Swift native library

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

```rust
// build.rs
use std::path::PathBuf;

fn main() {
let out_dir = PathBuf::from("./generated");

let bridges = vec!["src/lib.rs"];
for path in &bridges {
println!("cargo:rerun-if-changed={}", path);
}

swift_bridge_build::parse_bridges(bridges)
.write_all_concatenated(out_dir, env!("CARGO_PKG_NAME"));

println!("cargo:rustc-link-lib=static=swiftc_link_rust");
println!("cargo:rustc-link-lib=static=my_swift");
println!("cargo:rustc-link-search=./");
}
```
Expand All @@ -163,9 +151,10 @@ fn main() {
#!/bin/bash
set -e

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

swiftc -emit-library -static -module-name my_swift -import-objc-header bridging-header.h \
lib.swift ./generated/swift-and-rust/swift-and-rust.swift
Expand Down
35 changes: 34 additions & 1 deletion crates/swift-bridge-cli/src/clap_app.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use clap::{Arg, Command};
use clap::{Arg, ArgAction, Command};

/// The CLI application
pub fn cli() -> Command<'static> {
Expand All @@ -7,6 +7,7 @@ pub fn cli() -> Command<'static> {
.version(env!("CARGO_PKG_VERSION"))
.subcommand_required(true)
.subcommand(create_package_command())
.subcommand(create_bridges_command())
}

/// The command for creating a Swift Package
Expand Down Expand Up @@ -101,3 +102,35 @@ fn create_package_command() -> Command<'static> {
.help("The name for the Swift Package"),
)
}

fn create_bridges_command() -> Command<'static> {
Command::new("parse-bridges")
.about("Parse bridge library files and output generated headers")
.arg(
Arg::new("crate-name")
.action(ArgAction::Set)
.help(
"Crate name for which the bridging headers are generated; \
used as a part of header names",
)
.long("--crate-name")
.required(true),
)
.arg(
Arg::new("source-file")
.action(ArgAction::Append)
.help("source file(s) containing #[swift_bridge::bridge] macro")
.long("file")
.short('f')
.required(true),
)
.arg(
Arg::new("output")
.action(ArgAction::Set)
.help("Output destination folder")
.long("output")
.short('o')
.value_name("PATH")
.required(true),
)
}
20 changes: 16 additions & 4 deletions crates/swift-bridge-cli/src/clap_exec.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
use clap::ArgMatches;
use std::collections::HashMap;
use std::path::{Path, PathBuf};
use swift_bridge_build::{create_package, ApplePlatform, CreatePackageConfig};
use swift_bridge_build::{create_package, parse_bridges, ApplePlatform, CreatePackageConfig};

/// Executes the correct function depending on the cli input
pub fn handle_matches(matches: ArgMatches) {
match matches.subcommand_name() {
Some("create-package") => {
handle_create_package(matches.subcommand_matches("create-package").unwrap())
Some(cmd @ "create-package") => {
handle_create_package(matches.subcommand_matches(cmd).unwrap())
}
Some(cmd @ "parse-bridges") => {
handle_parse_bridges(matches.subcommand_matches(cmd).unwrap())
}
_ => unreachable!("No subcommand or unknown subcommand given"), // Shouldn't happen
}
Expand All @@ -16,7 +19,7 @@ pub fn handle_matches(matches: ArgMatches) {
/// Executes the `create-package` command
fn handle_create_package(matches: &ArgMatches) {
let bridges_dir = matches.value_of("bridges-dir").unwrap(); // required
let out_dir = matches.value_of("out-dir").map(|p| Path::new(p)).unwrap(); // required
let out_dir = matches.value_of("out-dir").map(Path::new).unwrap(); // required
let name = matches.value_of("name").unwrap(); // required

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

create_package(config);
}

/// Executes the `parse-bridges` command
fn handle_parse_bridges(matches: &ArgMatches) {
let crate_name = matches.get_one::<String>("crate-name").unwrap(); // required
let source_files: Vec<&String> = matches.get_many("source-file").unwrap().collect(); // required
let output = matches.get_one::<String>("output").map(Path::new).unwrap(); // required

parse_bridges(source_files.iter().map(Path::new)).write_all_concatenated(output, crate_name);
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,12 @@ mod ffi {
}
}

fn some_function(arg: u8) {}
fn some_function(_arg: u8) {}

struct SomeType;

impl SomeType {
fn some_method(&self, foo: u8) {}
fn some_method(&self, _foo: u8) {}
}

fn main() {}

0 comments on commit 717fcef

Please sign in to comment.