xref: /aosp_15_r20/external/bazelbuild-rules_rust/test/toolchain/toolchain_test.bzl (revision d4726bddaa87cc4778e7472feed243fa4b6c267f)
1"""End to end tests for rust toolchains."""
2
3load("@bazel_skylib//lib:unittest.bzl", "analysistest", "asserts")
4load("@bazel_skylib//rules:write_file.bzl", "write_file")
5load("//rust:defs.bzl", "rust_library", "rust_shared_library")
6load("//rust:toolchain.bzl", "rust_stdlib_filegroup", "rust_toolchain")
7
8EXEC_TOOLCHAIN_FLAG = "missing"
9TOOLCHAIN_FLAG = "before"
10CONFIG_FLAG = "after"
11CRATE_FLAGS = {"cdylib": ["cdylib_flag"], "rlib": ["rlib_flag"]}
12
13def _toolchain_adds_rustc_flags_impl(ctx, crate_type):
14    """ Tests adding extra_rustc_flags on the toolchain, asserts that:
15
16    - extra_rustc_flags added by the toolchain are applied BEFORE flags added by a config on the commandline
17    - The exec flags from the toolchain don't go on the commandline for a non-exec target
18    - crate type rustc flags are added
19    """
20    env = analysistest.begin(ctx)
21    target = analysistest.target_under_test(env)
22    action = target[DepActionsInfo].actions[0]
23
24    asserts.equals(env, "Rustc", action.mnemonic)
25
26    asserts.true(
27        env,
28        action.argv[-2:] == [TOOLCHAIN_FLAG, CONFIG_FLAG],
29        "Unexpected rustc flags: {}\nShould have ended with: {}".format(
30            action.argv,
31            [TOOLCHAIN_FLAG, CONFIG_FLAG],
32        ),
33    )
34
35    asserts.true(
36        env,
37        action.argv[-3] == CRATE_FLAGS[crate_type][0],
38        "Unexpected rustc flags: {}\nShould have contained: {}".format(
39            action.argv,
40            CRATE_FLAGS["rlib"],
41        ),
42    )
43
44    for type in CRATE_FLAGS.keys():
45        if type == crate_type:
46            continue
47        asserts.false(
48            env,
49            CRATE_FLAGS[type][0] in action.argv,
50            "Unexpected rustc flags: {}\nShould not contain: {}".format(
51                action.argv,
52                CRATE_FLAGS[type],
53            ),
54        )
55
56    asserts.true(
57        env,
58        EXEC_TOOLCHAIN_FLAG not in action.argv,
59        "Found exec toolchain flag ({}) in rustc flags: {}".format(EXEC_TOOLCHAIN_FLAG, action.argv),
60    )
61
62    found_sysroot = False
63    for arg in action.argv:
64        if arg.startswith("--sysroot") and arg.endswith("test/toolchain/rust_extra_flags_toolchain"):
65            found_sysroot = True
66    asserts.true(
67        env,
68        found_sysroot,
69        "Missing --sysroot flag or --sysroot does not point to correct sysroot directory",
70    )
71
72    return analysistest.end(env)
73
74def _toolchain_adds_rustc_flags_lib_impl(ctx):
75    return _toolchain_adds_rustc_flags_impl(ctx, "rlib")
76
77def _toolchain_adds_rustc_flags_shared_lib_impl(ctx):
78    return _toolchain_adds_rustc_flags_impl(ctx, "cdylib")
79
80toolchain_adds_rustc_flags_lib_test = analysistest.make(
81    _toolchain_adds_rustc_flags_lib_impl,
82    config_settings = {
83        str(Label("//:extra_rustc_flags")): [CONFIG_FLAG],
84        str(Label("//rust/settings:experimental_toolchain_generated_sysroot")): True,
85    },
86)
87
88toolchain_adds_rustc_flags_shared_lib_test = analysistest.make(
89    _toolchain_adds_rustc_flags_shared_lib_impl,
90    config_settings = {
91        str(Label("//:extra_rustc_flags")): [CONFIG_FLAG],
92        str(Label("//rust/settings:experimental_toolchain_generated_sysroot")): True,
93    },
94)
95
96def _extra_toolchain_transition_impl(settings, _attr):
97    return {"//command_line_option:extra_toolchains": [
98        "@rules_rust//test/toolchain:extra_flags_toolchain",
99    ] + settings["//command_line_option:extra_toolchains"]}
100
101_extra_toolchain_transition = transition(
102    implementation = _extra_toolchain_transition_impl,
103    inputs = ["//command_line_option:extra_toolchains"],
104    outputs = ["//command_line_option:extra_toolchains"],
105)
106
107DepActionsInfo = provider(
108    "Contains information about dependencies actions.",
109    fields = {"actions": "List[Action]"},
110)
111
112def _collect_dep_actions_aspect_impl(target, ctx):
113    actions = []
114    actions.extend(target.actions)
115    for dep in ctx.rule.attr.deps:
116        actions.extend(dep[DepActionsInfo].actions)
117    return [DepActionsInfo(actions = actions)]
118
119collect_dep_actions_aspect = aspect(
120    implementation = _collect_dep_actions_aspect_impl,
121    attr_aspects = ["deps"],
122)
123
124def _extra_toolchain_wrapper_impl(ctx):
125    return [ctx.attr.dep[DepActionsInfo]]
126
127extra_toolchain_wrapper = rule(
128    implementation = _extra_toolchain_wrapper_impl,
129    attrs = {
130        "dep": attr.label(aspects = [collect_dep_actions_aspect]),
131        "_allowlist_function_transition": attr.label(
132            default = "@bazel_tools//tools/allowlists/function_transition_allowlist",
133        ),
134    },
135    cfg = _extra_toolchain_transition,
136)
137
138def _define_targets():
139    rust_library(
140        name = "lib",
141        srcs = ["lib.rs"],
142        edition = "2021",
143    )
144
145    rust_shared_library(
146        name = "shared_lib",
147        srcs = ["lib.rs"],
148        edition = "2021",
149    )
150
151    native.filegroup(
152        name = "stdlib_srcs",
153        srcs = ["config.txt"],
154    )
155    rust_stdlib_filegroup(
156        name = "std_libs",
157        srcs = [":stdlib_srcs"],
158    )
159    write_file(
160        name = "mock_rustc",
161        out = "mock_rustc.exe",
162        content = [],
163        is_executable = True,
164    )
165    write_file(
166        name = "mock_rustdoc",
167        out = "mock_rustdoc.exe",
168        content = [],
169        is_executable = True,
170    )
171
172    rust_toolchain(
173        name = "rust_extra_flags_toolchain",
174        binary_ext = "",
175        dylib_ext = ".so",
176        exec_triple = "x86_64-unknown-none",
177        target_triple = "x86_64-unknown-none",
178        rust_doc = ":mock_rustdoc",
179        rust_std = ":std_libs",
180        rustc = ":mock_rustc",
181        staticlib_ext = ".a",
182        stdlib_linkflags = [],
183        extra_rustc_flags = [TOOLCHAIN_FLAG],
184        extra_exec_rustc_flags = [EXEC_TOOLCHAIN_FLAG],
185        extra_rustc_flags_for_crate_types = CRATE_FLAGS,
186        visibility = ["//visibility:public"],
187    )
188
189    native.toolchain(
190        name = "extra_flags_toolchain",
191        toolchain = ":rust_extra_flags_toolchain",
192        toolchain_type = "@rules_rust//rust:toolchain",
193    )
194
195    extra_toolchain_wrapper(
196        name = "lib_with_extra_toolchain",
197        dep = ":lib",
198    )
199
200    extra_toolchain_wrapper(
201        name = "shared_lib_with_extra_toolchain",
202        dep = ":shared_lib",
203    )
204
205def _rust_stdlib_filegroup_provides_runfiles_test_impl(ctx):
206    env = analysistest.begin(ctx)
207    target = analysistest.target_under_test(env)
208    runfiles = target[DefaultInfo].default_runfiles
209    asserts.true(env, len(runfiles.files.to_list()) > 0)
210
211    return analysistest.end(env)
212
213rust_stdlib_filegroup_provides_runfiles_test = analysistest.make(
214    _rust_stdlib_filegroup_provides_runfiles_test_impl,
215)
216
217def toolchain_test_suite(name):
218    """ Instantiates tests for rust toolchains.
219
220    Args:
221        name: a name for the test suite
222    """
223    _define_targets()
224
225    toolchain_adds_rustc_flags_lib_test(
226        name = "toolchain_adds_rustc_flags_lib_test",
227        target_under_test = ":lib_with_extra_toolchain",
228    )
229
230    toolchain_adds_rustc_flags_shared_lib_test(
231        name = "toolchain_adds_rustc_flags_shared_lib_test",
232        target_under_test = ":shared_lib_with_extra_toolchain",
233    )
234
235    rust_stdlib_filegroup_provides_runfiles_test(
236        name = "rust_stdlib_filegroup_provides_runfiles_test",
237        target_under_test = ":std_libs",
238    )
239
240    native.test_suite(
241        name = name,
242        tests = [
243            ":toolchain_adds_rustc_flags_lib_test",
244            ":toolchain_adds_rustc_flags_shared_lib_test",
245            ":rust_stdlib_filegroup_provides_runfiles_test",
246        ],
247    )
248