1# Copyright 2024 The Pigweed Authors 2# 3# Licensed under the Apache License, Version 2.0 (the "License"); you may not 4# use this file except in compliance with the License. You may obtain a copy of 5# the License at 6# 7# https://www.apache.org/licenses/LICENSE-2.0 8# 9# Unless required by applicable law or agreed to in writing, software 10# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12# License for the specific language governing permissions and limitations under 13# the License. 14"""A filegroup grouping .proto and .options files.""" 15 16PwProtoOptionsInfo = provider( 17 "Allows `pw_proto_filegroup` targets to pass along `.options` files " + 18 "without polluting the `DefaultInfo` provider, which means they can " + 19 "still be used in the `srcs` of `proto_library` targets.", 20 fields = { 21 "options_files": (".options file(s) associated with a proto_library " + 22 "for Pigweed codegen."), 23 }, 24) 25 26def _pw_proto_filegroup_impl(ctx): 27 source_files = list() 28 options_files = list() 29 30 for src in ctx.attr.srcs: 31 source_files += src.files.to_list() 32 33 for options_src in ctx.attr.options_files: 34 for file in options_src.files.to_list(): 35 if file.extension == "options" or file.extension == "pwpb_options": 36 options_files.append(file) 37 else: 38 fail(( 39 "Files provided as `options_files` to a " + 40 "`pw_proto_filegroup` must have the `.options` or " + 41 "`.pwpb_options` extensions; the file `{}` was provided." 42 ).format(file.basename)) 43 44 return [ 45 DefaultInfo(files = depset(source_files)), 46 PwProtoOptionsInfo(options_files = depset(options_files)), 47 ] 48 49pw_proto_filegroup = rule( 50 doc = ( 51 "Acts like a `filegroup`, but with an additional `options_files` " + 52 "attribute that accepts a list of `.options` files. These `.options` " + 53 "files should typically correspond to `.proto` files provided under " + 54 "the `srcs` attribute." + 55 "\n\n" + 56 "A `pw_proto_filegroup` is intended to be passed into the `srcs` of " + 57 "a `proto_library` target as if it were a normal `filegroup` " + 58 "containing only `.proto` files. For the purposes of the " + 59 "`proto_library` itself, the `pw_proto_filegroup` does indeed act " + 60 "just like a normal `filegroup`; the `options_files` attribute is " + 61 "ignored. However, if that `proto_library` target is then passed " + 62 "(directly or transitively) into the `deps` of a `pw_proto_library` " + 63 "for code generation, the `pw_proto_library` target will have access " + 64 "to the provided `.options` files and will pass them to the code " + 65 "generator." + 66 "\n\n" + 67 "Note that, in order for a `pw_proto_filegroup` to be a valid `srcs` " + 68 "entry for a `proto_library`, it must meet the same conditions " + 69 "required of a standard `filegroup` in that context. Namely, its " + 70 "`srcs` must provide at least one `.proto` (or `.protodevel`) file. " + 71 "Put simply, a `pw_proto_filegroup` cannot be used as a vector for " + 72 "injecting solely `.options` files; it must contain at least one " + 73 "proto as well (generally one associated with an included `.options` " + 74 "file in the interest of clarity)." + 75 "\n\n" + 76 "Regarding the somewhat unusual usage, this feature's design was " + 77 "mostly preordained by the combination of Bazel's strict access " + 78 "controls, the restrictions imposed on inputs to the `proto_library` " + 79 "rule, and the need to support `.options` files from transitive " + 80 "dependencies." 81 ), 82 implementation = _pw_proto_filegroup_impl, 83 attrs = { 84 "options_files": attr.label_list( 85 allow_files = True, 86 ), 87 "srcs": attr.label_list( 88 allow_files = True, 89 ), 90 }, 91 provides = [PwProtoOptionsInfo], 92) 93