Skip to content

Commit 6161993

Browse files
committed
[bazel] Switch to custom closure_js_deps rule
After `rules_closure` 0.12.0, the `closure_js_deps` rule was removed and it was advised to use an `npm` invocation to generate the deps file. However, we still want to use the deps file as it makes it a lot easier to iterate on the atoms when we work on them. The obvious solution is to write our own implementation, which is what happens in this commit.
1 parent 3da2883 commit 6161993

File tree

13 files changed

+166
-10
lines changed

13 files changed

+166
-10
lines changed

.bazelignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ dotnet/src/webdriver/obj
2222
java/build/production
2323
java/client/build
2424
java/server/build
25+
javascript/atoms/node_modules
2526
javascript/grid-ui/node_modules
2627
javascript/selenium-webdriver/node_modules
2728
node_modules

MODULE.bazel

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ npm.npm_translate_lock(
6666
data = [
6767
"@//:package.json",
6868
"@//:pnpm-workspace.yaml",
69+
"@//javascript/atoms:package.json",
6970
"@//javascript/grid-ui:package.json",
7071
"@//javascript/selenium-webdriver:package.json",
7172
],

javascript/atoms/BUILD.bazel

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
load("@io_bazel_rules_closure//closure:defs.bzl", "closure_js_deps", "closure_js_library")
2-
load("//javascript:defs.bzl", "closure_test_suite")
1+
load("@io_bazel_rules_closure//closure:defs.bzl", "closure_js_library")
2+
load("//javascript:defs.bzl", "closure_js_deps", "closure_test_suite")
33

44
package(default_visibility = ["//visibility:public"])
55

javascript/atoms/package.json

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
{
2+
"name": "selenium-atoms",
3+
"version": "1.0.0",
4+
"private": true,
5+
"description": "Build tools for Selenium Browser Automation Atoms",
6+
"license": "Apache-2.0",
7+
"repository": {
8+
"type": "git",
9+
"url": "https://github.com/SeleniumHQ/selenium.git"
10+
},
11+
"devDependencies": {
12+
"google-closure-deps": "^20230802.0.0"
13+
}
14+
}

javascript/chrome-driver/BUILD.bazel

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
load("@io_bazel_rules_closure//closure:defs.bzl", "closure_js_deps", "closure_js_library")
2-
load("//javascript:defs.bzl", "closure_fragment", "closure_lang_file", "closure_test_suite")
1+
load("@io_bazel_rules_closure//closure:defs.bzl", "closure_js_library")
2+
load("//javascript:defs.bzl", "closure_fragment", "closure_js_deps", "closure_lang_file", "closure_test_suite")
33

44
closure_js_library(
55
name = "lib",

javascript/defs.bzl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
1+
load("//javascript/private:closure_js_deps.bzl", _closure_js_deps = "closure_js_deps")
12
load("//javascript/private:fragment.bzl", _closure_fragment = "closure_fragment")
23
load("//javascript/private:header.bzl", _closure_lang_file = "closure_lang_file")
34
load("//javascript/private:mocha_test.bzl", _mocha_test = "mocha_test")
45
load("//javascript/private:test_suite.bzl", _closure_test_suite = "closure_test_suite")
56

67
closure_fragment = _closure_fragment
8+
closure_js_deps = _closure_js_deps
79
closure_lang_file = _closure_lang_file
810
closure_test_suite = _closure_test_suite
911
mocha_test = _mocha_test

javascript/ie-driver/BUILD.bazel

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
load("@io_bazel_rules_closure//closure:defs.bzl", "closure_js_deps", "closure_js_library")
2-
load("//javascript:defs.bzl", "closure_fragment", "closure_lang_file")
1+
load("@io_bazel_rules_closure//closure:defs.bzl", "closure_js_library")
2+
load("//javascript:defs.bzl", "closure_fragment", "closure_js_deps", "closure_lang_file")
33

44
closure_js_deps(
55
name = "deps",

javascript/private/BUILD.bazel

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
load("@npm//javascript/atoms:google-closure-deps/package_json.bzl", closure_bin = "bin")
12
load("@rules_python//python:defs.bzl", "py_binary")
23

34
py_binary(
@@ -9,3 +10,8 @@ py_binary(
910
"//visibility:public",
1011
],
1112
)
13+
14+
closure_bin.closure_make_deps_binary(
15+
name = "closure_make_deps",
16+
visibility = ["//javascript:__subpackages__"],
17+
)
Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
ClosureJsSrcsInfo = provider(fields = ["files"])
2+
3+
def _closure_js_srcs_aspect_impl(target, ctx):
4+
"""Aspect to collect transitive .js source files from closure_js_library targets."""
5+
direct = []
6+
if ctx.rule.kind == "closure_js_library" and hasattr(ctx.rule.attr, "srcs"):
7+
for s in ctx.rule.attr.srcs:
8+
for f in s.files.to_list():
9+
# Only include .js files from the main workspace, not external repos
10+
if f.extension == "js" and not f.owner.workspace_name:
11+
direct.append(f)
12+
13+
trans = []
14+
for d in getattr(ctx.rule.attr, "deps", []):
15+
if ClosureJsSrcsInfo in d:
16+
trans.append(d[ClosureJsSrcsInfo].files)
17+
18+
return [ClosureJsSrcsInfo(files = depset(direct = direct, transitive = trans))]
19+
20+
closure_js_srcs_aspect = aspect(
21+
implementation = _closure_js_srcs_aspect_impl,
22+
attr_aspects = ["deps"],
23+
)
24+
25+
def _collect_srcs_impl(ctx):
26+
"""Rule to collect all transitive JS sources from closure_js_library deps."""
27+
trans = []
28+
for d in ctx.attr.deps:
29+
if ClosureJsSrcsInfo in d:
30+
trans.append(d[ClosureJsSrcsInfo].files)
31+
all_files = depset(transitive = trans)
32+
return [
33+
DefaultInfo(files = all_files),
34+
ClosureJsSrcsInfo(files = all_files),
35+
]
36+
37+
collect_closure_js_srcs = rule(
38+
implementation = _collect_srcs_impl,
39+
attrs = {
40+
"deps": attr.label_list(aspects = [closure_js_srcs_aspect]),
41+
},
42+
provides = [ClosureJsSrcsInfo],
43+
)
44+
45+
def _closure_js_deps_wrapper_impl(ctx):
46+
"""Wrapper rule that adds runfiles to the generated deps.js file."""
47+
deps_file = ctx.file.deps_file
48+
srcs_depset = ctx.attr.srcs_collector[ClosureJsSrcsInfo].files
49+
50+
return [
51+
DefaultInfo(
52+
files = depset([deps_file]),
53+
runfiles = ctx.runfiles(
54+
files = [deps_file],
55+
transitive_files = srcs_depset,
56+
),
57+
),
58+
]
59+
60+
_closure_js_deps_wrapper = rule(
61+
implementation = _closure_js_deps_wrapper_impl,
62+
attrs = {
63+
"deps_file": attr.label(allow_single_file = True, mandatory = True),
64+
"srcs_collector": attr.label(mandatory = True),
65+
},
66+
)
67+
68+
def closure_js_deps(name, deps = [], testonly = None, **kwargs):
69+
"""Generate a deps.js file from closure_js_library dependencies.
70+
71+
This macro replaces the old closure_js_deps rule from rules_closure by using
72+
the closure-make-deps binary from the google-closure-deps npm package.
73+
74+
Args:
75+
name: Name of the target. The output will be 'deps.js'.
76+
deps: List of closure_js_library targets to analyze for dependencies.
77+
"""
78+
79+
srcs_collector = name + "_closure_srcs"
80+
collect_closure_js_srcs(
81+
name = srcs_collector,
82+
deps = deps,
83+
testonly = testonly,
84+
visibility = ["//visibility:private"],
85+
)
86+
87+
deps_genrule = name + "_genrule"
88+
native.genrule(
89+
name = deps_genrule,
90+
srcs = [":" + srcs_collector],
91+
outs = ["deps.js"],
92+
cmd = """
93+
export BAZEL_BINDIR=$(BINDIR) && \\
94+
ln -sf . _main && \\
95+
FILES="" && \\
96+
for f in $(SRCS); do \\
97+
FILES="$$FILES --file $$(pwd)/_main/$$f"; \\
98+
done && \\
99+
$(location //javascript/private:closure_make_deps) \\
100+
--closure-path $$(pwd)/external/com_google_javascript_closure_library/closure \\
101+
--no-validate \\
102+
$$FILES \\
103+
> $@
104+
""",
105+
tools = ["//javascript/private:closure_make_deps"],
106+
testonly = testonly,
107+
visibility = ["//visibility:private"],
108+
)
109+
110+
# Use the wrapper rule to add runfiles to the generated deps.js
111+
_closure_js_deps_wrapper(
112+
name = name,
113+
deps_file = deps_genrule,
114+
srcs_collector = ":" + srcs_collector,
115+
testonly = testonly,
116+
**kwargs
117+
)

javascript/webdriver/BUILD.bazel

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
load("@io_bazel_rules_closure//closure:defs.bzl", "closure_js_deps", "closure_js_library")
2-
load("//javascript:defs.bzl", "closure_test_suite")
1+
load("@io_bazel_rules_closure//closure:defs.bzl", "closure_js_library")
2+
load("//javascript:defs.bzl", "closure_js_deps", "closure_test_suite")
33

44
closure_js_library(
55
name = "http",

0 commit comments

Comments
 (0)