# Copyright (C) 2021 The Android Open Source Project # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. load("@bazel_skylib//lib:paths.bzl", "paths") # A rule to generate files based on provided srcs and tools def _gensrcs_impl(ctx): # The next two assignments can be created by using ctx.resolve_command # TODO: Switch to using ctx.resolve_command when it is out of experimental command = ctx.expand_location(ctx.attr.cmd, targets = ctx.attr.data) tools = [ tool[DefaultInfo].files_to_run for tool in ctx.attr.tools ] command = command.replace( "$(RULEDIR)", paths.join( ctx.var["GENDIR"], ctx.label.package, ), ) in_files = ctx.files.srcs out_files = [] for in_file in in_files: # /out_file # where path-to-in_file is relative to the workspace out_file_path = paths.join( paths.dirname(in_file.short_path), paths.replace_extension( in_file.basename, "." + ctx.attr.output_extension, ), ) # out_file is at output_file_path that is relative to / # Hence, the fullpath to out_file is # ///out_file out_file = ctx.actions.declare_file(out_file_path) shell_command = command \ .replace("$(SRC)", in_file.path) \ .replace("$(OUT)", out_file.path) ctx.actions.run_shell( tools = tools, outputs = [out_file], inputs = in_files + ctx.files.data, command = shell_command, progress_message = "Generating %s from %s" % ( out_file.path, in_file.path, ), ) out_files.append(out_file) return [DefaultInfo( files = depset(out_files), )] gensrcs = rule( implementation = _gensrcs_impl, doc = "This rule generates files, where each of the `srcs` files is " + "passed into the custom shell command`", attrs = { "srcs": attr.label_list( allow_files = True, mandatory = True, doc = "A list of inputs such as source files to process", ), "output_extension": attr.string( doc = "The extension that will be substituted for output files", ), "cmd": attr.string( mandatory = True, doc = "The command to run. Subject to $(location) expansion. " + "$(IN) represents each input file provided in `srcs` " + "while $(OUT) reprensents corresponding output file " + "generated by the rule. $(RULEDIR) is intepreted the same " + "as it is in genrule.", ), "tools": attr.label_list( allow_files = True, doc = "A list of tool dependencies for this rule. " + "The path of an individual `tools` target //x:y can be " + "obtained using `$(location //x:y)`", cfg = "exec", ), "data": attr.label_list( allow_files = True, doc = "Additional files needed for build that are not tooling " + "related.", ), }, )