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

uniffi-bindgen-swift #2248

Merged
merged 2 commits into from
Oct 3, 2024
Merged

uniffi-bindgen-swift #2248

merged 2 commits into from
Oct 3, 2024

Conversation

bendk
Copy link
Contributor

@bendk bendk commented Sep 27, 2024

This is a uniffi-bindgen variant dedicated to Swift code, with options specialized for Swift. I'm currently thinking that we should consider doing this for all languages. In addition to allowing specialized options, it also makes the in-tree bindings less special-cased compared to external bindings.

Reverted #2235, which was an attempt to do something similar. I like this approach better because it supports more features, like xcframework compatible module maps. It's also a non-breaking change, so we can release it in a 0.28.2.

@bendk bendk requested a review from a team as a code owner September 27, 2024 14:05
@bendk bendk requested review from gruberb and a team and removed request for a team September 27, 2024 14:05
Copy link
Member

@gruberb gruberb left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a couple of comments. I really like the Swift focused options, I think this makes it very clear what we can (and have to do) in each scenario!

@@ -66,15 +67,10 @@ impl BindingGenerator for SwiftBindingGenerator {

fn update_component_configs(
&self,
settings: &GenerationSettings,
_settings: &GenerationSettings,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I personally would rather see changing the trait to Option<&GenerationSettings> instead.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is implemented for all the bindings though. Some bindings, like Python, currently need the GenerationSettings to be passed.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, we would need to change a lot of files.


#[derive(Debug, Args)]
#[group(required = true, multiple = true)]
struct Kinds {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it be helpful to have a default? Like "building .Xcframework" could be the default. So we can set the bool values accordingly.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A default sounds good, but I'm not sure what default you're suggesting. Is it --xcframework is the default and --no-xcframework would disable it? Or is it that generating one these kinds of sources is the default?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would say we could add the default to always be xcframework, which I think will be most of the time the case. We need Swift specific settings at the moment just for the documentation. So we could shorten the command when building for xcframework and don't have to pass any parameters.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After thinking about this a bit more, I'm not so sure. --no-xcframework seems a bit awkward as a flag. It's harder to describe since it's a negative, and it also sort-of implies that if you don't have it then you're building an xcframework somehow. Something like --not-for-xcframework is more precise and easier to describe, but much harder to type out.

How about we leave it as-is for now, we can always change the flag later.

| `module_name` | `{namespace}`[^1] | The name of the Swift module containing the high-level foreign-language bindings. |
| `ffi_module_name` | `{module_name}FFI` | The name of the lower-level C module containing the FFI declarations. |
| `ffi_module_filename` | `{ffi_module_name}` | The filename stem for the lower-level C module containing the FFI declarations. |
| `generate_module_map` | `true` | Whether to generate a `.modulemap` file for the lower-level C module with FFI declarations. Not valid when using `--library`, in library-mode the modulemap is always generated.
| `generate_module_map` | `true` | Whether to generate a `.modulemap` file for the lower-level C module with FFI declarations. (ignored by `uniffi-bindgen-swift`) |
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we add an example command for both a Swift and a .Xcframework?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added a bunch to docs/manual/src/swift/uniffi-bindgen-swift.md.

This is a `uniffi-bindgen` variant dedicated to Swift code, with options
specialized for Swift.  I'm currently thinking that we should consider
doing this for all languages.  In addition to allowing specialized
options, it also makes the in-tree bindings less special-cased compared
to external bindings.
@mhammond
Copy link
Member

mhammond commented Oct 3, 2024

I'm currently thinking that we should consider doing this for all languages

I think later we should try and push the implementation down to the bindings. If we treat ourselves more like external bindings, instead of top-level uniffi::uniffi_bindgen_main variants, we require an explicit dep on, say, uniffi_bindgen::swift::uniffi_bindgen_main and a uniffi-bindgen-swift binary?

ie, let uniffi_bindgen::swift, uniffi_bindgen::python etc all use clap and have their own cli driver. uniffi::cli becomes helper functions and b/w compat - but the "new" way to generate python bindings is uniffi-bindgen-python.

This means uniffi_bindgen takes the dep for clap - but in practice, the dep is already there. And later, if we move the bindings to their own crate, (ie,uniffi_bindgen_swift::uniffi_bindgen_main) - uniffi_bindgen then no longer needs clap and becomes more of an "internal" crate.

WDYT? Does that make any sense for gecko @bendk?

@bendk
Copy link
Contributor Author

bendk commented Oct 3, 2024

I'm currently thinking that we should consider doing this for all languages

I think later we should try and push the implementation down to the bindings. If we treat ourselves more like external bindings, instead of top-level uniffi::uniffi_bindgen_main variants, we require an explicit dep on, say, uniffi_bindgen::swift::uniffi_bindgen_main and a uniffi-bindgen-swift binary?

ie, let uniffi_bindgen::swift, uniffi_bindgen::python etc all use clap and have their own cli driver. uniffi::cli becomes helper functions and b/w compat - but the "new" way to generate python bindings is uniffi-bindgen-python.

This means uniffi_bindgen takes the dep for clap - but in practice, the dep is already there. And later, if we move the bindings to their own crate, (ie,uniffi_bindgen_swift::uniffi_bindgen_main) - uniffi_bindgen then no longer needs clap and becomes more of an "internal" crate.

WDYT? Does that make any sense for gecko @bendk?

That makes a lot of sense to me. The one thing I like about this PR is that there's both a programmatic API and a CLI. That way users can either just use the CLI or they can make their own tools. I think we're going to want to do the latter for app-services.

The way it's currently split up, only uniffi needs a clap dependency. That seems a kind of nice to me, but I would also be fine with moving the CLI code into uniffi_bindgen and adding the clap dependency there.

Gecko is very similar since we write our own CLI there. I definitely would like it if uniffi-bindgen-python and uniffi-bindgen-gecko-js were on similar footing.

@bendk bendk merged commit 3662c84 into mozilla:main Oct 3, 2024
5 checks passed
@bendk bendk deleted the push-uunuklpxuxzo branch October 3, 2024 15:30
@mhammond
Copy link
Member

mhammond commented Oct 4, 2024

Gecko is very similar since we write our own CLI there. I definitely would like it if uniffi-bindgen-python and uniffi-bindgen-gecko-js were on similar footing.

Yeah exactly - which implies uniffi:: can't know about python etc - and the only way I can see for that to work is to have no cli in uniffi?

@bendk
Copy link
Contributor Author

bendk commented Oct 7, 2024

Yeah exactly - which implies uniffi:: can't know about python etc - and the only way I can see for that to work is to have no cli in uniffi?

Good point. You've convinced me that we should move the clap code into uniffi_bindgen.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants