xref: /aosp_15_r20/external/bazelbuild-rules_rust/test/link_std_dylib/link_std_dylib_test.bzl (revision d4726bddaa87cc4778e7472feed243fa4b6c267f)
1"""Analysis tests for experimental_link_std_dylib flag"""
2
3load("@rules_cc//cc:defs.bzl", "CcInfo")
4load("@rules_rust//rust:defs.bzl", "rust_binary", "rust_library")
5load("@rules_testing//lib:analysis_test.bzl", "analysis_test", "test_suite")
6
7# buildifier: disable=bzl-visibility
8load("//rust/private:utils.bzl", "is_std_dylib")
9
10def _test_rust_binary_impl(env, targets):
11    env.expect.that_action(targets.default_binary.actions[0]) \
12        .contains_none_of_flag_values([
13        ("--codegen", "prefer-dynamic"),
14    ])
15
16    # Make sure with @rules_rust//rust/settings:experimental_link_std_dylib,
17    # the linker flags are set up correct so that the binary dynamically links
18    # the stdlib
19    env.expect.that_action(targets.binary_with_std_dylib.actions[0]) \
20        .contains_flag_values([
21        ("--codegen", "prefer-dynamic"),
22    ])
23
24def _test_rust_binary(name):
25    rust_binary(
26        name = name + "_rust_binary",
27        srcs = ["main.rs"],
28        edition = "2021",
29        tags = ["manual"],
30    )
31
32    analysis_test(
33        name = name,
34        impl = _test_rust_binary_impl,
35        targets = {
36            "binary_with_std_dylib": name + "_rust_binary",
37            "default_binary": name + "_rust_binary",
38        },
39        attrs = {
40            "binary_with_std_dylib": {
41                "@config_settings": {
42                    str(Label("@rules_rust//rust/settings:experimental_link_std_dylib")): True,
43                },
44            },
45        },
46    )
47
48def _export_static_stdlibs_in_cc_info(target):
49    linker_inputs = target[CcInfo].linking_context.linker_inputs
50    for linker_input in linker_inputs.to_list():
51        for library in linker_input.libraries:
52            if hasattr(library, "pic_static_library") and library.pic_static_library != None:
53                basename = library.pic_static_library.basename
54                if basename.startswith("libstd") and basename.endswith(".a"):
55                    return True
56    return False
57
58def _export_libstd_dylib_in_cc_info(target):
59    linker_inputs = target[CcInfo].linking_context.linker_inputs
60    for linker_input in linker_inputs.to_list():
61        for library in linker_input.libraries:
62            if hasattr(library, "dynamic_library") and library.dynamic_library != None:
63                if is_std_dylib(library.dynamic_library):
64                    return True
65    return False
66
67def _test_rust_library_impl(env, targets):
68    # By default, rust_library exports static stdlibs to downstream shared
69    # and binary targets to statically link
70    env.expect \
71        .that_bool(_export_static_stdlibs_in_cc_info(targets.default_rlib)) \
72        .equals(True)
73    env.expect \
74        .that_bool(_export_libstd_dylib_in_cc_info(targets.default_rlib)) \
75        .equals(False)
76
77    # With @rules_rust//rust/settings:experimental_link_std_dylib
78    # rust_library exports dylib std and does not export static stdlibs to
79    # downstream shared and binary targets to dynamically link
80    env.expect \
81        .that_bool(_export_static_stdlibs_in_cc_info(targets.rlib_with_std_dylib)) \
82        .equals(False)
83    env.expect \
84        .that_bool(_export_libstd_dylib_in_cc_info(targets.rlib_with_std_dylib)) \
85        .equals(True)
86
87def _test_rust_library(name):
88    rust_library(
89        name = name + "_rust_library",
90        srcs = ["lib.rs"],
91        edition = "2021",
92        tags = ["manual"],
93    )
94
95    analysis_test(
96        name = name,
97        impl = _test_rust_library_impl,
98        targets = {
99            "default_rlib": name + "_rust_library",
100            "rlib_with_std_dylib": name + "_rust_library",
101        },
102        attrs = {
103            "rlib_with_std_dylib": {
104                "@config_settings": {
105                    str(Label("@rules_rust//rust/settings:experimental_link_std_dylib")): True,
106                },
107            },
108        },
109    )
110
111def link_std_dylib_test_suite(name):
112    test_suite(
113        name = name,
114        tests = [
115            _test_rust_binary,
116            _test_rust_library,
117        ],
118    )
119