diff --git a/BUILD b/BUILD new file mode 100644 index 00000000..e69de29b diff --git a/README.md b/README.md index 13f8c5e3..a68bf296 100644 --- a/README.md +++ b/README.md @@ -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 diff --git a/WORKSPACE b/WORKSPACE index a7826081..af7e448a 100644 --- a/WORKSPACE +++ b/WORKSPACE @@ -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", diff --git a/build/bazel/remote/execution/v2/BUILD b/build/bazel/remote/execution/v2/BUILD index a29bb714..81027882 100644 --- a/build/bazel/remote/execution/v2/BUILD +++ b/build/bazel/remote/execution/v2/BUILD @@ -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"]) diff --git a/build/bazel/semver/BUILD b/build/bazel/semver/BUILD index 1e6f9029..a404812d 100644 --- a/build/bazel/semver/BUILD +++ b/build/bazel/semver/BUILD @@ -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"]) diff --git a/repository_rules.bzl b/repository_rules.bzl new file mode 100644 index 00000000..6901d50e --- /dev/null +++ b/repository_rules.bzl @@ -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 ""