xref: /aosp_15_r20/external/skia/tools/testrunners/common/binary_wrapper_script_with_cmdline_flags.bzl (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
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