Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow the binding generator to not depend on builtin bindings. #2066

Merged
merged 1 commit into from
Apr 22, 2024
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
Allow the binding generator to not depend on builtin bindings.
Previously there were internal `Config` details which only worked with
builtin bindings types. This leans in to the `BindingGenerator` trait
to make things less coupled with the builtin bindings and better
for external bindings.

Follows up on #1991.
  • Loading branch information
mhammond committed Apr 19, 2024
commit f5558428a98889ed80a1611efae70c9c125c299b
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@
([#2073](https://github.com/mozilla/uniffi-rs/issues/2073))

### What's changed?
- The internal bindings generation has changed to make it friendlier for external language bindings.
However, this is likely to be a small **breaking change** for these bindings.
No consumers of any languages are impacted, only the maintainers of these language bindings.
([#2066](https://github.com/mozilla/uniffi-rs/issues/2066))

- The async runtime can be specified for constructors/methods, this will override the runtime specified at the impl block level.

[All changes in [[UnreleasedUniFFIVersion]]](https://github.com/mozilla/uniffi-rs/compare/v0.27.1...HEAD).
Expand Down
10 changes: 6 additions & 4 deletions fixtures/benchmarks/benches/benchmarks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@
use clap::Parser;
use std::env;
use uniffi_benchmarks::Args;
use uniffi_bindgen::bindings::{kotlin, python, swift, RunScriptOptions};
use uniffi_bindgen::bindings::{
kotlin_run_script, python_run_script, swift_run_script, RunScriptOptions,
};

fn main() {
let args = Args::parse();
Expand All @@ -18,7 +20,7 @@ fn main() {
};

if args.should_run_python() {
python::run_script(
python_run_script(
std::env!("CARGO_TARGET_TMPDIR"),
"uniffi-fixture-benchmarks",
"benches/bindings/run_benchmarks.py",
Expand All @@ -29,7 +31,7 @@ fn main() {
}

if args.should_run_kotlin() {
kotlin::run_script(
kotlin_run_script(
std::env!("CARGO_TARGET_TMPDIR"),
"uniffi-fixture-benchmarks",
"benches/bindings/run_benchmarks.kts",
Expand All @@ -40,7 +42,7 @@ fn main() {
}

if args.should_run_swift() {
swift::run_script(
swift_run_script(
std::env!("CARGO_TARGET_TMPDIR"),
"uniffi-fixture-benchmarks",
"benches/bindings/run_benchmarks.swift",
Expand Down
21 changes: 10 additions & 11 deletions fixtures/docstring-proc-macro/tests/test_generated_bindings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,7 @@ uniffi::build_foreign_language_testcases!(

#[cfg(test)]
mod tests {
use uniffi_bindgen::bindings::TargetLanguage;
use uniffi_bindgen::BindingGeneratorDefault;
use uniffi_bindgen::{bindings::*, BindingGenerator};
use uniffi_testing::UniFFITestHelper;

const DOCSTRINGS: &[&str] = &[
Expand Down Expand Up @@ -36,13 +35,16 @@ mod tests {
"<docstring-variant-field>",
];

fn test_docstring(language: TargetLanguage, file_extension: &str) {
fn test_docstring<T: BindingGenerator>(gen: T, file_extension: &str) {
let test_helper = UniFFITestHelper::new(std::env!("CARGO_PKG_NAME")).unwrap();

let out_dir = test_helper
.create_out_dir(
std::env!("CARGO_TARGET_TMPDIR"),
format!("test-docstring-proc-macro-{}", language),
format!(
"test-docstring-proc-macro-{}",
file_extension.to_string().replace('.', "")
),
)
.unwrap();

Expand All @@ -51,10 +53,7 @@ mod tests {
uniffi_bindgen::library_mode::generate_bindings(
&cdylib_path,
None,
&BindingGeneratorDefault {
target_languages: vec![language],
try_format_code: false,
},
&gen,
None,
&out_dir,
false,
Expand Down Expand Up @@ -88,16 +87,16 @@ mod tests {

#[test]
fn test_docstring_kotlin() {
test_docstring(TargetLanguage::Kotlin, "kt");
test_docstring(KotlinBindingGenerator, "kt");
}

#[test]
fn test_docstring_python() {
test_docstring(TargetLanguage::Python, "py");
test_docstring(PythonBindingGenerator, "py");
}

#[test]
fn test_docstring_swift() {
test_docstring(TargetLanguage::Swift, "swift");
test_docstring(SwiftBindingGenerator, "swift");
}
}
21 changes: 10 additions & 11 deletions fixtures/docstring/tests/test_generated_bindings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,7 @@ uniffi::build_foreign_language_testcases!(
#[cfg(test)]
mod tests {
use camino::Utf8PathBuf;
use uniffi_bindgen::bindings::TargetLanguage;
use uniffi_bindgen::BindingGeneratorDefault;
use uniffi_bindgen::{bindings::*, BindingGenerator};
use uniffi_testing::UniFFITestHelper;

const DOCSTRINGS: &[&str] = &[
Expand Down Expand Up @@ -36,23 +35,23 @@ mod tests {
"<docstring-record>",
];

fn test_docstring(language: TargetLanguage, file_extension: &str) {
fn test_docstring<T: BindingGenerator>(gen: T, file_extension: &str) {
let test_helper = UniFFITestHelper::new(std::env!("CARGO_PKG_NAME")).unwrap();

let out_dir = test_helper
.create_out_dir(
std::env!("CARGO_TARGET_TMPDIR"),
format!("test-docstring-{}", language),
format!(
"test-docstring-{}",
file_extension.to_string().replace('.', "")
),
)
.unwrap();

uniffi_bindgen::generate_bindings(
&Utf8PathBuf::from("src/docstring.udl"),
None,
BindingGeneratorDefault {
target_languages: vec![language],
try_format_code: false,
},
gen,
Some(&out_dir),
None,
None,
Expand Down Expand Up @@ -87,16 +86,16 @@ mod tests {

#[test]
fn test_docstring_kotlin() {
test_docstring(TargetLanguage::Kotlin, "kt");
test_docstring(KotlinBindingGenerator, "kt");
}

#[test]
fn test_docstring_python() {
test_docstring(TargetLanguage::Python, "py");
test_docstring(PythonBindingGenerator, "py");
}

#[test]
fn test_docstring_swift() {
test_docstring(TargetLanguage::Swift, "swift");
test_docstring(SwiftBindingGenerator, "swift");
}
}
123 changes: 111 additions & 12 deletions uniffi/src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,7 @@

use camino::Utf8PathBuf;
use clap::{Parser, Subcommand};
use uniffi_bindgen::bindings::TargetLanguage;
use uniffi_bindgen::BindingGeneratorDefault;
use uniffi_bindgen::bindings::*;

// Structs to help our cmdline parsing. Note that docstrings below form part
// of the "help" output.
Expand Down Expand Up @@ -79,6 +78,112 @@ enum Commands {
},
}

fn gen_library_mode(
library_path: &camino::Utf8Path,
crate_name: Option<String>,
languages: Vec<TargetLanguage>,
cfo: Option<&camino::Utf8Path>,
out_dir: &camino::Utf8Path,
fmt: bool,
) -> anyhow::Result<()> {
use uniffi_bindgen::library_mode::generate_bindings;
for language in languages {
// Type-bounds on trait implementations makes selecting between languages a bit tedious.
match language {
TargetLanguage::Kotlin => generate_bindings(
library_path,
crate_name.clone(),
&KotlinBindingGenerator,
cfo,
out_dir,
fmt,
)?
.len(),
TargetLanguage::Python => generate_bindings(
library_path,
crate_name.clone(),
&PythonBindingGenerator,
cfo,
out_dir,
fmt,
)?
.len(),
TargetLanguage::Ruby => generate_bindings(
library_path,
crate_name.clone(),
&RubyBindingGenerator,
cfo,
out_dir,
fmt,
)?
.len(),
TargetLanguage::Swift => generate_bindings(
library_path,
crate_name.clone(),
&SwiftBindingGenerator,
cfo,
out_dir,
fmt,
)?
.len(),
};
}
Ok(())
}

fn gen_bindings(
udl_file: &camino::Utf8Path,
cfo: Option<&camino::Utf8Path>,
languages: Vec<TargetLanguage>,
odo: Option<&camino::Utf8Path>,
library_file: Option<&camino::Utf8Path>,
crate_name: Option<&str>,
fmt: bool,
) -> anyhow::Result<()> {
use uniffi_bindgen::generate_bindings;
for language in languages {
match language {
TargetLanguage::Kotlin => generate_bindings(
udl_file,
cfo,
KotlinBindingGenerator,
odo,
library_file,
crate_name,
fmt,
)?,
TargetLanguage::Python => generate_bindings(
udl_file,
cfo,
PythonBindingGenerator,
odo,
library_file,
crate_name,
fmt,
)?,
TargetLanguage::Ruby => generate_bindings(
udl_file,
cfo,
RubyBindingGenerator,
odo,
library_file,
crate_name,
fmt,
)?,
TargetLanguage::Swift => generate_bindings(
udl_file,
cfo,
SwiftBindingGenerator,
odo,
library_file,
crate_name,
fmt,
)?,
};
}
Ok(())
}

pub fn run_main() -> anyhow::Result<()> {
let cli = Cli::parse();
match cli.command {
Expand All @@ -100,25 +205,19 @@ pub fn run_main() -> anyhow::Result<()> {
if language.is_empty() {
panic!("please specify at least one language with --language")
}
uniffi_bindgen::library_mode::generate_bindings(
gen_library_mode(
&source,
crate_name,
&BindingGeneratorDefault {
target_languages: language,
try_format_code: !no_format,
},
language,
config.as_deref(),
&out_dir,
!no_format,
)?;
} else {
uniffi_bindgen::generate_bindings(
gen_bindings(
&source,
config.as_deref(),
BindingGeneratorDefault {
target_languages: language,
try_format_code: !no_format,
},
language,
out_dir.as_deref(),
lib_file.as_deref(),
crate_name.as_deref(),
Expand Down
19 changes: 10 additions & 9 deletions uniffi/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,21 @@ pub use uniffi_macros::*;
#[cfg(feature = "cli")]
mod cli;
#[cfg(feature = "bindgen-tests")]
pub use uniffi_bindgen::bindings::kotlin::run_test as kotlin_run_test;
pub use uniffi_bindgen::bindings::kotlin_run_test;
#[cfg(feature = "bindgen-tests")]
pub use uniffi_bindgen::bindings::python::run_test as python_run_test;
pub use uniffi_bindgen::bindings::python_run_test;
#[cfg(feature = "bindgen-tests")]
pub use uniffi_bindgen::bindings::ruby::run_test as ruby_run_test;
pub use uniffi_bindgen::bindings::ruby_run_test;
#[cfg(feature = "bindgen-tests")]
pub use uniffi_bindgen::bindings::swift::run_test as swift_run_test;
pub use uniffi_bindgen::bindings::swift_run_test;
#[cfg(feature = "bindgen")]
pub use uniffi_bindgen::{
bindings::kotlin::gen_kotlin::KotlinBindingGenerator,
bindings::python::gen_python::PythonBindingGenerator,
bindings::ruby::gen_ruby::RubyBindingGenerator,
bindings::swift::gen_swift::SwiftBindingGenerator, bindings::TargetLanguage, generate_bindings,
generate_component_scaffolding, generate_component_scaffolding_for_crate, print_repr,
bindings::{
KotlinBindingGenerator, PythonBindingGenerator, RubyBindingGenerator,
SwiftBindingGenerator, TargetLanguage,
},
generate_bindings, generate_component_scaffolding, generate_component_scaffolding_for_crate,
print_repr,
};
#[cfg(feature = "build")]
pub use uniffi_build::{generate_scaffolding, generate_scaffolding_for_crate};
Expand Down
Loading