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

build: Add Bazel java_grpc_library rule #2975

Merged
merged 19 commits into from
Jun 22, 2017
Merged

Conversation

simonhorlick
Copy link
Contributor

Bazel third party dependencies are specified in repositories.bzl which
gives the consumer the ability to opt-out of any dependencies they use
directly in their own project. Also note that reposititories.bzl
uses java_import_external from rules_closure instead of Bazel's built in
maven_jar. This allows us to specify multiple urls for each jar,
reducing the likelyhood of build failures due to repositories becoming
unavailable and also define dependencies between libraries.

Fixes #2756

References: bazelbuild/bazel#1952

@grpc-kokoro
Copy link

Thanks for your pull request. The automated tests will run as soon as one of the admins verifies this change is ok for us to run on our infrastructure.

@buchgr
Copy link
Collaborator

buchgr commented May 5, 2017

ok to test

buchgr
buchgr previously requested changes May 5, 2017
Copy link
Collaborator

@buchgr buchgr left a comment

Choose a reason for hiding this comment

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

I glanced over it and it looks good.

Two things:

  1. Tests for java_grpc_library would be great
  2. I think maven_jar might be better than copying java_import_external from the closure rules.

@ejona86
Copy link
Member

ejona86 commented May 5, 2017

Tests for java_grpc_library would be great

I can add some tests post-merge.

BUILD Outdated
@@ -0,0 +1,126 @@
package(default_visibility = ["//visibility:public"])

cc_binary(
Copy link
Contributor

Choose a reason for hiding this comment

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

Consider moving these build targets into the directory that they reference. For example, this rule should probably go in a BUILD file under compiler/

BUILD Outdated
java_library(
name = "core",
srcs = glob([
"core/src/main/java/**/*.java",
Copy link
Contributor

Choose a reason for hiding this comment

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

Please don't use super globs. We are trying to split up the core and core internal package, and this pulls it in. It also unnnessarily pulls in inprocess and util.

BUILD Outdated
)

java_library(
name = "protobuf-nano",
Copy link
Contributor

Choose a reason for hiding this comment

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

Please be consistent with underscores and dashes for name rules. I think underscores are more common.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

In that case, if I move the BUILD file to protobuf-nano should I keep the target the same as the directory name, or still replace with underscores?

Copy link
Contributor

Choose a reason for hiding this comment

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

underscores

@ejona86
Copy link
Member

ejona86 commented May 10, 2017

@simonhorlick I'm a bit busy at the moment, so it may be a week before I can look at this closer.

@simonhorlick
Copy link
Contributor Author

It looks like my change to the gradle output directory is causing the Windows Jenkins build to fail. Presumably because it can't find the test outputs any more.

bazel-io pushed a commit to bazelbuild/bazel that referenced this pull request Jun 6, 2017
Code taken from PR: grpc/grpc-java#2975

Once this is merged into gRPC we can directly depend on gRPC.

Change-Id: Ide77414276b4125e85dfa6f93725143e3149d8ec
@simonhorlick
Copy link
Contributor Author

In 98bee07 I renamed the output directory that gradle uses because it clashes with the BUILD files. Alternatively it seems Bazel supports naming build files BUILD.bazel, which might be a less invasive way of achieving the same thing. Let me know if you think that would be better.

ctx.action(
inputs = [ctx.executable._java_plugin] + srcs + includes,
outputs = [srcdotjar],
executable = ctx.executable._protoc,
Copy link
Collaborator

Choose a reason for hiding this comment

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

When hacking this into bazel [1], I found that creating the action this way let's protoc crash on Windows. Instead, I am building the command line myself.

I am quite sure this is a bazel bug, but haven't had time to investigate yet.

[1] https://github.com/bazelbuild/bazel/blob/master/third_party/grpc/build_defs.bzl

Copy link
Member

Choose a reason for hiding this comment

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

I don't want us to make the command line ourselves, as then we have to deal with more possibilities of escaping. I'd rather us figure out what's wrong with using executable on Windows. That can happen after the merging of this PR.

@ejona86
Copy link
Member

ejona86 commented Jun 16, 2017

@simonhorlick, Hmm... The BUILD vs build/ is an interesting problem. We'll have a similar problem internally as we have pre-existing Blaze BUILD files and we'll probably want both of them around for a bit as we migrate to have one canonical set. I've started a conversation internally asking about Blaze vs Bazel behavior; depending on how the two differ I'll be able to provide a recommendation.

@ejona86
Copy link
Member

ejona86 commented Jun 16, 2017

@simonhorlick, I'm pretty sure I want to use BUILD.bazel for now. I think it will make life easier for us as we support Blaze internally and also be convenient during migrating to a single set of BUILD files (Blaze+Bazel). In the future we may actually swap to using BUILD, but that's still TBD.

Copy link
Member

@ejona86 ejona86 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 pretty good.

BUILD Outdated
@@ -0,0 +1,11 @@
package(default_visibility = ["//visibility:public"])
Copy link
Member

Choose a reason for hiding this comment

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

Please don't set the default visibility to public. It makes it far too easy to leak targets. I say this as someone who has been surprised multiple times to learn a target was public and then needed to clean it up. Yes, I know it'll be annoying now because everything is actually public, but once we start adding tests and using java_libraries it is asking for trouble.

BUILD Outdated
package(default_visibility = ["//visibility:public"])

java_library(
name = "grpc_java",
Copy link
Member

Choose a reason for hiding this comment

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

What is this target used for?

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 was using it just to reduce the number of deps in rules that use grpc-java. You can see an example here: https://github.com/simonhorlick/grpc-java-helloworld/blob/master/java/io/grpc/examples/helloworld/BUILD#L44

Copy link
Member

Choose a reason for hiding this comment

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

We had one of these targets internally, and it caused problems, because tons got added to it. If it is just core+stub, that seems like it could be fine. But on the other hand, one vs two targets for deps isn't that bad. @carl-mastrangelo, thoughts?

actual = "@com_google_code_gson//jar",
)

def com_google_api_grpc_google_common_protos():
Copy link
Member

Choose a reason for hiding this comment

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

Was there a tool that created this stuff or that can help maintain it?

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 made this manually, I'm not actually sure if there are tools available.

Copy link
Member

@ejona86 ejona86 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 very close now, in my mind. @buchgr, wanna take another look?

BUILD Outdated
package(default_visibility = ["//visibility:public"])

java_library(
name = "grpc_java",
Copy link
Member

Choose a reason for hiding this comment

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

We had one of these targets internally, and it caused problems, because tons got added to it. If it is just core+stub, that seems like it could be fine. But on the other hand, one vs two targets for deps isn't that bad. @carl-mastrangelo, thoughts?

BUILD Outdated
exports = [
"//core",
"//stub",
"@com_google_code_findbugs_jsr305//jar",
Copy link
Member

Choose a reason for hiding this comment

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

Remove export of jsr305 and guava.

Copy link
Contributor

Choose a reason for hiding this comment

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

I would strongly prefer leaving the meta target out for now. It's something we can easily add in later.

There are a couple reasons for this:

  • Right now auto generated build files and tools that auto add deps have a hard time figuring out what to do when a file is exposed through multiple targets. I think that making life easier for tools is a better long term strategy than making life easier for humans. (the former is a better deal for the latter).
  • Bazel is not currently smart enough to trim deps not actually needed. For example, IIRC core depends on the Census library. Even if users really only needed stub, they would pull in Census too (I realize that stub depends on core, but that's a much easier thing to fix). Same with the auth library, which depends on Google client libraries. (this had the sad effect of pulling in additional licences for hundreds of Android apps that are infeasible to back out, despite none of them actually needing it)
  • Bazel cannot figure out which deps are needed for compilation. It knows if they are missing, but it cannot decide if they happened to be unnecessary. This bloats jars. There have been at least 5 or 6 tools internally that try to find unnecessary deps, but in practice they each failed on a different set of corner cases, and have a pretty high rate of being ignored.

The temptation is strong to put everything in the grpc_java, especially for new deps. (this happened for grpc's predecessor, and led to no jar being smaller than 200MB.) Let's stay lean and mean for now, and add this target back in once there is strong evidence that it would be widely useful.

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 for the explanation, that makes a lot of sense.

core/BUILD.bazel Outdated
name = "internal",
srcs = glob([
"src/main/java/io/grpc/internal/*.java",
]),
visibility = ["//visibility:public"],
Copy link
Member

Choose a reason for hiding this comment

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

It seems this should have reduced visibility. I guess everything in grpc-java can use it, though? I guess I don't know how cross-repo visibility works in Bazel...

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 updated this to visibility = ["//:__subpackages__"] and then tested it by depending on this target from another repo, bazel throws a visibility error as expected.

"src/main/java/**/*.java",
]),
resources = glob([
"src/main/resources/**/*",
Copy link
Contributor

Choose a reason for hiding this comment

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

/** should be sufficient no?


def com_google_api_grpc_google_common_protos():
native.maven_jar(
name = "com_google_api_grpc_google_common_protos",
Copy link
Contributor

Choose a reason for hiding this comment

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

please sort args, or at least make arg order consistent across this and the the rules below. (e.g. sha1 comes after name)

Bazel requires an empty BUILD file here so users can reference
//:repositories.bzl and //:java_grpc_library.bzl.
Copy link
Member

@ejona86 ejona86 left a comment

Choose a reason for hiding this comment

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

Let's give @buchgr a day to mention whether he wants to take more of a look. If still no response, any issues can be cleaned up later. (I say this also because I spoke with him in person before my review and he sounded favorable toward the approaches that I knew nothing about.)

@ejona86 ejona86 dismissed buchgr’s stale review June 22, 2017 19:59

Of the two issues raised, I said I'd handle one later and the other seems resolved.

@ejona86
Copy link
Member

ejona86 commented Jun 22, 2017

All comments appear addressed. Merging.

@simonhorlick
Copy link
Contributor Author

Great, thanks for the reviews!

@buchgr
Copy link
Collaborator

buchgr commented Jul 3, 2017

Sorry, I was on a two week vacation, with mostly no internet :(.

I am excited that this go merged! Thanks @simonhorlick !

@ejona86
Copy link
Member

ejona86 commented Jul 5, 2017

CC @cgrushko. It's been a couple weeks, and it seems the Bazel build is working well.

@lock lock bot locked as resolved and limited conversation to collaborators Jan 20, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants