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. (#81)

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.

I've tested with with tools_remote, and builds there now work when this snippet is added to the workspace, even without adding go workspace dependencies:

```
load("@remoteapis//:repository_rules.bzl", "switched_rules_by_language")
switched_rules_by_language(
    name = "bazel_remote_apis_imports",
    java = True,
)
```

Fixes #78.
  • Loading branch information
jasharpe authored and Ola Rozenfeld committed May 24, 2019
1 parent 9d0e124 commit c0682f0
Show file tree
Hide file tree
Showing 6 changed files with 151 additions and 6 deletions.
Empty file added BUILD
Empty file.
20 changes: 20 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,26 @@ packages from that repository in order to generate code using this API. If you
build the repository using the included `BUILD` files, Bazel will fetch the
protobuf compiler and googleapis automatically.

## Selecting language support

The repository provides a rule that you can use in your `WORKSPACE` file to
select which languages you are using. This allows you to depend on this
repository without pulling in Go rules, for instance, if you aren't using Go
rules.

For instance, if you only use Java in your project, add the following to your
`WORKSPACE` file:

```
load("@remoteapis//:repository_rules.bzl", "switched_rules_by_language")
switched_rules_by_language(
name = "bazel_remote_apis_imports",
java = True,
)
```

You can find the complete list of supported languages in `repository_rules.bzl`.

## Using the APIs

The repository contains `BUILD` files to build the protobuf library with
Expand Down
8 changes: 8 additions & 0 deletions WORKSPACE
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,14 @@ workspace(name = "bazel_remote_apis")

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

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 c0682f0

Please sign in to comment.