1"""Unittests for rust rules.""" 2 3load("@bazel_skylib//lib:unittest.bzl", "analysistest", "asserts") 4load("//rust:defs.bzl", "rust_binary", "rust_library", "rust_proc_macro", "rust_shared_library", "rust_static_library") 5 6def _is_dylib_on_windows(ctx): 7 return ctx.target_platform_has_constraint(ctx.attr._windows[platform_common.ConstraintValueInfo]) 8 9def _assert_cc_info_has_library_to_link(env, tut, type, ccinfo_count): 10 asserts.true(env, CcInfo in tut, "rust_library should provide CcInfo") 11 cc_info = tut[CcInfo] 12 linker_inputs = cc_info.linking_context.linker_inputs.to_list() 13 asserts.equals(env, ccinfo_count, len(linker_inputs)) 14 library_to_link = linker_inputs[0].libraries[0] 15 asserts.equals(env, False, library_to_link.alwayslink) 16 17 asserts.equals(env, [], library_to_link.lto_bitcode_files) 18 asserts.equals(env, [], library_to_link.pic_lto_bitcode_files) 19 20 asserts.equals(env, [], library_to_link.objects) 21 asserts.equals(env, [], library_to_link.pic_objects) 22 23 if type == "cdylib": 24 asserts.true(env, library_to_link.dynamic_library != None) 25 if _is_dylib_on_windows(env.ctx): 26 asserts.true(env, library_to_link.interface_library != None) 27 asserts.true(env, library_to_link.resolved_symlink_dynamic_library == None) 28 else: 29 asserts.equals(env, None, library_to_link.interface_library) 30 asserts.true(env, library_to_link.resolved_symlink_dynamic_library != None) 31 asserts.equals(env, None, library_to_link.resolved_symlink_interface_library) 32 asserts.equals(env, None, library_to_link.static_library) 33 asserts.equals(env, None, library_to_link.pic_static_library) 34 else: 35 asserts.equals(env, None, library_to_link.dynamic_library) 36 asserts.equals(env, None, library_to_link.interface_library) 37 asserts.equals(env, None, library_to_link.resolved_symlink_dynamic_library) 38 asserts.equals(env, None, library_to_link.resolved_symlink_interface_library) 39 asserts.true(env, library_to_link.static_library != None) 40 if type in ("rlib", "lib"): 41 asserts.true(env, library_to_link.static_library.basename.startswith("lib" + tut.label.name)) 42 asserts.true(env, library_to_link.pic_static_library != None) 43 asserts.equals(env, library_to_link.static_library, library_to_link.pic_static_library) 44 45def _collect_user_link_flags(env, tut): 46 asserts.true(env, CcInfo in tut, "rust_library should provide CcInfo") 47 cc_info = tut[CcInfo] 48 linker_inputs = cc_info.linking_context.linker_inputs.to_list() 49 return [f for i in linker_inputs for f in i.user_link_flags] 50 51def _rlib_provides_cc_info_test_impl(ctx): 52 env = analysistest.begin(ctx) 53 tut = analysistest.target_under_test(env) 54 _assert_cc_info_has_library_to_link(env, tut, "rlib", 4) 55 return analysistest.end(env) 56 57def _rlib_with_dep_only_has_stdlib_linkflags_once_test_impl(ctx): 58 env = analysistest.begin(ctx) 59 tut = analysistest.target_under_test(env) 60 user_link_flags = _collect_user_link_flags(env, tut) 61 asserts.equals( 62 env, 63 depset(user_link_flags).to_list(), 64 user_link_flags, 65 "user_link_flags_should_not_have_duplicates_here", 66 ) 67 return analysistest.end(env) 68 69def _bin_does_not_provide_cc_info_test_impl(ctx): 70 env = analysistest.begin(ctx) 71 tut = analysistest.target_under_test(env) 72 asserts.false(env, CcInfo in tut, "rust_binary should not provide CcInfo") 73 return analysistest.end(env) 74 75def _proc_macro_does_not_provide_cc_info_test_impl(ctx): 76 env = analysistest.begin(ctx) 77 tut = analysistest.target_under_test(env) 78 asserts.false(env, CcInfo in tut, "rust_proc_macro should not provide CcInfo") 79 return analysistest.end(env) 80 81def _cdylib_provides_cc_info_test_impl(ctx): 82 env = analysistest.begin(ctx) 83 tut = analysistest.target_under_test(env) 84 _assert_cc_info_has_library_to_link(env, tut, "cdylib", 2) 85 return analysistest.end(env) 86 87def _staticlib_provides_cc_info_test_impl(ctx): 88 env = analysistest.begin(ctx) 89 tut = analysistest.target_under_test(env) 90 _assert_cc_info_has_library_to_link(env, tut, "staticlib", 2) 91 return analysistest.end(env) 92 93rlib_provides_cc_info_test = analysistest.make(_rlib_provides_cc_info_test_impl) 94rlib_with_dep_only_has_stdlib_linkflags_once_test = analysistest.make( 95 _rlib_with_dep_only_has_stdlib_linkflags_once_test_impl, 96) 97bin_does_not_provide_cc_info_test = analysistest.make(_bin_does_not_provide_cc_info_test_impl) 98staticlib_provides_cc_info_test = analysistest.make(_staticlib_provides_cc_info_test_impl) 99cdylib_provides_cc_info_test = analysistest.make(_cdylib_provides_cc_info_test_impl, attrs = { 100 "_windows": attr.label(default = Label("@platforms//os:windows")), 101}) 102proc_macro_does_not_provide_cc_info_test = analysistest.make(_proc_macro_does_not_provide_cc_info_test_impl) 103 104def _cc_info_test(): 105 rust_library( 106 name = "rlib", 107 srcs = ["foo.rs"], 108 edition = "2018", 109 ) 110 111 rust_library( 112 name = "rlib_with_dep", 113 srcs = ["foo.rs"], 114 edition = "2018", 115 deps = [":rlib"], 116 ) 117 118 rust_binary( 119 name = "bin", 120 srcs = ["foo.rs"], 121 edition = "2018", 122 ) 123 124 rust_static_library( 125 name = "staticlib", 126 srcs = ["foo.rs"], 127 edition = "2018", 128 ) 129 130 rust_shared_library( 131 name = "cdylib", 132 srcs = ["foo.rs"], 133 edition = "2018", 134 ) 135 136 rust_proc_macro( 137 name = "proc_macro", 138 srcs = ["proc_macro.rs"], 139 edition = "2018", 140 deps = ["//test/unit/native_deps:native_dep"], 141 ) 142 143 rlib_provides_cc_info_test( 144 name = "rlib_provides_cc_info_test", 145 target_under_test = ":rlib", 146 ) 147 rlib_with_dep_only_has_stdlib_linkflags_once_test( 148 name = "rlib_with_dep_only_has_stdlib_linkflags_once_test", 149 target_under_test = ":rlib_with_dep", 150 ) 151 bin_does_not_provide_cc_info_test( 152 name = "bin_does_not_provide_cc_info_test", 153 target_under_test = ":bin", 154 ) 155 cdylib_provides_cc_info_test( 156 name = "cdylib_provides_cc_info_test", 157 target_under_test = ":cdylib", 158 ) 159 staticlib_provides_cc_info_test( 160 name = "staticlib_provides_cc_info_test", 161 target_under_test = ":staticlib", 162 ) 163 proc_macro_does_not_provide_cc_info_test( 164 name = "proc_macro_does_not_provide_cc_info_test", 165 target_under_test = ":proc_macro", 166 ) 167 168def cc_info_test_suite(name): 169 """Entry-point macro called from the BUILD file. 170 171 Args: 172 name: Name of the macro. 173 """ 174 _cc_info_test() 175 176 native.test_suite( 177 name = name, 178 tests = [ 179 ":rlib_provides_cc_info_test", 180 ":rlib_with_dep_only_has_stdlib_linkflags_once_test", 181 ":staticlib_provides_cc_info_test", 182 ":cdylib_provides_cc_info_test", 183 ":proc_macro_does_not_provide_cc_info_test", 184 ":bin_does_not_provide_cc_info_test", 185 ], 186 ) 187