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