1""" 2THIS IS THE EXTERNAL-ONLY VERSION OF THIS FILE. G3 HAS ITS OWN. 3 4This file contains a way to set flags from BUILD.bazel instead of requiring users to set them from 5the CLI. This allows us to have tests that build with a specific set of features (e.g. the pdf 6backend or the codecs) without having a large number of flags to set (easier to forget). 7 8It uses the same core implementation as cc_binary_with_flags. 9 10It is based off of: 11https://github.com/bazelbuild/examples/blob/7fc3f8b587ee415ff02ce358caa960f9533a912c/configurations/cc_test/defs.bzl 12 13""" 14 15load("@skia_user_config//:copts.bzl", "DEFAULT_COPTS") 16load("@skia_user_config//:linkopts.bzl", "DEFAULT_LINKOPTS") 17load("//bazel:cc_binary_with_flags.bzl", "with_flags_transition") 18 19def _transition_rule_impl(ctx): 20 executable_src = ctx.executable.actual_test 21 executable_dst = ctx.actions.declare_file(ctx.label.name) 22 ctx.actions.run_shell( 23 tools = [executable_src], 24 outputs = [executable_dst], 25 command = "cp %s %s" % (executable_src.path, executable_dst.path), 26 ) 27 runfiles = ctx.attr.actual_test[0][DefaultInfo].default_runfiles 28 return [DefaultInfo(runfiles = runfiles, executable = executable_dst)] 29 30# This rule must end with a _test suffix or Bazel doesn't allow the test attribute to be true. 31transition_test = rule( 32 implementation = _transition_rule_impl, 33 attrs = { 34 # set_flags is a dictionary with the keys being the short-form of a flag name 35 # (e.g. the part that comes after the colon) and the value being a list of values 36 # that the flag should be set to, regardless of the relevant CLI flags. 37 # https://bazel.build/rules/lib/attr#string_list_dict 38 "set_flags": attr.string_list_dict(), 39 # This is the cc_test that should be made with the flags being set. 40 # Note specifically how it is modified using with_flags_transition, which 41 # ensures that the flags propagates down the graph. Must be executable 42 # so the _transition_rule_impl can use it as an executable. 43 # https://bazel.build/rules/lib/attr#label 44 "actual_test": attr.label(cfg = with_flags_transition, executable = True), 45 # This is a stock Bazel requirement for any rule that uses Starlark 46 # transitions. It's okay to copy the below verbatim for all such rules. 47 # 48 # The purpose of this requirement is to give the ability to restrict 49 # which packages can invoke these rules, since Starlark transitions 50 # make much larger graphs possible that can have memory and performance 51 # consequences for your build. The allowlist defaults to "everything". 52 # But you can redefine it more strictly if you feel that's prudent. 53 "_allowlist_function_transition": attr.label( 54 default = "@bazel_tools//tools/allowlists/function_transition_allowlist", 55 ), 56 }, 57 # Means it works with "$ bazel test". https://bazel.build/rules/lib/globals#rule.test 58 test = True, 59) 60 61def cc_test_with_flags(name, set_flags = {}, copts = DEFAULT_COPTS, linkopts = DEFAULT_LINKOPTS, args = [], **kwargs): 62 """Builds a cc_test as if set_flags were set on the CLI. 63 64 Args: 65 name: string, the name for the rule that is the binary, but with the flags changed via 66 a transition. Any dependents should use this name. 67 set_flags: dictionary of string to list of strings. The keys should be the name of the 68 flag, and the values should be the desired valid settings for that flag. 69 copts: a list of strings or select statements that control the compiler flags. 70 It has a sensible list of defaults. 71 linkopts: a list of strings or select statements that control the linker flags. 72 It has a sensible list of defaults. 73 args: A list of strings with any command-line arguments to pass to the binary. 74 **kwargs: Any flags that a cc_binary normally takes. 75 """ 76 cc_test_name = name + "_native_test" 77 transition_test( 78 name = name, 79 actual_test = ":%s" % cc_test_name, 80 set_flags = set_flags, 81 args = args, 82 testonly = True, 83 ) 84 tags = kwargs.get("tags", []) 85 tags.append("manual") # We want to exclude this helper test from bazel test foo/... 86 kwargs["tags"] = tags 87 native.cc_test( 88 name = cc_test_name, 89 copts = copts, 90 linkopts = linkopts, 91 **kwargs 92 ) 93