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

Add "Converting an existing Component to use UniFFI" howto [ci skip] #4004

Merged
merged 2 commits into from
Apr 1, 2021

Conversation

rfk
Copy link
Contributor

@rfk rfk commented Mar 31, 2021

Rendered View

@lougeniaC64 @mhammond, pinging you both for review here because I hope you will both find yourselves either doing this or walking someone else through it in the near-to-mid-term future.

```

In future, we intend to automatically extract documentation from the Rust code
and make it easily available to consumers of the generated bindings.
Copy link
Contributor Author

Choose a reason for hiding this comment

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

What I would like to write here is "run this cool script to copy the doc comments over into your UDL file" but I'm not sure that can be run by anyone but me currently. I'll take a look at what would be required to let that be runnable by someone else...

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@mhammond what do you think, is it worth me trying to make the automagical "copy docstrings from the Rust code into the UDL" functionality from mozilla/uniffi-rs#416 into something more generally usable, or is that just getting ahead of ourselves?

Copy link
Member

Choose a reason for hiding this comment

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

In one day? :) I think would be valuable, but not at all urgent. Maybe leaving a breadcrumb here would be worthwhile?

Copy link
Member

@mhammond mhammond left a comment

Choose a reason for hiding this comment

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

This is awesome, thanks.

As we've gained more experience with building components in this way, we've
started to automated bindings generation and capture best practices in a
tool called [UniFFI](https://mozilla.github.io/uniffi-rs/), which is the
current recommended approach when [adding a new component from scratch](
Copy link
Member

Choose a reason for hiding this comment

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

trivial nit that's probably not even correct - 'currently'?

* The low-level `LibComponentNameFFI.kt` file will disappear entirely, as will some of the
code that converts it back into nice high-level Kotlin classes and interfaces.
* Some of the hand-written Kotlin code may remain, if it provides functionality that
cannot be implemented in Rust.
Copy link
Member

Choose a reason for hiding this comment

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

nit: indentation (I only mention this because I'm too lazy to check whether it is rendered OK or not - ignore if so)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

it did not render ok, thanks for noticing!

The goal here is to replace much of the hand-written wrapper layers with autogenerated
code:

* The `./ffi/` crate will disappear entirely, its work is automated by UniFFI
Copy link
Member

Choose a reason for hiding this comment

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

Unless I misunderstand, if you are only doing a partial conversion, this might remain, right? If that's true, I think it might be worth setting the scene for that above - there are lots of places below which assume "will be removed", so I don't think it's worth trying to qualify that everwhere, but calling it out as an intro to this section might make sense.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

That's a good point, I hadn't really considered partial conversions here...I guess that would be for the case if there's something that UniFFI doesn't support yet, and you need to write your own pub extern "C" functions?

I think I would still argue that those functions should live in the main crate and be part of lib.rs and your top-level public API, rather than squirreled away in a separate ./ffi/ crate. But I could add some words to this effect if you think it would be helpful?

(In fact I don't really recall why we settled on this convention of having a separate ffi crate at all to be honest...)

Copy link
Member

Choose a reason for hiding this comment

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

Yes, that would be perfect - just a small note saying "things which are unable to be converted should be moved into lib.rs" would be perfect and about all the detail needed here.

cannot be implemented in Rust.
* The low-level `RustComponentNameAPI.h` file will disappear entirely, as will some of the
code that converts it back into nice high-level Swift classes and interfaces.
* Some of the hand-written Kotlin code may remain, if it provides functionality that
Copy link
Member

Choose a reason for hiding this comment

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

ditto indentation and s/Kotlin/Swift/ here?

it was using Protocol Buffers to serialize data to pass over the FFI. The message types
defined in the `.proto` file will need to be converted into `dictionary` or `enum` definitions
in your `.udl` file. See the section below for more details.

Copy link
Member

Choose a reason for hiding this comment

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

I'd consider adding a new point along the lines of "Don't be too concerned about making small changes to the 'spelling' of the API - if there are small differences in the names generated by uniffi vs what is in the hand-written FFI, it's probably in everyones interest to take that hit and update the consumers." - I see you do make that point a bit later, but IMO it's worth introducing it here.

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'm going to add this under the earlier "write a draft of the .udl" section and then reinforce it again at several points further down.

If it happen to find that you've deleted the last crate from the list in `protobuf_files.toml`,
congratulations! You've successfully removed protocol buffers from this repo entirely, and should
file a bug to track the complete removal of protobuf from our tooling and dependency chain.

Copy link
Member

Choose a reason for hiding this comment

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

Ditto the "Don't be concerned about small naming changes here" or similar?

previous hand-written ones. For example, UniFFI insists on CAMEL_CASING variant names in
Kotlin enums while the hand-written code does not to this consistently. Some components
also have small naming differences between the Rust code and the hand-written Kotlin bindings,
which UniFFI will not allow.
Copy link
Member

Choose a reason for hiding this comment

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

If you take the previous "don't be afraid" suggestions, maybe add here "As noted above"?

@rfk
Copy link
Contributor Author

rfk commented Apr 1, 2021

I'm going to go ahead and merge this (with nits addressed) so that I don't leave it hanging around while I'm on PTO, but @lougeniaC64 any feedback you may have is still very welcome.

@rfk rfk merged commit f3f0cf6 into main Apr 1, 2021
@rfk rfk deleted the document-uniffiying-a-component branch April 1, 2021 00:40
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.

2 participants