Skip to content

Commit

Permalink
Add a way for users of remote-apis to only require dependencies for t…
Browse files Browse the repository at this point in the history
…he rules of languages they actually use.

We reuse the solution developed for googleapis, see "switched_rules_by_language": https://github.com/googleapis/googleapis/blob/master/repository_rules.bzl

Basically the way this works is that we generate a Bazel repository that wraps the enabled language rules, and implements them as no-ops if they are not specifically enabled.

Fixes bazelbuild#78.
  • Loading branch information
Jeremy Sharpe committed May 23, 2019
1 parent 9d0e124 commit acab5d6
Show file tree
Hide file tree
Showing 5 changed files with 136 additions and 6 deletions.
Empty file added BUILD
Empty file.
13 changes: 13 additions & 0 deletions WORKSPACE
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,19 @@ workspace(name = "bazel_remote_apis")

load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")

##############################################################################
# Common
##############################################################################

load("//:repository_rules.bzl", "switched_rules_by_language")

switched_rules_by_language(
name = "bazel_remote_apis_imports",
go = True,
java = True,
cc = True,
)

# Needed for protobuf.
http_archive(
name = "bazel_skylib",
Expand Down
4 changes: 1 addition & 3 deletions build/bazel/remote/execution/v2/BUILD
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
package(default_visibility = ["//visibility:public"])
load("@com_github_grpc_grpc//bazel:cc_grpc_library.bzl", "cc_grpc_library")
load("@io_bazel_rules_go//go:def.bzl", "go_library")
load("@io_bazel_rules_go//proto:def.bzl", "go_proto_library")
load("@bazel_remote_apis_imports//:imports.bzl", "java_proto_library", "go_library", "go_proto_library", "cc_grpc_library")

licenses(["notice"])

Expand Down
4 changes: 1 addition & 3 deletions build/bazel/semver/BUILD
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
package(default_visibility = ["//visibility:public"])
load("@com_github_grpc_grpc//bazel:cc_grpc_library.bzl", "cc_grpc_library")
load("@io_bazel_rules_go//go:def.bzl", "go_library")
load("@io_bazel_rules_go//proto:def.bzl", "go_proto_library")
load("@bazel_remote_apis_imports//:imports.bzl", "java_proto_library", "go_library", "go_proto_library", "cc_grpc_library")

licenses(["notice"])

Expand Down
121 changes: 121 additions & 0 deletions repository_rules.bzl
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
"""Repository rules and macros which are expected to be called from WORKSPACE
file of either bazel_remote_apis itself or any third_party repository which
consumes bazel_remote_apis as its dependency.
This is adapted from
https://github.com/googleapis/googleapis/blob/master/repository_rules.bzl
"""

def _switched_rules_impl(ctx):
disabled_rule_script = """
def {rule_name}(**kwargs):
print("Ignoring {rule_name}(name = %s)" % kwargs.get("name", None))
"""
enabled_native_rule_script = """
{rule_name} = {native_rule_name}
"""
enabled_rule_script = """
load("{file_label}", _{rule_name} = "{rule_name}")
"""
elabled_rule_scrip_alias = """
{rule_name} = _{rule_name}
"""
load_rules = [] # load() must go before everything else in .bzl files since Bazel 0.25.0
rules = []

for rule_name, value in ctx.attr.rules.items():
if not value:
rules.append(disabled_rule_script.format(rule_name = rule_name))
elif value.startswith("@"):
load_rules.append(enabled_rule_script.format(file_label = value, rule_name = rule_name))
rules.append(elabled_rule_scrip_alias.format(rule_name = rule_name))
elif value.startswith("native."):
rules.append(
enabled_native_rule_script.format(rule_name = rule_name, native_rule_name = value),
)
else:
rules.append(value)

ctx.file("BUILD.bazel", "")
ctx.file("imports.bzl", "".join(load_rules + rules))

switched_rules = repository_rule(
implementation = _switched_rules_impl,
attrs = {
"rules": attr.string_dict(
allow_empty = True,
mandatory = False,
default = {},
),
},
)

def switched_rules_by_language(
name,
java = False,
go = False,
cc = False,
rules_override = {}):
"""Switches rules in the generated imports.bzl between no-op and the actual
implementation.
This defines which language-specific rules should be enabled during the
build. All non-enabled language-specific rules will default to no-op
implementations.
For example, to use this rule and enable Java and Go rules, add the
following in the external repository which imports bazel_remote_apis
repository and its corresponding dependencies:
load("@bazel_remote_apis//:repository_rules.bzl", "switched_rules_by_language")
switched_rules_by_language(
name = "bazel_remote_apis_imports",
go = True,
java = True,
)
Then import e.g. "go_library" from @bazel_remote_apis_imports in your BUILD files:
load("@bazel_remote_apis_imports//:imports.bzl", "go_library")
Note, for build to work you must also import the language-specific transitive dependencies.
Args:
name (str): name of a target, is expected to be "bazel_remote_apis_imports".
java (bool): Enable Java specific rules. False by default.
go (bool): Enable Go specific rules. False by default.
cc (bool): Enable C++ specific rules. False by default.
rules_override (dict): Custom rule overrides (for advanced usage).
"""

rules = {}

rules["java_proto_library"] = _switch(
java,
"native.java_proto_library",
)

rules["go_proto_library"] = _switch(
go,
"@io_bazel_rules_go//proto:def.bzl",
)
rules["go_library"] = _switch(
go,
"@io_bazel_rules_go//go:def.bzl",
)

rules["cc_grpc_library"] = _switch(
cc,
"@com_github_grpc_grpc//bazel:cc_grpc_library.bzl",
)

rules.update(rules_override)

switched_rules(
name = name,
rules = rules,
)

def _switch(enabled, enabled_value):
return enabled_value if enabled else ""

0 comments on commit acab5d6

Please sign in to comment.