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 ruby adapter #436

Closed
wants to merge 10 commits into from
Closed

Add ruby adapter #436

wants to merge 10 commits into from

Conversation

saks
Copy link
Contributor

@saks saks commented May 6, 2021

Hey!

First of all, thanks for your hard work on this project. I really like the idea and the code quality that it produces for mobile platforms.

I was wondering if I can use uniffi-rs to generate ruby library in addition to swift and kotlin. While experimenting I have reached the point where the generated ruby code is good enough as a direct replacement to my FFI layer that was written by hand.

This adapter is by no mean on par with all features but it does provide basic integration that can be useful for starters. I happy to continue improving and maintaining this code.

FYI: this PR is heavily influenced and based on python integration.

Any feedback is very much appreciated!

@@ -47,6 +47,12 @@ jobs:
name: "Set RUSTFLAGS to fail the build if there are warnings"
command: echo 'export RUSTFLAGS="-D warnings"' >> $BASH_ENV
- checkout
- run:
name: "Install ruby"
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 step can certainly be added to the docker image if necessary

Copy link
Collaborator

Choose a reason for hiding this comment

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

Yep, I'd be happy to add it to the docker image, and that would make each individual test run go a little faster.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks!

Copy link
Collaborator

Choose a reason for hiding this comment

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

Would you mind preparing a separate PR that adds this to the docker image? I can land and publish that change first and then we can use it for CI on the rest of this PR.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sure thing! (#461)

Copy link
Collaborator

Choose a reason for hiding this comment

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

Great; I've pushed the updated docker image, so in theory we can remove this from the CircleCI config and everything should still run and pass 🤞🏻

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done 👍

FYI: I've noticed that docker image is built with rust 1.50.0 but then we install a different version based on rust-toolchain.toml (1.47.0 at the moment). I've been following why this repo uses a specific rust version, but I guess we can cut a bit of time from each test if we build docker image with rust 1.50.0. I can prepare a PR if this is useful :)

Copy link
Collaborator

Choose a reason for hiding this comment

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

FYI: I've noticed that docker image is built with rust 1.50.0 but then we install a different version based on
rust-toolchain.toml (1.47.0 at the moment).

Huh, so we do! I guess the scripting for the docker image there may pre-date our decision to pin to an earlier Rust. If you have a moment to prep a PR, that would be helpful, please do.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

hey @rfk, #463

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 looks good to me with a quick glance by someone who has never written Ruby :) It does raise a good question re CI and the level of support - I'm not sure that it should be a hard requirement that we never break the Ruby bindings. Or if we consider a future where more bindings are supported, there certainly will be some point where we need to declare that some bindings are "tier 1" and others are lower.

I'd welcome any thoughts on that.

Note that for various reasons, there might not be much movement on this PR for a week or few, but don't take that as a lack of interest.


// Some config options for it the caller wants to customize the generated ruby.
// Note that this can only be used to control details of the ruby *that do not affect the underlying component*,
// sine the details of the underlying component are entirely determined by the `ComponentInterface`.
Copy link
Member

Choose a reason for hiding this comment

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

typo - since

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks!

@mhammond
Copy link
Member

mhammond commented May 8, 2021

Might also be worth adding support for the new "coverall" fixture (#431) - there are significant changes coming (see the other various open PRs) which will cause some churn here, so getting base-level support in early might help you later :)

@saks
Copy link
Contributor Author

saks commented May 8, 2021

Thanks for pointing that out @mhammond! Done 👍
I'm totally fine further changes based on upcoming PRs, no worries.

I'm not sure that it should be a hard requirement that we never break the Ruby bindings

I certainly agree, please let me know if you have an idea on how to organize CI so that failed ruby tests will be easy to detect but these won't fail entire CI run.

@saks saks marked this pull request as ready for review May 11, 2021 14:10
@@ -47,6 +47,12 @@ jobs:
name: "Set RUSTFLAGS to fail the build if there are warnings"
command: echo 'export RUSTFLAGS="-D warnings"' >> $BASH_ENV
- checkout
- run:
name: "Install ruby"
Copy link
Collaborator

Choose a reason for hiding this comment

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

Yep, I'd be happy to add it to the docker image, and that would make each individual test run go a little faster.


fn is_reserved_word(word: &str) -> bool {
RESERVED_WORDS.contains(&word)
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

Ah yes, we've put off dealing with reserved words for far too long. We might be able to find a way to push some of the logic for handling this down into shared code.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

We might be able to find a way to push some of the logic for handling this down into shared code.

@rfk, sounds good. Do you think we should look into that as part of this PR?

Copy link
Collaborator

Choose a reason for hiding this comment

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

Do you think we should look into that as part of this PR?

No, unless you have any good ideas you'd like to explore. I think it's fine to start with figuring out how to handle it here in a specific language backend, and evolve the approach as we understand it better.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sounds good @rfk, I'd prefer to avoid scope creep and deal with one issue at the time. I'm open to look at it later as a separate PR.

@saks
Copy link
Contributor Author

saks commented May 21, 2021

hey @rfk! Is there anything that I can do to facilitate code review of this PR?

@rfk
Copy link
Collaborator

rfk commented May 24, 2021

Is there anything that I can do to facilitate code review of this PR?

@saks hey, thanks for asking - nothing specific yet, I have it on my stack to look at in detail this week.

One thing that's on my mind is how this will interact with some changes to the way we handle object references, which I'm hoping to also start landing this week (ref ADR-0004 and the proposed ADR-0005). These will mean that the handlemap-related parts of the Ruby backend will need to change, and I'm thinking it may be worth holding off on merging this until that work is complete, and asking you to rebase this PR on top of those changes. (I'll cross-reference the active PRs for that work from here when they're ready to be consumed).

Of course, I can still review the PR in its current state in order to give broader feedback, pending those changes.

Does that sound OK?

@saks
Copy link
Contributor Author

saks commented May 24, 2021

hey @rfk, thanks for getting back to me. I'm glad to see how UniFFI is evolving and I'm looking forward to new opportunities that both ADR-0004 and ADR-0005 would enable.

As for the ruby adapter, the code was prepared and tested with the current UniFFI architecture. Landing this PR before implementing upcoming changes can be beneficial since I can start migrating my projects from hand-written FFI layers into UniFFI and unblock implementation of new functionality.

At the same time I'm sympathetic to development plans for UniFFI and respect decisions made according to it. I'm happy to see what changes are going to be necessary to make ruby adapter work with new pointers handling and thread safety rules.

Thanks!

Copy link
Collaborator

@rfk rfk left a comment

Choose a reason for hiding this comment

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

With the very large caveat that I don't really know much Ruby, let alone idiomatic Ruby, this looks solid to me 👍🏻. I'm really happy to see that you went through and made Ruby versions of all the tests. Thanks again for your interest and for diving in here!

I think we can merge this, but I want to reinforce again that we'll have to treat it as a "best effort" maintenance situation. We'll try to keep it running while we work on new features for UniFFI, but if we need to get a new feature released and we can't figure out how to make it work for the Ruby backend, then we won't be able to block the release on getting it working in Ruby. (This is basically how we treat the current gecko_js backend as well, FWIW).

That said, I hope you'll stick around to help keep the Ruby backend running, and feel welcome to dive in to any discussions about new features! Please don't hesitate to open an issue or email me if there are things I can do to help you stay involved on an ongoing basis.

Longer term, I hope that we can find a way to decouple the development of specific language backends from all being in the same repo. Assuming that we do, I will probably advocate for the Ruby backend to move into its own separate repository (and the Python backend as well).

What I think we should do from here:

  • If you're happy to, please make a separate PR that just adds Ruby to the Docker image. I'll get that pushed and then we can update this PR to use it.
  • Please rebase this PR on top of current main, which I think will involve some minor conflicts in the test setup code.
  • I will finish up my current batch of work on replacing handlemaps, and see how much that's likely to affect the code here. Having had a closer look, I'm actually fairly hopeful that it won't conflict too badly.
  • With luck, I'll be able to apply my changes cleanly on top of this PR, in which case I'll go ahead and merge it while we keep working on those handlemap changes.

@@ -47,6 +47,12 @@ jobs:
name: "Set RUSTFLAGS to fail the build if there are warnings"
command: echo 'export RUSTFLAGS="-D warnings"' >> $BASH_ENV
- checkout
- run:
name: "Install ruby"
Copy link
Collaborator

Choose a reason for hiding this comment

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

Would you mind preparing a separate PR that adds this to the docker image? I can land and publish that change first and then we can use it for CI on the rest of this PR.

@@ -5,5 +5,8 @@ cdylib_name = "arithmetical"
[bindings.python]
cdylib_name = "arithmetical"

[bindings.ruby]
cdylib_name = "arithmetical"

Copy link
Collaborator

Choose a reason for hiding this comment

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

Note to self: we shouldn't need to repeat this individually for each binding backend in the config file 😬

(That's something we can improve in a future PR though)

assert_raise_message /expected panic: oh no/ do
coveralls.panic 'expected panic: oh no'
end
end
Copy link
Collaborator

Choose a reason for hiding this comment

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

Latest main has a new test here called test_self_by_arc, could you please rebase this on top of latest main and add an equivalent test here for Ruby?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done! Thanks for pointing that out :)

Type::Enum(name) => format!("{}::{}", class_name_rb(name)?, enum_name_rb(v)?),
_ => panic!("Unexpected type in enum literal: {:?}", type_),
},
// https://docs.ruby-lang.org/en/2.0.0/syntax/literals_rdoc.html
Copy link
Collaborator

Choose a reason for hiding this comment

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

Thanks for this link for context 👍🏻


{% when Type::CallbackInterface with (object_name) -%}
# The Callback Interface type {{ object_name }}.
# Objects cannot currently be serialized, but we can produce a helpful error.
Copy link
Collaborator

Choose a reason for hiding this comment

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

"Objects" should be "Callback Interfaces" here (this might be my own typo from the Python backend, but at least we can fix it up while we're in here 😄)

@rfk
Copy link
Collaborator

rfk commented May 26, 2021

This branch needs a couple of tweaks before final landing, for compatibility with other things that have merged to main. I'm going to go ahead and so those myself in a fresh PR over in #464 so that we can get this into a release for you to try out. Thanks again!

@rfk
Copy link
Collaborator

rfk commented May 26, 2021

Landed in 962320b

@rfk rfk closed this May 26, 2021
@rfk
Copy link
Collaborator

rfk commented May 27, 2021

The ruby adapter is now availalbe in the v0.10.0 release of UniFFI 🎉

@stan-irl stan-irl mentioned this pull request Dec 6, 2022
@saks saks deleted the rb branch October 19, 2024 06:24
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