Skip to content

Commit

Permalink
Make create_closure_js_library work on providers. (#607)
Browse files Browse the repository at this point in the history
This follows a more common provider approach where rules are
responsible for providing supplier to helper functions vs. helper
functions trying make it workaround with a mix of targets and
providers.

This also unbundles provider extraction from unfurl to remove
implicit and optional behaviors behind it.
  • Loading branch information
gkdn authored Mar 8, 2024
1 parent 23c6090 commit b4c4a5a
Show file tree
Hide file tree
Showing 5 changed files with 36 additions and 28 deletions.
5 changes: 3 additions & 2 deletions closure/compiler/closure_js_binary.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ load(
"collect_js",
"collect_runfiles",
"difference",
"extract_providers",
"find_js_module_roots",
"get_jsfile_path",
"sort_roots",
Expand Down Expand Up @@ -81,8 +82,8 @@ def _impl(ctx):
", ".join(JS_LANGUAGES.to_list()),
))

deps = unfurl(ctx.attr.deps, provider = ClosureJsLibraryInfo)
js = collect_js(deps, ctx.attr._closure_library_base, css = ctx.attr.css)
deps = extract_providers(ctx.attr.deps, ClosureJsLibraryInfo)
js = collect_js(unfurl(deps), css = ctx.attr.css)
if not js.srcs:
fail("There are no JS source files in the transitive closure")

Expand Down
22 changes: 13 additions & 9 deletions closure/compiler/closure_js_library.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ load(
"collect_js",
"collect_runfiles",
"convert_path_to_es6_module_name",
"extract_providers",
"find_js_module_roots",
"get_jsfile_path",
"library_level_checks",
Expand Down Expand Up @@ -100,6 +101,8 @@ def _closure_js_library_impl(
convention,
includes = (),
exports = depset(),
deps_stylesheets = [],
exports_stylesheets = [],
internal_descriptors = depset(),
no_closure_library = False,
internal_expect_failure = False,
Expand All @@ -121,7 +124,7 @@ def _closure_js_library_impl(
):
fail("Closure toolchain undefined; rule should include CLOSURE_JS_TOOLCHAIN_ATTRS")

closure_library_base = ctx.attr._closure_library_base
closure_library_base = extract_providers(ctx.attr._closure_library_base, ClosureJsLibraryInfo)
closure_worker = ctx.executable._ClosureWorker
unusable_type_definition = ctx.files._unusable_type_definition
actions = ctx.actions
Expand Down Expand Up @@ -165,7 +168,7 @@ def _closure_js_library_impl(

# Create a list of direct children of this rule. If any direct dependencies
# have the exports attribute, those labels become direct dependencies here.
deps = unfurl(deps, provider = ClosureJsLibraryInfo)
deps = unfurl(deps)

# Collect all the transitive stuff the child rules have propagated. Bazel has
# a special nested set data structure that makes this efficient.
Expand All @@ -178,9 +181,8 @@ def _closure_js_library_impl(
# JS binary is compiled, we'll make sure it's linked against a CSS binary
# which is a superset of the CSS libraries in its transitive closure.
stylesheets = []
for dep in deps:
if ClosureCssLibraryInfo in dep:
stylesheets.append(dep.label)
for dep in deps_stylesheets:
stylesheets.append(dep.label)

# JsChecker is a program that's run via the ClosureWorker persistent Bazel
# worker. This program is a modded version of the Closure Compiler. It does
Expand Down Expand Up @@ -265,7 +267,7 @@ def _closure_js_library_impl(
info_files = []
for dep in deps:
# Polymorphic rules, e.g. closure_css_library, might not provide this.
info = getattr(dep[ClosureJsLibraryInfo], "info", None)
info = getattr(dep, "info", None)
if info:
args.add("--dep", info)
info_files.append(info)
Expand Down Expand Up @@ -386,13 +388,15 @@ def _closure_js_library(ctx):
library = _closure_js_library_impl(
ctx,
srcs,
ctx.attr.deps,
extract_providers(ctx.attr.deps, ClosureJsLibraryInfo),
ctx.attr.testonly,
ctx.attr.suppress,
ctx.attr.lenient,
ctx.attr.convention,
getattr(ctx.attr, "includes", []),
ctx.attr.exports,
extract_providers(ctx.attr.exports, ClosureJsLibraryInfo),
extract_providers(ctx.attr.deps, ClosureCssLibraryInfo),
extract_providers(ctx.attr.exports, ClosureCssLibraryInfo),
ctx.files.internal_descriptors,
ctx.attr.no_closure_library,
ctx.attr.internal_expect_failure,
Expand All @@ -409,7 +413,7 @@ def _closure_js_library(ctx):
DefaultInfo(
files = depset(),
# The usual suspects are exported as runfiles, in addition to raw source.
runfiles = collect_runfiles(
runfiles = collect_runfiles(
ctx,
files = ctx.files.srcs,
extra_runfiles_attrs = ["exports"],
Expand Down
30 changes: 16 additions & 14 deletions closure/private/defs.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ ClosureJsBinaryInfo = provider("ClosureJsBinaryInfo", fields = ["bin", "map", "l
ClosureCssBinaryInfo = provider("ClosureCssBinaryInfo", fields = ["bin", "map", "renaming_map", "labels"])

ClosureCssLibraryInfo = provider("ClosureCssLibraryInfo", fields = [
"label",
"srcs",
"labels",
"transitive",
Expand All @@ -131,16 +132,17 @@ def get_jsfile_path(f):
# TODO(tjgq): Remove .zip once J2CL is switched to tree artifacts.
return f.path if f.extension in ["js", "zip"] else None

def extract_providers(deps, provider):
return [dep[provider] for dep in deps if provider in dep]

def unfurl(deps, provider = ""):
"""Returns deps as well as deps exported by parent rules."""
res = []
for dep in deps:
if not provider or provider in dep:
res.append(dep)
if type(provider) == "Provider" and provider in dep and hasattr(dep[provider], "exports"):
for edep in dep[provider].exports:
if not provider or provider in edep:
res.append(edep)
res.append(dep)
if hasattr(dep, "exports"):
for edep in dep.exports:
res.append(edep)
return res

def collect_js(
Expand All @@ -159,16 +161,16 @@ def collect_js(
js_module_roots = []
has_closure_library = False
for dep in deps:
srcs += [getattr(dep[ClosureJsLibraryInfo], "srcs", depset())]
ijs_files += [getattr(dep[ClosureJsLibraryInfo], "ijs_files", depset())]
infos += [getattr(dep[ClosureJsLibraryInfo], "infos", depset())]
modules += [getattr(dep[ClosureJsLibraryInfo], "modules", depset())]
descriptors += [getattr(dep[ClosureJsLibraryInfo], "descriptors", depset())]
stylesheets += [getattr(dep[ClosureJsLibraryInfo], "stylesheets", depset())]
js_module_roots += [getattr(dep[ClosureJsLibraryInfo], "js_module_roots", depset())]
srcs += [getattr(dep, "srcs", depset())]
ijs_files += [getattr(dep, "ijs_files", depset())]
infos += [getattr(dep, "infos", depset())]
modules += [getattr(dep, "modules", depset())]
descriptors += [getattr(dep, "descriptors", depset())]
stylesheets += [getattr(dep, "stylesheets", depset())]
js_module_roots += [getattr(dep, "js_module_roots", depset())]
has_closure_library = (
has_closure_library or
getattr(dep[ClosureJsLibraryInfo], "has_closure_library", False)
getattr(dep, "has_closure_library", False)
)
if no_closure_library:
if has_closure_library:
Expand Down
6 changes: 3 additions & 3 deletions closure/protobuf/closure_proto_library.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@

load("@rules_proto//proto:defs.bzl", "ProtoInfo")
load("//closure/compiler:closure_js_library.bzl", "create_closure_js_library")
load("//closure/private:defs.bzl", "CLOSURE_JS_TOOLCHAIN_ATTRS", "ClosureJsLibraryInfo", "unfurl")
load("//closure/private:defs.bzl", "CLOSURE_JS_TOOLCHAIN_ATTRS", "ClosureJsLibraryInfo", "extract_providers")

def _generate_closure_js_progress_message(name):
# TODO(yannic): Add a better message?
Expand Down Expand Up @@ -61,8 +61,8 @@ def _closure_proto_aspect_impl(target, ctx):
js = _generate_closure_js(target, ctx)

srcs = depset([js])
deps = unfurl(ctx.rule.attr.deps, provider = ClosureJsLibraryInfo)
deps += [ctx.attr._closure_library, ctx.attr._closure_protobuf_jspb]
deps = ctx.rule.attr.deps + [ctx.attr._closure_library, ctx.attr._closure_protobuf_jspb]
deps = extract_providers(deps, ClosureJsLibraryInfo)

suppress = [
"missingProperties",
Expand Down
1 change: 1 addition & 0 deletions closure/stylesheets/closure_css_library.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ def _closure_css_library(ctx):
css = collect_css(deps, ctx.attr.orientation)
return [
ClosureCssLibraryInfo(
label = ctx.label,
srcs = depset(ctx.files.srcs, transitive = [css.srcs]),
labels = depset([ctx.label], transitive = [css.labels]),
orientation = ctx.attr.orientation,
Expand Down

0 comments on commit b4c4a5a

Please sign in to comment.