Skip to content

Commit 9b7b2d5

Browse files
Merge pull request #219 from Yannic/rules_closure
Add bazel rule closure_grpc_web_library
2 parents 1a57d2b + 76a4de8 commit 9b7b2d5

File tree

8 files changed

+221
-7
lines changed

8 files changed

+221
-7
lines changed

WORKSPACE

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
workspace(name = "com_github_grpc_grpc_web")
22

3+
# TODO(yannic): Update to use official repository.
4+
# See https://github.com/bazelbuild/rules_closure/pull/278
35
http_archive(
46
name = "io_bazel_rules_closure",
5-
sha256 = "a80acb69c63d5f6437b099c111480a4493bad4592015af2127a2f49fb7512d8d",
6-
strip_prefix = "rules_closure-0.7.0",
7+
sha256 = "248a7a98eb3962d9f0013e543ea79c5063a83bac7af349ebf412d844e6ab3035",
8+
strip_prefix = "rules_closure-53f2cab21fa6c608f32f114387d88ffd7868c5fc",
79
urls = [
8-
"https://mirror.bazel.build/github.com/bazelbuild/rules_closure/archive/0.7.0.tar.gz",
9-
"https://github.com/bazelbuild/rules_closure/archive/0.7.0.tar.gz",
10+
"https://github.com/Yannic/rules_closure/archive/53f2cab21fa6c608f32f114387d88ffd7868c5fc.zip",
1011
],
1112
)
1213

bazel/BUILD.bazel

Whitespace-only changes.

bazel/closure_grpc_web_library.bzl

Lines changed: 195 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,195 @@
1+
# This rule was inspired by rules_closure`s implementation of
2+
# |closure_proto_library|, licensed under Apache 2.
3+
# https://github.com/bazelbuild/rules_closure/blob/3555e5ba61fdcc17157dd833eaf7d19b313b1bca/closure/protobuf/closure_proto_library.bzl
4+
5+
load(
6+
"@io_bazel_rules_closure//closure/compiler:closure_js_library.bzl",
7+
"closure_js_library_impl",
8+
)
9+
load(
10+
"@io_bazel_rules_closure//closure/private:defs.bzl",
11+
"CLOSURE_WORKER_ATTR",
12+
"CLOSURE_LIBRARY_BASE_ATTR",
13+
"unfurl",
14+
)
15+
load(
16+
"@io_bazel_rules_closure//closure/protobuf:closure_proto_library.bzl",
17+
"closure_proto_aspect",
18+
)
19+
20+
# This was borrowed from Rules Go, licensed under Apache 2.
21+
# https://github.com/bazelbuild/rules_go/blob/67f44035d84a352cffb9465159e199066ecb814c/proto/compiler.bzl#L72
22+
def _proto_path(proto):
23+
path = proto.path
24+
root = proto.root.path
25+
ws = proto.owner.workspace_root
26+
if path.startswith(root):
27+
path = path[len(root):]
28+
if path.startswith("/"):
29+
path = path[1:]
30+
if path.startswith(ws):
31+
path = path[len(ws):]
32+
if path.startswith("/"):
33+
path = path[1:]
34+
return path
35+
36+
def _proto_include_path(proto):
37+
path = proto.path[:-len(_proto_path(proto))]
38+
if not path:
39+
return "."
40+
if path.endswith("/"):
41+
path = path[:-1]
42+
return path
43+
44+
def _proto_include_paths(protos):
45+
return depset([_proto_include_path(proto) for proto in protos])
46+
47+
def _generate_closure_grpc_web_src_progress_message(name):
48+
# TODO(yannic): Add a better message?
49+
return "Generating GRPC Web %s" % name
50+
51+
def _generate_closure_grpc_web_srcs(
52+
actions, protoc, protoc_gen_grpc_web, import_style, mode,
53+
sources, transitive_sources):
54+
all_sources = [src for src in sources] + [src for src in transitive_sources]
55+
proto_include_paths = [
56+
"-I%s" % p for p in _proto_include_paths(
57+
[f for f in all_sources])
58+
]
59+
60+
grpc_web_out_common_options = ",".join([
61+
"import_style={}".format(import_style),
62+
"mode={}".format(mode),
63+
])
64+
65+
files = []
66+
for src in sources:
67+
name = "{}.grpc.js".format(
68+
".".join(src.path.split("/")[-1].split(".")[:-1]))
69+
js = actions.declare_file(name)
70+
files.append(js)
71+
72+
args = proto_include_paths + [
73+
"--plugin=protoc-gen-grpc-web={}".format(protoc_gen_grpc_web.path),
74+
"--grpc-web_out={options},out={out_file}:{path}".format(
75+
options = grpc_web_out_common_options,
76+
out_file = name,
77+
path = js.path[:js.path.rfind("/")],
78+
),
79+
src.path
80+
]
81+
82+
actions.run(
83+
inputs = [protoc_gen_grpc_web] + all_sources,
84+
outputs = [js],
85+
executable = protoc,
86+
arguments = args,
87+
progress_message =
88+
_generate_closure_grpc_web_src_progress_message(name),
89+
)
90+
91+
return files
92+
93+
_error_multiple_deps = "".join([
94+
"'deps' attribute must contain exactly one label ",
95+
"(we didn't name it 'dep' for consistency). ",
96+
"We may revisit this restriction later.",
97+
])
98+
99+
def _closure_grpc_web_library_impl(ctx):
100+
if len(ctx.attr.deps) > 1:
101+
# TODO(yannic): Revisit this restriction.
102+
fail(_error_multiple_deps, "deps");
103+
104+
dep = ctx.attr.deps[0]
105+
106+
srcs = _generate_closure_grpc_web_srcs(
107+
actions = ctx.actions,
108+
protoc = ctx.executable._protoc,
109+
protoc_gen_grpc_web = ctx.executable._protoc_gen_grpc_web,
110+
import_style = ctx.attr.import_style,
111+
mode = ctx.attr.mode,
112+
sources = dep.proto.direct_sources,
113+
transitive_sources = dep.proto.transitive_imports,
114+
)
115+
116+
deps = unfurl(ctx.attr.deps, provider = "closure_js_library")
117+
deps += [
118+
ctx.attr._grpc_web_abstractclientbase,
119+
ctx.attr._grpc_web_clientreadablestream,
120+
ctx.attr._grpc_web_error,
121+
ctx.attr._grpc_web_grpcwebclientbase
122+
]
123+
124+
suppress = [
125+
"misplacedTypeAnnotation",
126+
]
127+
128+
library = closure_js_library_impl(
129+
actions = ctx.actions,
130+
label = ctx.label,
131+
workspace_name = ctx.workspace_name,
132+
133+
srcs = srcs,
134+
deps = deps,
135+
testonly = ctx.attr.testonly,
136+
suppress = suppress,
137+
lenient = False,
138+
139+
closure_library_base = ctx.files._closure_library_base,
140+
_ClosureWorker = ctx.executable._ClosureWorker,
141+
)
142+
return struct(
143+
exports = library.exports,
144+
closure_js_library = library.closure_js_library,
145+
# The usual suspects are exported as runfiles, in addition to raw source.
146+
runfiles = ctx.runfiles(files = srcs),
147+
)
148+
149+
closure_grpc_web_library = rule(
150+
implementation = _closure_grpc_web_library_impl,
151+
attrs = {
152+
"deps": attr.label_list(
153+
mandatory = True,
154+
providers = ["proto", "closure_js_library"],
155+
# The files generated by this aspect are required dependencies.
156+
aspects = [closure_proto_aspect],
157+
),
158+
"import_style": attr.string(
159+
default = "closure",
160+
values = ["closure"],
161+
),
162+
"mode": attr.string(
163+
default = "grpcwebtext",
164+
values = ["grpcwebtext", "grpcweb"],
165+
),
166+
167+
# Required for closure_js_library_impl
168+
"_ClosureWorker": CLOSURE_WORKER_ATTR,
169+
"_closure_library_base": CLOSURE_LIBRARY_BASE_ATTR,
170+
171+
# internal only
172+
"_protoc": attr.label(
173+
default = Label("@com_google_protobuf//:protoc"),
174+
executable = True,
175+
cfg = "host",
176+
),
177+
"_protoc_gen_grpc_web": attr.label(
178+
default = Label("//javascript/net/grpc/web:protoc-gen-grpc-web"),
179+
executable = True,
180+
cfg = "host",
181+
),
182+
"_grpc_web_abstractclientbase": attr.label(
183+
default = Label("//javascript/net/grpc/web:abstractclientbase"),
184+
),
185+
"_grpc_web_clientreadablestream": attr.label(
186+
default = Label("//javascript/net/grpc/web:clientreadablestream"),
187+
),
188+
"_grpc_web_error": attr.label(
189+
default = Label("//javascript/net/grpc/web:error"),
190+
),
191+
"_grpc_web_grpcwebclientbase": attr.label(
192+
default = Label("//javascript/net/grpc/web:grpcwebclientbase"),
193+
),
194+
},
195+
)

javascript/net/grpc/web/BUILD.bazel

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ closure_js_library(
8686
"@io_bazel_rules_closure//closure/library/net:eventtype",
8787
"@io_bazel_rules_closure//closure/library/net:xhrio",
8888
"@io_bazel_rules_closure//closure/library/net:xmlhttp",
89+
"@io_bazel_rules_closure//closure/library/string",
8990
],
9091
suppress = [
9192
"reportUnknownTypes",

javascript/net/grpc/web/grpc_generator.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -333,7 +333,7 @@ class GrpcCodeGenerator : public CodeGenerator {
333333
string mode;
334334
string import_style_str;
335335
ImportStyle import_style;
336-
336+
337337
for (size_t i = 0; i < options.size(); ++i) {
338338
if (options[i].first == "out") {
339339
file_name = options[i].second;
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
load("//bazel:closure_grpc_web_library.bzl", "closure_grpc_web_library")
2+
3+
proto_library(
4+
name = "echo_proto",
5+
srcs = [
6+
"echo.proto",
7+
],
8+
)
9+
10+
closure_grpc_web_library(
11+
name = "echo",
12+
deps = [
13+
":echo_proto",
14+
],
15+
)

net/grpc/gateway/examples/echo/echoapp.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ echoapp.EchoApp.prototype.load = function() {
113113
if (e.keyCode == 13) self.send(); // enter key
114114
return false;
115115
});
116-
116+
117117
$("#msg").focus();
118118
});
119119
};

scripts/kokoro.sh

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,9 @@ docker build -t grpc-web:ubuntu_16_04 \
2424

2525
docker-compose build
2626

27-
bazel test javascript/net/grpc/web/...
27+
bazel test \
28+
//javascript/net/grpc/web/... \
29+
//net/grpc/gateway/examples/...
2830

2931
cd packages/grpc-web && \
3032
npm install && \

0 commit comments

Comments
 (0)