xref: /aosp_15_r20/build/bazel/rules/cc/testing/transitions.bzl (revision 7594170e27e0732bc44b93d1440d87a54b6ffe7c)
1*7594170eSAndroid Build Coastguard Workerload("@bazel_skylib//lib:dicts.bzl", "dicts")
2*7594170eSAndroid Build Coastguard Workerload("@bazel_skylib//lib:sets.bzl", "sets")
3*7594170eSAndroid Build Coastguard Workerload("@bazel_skylib//lib:unittest.bzl", "analysistest", "asserts")
4*7594170eSAndroid Build Coastguard Worker
5*7594170eSAndroid Build Coastguard WorkerActionArgsInfo = provider(
6*7594170eSAndroid Build Coastguard Worker    fields = {
7*7594170eSAndroid Build Coastguard Worker        "argv_map": "A dict with compile action arguments keyed by the target label",
8*7594170eSAndroid Build Coastguard Worker    },
9*7594170eSAndroid Build Coastguard Worker)
10*7594170eSAndroid Build Coastguard Worker
11*7594170eSAndroid Build Coastguard Workerdef _action_argv_aspect_impl(target, ctx):
12*7594170eSAndroid Build Coastguard Worker    argv_map = {}
13*7594170eSAndroid Build Coastguard Worker    if ctx.rule.kind == ctx.attr._target_rule:
14*7594170eSAndroid Build Coastguard Worker        _cpp_commands_args = []
15*7594170eSAndroid Build Coastguard Worker        for action in target.actions:
16*7594170eSAndroid Build Coastguard Worker            if action.mnemonic == ctx.attr._action:
17*7594170eSAndroid Build Coastguard Worker                _cpp_commands_args.extend(action.argv)
18*7594170eSAndroid Build Coastguard Worker
19*7594170eSAndroid Build Coastguard Worker        if len(_cpp_commands_args):
20*7594170eSAndroid Build Coastguard Worker            argv_map = dicts.add(
21*7594170eSAndroid Build Coastguard Worker                argv_map,
22*7594170eSAndroid Build Coastguard Worker                {
23*7594170eSAndroid Build Coastguard Worker                    target.label.name: _cpp_commands_args,
24*7594170eSAndroid Build Coastguard Worker                },
25*7594170eSAndroid Build Coastguard Worker            )
26*7594170eSAndroid Build Coastguard Worker    elif ctx.rule.kind in ctx.attr._attr_aspect_dict.keys():
27*7594170eSAndroid Build Coastguard Worker        attrs = ctx.attr._attr_aspect_dict.get(ctx.rule.kind, [])
28*7594170eSAndroid Build Coastguard Worker        for attr_name in attrs:
29*7594170eSAndroid Build Coastguard Worker            value = getattr(ctx.rule.attr, attr_name)
30*7594170eSAndroid Build Coastguard Worker            vlist = value if type(value) == type([]) else [value]
31*7594170eSAndroid Build Coastguard Worker            for value in vlist:
32*7594170eSAndroid Build Coastguard Worker                argv_map = dicts.add(
33*7594170eSAndroid Build Coastguard Worker                    argv_map,
34*7594170eSAndroid Build Coastguard Worker                    value[ActionArgsInfo].argv_map,
35*7594170eSAndroid Build Coastguard Worker                )
36*7594170eSAndroid Build Coastguard Worker    return ActionArgsInfo(
37*7594170eSAndroid Build Coastguard Worker        argv_map = argv_map,
38*7594170eSAndroid Build Coastguard Worker    )
39*7594170eSAndroid Build Coastguard Worker
40*7594170eSAndroid Build Coastguard Workerdef _get_attr_aspects_list(attr_aspects_dict):
41*7594170eSAndroid Build Coastguard Worker    return sets.to_list(
42*7594170eSAndroid Build Coastguard Worker        sets.make(
43*7594170eSAndroid Build Coastguard Worker            [attr for rule in attr_aspects_dict.values() for attr in rule],
44*7594170eSAndroid Build Coastguard Worker        ),
45*7594170eSAndroid Build Coastguard Worker    )
46*7594170eSAndroid Build Coastguard Worker
47*7594170eSAndroid Build Coastguard Worker# The aspects generated by this function are used to examine compile actions
48*7594170eSAndroid Build Coastguard Worker# from cc_library targets generated by our macros for the purpose of assessing
49*7594170eSAndroid Build Coastguard Worker# the results of transitions. Checking the targets directly using their names
50*7594170eSAndroid Build Coastguard Worker# gives info from before the transition is applied.
51*7594170eSAndroid Build Coastguard Worker# attr_aspects should be a dict where the keys are the names of rules and the
52*7594170eSAndroid Build Coastguard Worker# values are lists of attrs that should be traversed by the aspect looking for
53*7594170eSAndroid Build Coastguard Worker# cc_library targets.
54*7594170eSAndroid Build Coastguard Workerdef compile_action_argv_aspect_generator(attr_aspects):
55*7594170eSAndroid Build Coastguard Worker    return aspect(
56*7594170eSAndroid Build Coastguard Worker        implementation = _action_argv_aspect_impl,
57*7594170eSAndroid Build Coastguard Worker        attr_aspects = _get_attr_aspects_list(attr_aspects),
58*7594170eSAndroid Build Coastguard Worker        attrs = {
59*7594170eSAndroid Build Coastguard Worker            "_attr_aspect_dict": attr.string_list_dict(default = attr_aspects),
60*7594170eSAndroid Build Coastguard Worker            "_action": attr.string(default = "CppCompile"),
61*7594170eSAndroid Build Coastguard Worker            "_target_rule": attr.string(default = "cc_library"),
62*7594170eSAndroid Build Coastguard Worker        },
63*7594170eSAndroid Build Coastguard Worker    )
64*7594170eSAndroid Build Coastguard Worker
65*7594170eSAndroid Build Coastguard Workerdef link_action_argv_aspect_generator(attr_aspects, target_rule):
66*7594170eSAndroid Build Coastguard Worker    return aspect(
67*7594170eSAndroid Build Coastguard Worker        implementation = _action_argv_aspect_impl,
68*7594170eSAndroid Build Coastguard Worker        attr_aspects = _get_attr_aspects_list(attr_aspects),
69*7594170eSAndroid Build Coastguard Worker        attrs = {
70*7594170eSAndroid Build Coastguard Worker            "_attr_aspect_dict": attr.string_list_dict(default = attr_aspects),
71*7594170eSAndroid Build Coastguard Worker            "_action": attr.string(default = "CppLink"),
72*7594170eSAndroid Build Coastguard Worker            "_target_rule": attr.string(default = target_rule),
73*7594170eSAndroid Build Coastguard Worker        },
74*7594170eSAndroid Build Coastguard Worker    )
75*7594170eSAndroid Build Coastguard Worker
76*7594170eSAndroid Build Coastguard Workerdef transition_deps_test_impl(ctx):
77*7594170eSAndroid Build Coastguard Worker    env = analysistest.begin(ctx)
78*7594170eSAndroid Build Coastguard Worker    target_under_test = analysistest.target_under_test(env)
79*7594170eSAndroid Build Coastguard Worker    argv_map = target_under_test[ActionArgsInfo].argv_map
80*7594170eSAndroid Build Coastguard Worker
81*7594170eSAndroid Build Coastguard Worker    for target in ctx.attr.targets_with_flag:
82*7594170eSAndroid Build Coastguard Worker        asserts.true(
83*7594170eSAndroid Build Coastguard Worker            env,
84*7594170eSAndroid Build Coastguard Worker            target in argv_map,
85*7594170eSAndroid Build Coastguard Worker            "can't find {} in argv map".format(target),
86*7594170eSAndroid Build Coastguard Worker        )
87*7594170eSAndroid Build Coastguard Worker        if target in argv_map:
88*7594170eSAndroid Build Coastguard Worker            argv = argv_map[target]
89*7594170eSAndroid Build Coastguard Worker            for flag in ctx.attr.flags:
90*7594170eSAndroid Build Coastguard Worker                asserts.true(
91*7594170eSAndroid Build Coastguard Worker                    env,
92*7594170eSAndroid Build Coastguard Worker                    flag in argv,
93*7594170eSAndroid Build Coastguard Worker                    "Action of {} didn't have {} flag but it was expected".format(
94*7594170eSAndroid Build Coastguard Worker                        target,
95*7594170eSAndroid Build Coastguard Worker                        flag,
96*7594170eSAndroid Build Coastguard Worker                    ),
97*7594170eSAndroid Build Coastguard Worker                )
98*7594170eSAndroid Build Coastguard Worker    for target in ctx.attr.targets_without_flag:
99*7594170eSAndroid Build Coastguard Worker        asserts.true(
100*7594170eSAndroid Build Coastguard Worker            env,
101*7594170eSAndroid Build Coastguard Worker            target in argv_map,
102*7594170eSAndroid Build Coastguard Worker            "can't find {} in argv map".format(target),
103*7594170eSAndroid Build Coastguard Worker        )
104*7594170eSAndroid Build Coastguard Worker        if target in argv_map:
105*7594170eSAndroid Build Coastguard Worker            argv = argv_map[target]
106*7594170eSAndroid Build Coastguard Worker            for flag in ctx.attr.flags:
107*7594170eSAndroid Build Coastguard Worker                asserts.true(
108*7594170eSAndroid Build Coastguard Worker                    env,
109*7594170eSAndroid Build Coastguard Worker                    flag not in argv,
110*7594170eSAndroid Build Coastguard Worker                    "Action of {} had {} flag but it wasn't expected".format(
111*7594170eSAndroid Build Coastguard Worker                        target,
112*7594170eSAndroid Build Coastguard Worker                        flag,
113*7594170eSAndroid Build Coastguard Worker                    ),
114*7594170eSAndroid Build Coastguard Worker                )
115*7594170eSAndroid Build Coastguard Worker    return analysistest.end(env)
116*7594170eSAndroid Build Coastguard Worker
117*7594170eSAndroid Build Coastguard Workertransition_deps_test_attrs = {
118*7594170eSAndroid Build Coastguard Worker    "targets_with_flag": attr.string_list(),
119*7594170eSAndroid Build Coastguard Worker    "targets_without_flag": attr.string_list(),
120*7594170eSAndroid Build Coastguard Worker    "flags": attr.string_list(),
121*7594170eSAndroid Build Coastguard Worker}
122