Skip to content
Open
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
Original file line number Diff line number Diff line change
Expand Up @@ -52,10 +52,7 @@ mod tests {

let config_supplier = {
use uniffi_bindgen::cargo_metadata::CrateConfigSupplier;
let metadata = cargo_metadata::MetadataCommand::new()
.exec()
.expect("error running cargo metadata");
CrateConfigSupplier::from(metadata)
CrateConfigSupplier::from_cargo_metadata_command(false).unwrap()
};

uniffi_bindgen::library_mode::generate_bindings(
Expand Down
29 changes: 14 additions & 15 deletions uniffi/src/cli/uniffi_bindgen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,13 @@
* 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 anyhow::{bail, Context, Result};
use anyhow::{bail, Result};
use camino::Utf8PathBuf;
use clap::{Args, Parser, Subcommand, ValueEnum};
use std::fmt;
use uniffi_bindgen::bindings::*;
use uniffi_bindgen::pipeline::initial;
use uniffi_bindgen::BindgenLoader;
use uniffi_pipeline::PrintOptions;

/// Enumeration of all foreign language targets currently supported by our CLI.
Expand Down Expand Up @@ -187,15 +188,10 @@ fn config_supplier(
metadata_no_deps: bool,
) -> Result<impl uniffi_bindgen::BindgenCrateConfigSupplier> {
#[cfg(feature = "cargo-metadata")]
{
use uniffi_bindgen::cargo_metadata::CrateConfigSupplier;
let mut cmd = cargo_metadata::MetadataCommand::new();
if metadata_no_deps {
cmd.no_deps();
}
let metadata = cmd.exec().context("error running cargo metadata")?;
Ok(CrateConfigSupplier::from(metadata))
}
return uniffi_bindgen::cargo_metadata::CrateConfigSupplier::from_cargo_metadata_command(
metadata_no_deps,
);

#[cfg(not(feature = "cargo-metadata"))]
Ok(uniffi_bindgen::EmptyCrateConfigSupplier)
}
Expand Down Expand Up @@ -330,11 +326,14 @@ pub fn run_main() -> anyhow::Result<()> {
.as_ref()
.expect("--out-dir is required when generating {language} bindings");
let config_supplier = config_supplier(metadata_no_deps)?;
let initial_root = if library_mode {
initial::Root::from_library(config_supplier, &source, crate_name.clone())?
} else {
initial::Root::from_udl(config_supplier, &source, crate_name.clone())?
};
let loader = BindgenLoader::new(&config_supplier);
// Note: we ignore `library_mode` in this case, `BindgenLoader` is smart enough to
// auto-detect the source type
let mut metadata = loader.load_metadata(&source)?;
if let Some(crate_name) = &crate_name {
loader.filter_metadata_by_crate_name(&mut metadata, crate_name);
}
let initial_root = loader.load_pipeline_initial_root(metadata)?;

match language {
TargetLanguage::Python => python::run_pipeline(initial_root, out_dir)?,
Expand Down
11 changes: 3 additions & 8 deletions uniffi_bindgen/src/bindings/swift/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -146,14 +146,9 @@ impl BindingGenerator for SwiftBindingGenerator {
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();
}
let metadata = cmd.exec().context("error running cargo metadata")?;
CrateConfigSupplier::from(metadata)
crate::cargo_metadata::CrateConfigSupplier::from_cargo_metadata_command(
options.metadata_no_deps,
)?
};
#[cfg(not(feature = "cargo-metadata"))]
let config_supplier = crate::EmptyCrateConfigSupplier;
Expand Down
17 changes: 14 additions & 3 deletions uniffi_bindgen/src/cargo_metadata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
//! Helpers for data returned by cargo_metadata. Note that this doesn't
//! execute cargo_metadata, just parses its output.

use anyhow::{bail, Context};
use anyhow::{bail, Context, Result};
use camino::Utf8PathBuf;
use cargo_metadata::Metadata;
use std::{collections::HashMap, fs};
Expand All @@ -17,16 +17,27 @@ pub struct CrateConfigSupplier {
paths: HashMap<String, Utf8PathBuf>,
}

impl CrateConfigSupplier {
pub fn from_cargo_metadata_command(no_deps: bool) -> Result<Self> {
let mut cmd = cargo_metadata::MetadataCommand::new();
if no_deps {
cmd.no_deps();
}
let metadata = cmd.exec().context("error running cargo metadata")?;
Ok(Self::from(metadata))
}
}

impl BindgenCrateConfigSupplier for CrateConfigSupplier {
fn get_toml(&self, crate_name: &str) -> anyhow::Result<Option<toml::value::Table>> {
fn get_toml(&self, crate_name: &str) -> Result<Option<toml::value::Table>> {
crate::load_toml_file(self.get_toml_path(crate_name).as_deref())
}

fn get_toml_path(&self, crate_name: &str) -> Option<Utf8PathBuf> {
self.paths.get(crate_name).map(|p| p.join("uniffi.toml"))
}

fn get_udl(&self, crate_name: &str, udl_name: &str) -> anyhow::Result<String> {
fn get_udl(&self, crate_name: &str, udl_name: &str) -> Result<String> {
let path = self
.paths
.get(crate_name)
Expand Down
64 changes: 61 additions & 3 deletions uniffi_bindgen/src/loader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ use uniffi_meta::{
};

use crate::{
crate_name_from_cargo_toml, macro_metadata, BindgenCrateConfigSupplier, Component,
ComponentInterface, Result,
crate_name_from_cargo_toml, interface, macro_metadata, pipeline, BindgenCrateConfigSupplier,
Component, ComponentInterface, Result,
};

/// Load metadata, component interfaces, configuration, etc. for binding generators.
Expand Down Expand Up @@ -61,7 +61,9 @@ impl<'config> BindgenLoader<'config> {
match source_path.extension() {
Some(ext) if ext.to_lowercase() == "udl" => {
let crate_name = crate_name_from_cargo_toml(source_path)?;
let group = uniffi_udl::parse_udl(&fs::read_to_string(source_path)?, &crate_name)?;
let mut group =
uniffi_udl::parse_udl(&fs::read_to_string(source_path)?, &crate_name)?;
Self::add_checksums(&mut group);
Ok(HashMap::from([(crate_name, group)]))
}
_ => {
Expand All @@ -88,6 +90,39 @@ impl<'config> BindgenLoader<'config> {
}
}

/// Add checksums for metadata parsed from UDL
fn add_checksums(metadata_group: &mut MetadataGroup) {
// Need to temporarily take items BTree set, since we're technically mutating it's contents
// Each item will be added back at the bottom of the for loop.
let items = std::mem::take(&mut metadata_group.items);
for mut meta in items {
// Make sure metadata checksums are set
match &mut meta {
Metadata::Func(func) => {
func.checksum = Some(uniffi_meta::checksum(&interface::Function::from(
func.clone(),
)));
}
Metadata::Method(meth) => {
// making a method is mildly tricky as we need a type for self.
// for the purposes of a checksum we ignore self info from udl.
let method_object =
interface::Method::from_metadata(meth.clone(), uniffi_meta::Type::UInt8);
meth.checksum = Some(uniffi_meta::checksum(&method_object));
}
Metadata::Constructor(cons) => {
cons.checksum = Some(uniffi_meta::checksum(&interface::Constructor::from(
cons.clone(),
)));
}
// Note: UDL-based callbacks don't have checksum functions, don't set the
// checksum for those.
_ => (),
}
metadata_group.items.insert(meta);
}
}

/// Load a [ComponentInterface] list
///
/// This converts the metadata into `ComponentInterface` instances, which contains additional
Expand Down Expand Up @@ -182,6 +217,25 @@ impl<'config> BindgenLoader<'config> {
.collect()
}

/// Load a [pipeline::initial::Root] value from the metadata
pub fn load_pipeline_initial_root(
&self,
metadata: MetadataGroupMap,
) -> Result<pipeline::initial::Root> {
let mut metadata_converter = pipeline::initial::UniffiMetaConverter::default();
for metadata_group in metadata.into_values() {
if let Some(docstring) = metadata_group.namespace_docstring {
metadata_converter
.add_module_docstring(metadata_group.namespace.name.clone(), docstring);
}
metadata_converter.add_metadata_item(Metadata::Namespace(metadata_group.namespace))?;
for meta in metadata_group.items {
metadata_converter.add_metadata_item(meta)?;
}
}
metadata_converter.try_into_initial_ir()
}

/// Get the basename for a source file
///
/// This will remove any file extension.
Expand All @@ -206,4 +260,8 @@ impl<'config> BindgenLoader<'config> {
Some(ext) if ext.to_lowercase() == "udl"
)
}

pub fn filter_metadata_by_crate_name(&self, metadata: &mut MetadataGroupMap, crate_name: &str) {
metadata.retain(|_, metadata_group| metadata_group.namespace.crate_name == crate_name)
}
}
2 changes: 1 addition & 1 deletion uniffi_bindgen/src/pipeline/initial/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ use anyhow::Result;
use camino::Utf8Path;

use crate::{crate_name_from_cargo_toml, interface, macro_metadata, BindgenCrateConfigSupplier};
use from_uniffi_meta::UniffiMetaConverter;
pub use from_uniffi_meta::UniffiMetaConverter;

impl Root {
pub fn from_library(
Expand Down