diff options
Diffstat (limited to 'third_party/bazel/rules_haskell/haskell/protobuf.bzl')
-rw-r--r-- | third_party/bazel/rules_haskell/haskell/protobuf.bzl | 395 |
1 files changed, 0 insertions, 395 deletions
diff --git a/third_party/bazel/rules_haskell/haskell/protobuf.bzl b/third_party/bazel/rules_haskell/haskell/protobuf.bzl deleted file mode 100644 index 5c8b9a817648..000000000000 --- a/third_party/bazel/rules_haskell/haskell/protobuf.bzl +++ /dev/null @@ -1,395 +0,0 @@ -"""Support for protocol buffers""" - -load( - ":private/haskell_impl.bzl", - _haskell_library_impl = "haskell_library_impl", -) -load("@bazel_skylib//lib:paths.bzl", "paths") -load( - "@io_tweag_rules_haskell//haskell:providers.bzl", - "HaskellInfo", - "HaskellLibraryInfo", - "HaskellProtobufInfo", -) - -def _capitalize_first_letter(c): - """Capitalize the first letter of the input. Unlike the built-in - `capitalize()` method, doesn't lower-case the other characters. This helps - mimic the behavior of `proto-lens-protoc`, which turns `Foo/Bar/BAZ.proto` - into `Foo/Bar/BAZ.hs` (rather than `Foo/Bar/Baz.hs`). - - Args: - c: A non-empty string word. - - Returns: - The input with the first letter upper-cased. - """ - return c[0].capitalize() + c[1:] - -def _camel_case(comp): - """Camel-case the input string, preserving any existing capital letters. - """ - - # Split on both "-" and "_", matching the behavior of proto-lens-protoc. - # Be sure to ignore any empty segments from input with leading or trailing - # delimiters. - return "".join([ - _capitalize_first_letter(c2) - for c1 in comp.split("_") - for c2 in c1.split("-") - if len(c2) > 0 - ]) - -def _proto_lens_output_file(path): - """The output file from `proto-lens-protoc` when run on the given `path`. - """ - - path = path[:-len(".proto")] - result = "/".join([_camel_case(p) for p in path.split("/")]) + ".hs" - - return "Proto/" + result - -def _proto_lens_fields_file(path): - """The fields file from `proto-lens-protoc` when run on the given `path`. - """ - - path = path[:-len(".proto")] - result = "/".join([_camel_case(p) for p in path.split("/")]) + "_Fields.hs" - - return "Proto/" + result - -def _proto_path(proto, proto_source_roots): - """A path to the proto file which matches any import statements.""" - proto_path = proto.path - for p in proto_source_roots: - if proto_path.startswith(p): - return paths.relativize(proto_path, p) - - return paths.relativize( - proto_path, - paths.join(proto.root.path, proto.owner.workspace_root), - ) - -def _haskell_proto_aspect_impl(target, ctx): - pb = ctx.toolchains["@io_tweag_rules_haskell//protobuf:toolchain"].tools - - args = ctx.actions.args() - - src_prefix = paths.join( - ctx.label.workspace_root, - ctx.label.package, - ) - - args.add("--plugin=protoc-gen-haskell=" + pb.plugin.path) - - hs_files = [] - inputs = [] - - direct_proto_paths = [target.proto.proto_source_root] - transitive_proto_paths = target.proto.transitive_proto_path - - args.add_all([ - "-I{0}={1}".format(_proto_path(s, transitive_proto_paths), s.path) - for s in target.proto.transitive_sources.to_list() - ]) - - inputs.extend(target.proto.transitive_sources.to_list()) - - for src in target.proto.direct_sources: - inputs.append(src) - - # As with the native rules, require the .proto file to be in the same - # Bazel package as the proto_library rule. This allows us to put the - # output .hs file next to the input .proto file. Unfortunately Skylark - # doesn't let us check the package of the file directly, so instead we - # just look at its short_path and rely on the proto_library rule itself - # to check for consistency. We use the file's path rather than its - # dirname/basename in case it's in a subdirectory; for example, if the - # proto_library rule is in "foo/BUILD" but the .proto file is - # "foo/bar/baz.proto". - - if not src.path.startswith(paths.join(src.root.path, src_prefix)): - fail("Mismatch between rule context " + str(ctx.label.package) + - " and source file " + src.short_path) - if src.basename[-6:] != ".proto": - fail("bad extension for proto file " + src) - - args.add(src.path) - hs_files.append(ctx.actions.declare_file( - _proto_lens_output_file( - _proto_path(src, direct_proto_paths), - ), - )) - hs_files.append(ctx.actions.declare_file( - _proto_lens_fields_file( - _proto_path(src, direct_proto_paths), - ), - )) - - args.add_all([ - "--proto_path=" + target.proto.proto_source_root, - "--haskell_out=no-runtime:" + paths.join( - hs_files[0].root.path, - src_prefix, - ), - ]) - - ctx.actions.run( - inputs = depset([pb.protoc, pb.plugin] + inputs), - outputs = hs_files, - mnemonic = "HaskellProtoc", - executable = pb.protoc, - arguments = [args], - ) - - patched_attrs = { - "compiler_flags": [], - "src_strip_prefix": "", - "repl_interpreted": True, - "repl_ghci_args": [], - "version": "", - "linkstatic": False, - "_ghci_script": ctx.attr._ghci_script, - "_ghci_repl_wrapper": ctx.attr._ghci_repl_wrapper, - "hidden_modules": [], - "exports": {}, - "name": "proto-autogen-" + ctx.rule.attr.name, - "srcs": hs_files, - "deps": ctx.rule.attr.deps + - ctx.toolchains["@io_tweag_rules_haskell//protobuf:toolchain"].deps, - "prebuilt_dependencies": ctx.toolchains["@io_tweag_rules_haskell//protobuf:toolchain"].prebuilt_deps, - "plugins": [], - "_cc_toolchain": ctx.attr._cc_toolchain, - } - - patched_ctx = struct( - actions = ctx.actions, - attr = struct(**patched_attrs), - bin_dir = ctx.bin_dir, - disabled_features = ctx.rule.attr.features, - executable = struct( - _ls_modules = ctx.executable._ls_modules, - ), - # Necessary for CC interop (see cc.bzl). - features = ctx.rule.attr.features, - file = ctx.file, - files = struct( - srcs = hs_files, - _cc_toolchain = ctx.files._cc_toolchain, - extra_srcs = depset(), - ), - genfiles_dir = ctx.genfiles_dir, - label = ctx.label, - toolchains = ctx.toolchains, - var = ctx.var, - ) - - # TODO this pattern match is very brittle. Let's not do this. The - # order should match the order in the return value expression in - # haskell_library_impl(). - [hs_info, cc_info, coverage_info, default_info, library_info] = _haskell_library_impl(patched_ctx) - - return [ - cc_info, # CcInfo - hs_info, # HaskellInfo - library_info, # HaskellLibraryInfo - # We can't return DefaultInfo here because target already provides that. - HaskellProtobufInfo(files = default_info.files), - ] - -_haskell_proto_aspect = aspect( - _haskell_proto_aspect_impl, - attr_aspects = ["deps"], - attrs = { - "_ghci_script": attr.label( - allow_single_file = True, - default = Label("@io_tweag_rules_haskell//haskell:assets/ghci_script"), - ), - "_ghci_repl_wrapper": attr.label( - allow_single_file = True, - default = Label("@io_tweag_rules_haskell//haskell:private/ghci_repl_wrapper.sh"), - ), - "_ls_modules": attr.label( - executable = True, - cfg = "host", - default = Label("@io_tweag_rules_haskell//haskell:ls_modules"), - ), - "_cc_toolchain": attr.label( - default = Label("@bazel_tools//tools/cpp:current_cc_toolchain"), - ), - }, - toolchains = [ - "@io_tweag_rules_haskell//haskell:toolchain", - "@io_tweag_rules_haskell//protobuf:toolchain", - ], -) - -def _haskell_proto_library_impl(ctx): - dep = ctx.attr.deps[0] # FIXME - return [ - dep[CcInfo], - dep[HaskellInfo], - dep[HaskellLibraryInfo], - DefaultInfo(files = dep[HaskellProtobufInfo].files), - ] - -haskell_proto_library = rule( - _haskell_proto_library_impl, - attrs = { - "deps": attr.label_list( - mandatory = True, - allow_files = False, - aspects = [_haskell_proto_aspect], - doc = "List of `proto_library` targets to use for generation.", - ), - }, - toolchains = [ - "@io_tweag_rules_haskell//haskell:toolchain", - "@io_tweag_rules_haskell//protobuf:toolchain", - ], -) - -"""Generate Haskell library allowing to use protobuf definitions with help -of [`proto-lens`](https://github.com/google/proto-lens#readme). - -Example: - ```bzl - proto_library( - name = "foo_proto", - srcs = ["foo.proto"], - ) - - haskell_proto_library( - name = "foo_haskell_proto", - deps = [":foo_proto"], - ) - ``` - -`haskell_proto_library` targets require `haskell_proto_toolchain` to be -registered. -""" - -def _protobuf_toolchain_impl(ctx): - if ctx.attr.prebuilt_deps: - print("""The attribute 'prebuilt_deps' has been deprecated, -use the 'deps' attribute instead. -""") - - return [ - platform_common.ToolchainInfo( - name = ctx.label.name, - tools = struct( - plugin = ctx.executable.plugin, - protoc = ctx.executable.protoc, - ), - deps = ctx.attr.deps, - prebuilt_deps = ctx.attr.prebuilt_deps, - ), - ] - -_protobuf_toolchain = rule( - _protobuf_toolchain_impl, - attrs = { - "protoc": attr.label( - executable = True, - cfg = "host", - allow_single_file = True, - mandatory = True, - doc = "protoc compiler", - ), - "plugin": attr.label( - executable = True, - cfg = "host", - allow_single_file = True, - mandatory = True, - doc = "proto-lens-protoc plugin for protoc", - ), - "deps": attr.label_list( - doc = "List of other Haskell libraries to be linked to protobuf libraries.", - ), - "prebuilt_deps": attr.string_list( - doc = "Non-Bazel supplied Cabal dependencies for protobuf libraries.", - ), - }, -) - -def haskell_proto_toolchain( - name, - plugin, - deps = [], - prebuilt_deps = [], - protoc = Label("@com_google_protobuf//:protoc"), - **kwargs): - """Declare a Haskell protobuf toolchain. - - You need at least one of these declared somewhere in your `BUILD` files - for the `haskell_proto_library` rules to work. Once declared, you then - need to *register* the toolchain using `register_toolchains` in your - `WORKSPACE` file (see example below). - - Example: - - In a `BUILD` file: - - ```bzl - haskell_proto_toolchain( - name = "protobuf-toolchain", - protoc = "@com_google_protobuf//:protoc", - plugin = "@hackage-proto-lens-protoc//:bin/proto-lens-protoc", - prebuilt_deps = [ - "base", - "bytestring", - "containers", - "data-default-class", - "lens-family", - "lens-labels", - "proto-lens", - "text", - ], - ) - ``` - - The `prebuilt_deps` and `deps` arguments allow to specify Haskell - libraries to use to compile the auto-generated source files. - - In `WORKSPACE` you could have something like this: - - ```bzl - http_archive( - name = "com_google_protobuf", - sha256 = "cef7f1b5a7c5fba672bec2a319246e8feba471f04dcebfe362d55930ee7c1c30", - strip_prefix = "protobuf-3.5.0", - urls = ["https://github.com/google/protobuf/archive/v3.5.0.zip"], - ) - - nixpkgs_package( - name = "protoc_gen_haskell", - repository = "@nixpkgs", - attribute_path = "haskell.packages.ghc822.proto-lens-protoc - ) - - register_toolchains( - "//tests:ghc", # assuming you called your Haskell toolchain "ghc" - "//tests:protobuf-toolchain", - ) - ``` - """ - impl_name = name + "-impl" - _protobuf_toolchain( - name = impl_name, - plugin = plugin, - deps = deps, - prebuilt_deps = prebuilt_deps, - protoc = protoc, - visibility = ["//visibility:public"], - **kwargs - ) - - native.toolchain( - name = name, - toolchain_type = "@io_tweag_rules_haskell//protobuf:toolchain", - toolchain = ":" + impl_name, - exec_compatible_with = [ - "@bazel_tools//platforms:x86_64", - ], - ) |