1*d4726bddSHONG Yifan"Module extensions for using rules_rust with bzlmod" 2*d4726bddSHONG Yifan 3*d4726bddSHONG Yifanload("@bazel_features//:features.bzl", "bazel_features") 4*d4726bddSHONG Yifanload("//rust:defs.bzl", "rust_common") 5*d4726bddSHONG Yifanload("//rust:repositories.bzl", "rust_register_toolchains", "rust_toolchain_tools_repository") 6*d4726bddSHONG Yifanload("//rust/platform:triple.bzl", "get_host_triple") 7*d4726bddSHONG Yifanload( 8*d4726bddSHONG Yifan "//rust/private:repository_utils.bzl", 9*d4726bddSHONG Yifan "DEFAULT_EXTRA_TARGET_TRIPLES", 10*d4726bddSHONG Yifan "DEFAULT_NIGHTLY_VERSION", 11*d4726bddSHONG Yifan "DEFAULT_STATIC_RUST_URL_TEMPLATES", 12*d4726bddSHONG Yifan) 13*d4726bddSHONG Yifan 14*d4726bddSHONG Yifandef _find_modules(module_ctx): 15*d4726bddSHONG Yifan root = None 16*d4726bddSHONG Yifan our_module = None 17*d4726bddSHONG Yifan for mod in module_ctx.modules: 18*d4726bddSHONG Yifan if mod.is_root: 19*d4726bddSHONG Yifan root = mod 20*d4726bddSHONG Yifan if mod.name == "rules_rust": 21*d4726bddSHONG Yifan our_module = mod 22*d4726bddSHONG Yifan if root == None: 23*d4726bddSHONG Yifan root = our_module 24*d4726bddSHONG Yifan if our_module == None: 25*d4726bddSHONG Yifan fail("Unable to find rules_rust module") 26*d4726bddSHONG Yifan 27*d4726bddSHONG Yifan return root, our_module 28*d4726bddSHONG Yifan 29*d4726bddSHONG Yifandef _rust_impl(module_ctx): 30*d4726bddSHONG Yifan # Toolchain configuration is only allowed in the root module, or in 31*d4726bddSHONG Yifan # rules_rust. 32*d4726bddSHONG Yifan # See https://github.com/bazelbuild/bazel/discussions/22024 for discussion. 33*d4726bddSHONG Yifan root, rules_rust = _find_modules(module_ctx) 34*d4726bddSHONG Yifan 35*d4726bddSHONG Yifan toolchains = root.tags.toolchain or rules_rust.tags.toolchain 36*d4726bddSHONG Yifan 37*d4726bddSHONG Yifan for toolchain in toolchains: 38*d4726bddSHONG Yifan rust_register_toolchains( 39*d4726bddSHONG Yifan dev_components = toolchain.dev_components, 40*d4726bddSHONG Yifan edition = toolchain.edition, 41*d4726bddSHONG Yifan allocator_library = toolchain.allocator_library, 42*d4726bddSHONG Yifan rustfmt_version = toolchain.rustfmt_version, 43*d4726bddSHONG Yifan rust_analyzer_version = toolchain.rust_analyzer_version, 44*d4726bddSHONG Yifan sha256s = toolchain.sha256s, 45*d4726bddSHONG Yifan extra_target_triples = toolchain.extra_target_triples, 46*d4726bddSHONG Yifan urls = toolchain.urls, 47*d4726bddSHONG Yifan versions = toolchain.versions, 48*d4726bddSHONG Yifan register_toolchains = False, 49*d4726bddSHONG Yifan ) 50*d4726bddSHONG Yifan 51*d4726bddSHONG Yifan_COMMON_TAG_KWARGS = dict( 52*d4726bddSHONG Yifan allocator_library = attr.string( 53*d4726bddSHONG Yifan doc = "Target that provides allocator functions when rust_library targets are embedded in a cc_binary.", 54*d4726bddSHONG Yifan default = "@rules_rust//ffi/cc/allocator_library", 55*d4726bddSHONG Yifan ), 56*d4726bddSHONG Yifan dev_components = attr.bool( 57*d4726bddSHONG Yifan doc = "Whether to download the rustc-dev components (defaults to False). Requires version to be \"nightly\".", 58*d4726bddSHONG Yifan default = False, 59*d4726bddSHONG Yifan ), 60*d4726bddSHONG Yifan edition = attr.string( 61*d4726bddSHONG Yifan doc = ( 62*d4726bddSHONG Yifan "The rust edition to be used by default (2015, 2018, or 2021). " + 63*d4726bddSHONG Yifan "If absent, every rule is required to specify its `edition` attribute." 64*d4726bddSHONG Yifan ), 65*d4726bddSHONG Yifan ), 66*d4726bddSHONG Yifan rustfmt_version = attr.string( 67*d4726bddSHONG Yifan doc = "The version of the tool among \"nightly\", \"beta\", or an exact version.", 68*d4726bddSHONG Yifan default = DEFAULT_NIGHTLY_VERSION, 69*d4726bddSHONG Yifan ), 70*d4726bddSHONG Yifan sha256s = attr.string_dict( 71*d4726bddSHONG Yifan doc = "A dict associating tool subdirectories to sha256 hashes. See [rust_repositories](#rust_repositories) for more details.", 72*d4726bddSHONG Yifan ), 73*d4726bddSHONG Yifan urls = attr.string_list( 74*d4726bddSHONG Yifan doc = "A list of mirror urls containing the tools from the Rust-lang static file server. These must contain the '{}' used to substitute the tool being fetched (using .format).", 75*d4726bddSHONG Yifan default = DEFAULT_STATIC_RUST_URL_TEMPLATES, 76*d4726bddSHONG Yifan ), 77*d4726bddSHONG Yifan) 78*d4726bddSHONG Yifan 79*d4726bddSHONG Yifan_RUST_TOOLCHAIN_TAG = tag_class( 80*d4726bddSHONG Yifan attrs = dict( 81*d4726bddSHONG Yifan extra_target_triples = attr.string_list( 82*d4726bddSHONG Yifan default = DEFAULT_EXTRA_TARGET_TRIPLES, 83*d4726bddSHONG Yifan ), 84*d4726bddSHONG Yifan rust_analyzer_version = attr.string( 85*d4726bddSHONG Yifan doc = "The version of Rustc to pair with rust-analyzer.", 86*d4726bddSHONG Yifan ), 87*d4726bddSHONG Yifan versions = attr.string_list( 88*d4726bddSHONG Yifan doc = ( 89*d4726bddSHONG Yifan "A list of toolchain versions to download. This paramter only accepts one versions " + 90*d4726bddSHONG Yifan "per channel. E.g. `[\"1.65.0\", \"nightly/2022-11-02\", \"beta/2020-12-30\"]`." 91*d4726bddSHONG Yifan ), 92*d4726bddSHONG Yifan default = [], 93*d4726bddSHONG Yifan ), 94*d4726bddSHONG Yifan **_COMMON_TAG_KWARGS 95*d4726bddSHONG Yifan ), 96*d4726bddSHONG Yifan) 97*d4726bddSHONG Yifan 98*d4726bddSHONG Yifan_RUST_HOST_TOOLS_TAG = tag_class( 99*d4726bddSHONG Yifan attrs = dict( 100*d4726bddSHONG Yifan version = attr.string( 101*d4726bddSHONG Yifan default = rust_common.default_version, 102*d4726bddSHONG Yifan doc = "The version of Rust to use for tools executed on the Bazel host.", 103*d4726bddSHONG Yifan ), 104*d4726bddSHONG Yifan **_COMMON_TAG_KWARGS 105*d4726bddSHONG Yifan ), 106*d4726bddSHONG Yifan) 107*d4726bddSHONG Yifan 108*d4726bddSHONG Yifanrust = module_extension( 109*d4726bddSHONG Yifan implementation = _rust_impl, 110*d4726bddSHONG Yifan tag_classes = { 111*d4726bddSHONG Yifan "toolchain": _RUST_TOOLCHAIN_TAG, 112*d4726bddSHONG Yifan }, 113*d4726bddSHONG Yifan) 114*d4726bddSHONG Yifan 115*d4726bddSHONG Yifan# This is a separate module extension so that only the host tools are 116*d4726bddSHONG Yifan# marked as reproducible and os and arch dependent 117*d4726bddSHONG Yifandef _rust_host_tools_impl(module_ctx): 118*d4726bddSHONG Yifan root, _ = _find_modules(module_ctx) 119*d4726bddSHONG Yifan 120*d4726bddSHONG Yifan if len(root.tags.host_tools) == 1: 121*d4726bddSHONG Yifan attrs = root.tags.host_tools[0] 122*d4726bddSHONG Yifan 123*d4726bddSHONG Yifan iso_date = None 124*d4726bddSHONG Yifan version = attrs.version 125*d4726bddSHONG Yifan 126*d4726bddSHONG Yifan # Any version containing a slash is expected to be a nightly/beta release with iso date. E.g. `nightly/2024-03-21` 127*d4726bddSHONG Yifan if "/" in version: 128*d4726bddSHONG Yifan version, _, iso_date = version.partition("/") 129*d4726bddSHONG Yifan 130*d4726bddSHONG Yifan host_tools = { 131*d4726bddSHONG Yifan "allocator_library": attrs.allocator_library, 132*d4726bddSHONG Yifan "dev_components": attrs.dev_components, 133*d4726bddSHONG Yifan "edition": attrs.edition, 134*d4726bddSHONG Yifan "iso_date": iso_date, 135*d4726bddSHONG Yifan "rustfmt_version": attrs.rustfmt_version, 136*d4726bddSHONG Yifan "sha256s": attrs.sha256s, 137*d4726bddSHONG Yifan "urls": attrs.urls, 138*d4726bddSHONG Yifan "version": version, 139*d4726bddSHONG Yifan } 140*d4726bddSHONG Yifan elif not root.tags.host_tools: 141*d4726bddSHONG Yifan host_tools = { 142*d4726bddSHONG Yifan "version": rust_common.default_version, 143*d4726bddSHONG Yifan } 144*d4726bddSHONG Yifan else: 145*d4726bddSHONG Yifan fail("Multiple host_tools were defined in your root MODULE.bazel") 146*d4726bddSHONG Yifan 147*d4726bddSHONG Yifan host_triple = get_host_triple(module_ctx) 148*d4726bddSHONG Yifan rust_toolchain_tools_repository( 149*d4726bddSHONG Yifan name = "rust_host_tools", 150*d4726bddSHONG Yifan exec_triple = host_triple.str, 151*d4726bddSHONG Yifan target_triple = host_triple.str, 152*d4726bddSHONG Yifan **host_tools 153*d4726bddSHONG Yifan ) 154*d4726bddSHONG Yifan 155*d4726bddSHONG Yifan metadata_kwargs = {} 156*d4726bddSHONG Yifan if bazel_features.external_deps.extension_metadata_has_reproducible: 157*d4726bddSHONG Yifan metadata_kwargs["reproducible"] = True 158*d4726bddSHONG Yifan return module_ctx.extension_metadata(**metadata_kwargs) 159*d4726bddSHONG Yifan 160*d4726bddSHONG Yifan_conditional_rust_host_tools_args = { 161*d4726bddSHONG Yifan "arch_dependent": True, 162*d4726bddSHONG Yifan "os_dependent": True, 163*d4726bddSHONG Yifan} if bazel_features.external_deps.module_extension_has_os_arch_dependent else {} 164*d4726bddSHONG Yifan 165*d4726bddSHONG Yifanrust_host_tools = module_extension( 166*d4726bddSHONG Yifan implementation = _rust_host_tools_impl, 167*d4726bddSHONG Yifan tag_classes = { 168*d4726bddSHONG Yifan "host_tools": _RUST_HOST_TOOLS_TAG, 169*d4726bddSHONG Yifan }, 170*d4726bddSHONG Yifan **_conditional_rust_host_tools_args 171*d4726bddSHONG Yifan) 172