1"""This module defines the binary_wrapper_script_with_cmdline_flags rule.""" 2 3load("//bazel:remove_indentation.bzl", "remove_indentation") 4 5# https://bazel.build/rules/lib/builtins/ctx 6def _binary_wrapper_script_with_cmdline_flags_impl(ctx): 7 args = ([ 8 "--resourcePath", 9 "$(dirname $(realpath $(rootpath %s)))" % ctx.attr._arbitrary_file_in_resources_dir.label, 10 ] if ctx.attr.requires_resources_dir else []) 11 args += ctx.attr.extra_args 12 13 # This will gather any additional command-line arguments passed to the C++ binary. When running 14 # the binary via "bazel test", additional arguments can be passed via Bazel's --test_arg flag. 15 # When building the binary with "bazel build" and running the resulting binary outside of 16 # Bazel, any arguments passed to the Bazel-built binary will be captured here. 17 args.append("$@") 18 19 template = remove_indentation(""" 20 #!/bin/sh 21 $(rootpath {binary}) {args} 22 """) 23 24 template = ctx.expand_location(template.format( 25 binary = ctx.attr.binary.label, 26 args = " ".join(args), 27 ), targets = [ 28 ctx.attr.binary, 29 ctx.attr._arbitrary_file_in_resources_dir, 30 ]) 31 32 # https://bazel.build/rules/lib/builtins/actions.html#declare_file 33 output_file = ctx.actions.declare_file(ctx.attr.name) 34 ctx.actions.write(output_file, template, is_executable = True) 35 36 runfiles = ctx.runfiles( 37 files = ctx.files._resources_dir if ctx.attr.requires_resources_dir else [], 38 ) 39 runfiles = runfiles.merge(ctx.attr.binary[DefaultInfo].default_runfiles) 40 41 return [DefaultInfo( 42 executable = output_file, 43 runfiles = runfiles, 44 )] 45 46binary_wrapper_script_with_cmdline_flags = rule( 47 doc = """Produces a script that invokes a C++ test runner with the given command-line flags. 48 49 This rule is intended to wrap C++ test runners and therefore has convenience attributes 50 specific to said binaries, such as requires_resources_dir. 51 52 The reason why we use a custom rule rather than a genrule is that we wish to select() the 53 extra_args attribute based e.g. on the device under test and various build settings. 54 """, 55 implementation = _binary_wrapper_script_with_cmdline_flags_impl, 56 attrs = { 57 "binary": attr.label( 58 doc = "Binary to wrap.", 59 mandatory = True, 60 executable = True, 61 allow_single_file = True, 62 cfg = "target", 63 ), 64 "requires_resources_dir": attr.bool( 65 doc = ( 66 "If true, the test will be passed flag --resourcePath <path to //resources dir>." 67 ), 68 ), 69 "extra_args": attr.string_list( 70 doc = "Any additional command-line arguments to pass to the C++ test binary.", 71 ), 72 "_resources_dir": attr.label( 73 doc = "This directory will optionally be added to the test's runfiles.", 74 default = Label("//resources"), 75 ), 76 "_arbitrary_file_in_resources_dir": attr.label( 77 doc = "Used to compute the --resourcePath flag.", 78 default = Label("//resources:README"), 79 allow_single_file = True, 80 ), 81 }, 82) 83