Skip to content
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions uniffi/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -68,3 +68,9 @@ name = "uniffi-bindgen"
path = "uniffi-bindgen.rs"
required-features = ["cli"]
doc = false

[[bin]]
name = "uniffi-bindgen-swift"
path = "uniffi-bindgen-swift.rs"
required-features = ["cli"]
doc = false
7 changes: 4 additions & 3 deletions uniffi/src/cli/swift.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,9 @@ use uniffi_bindgen::bindings::{generate_swift_bindings, SwiftBindingsOptions};
struct Cli {
#[command(flatten)]
kinds: Kinds,
/// Library path to generate bindings for
library_path: Utf8PathBuf,
#[clap(name = "PATH_TO_LIBRARY_OR_UDL")]
/// UDL File / path to generate bindings for
source: Utf8PathBuf,
/// Directory to generate files in
out_dir: Utf8PathBuf,
/// Generate a XCFramework-compatible modulemap
Expand Down Expand Up @@ -65,7 +66,7 @@ impl From<Cli> for SwiftBindingsOptions {
generate_swift_sources: cli.kinds.swift_sources,
generate_headers: cli.kinds.headers,
generate_modulemap: cli.kinds.modulemap,
library_path: cli.library_path,
source: cli.source,
out_dir: cli.out_dir,
xcframework: cli.xcframework,
module_name: cli.module_name,
Expand Down
9 changes: 9 additions & 0 deletions uniffi/uniffi-bindgen-swift.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use uniffi::uniffi_bindgen_swift;

fn main() {
uniffi_bindgen_swift();
}
50 changes: 23 additions & 27 deletions uniffi_bindgen/src/bindings/swift/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@
//! * How to read from and write into a byte buffer.
//!

use crate::{BindingGenerator, Component, GenerationSettings};
use anyhow::{Context, Result};
use crate::{BindgenLoader, BindingGenerator, Component, ComponentInterface, GenerationSettings};
use anyhow::Result;
use camino::Utf8PathBuf;
use fs_err as fs;
use std::process::Command;
Expand Down Expand Up @@ -147,6 +147,7 @@ pub fn generate_swift_bindings(options: SwiftBindingsOptions) -> Result<()> {
#[cfg(feature = "cargo-metadata")]
let config_supplier = {
use crate::cargo_metadata::CrateConfigSupplier;
use anyhow::Context;
let mut cmd = cargo_metadata::MetadataCommand::new();
if options.metadata_no_deps {
cmd.no_deps();
Expand All @@ -159,17 +160,10 @@ pub fn generate_swift_bindings(options: SwiftBindingsOptions) -> Result<()> {

fs::create_dir_all(&options.out_dir)?;

let mut components =
crate::library_mode::find_components(&options.library_path, &config_supplier)?
// map the TOML configs into a our Config struct
.into_iter()
.map(|Component { ci, config }| {
let config = SwiftBindingGenerator.new_config(&config.into())?;
Ok(Component { ci, config })
})
.collect::<Result<Vec<_>>>()?;
SwiftBindingGenerator
.update_component_configs(&GenerationSettings::default(), &mut components)?;
let loader = BindgenLoader::new(&config_supplier);
let metadata = loader.load_metadata(&options.source)?;
let cis = loader.load_cis(metadata)?;
let components = loader.load_components(cis, parse_config)?;

for Component { ci, config } in &components {
if options.generate_swift_sources {
Expand All @@ -185,24 +179,15 @@ pub fn generate_swift_bindings(options: SwiftBindingsOptions) -> Result<()> {
}
}

// find the library name by stripping the extension and leading `lib` from the library path
let library_name = {
let stem = options
.library_path
.file_stem()
.with_context(|| format!("Invalid library path {}", options.library_path))?;
match stem.strip_prefix("lib") {
Some(name) => name,
None => stem,
}
};
// Derive the default module_name/modulemap_filename from the source filename.
let source_basename = loader.source_basename(&options.source);

let module_name = options
.module_name
.unwrap_or_else(|| library_name.to_string());
.unwrap_or_else(|| source_basename.to_string());
let modulemap_filename = options
.modulemap_filename
.unwrap_or_else(|| format!("{library_name}.modulemap"));
.unwrap_or_else(|| format!("{source_basename}.modulemap"));

if options.generate_modulemap {
let mut header_filenames: Vec<_> = components
Expand All @@ -223,12 +208,23 @@ pub fn generate_swift_bindings(options: SwiftBindingsOptions) -> Result<()> {
Ok(())
}

fn parse_config(ci: &ComponentInterface, root_toml: toml::Value) -> Result<Config> {
let mut config: Config = match root_toml.get("bindings").and_then(|b| b.get("swift")) {
Some(v) => v.clone().try_into()?,
None => Default::default(),
};
config
.module_name
.get_or_insert_with(|| ci.namespace().into());
Ok(config)
}

#[derive(Debug, Default)]
pub struct SwiftBindingsOptions {
pub generate_swift_sources: bool,
pub generate_headers: bool,
pub generate_modulemap: bool,
pub library_path: Utf8PathBuf,
pub source: Utf8PathBuf,
pub out_dir: Utf8PathBuf,
pub xcframework: bool,
pub module_name: Option<String>,
Expand Down
3 changes: 3 additions & 0 deletions uniffi_bindgen/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ use std::process::Command;
pub mod bindings;
pub mod interface;
pub mod library_mode;
mod loader;
pub mod macro_metadata;
pub mod pipeline;
pub mod scaffolding;
Expand All @@ -120,6 +121,8 @@ pub use library_mode::find_components;
use scaffolding::RustScaffolding;
use uniffi_meta::Type;

pub use loader::BindgenLoader;

/// The options used when creating bindings. Named such
/// it doesn't cause confusion that it's settings specific to
/// the generator itself.
Expand Down
25 changes: 22 additions & 3 deletions uniffi_bindgen/src/library_mode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -107,10 +107,10 @@ pub fn calc_cdylib_name(library_path: &Utf8Path) -> Option<&str> {
/// calls.
///
/// `config_supplier` is used to find UDL files on disk and load config data.
pub fn find_components(
pub fn find_cis(
library_path: &Utf8Path,
config_supplier: &dyn BindgenCrateConfigSupplier,
) -> Result<Vec<Component<TomlTable>>> {
) -> Result<Vec<ComponentInterface>> {
let items = macro_metadata::extract_from_library(library_path)?;
let mut metadata_groups = create_metadata_groups(&items);
group_metadata(&mut metadata_groups, items)?;
Expand All @@ -137,10 +137,29 @@ pub fn find_components(
let crate_name = &group.namespace.crate_name;
let mut ci = ComponentInterface::new(crate_name);
ci.add_metadata(group)?;
ci.set_crate_to_namespace_map(crate_to_namespace_map.clone());
Ok(ci)
})
.collect()
}

/// Find UniFFI components from a shared library file
///
/// This method inspects the library file and creates [ComponentInterface] instances for each
/// component used to build it. It parses the UDL files from `uniffi::include_scaffolding!` macro
/// calls.
///
/// `config_supplier` is used to find UDL files on disk and load config data.
pub fn find_components(
library_path: &Utf8Path,
config_supplier: &dyn BindgenCrateConfigSupplier,
) -> Result<Vec<Component<TomlTable>>> {
find_cis(library_path, config_supplier)?
.into_iter()
.map(|ci| {
let config = config_supplier
.get_toml(ci.crate_name())?
.unwrap_or_default();
ci.set_crate_to_namespace_map(crate_to_namespace_map.clone());
Ok(Component { ci, config })
})
.collect()
Expand Down
Loading