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") 6load("//rust:toolchain.bzl", "rust_stdlib_filegroup", "rust_toolchain") 7 8EXEC_TOOLCHAIN_FLAG = "missing" 9TOOLCHAIN_FLAG = "before" 10CONFIG_FLAG = "after" 11 12def _toolchain_adds_rustc_flags_impl(ctx): 13 """ Tests adding extra_rustc_flags on the toolchain, asserts that: 14 15 - extra_rustc_flags added by the toolchain are applied BEFORE flags added by a config on the commandline 16 - The exec flags from the toolchain don't go on the commandline for a non-exec target 17 """ 18 env = analysistest.begin(ctx) 19 target = analysistest.target_under_test(env) 20 action = target[DepActionsInfo].actions[0] 21 22 asserts.equals(env, "Rustc", action.mnemonic) 23 24 asserts.true( 25 env, 26 action.argv[-2:] == [TOOLCHAIN_FLAG, CONFIG_FLAG], 27 "Unexpected rustc flags: {}\nShould have ended with: {}".format( 28 action.argv, 29 [TOOLCHAIN_FLAG, CONFIG_FLAG], 30 ), 31 ) 32 33 asserts.true( 34 env, 35 EXEC_TOOLCHAIN_FLAG not in action.argv, 36 "Found exec toolchain flag ({}) in rustc flags: {}".format(EXEC_TOOLCHAIN_FLAG, action.argv), 37 ) 38 39 found_sysroot = False 40 for arg in action.argv: 41 if arg.startswith("--sysroot") and arg.endswith("test/toolchain/rust_extra_flags_toolchain"): 42 found_sysroot = True 43 asserts.true( 44 env, 45 found_sysroot, 46 "Missing --sysroot flag or --sysroot does not point to correct sysroot directory", 47 ) 48 49 return analysistest.end(env) 50 51toolchain_adds_rustc_flags_test = analysistest.make( 52 _toolchain_adds_rustc_flags_impl, 53 config_settings = { 54 str(Label("//:extra_rustc_flags")): [CONFIG_FLAG], 55 str(Label("//rust/settings:experimental_toolchain_generated_sysroot")): True, 56 }, 57) 58 59def _extra_toolchain_transition_impl(settings, _attr): 60 return {"//command_line_option:extra_toolchains": [ 61 "@rules_rust//test/toolchain:extra_flags_toolchain", 62 ] + settings["//command_line_option:extra_toolchains"]} 63 64_extra_toolchain_transition = transition( 65 implementation = _extra_toolchain_transition_impl, 66 inputs = ["//command_line_option:extra_toolchains"], 67 outputs = ["//command_line_option:extra_toolchains"], 68) 69 70DepActionsInfo = provider( 71 "Contains information about dependencies actions.", 72 fields = {"actions": "List[Action]"}, 73) 74 75def _collect_dep_actions_aspect_impl(target, ctx): 76 actions = [] 77 actions.extend(target.actions) 78 for dep in ctx.rule.attr.deps: 79 actions.extend(dep[DepActionsInfo].actions) 80 return [DepActionsInfo(actions = actions)] 81 82collect_dep_actions_aspect = aspect( 83 implementation = _collect_dep_actions_aspect_impl, 84 attr_aspects = ["deps"], 85) 86 87def _extra_toolchain_wrapper_impl(ctx): 88 return [ctx.attr.dep[DepActionsInfo]] 89 90extra_toolchain_wrapper = rule( 91 implementation = _extra_toolchain_wrapper_impl, 92 attrs = { 93 "dep": attr.label(aspects = [collect_dep_actions_aspect]), 94 "_allowlist_function_transition": attr.label( 95 default = "@bazel_tools//tools/allowlists/function_transition_allowlist", 96 ), 97 }, 98 cfg = _extra_toolchain_transition, 99) 100 101def _define_targets(): 102 rust_library( 103 name = "lib", 104 srcs = ["lib.rs"], 105 edition = "2021", 106 ) 107 108 native.filegroup( 109 name = "stdlib_srcs", 110 srcs = ["config.txt"], 111 ) 112 rust_stdlib_filegroup( 113 name = "std_libs", 114 srcs = [":stdlib_srcs"], 115 ) 116 write_file( 117 name = "mock_rustc", 118 out = "mock_rustc.exe", 119 content = [], 120 is_executable = True, 121 ) 122 write_file( 123 name = "mock_rustdoc", 124 out = "mock_rustdoc.exe", 125 content = [], 126 is_executable = True, 127 ) 128 129 rust_toolchain( 130 name = "rust_extra_flags_toolchain", 131 binary_ext = "", 132 dylib_ext = ".so", 133 exec_triple = "x86_64-unknown-none", 134 target_triple = "x86_64-unknown-none", 135 rust_doc = ":mock_rustdoc", 136 rust_std = ":std_libs", 137 rustc = ":mock_rustc", 138 staticlib_ext = ".a", 139 stdlib_linkflags = [], 140 extra_rustc_flags = [TOOLCHAIN_FLAG], 141 extra_exec_rustc_flags = [EXEC_TOOLCHAIN_FLAG], 142 visibility = ["//visibility:public"], 143 ) 144 145 native.toolchain( 146 name = "extra_flags_toolchain", 147 toolchain = ":rust_extra_flags_toolchain", 148 toolchain_type = "@rules_rust//rust:toolchain", 149 ) 150 151 extra_toolchain_wrapper( 152 name = "lib_with_extra_toolchain", 153 dep = ":lib", 154 ) 155 156def _rust_stdlib_filegroup_provides_runfiles_test_impl(ctx): 157 env = analysistest.begin(ctx) 158 target = analysistest.target_under_test(env) 159 runfiles = target[DefaultInfo].default_runfiles 160 asserts.true(env, len(runfiles.files.to_list()) > 0) 161 162 return analysistest.end(env) 163 164rust_stdlib_filegroup_provides_runfiles_test = analysistest.make( 165 _rust_stdlib_filegroup_provides_runfiles_test_impl, 166) 167 168def toolchain_test_suite(name): 169 _define_targets() 170 171 toolchain_adds_rustc_flags_test( 172 name = "toolchain_adds_rustc_flags_test", 173 target_under_test = ":lib_with_extra_toolchain", 174 ) 175 176 rust_stdlib_filegroup_provides_runfiles_test( 177 name = "rust_stdlib_filegroup_provides_runfiles_test", 178 target_under_test = ":std_libs", 179 ) 180 181 native.test_suite( 182 name = name, 183 tests = [ 184 ":toolchain_adds_rustc_flags_test", 185 ":rust_stdlib_filegroup_provides_runfiles_test", 186 ], 187 ) 188