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

Rust support #226

Closed
wants to merge 11 commits into from
Closed

Rust support #226

wants to merge 11 commits into from

Conversation

damienmg
Copy link

@damienmg damienmg commented Jun 1, 2018

Add support for the rust language.

This also adds the support for output_to_libsubdir so we can create a crates directly. This start to have a lot of output_to_xxx in the proto_language and I wonder if that would not make sense to simply make that a enum like.

I will update this PR as soon as bazelbuild/rules_rust#90 is merged to point to upstream

@damienmg
Copy link
Author

damienmg commented Jun 1, 2018

/cc @pcj @acmcarther @mhlopko

This is a preliminary work for Rust support. This the result of running
cargo raze on the grpc-rust crate at the 0.4.0 version with protobuf crates
removed (since we import them directly).
@damienmg
Copy link
Author

damienmg commented Jun 1, 2018

And now with tests

@damienmg
Copy link
Author

damienmg commented Jun 1, 2018

For some reason Travis fails in some python tests...

@pcj
Copy link
Contributor

pcj commented Jun 2, 2018

@damienmg This is great work.

  1. Can you provide more context on why the generated cargo-raze files need to be checked in?
  2. Can we document how to regenerate those files (did I miss it)?

Looking into the travis failure, not seeing why it would be related to this change. Otherwise should be able to get this merged soon.

@damienmg
Copy link
Author

damienmg commented Jun 3, 2018

@pcj:

  1. I think that would be great to simply have cargo_crarte rules that would generate those file but cargo raze use cargo cache to generate those file so I am not sure how easy it would be. /cc @acmcarther

  2. Sorry there was none, I changed the format with some CL to make it easier to regenerate. Now all the deps are generated using cargo raze and the small shell wrapper simply rewrite the build file labels.

WDYT?

@damienmg
Copy link
Author

damienmg commented Jun 3, 2018

(Also: if you wish I can try to rewrite the history of that branch to skip all the BUILD file CL and only have one)

@pcj
Copy link
Contributor

pcj commented Jun 3, 2018

No need, I'll just squash it when merging.

Copy link

@acmcarther acmcarther left a comment

Choose a reason for hiding this comment

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

Thanks for this CL! Its a major step forward I think for the Rust-Bazel story.

Its going to take me a bit longer for a real rigorous review as I'm traveling this week. A couple of initial questions here, plus a more general statement:


I'm not convinced that cargo-raze is ready to play this kind of role in a library yet particularly because it doesn't have a good story w.r.t. platform management. In the current implementation, you've provided BUILD files for x86_64-unknown-linux-gnu. This will probably end poorly if someone tries to use these rules for another platform.

Your comments above gave me a pretty good idea of how to work toward a solution to this problem though and I'm going to be thinking about it and documenting that thinking in the cargo-raze repo this week.

README.md Outdated
| [Objective-C](objc) | [objc_proto_compile](objc#objc_proto_compile) | [objc_proto_library](objc#objc_proto_library) <sup>4</sup> | [v1.6.1](https://github.com/grpc/grpc/commit/f5600e99be0fdcada4b3039c0f656a305264884a) |
| [Python](python) | [py_proto_compile](python#py_proto_compile) | [py_proto_library](python#py_proto_library) | [v1.6.1](https://github.com/grpc/grpc/commit/f5600e99be0fdcada4b3039c0f656a305264884a) |
| [Ruby](ruby) | [ruby_proto_compile](ruby#ruby_proto_compile) | | [v1.6.1](https://github.com/grpc/grpc/commit/f5600e99be0fdcada4b3039c0f656a305264884a) |
| [Rust](rust) | [rust_proto_compile](rust#rust_proto_compile) | | [v1.6.1](https://github.com/grpc/grpc/commit/f5600e99be0fdcada4b3039c0f656a305264884a) |

Choose a reason for hiding this comment

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

Add rust_proto_library here as well?

Copy link
Author

Choose a reason for hiding this comment

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

Done.

"@org_pubref_rules_protobuf//rust/raze:protobuf",
]

GRPC_COMPILE_DEPS = PB_COMPILE_DEPS + [
Copy link

@acmcarther acmcarther Jun 4, 2018

Choose a reason for hiding this comment

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

I think these need to be a (default) parameter of the rust_proto_library rule. My thinking is that folks will want to centrally control the whole set of third party crates that they bring in, and maintaining compatibility with the dependencies that rust_proto_library uses internally might be important.

In the event that they don't care (yet), the default value will give them something functional.

EDIT: Added "internally" after "rust_proto_library uses"

Copy link
Author

Choose a reason for hiding this comment

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

Add a compile_deps argument, defaulted to None so people can overwrite it.

rust/rules.bzl Outdated
content.append("extern crate tls_api;")
for dep in ctx.attr.deps:
content.append("extern crate %s;" % dep.label.name)
content.append("use %s::*;" % dep.label.name)

Choose a reason for hiding this comment

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

Have you tested this with the protobuf file generator you're using? I was historically using stepancheg's rust proto library, and it uses crate-wide "allow" directives. These directives must appear before any use statement. To solve that, I just put the use statements after the content.

This may not be an issue for your particular proto library.

Copy link
Author

Choose a reason for hiding this comment

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

I haven't seen any issue in the examples I am testing on, but I moved the use statement at the end.

content.append("pub use %s_grpc::*;" % _basename(f))
ctx.actions.write(
ctx.outputs.out,
"\n".join(content),

Choose a reason for hiding this comment

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

As an extension of the above content, I had to do some postprocessing to the generated protobuf content -- specifically replacing super:: stuff. Is this not applicable for you?

Actually, as I look at this, I'm not seeing where the complied source even goes...

Copy link
Author

Choose a reason for hiding this comment

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

The generated source goes into the same folder as the lib.rs. I don't need to replace supper:: stuff because I maintain the same lib structure. I don't know though how it will behave with some multi component package in proto.

Copy link
Author

@damienmg damienmg left a comment

Choose a reason for hiding this comment

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

I am fine with waiting for a better cargo-raze story to polish that CL. I would be especially happy to drop all those build file and replace them with only a bzl file that load cargo_crate rules :)

As a side-note, I have a prototype approach of a different implementation for rust Proto/gRPC support. There are native proto_library rules that expose a provider and you can use aspect to generate 1 crate per proto_library. This generate a lot of crates so I am not sure it is better but that increase incrementality around protobuf. It also integrate with native protobuf but the code is 3 times the size of this PR (Skylark equivalent of rules.bzl) mostly because @pcj made an awesome work at making it easy to add new language on rules_protobuf.

This new approach would live in the rules_rust repository in the same way that rules_go provide a go_proto_library and provide I believe a bit nicer experience for the end-user (use native proto_library) but it adds a lot of complexity.

I am up to whatever people prefer (check in both contrib, only rules_protobuf or only rules_rust), I just need one rust gRPC support for myself and incrementality is not a problem at the moment. Anyway I'll try to clean-up the prototype and share it as a work in progress so you can have a look at it.

README.md Outdated
| [Objective-C](objc) | [objc_proto_compile](objc#objc_proto_compile) | [objc_proto_library](objc#objc_proto_library) <sup>4</sup> | [v1.6.1](https://github.com/grpc/grpc/commit/f5600e99be0fdcada4b3039c0f656a305264884a) |
| [Python](python) | [py_proto_compile](python#py_proto_compile) | [py_proto_library](python#py_proto_library) | [v1.6.1](https://github.com/grpc/grpc/commit/f5600e99be0fdcada4b3039c0f656a305264884a) |
| [Ruby](ruby) | [ruby_proto_compile](ruby#ruby_proto_compile) | | [v1.6.1](https://github.com/grpc/grpc/commit/f5600e99be0fdcada4b3039c0f656a305264884a) |
| [Rust](rust) | [rust_proto_compile](rust#rust_proto_compile) | | [v1.6.1](https://github.com/grpc/grpc/commit/f5600e99be0fdcada4b3039c0f656a305264884a) |
Copy link
Author

Choose a reason for hiding this comment

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

Done.

rust/rules.bzl Outdated
content.append("extern crate tls_api;")
for dep in ctx.attr.deps:
content.append("extern crate %s;" % dep.label.name)
content.append("use %s::*;" % dep.label.name)
Copy link
Author

Choose a reason for hiding this comment

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

I haven't seen any issue in the examples I am testing on, but I moved the use statement at the end.

"@org_pubref_rules_protobuf//rust/raze:protobuf",
]

GRPC_COMPILE_DEPS = PB_COMPILE_DEPS + [
Copy link
Author

Choose a reason for hiding this comment

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

Add a compile_deps argument, defaulted to None so people can overwrite it.

content.append("pub use %s_grpc::*;" % _basename(f))
ctx.actions.write(
ctx.outputs.out,
"\n".join(content),
Copy link
Author

Choose a reason for hiding this comment

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

The generated source goes into the same folder as the lib.rs. I don't need to replace supper:: stuff because I maintain the same lib structure. I don't know though how it will behave with some multi component package in proto.

@pcj
Copy link
Contributor

pcj commented Jun 5, 2018

Obviously I'm a little biased towards rules_protobuf but am happy with either approach. My observations from rules_go was that after the initial commit of a go_proto_library rule in that repository, people celebrated, but it took a lot of further effort to then hash out all the corner cases and redesigns that we'd already had to work out here. So while I think the end product was good, it was a significant amount of duplicate effort.

@damienmg
Copy link
Author

damienmg commented Jun 5, 2018

Yes I had to duplicate a lot of effort and used the rules_protobuf as an exemple. I think the end-user experience is better with the native proto_library approach but the developer experience is way better with rules_protobuf. Maybe that would be a way to look at it: transform rules_protobuf into something that works well with proto_library and offer the same kind of simple interface? Then rules author depends on it and just use rules_protobuf as a skylark library?

I wonder what are the plan for Bazel protobuf support now, maybe @lberki knows.

This give SHA-256 in crates.bzl improving caching
@damienmg
Copy link
Author

/cc @mfarrugi since he expressed interest in the other PR.

I would love to get rules_rust's maintainer's opinion on which one we should pursue

@mfarrugi
Copy link

I don't have much to add for the developer perspective. From a user perspective, I slightly prefer having something that is wired up to the native rules because it is one less dependency, but is essentially the same ux otherwise.

@damienmg
Copy link
Author

@mfarrugi there is a slight UX diff in the native approach you declare your proto_library and just depends on a leaf rust_{grpc,proto}_library that specialize all the depdenncies for rust. This is the same approach for native java rules and go rules.

In the rules_protobuf way, you declare a rust_proto_{library, compile} per proto library. This creates more library in the end if you are multi language but it is simpler if you are mono language.

@mfarrugi
Copy link

mfarrugi commented Jun 13, 2018

If I understand correctly it is not a large difference, though I expect the majority of bazel users are not going to be mono language.

@damienmg
Copy link
Author

I'll close this one in favor of integrating inside the rules_rust repository

@damienmg damienmg closed this Oct 26, 2018
@pcj
Copy link
Contributor

pcj commented Oct 26, 2018

OK, I have also rewritten rules_proto in the meantime with a rust implementation based on yours at https://github.com/stackb/rules_proto/tree/master/rust. I'm OK maintaining those for the time being.

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.

4 participants