xref: /aosp_15_r20/external/bazelbuild-rules_rust/rust/repositories.bzl (revision d4726bddaa87cc4778e7472feed243fa4b6c267f)
1*d4726bddSHONG Yifan"""Repository rules for defining Rust dependencies and toolchains"""
2*d4726bddSHONG Yifan
3*d4726bddSHONG Yifanload("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
4*d4726bddSHONG Yifanload("@bazel_tools//tools/build_defs/repo:utils.bzl", "maybe")
5*d4726bddSHONG Yifanload("//rust/platform:triple.bzl", "get_host_triple", "triple")
6*d4726bddSHONG Yifanload("//rust/platform:triple_mappings.bzl", "triple_to_constraint_set")
7*d4726bddSHONG Yifanload("//rust/private:common.bzl", "DEFAULT_NIGHTLY_ISO_DATE", "rust_common")
8*d4726bddSHONG Yifanload(
9*d4726bddSHONG Yifan    "//rust/private:repository_utils.bzl",
10*d4726bddSHONG Yifan    "BUILD_for_rust_analyzer_proc_macro_srv",
11*d4726bddSHONG Yifan    "BUILD_for_rust_analyzer_toolchain",
12*d4726bddSHONG Yifan    "BUILD_for_rust_toolchain",
13*d4726bddSHONG Yifan    "BUILD_for_rustfmt_toolchain",
14*d4726bddSHONG Yifan    "BUILD_for_toolchain",
15*d4726bddSHONG Yifan    "DEFAULT_EXTRA_TARGET_TRIPLES",
16*d4726bddSHONG Yifan    "DEFAULT_NIGHTLY_VERSION",
17*d4726bddSHONG Yifan    "DEFAULT_STATIC_RUST_URL_TEMPLATES",
18*d4726bddSHONG Yifan    "TINYJSON_KWARGS",
19*d4726bddSHONG Yifan    "check_version_valid",
20*d4726bddSHONG Yifan    "includes_rust_analyzer_proc_macro_srv",
21*d4726bddSHONG Yifan    "load_cargo",
22*d4726bddSHONG Yifan    "load_clippy",
23*d4726bddSHONG Yifan    "load_llvm_tools",
24*d4726bddSHONG Yifan    "load_rust_compiler",
25*d4726bddSHONG Yifan    "load_rust_src",
26*d4726bddSHONG Yifan    "load_rust_stdlib",
27*d4726bddSHONG Yifan    "load_rustc_dev_nightly",
28*d4726bddSHONG Yifan    "load_rustfmt",
29*d4726bddSHONG Yifan    "select_rust_version",
30*d4726bddSHONG Yifan    "toolchain_repository_hub",
31*d4726bddSHONG Yifan    _load_arbitrary_tool = "load_arbitrary_tool",
32*d4726bddSHONG Yifan)
33*d4726bddSHONG Yifan
34*d4726bddSHONG Yifan# Re-export `load_arbitrary_tool` as it's historically been used in external repositories.
35*d4726bddSHONG Yifanload_arbitrary_tool = _load_arbitrary_tool
36*d4726bddSHONG Yifan
37*d4726bddSHONG Yifan# Note: Code in `.github/workflows/crate_universe.yaml` looks for this line, if you remove it or change its format, you will also need to update that code.
38*d4726bddSHONG YifanDEFAULT_TOOLCHAIN_TRIPLES = {
39*d4726bddSHONG Yifan    "aarch64-apple-darwin": "rust_darwin_aarch64",
40*d4726bddSHONG Yifan    "aarch64-pc-windows-msvc": "rust_windows_aarch64",
41*d4726bddSHONG Yifan    "aarch64-unknown-linux-gnu": "rust_linux_aarch64",
42*d4726bddSHONG Yifan    "x86_64-apple-darwin": "rust_darwin_x86_64",
43*d4726bddSHONG Yifan    "x86_64-pc-windows-msvc": "rust_windows_x86_64",
44*d4726bddSHONG Yifan    "x86_64-unknown-freebsd": "rust_freebsd_x86_64",
45*d4726bddSHONG Yifan    "x86_64-unknown-linux-gnu": "rust_linux_x86_64",
46*d4726bddSHONG Yifan}
47*d4726bddSHONG Yifan
48*d4726bddSHONG Yifandef rules_rust_dependencies():
49*d4726bddSHONG Yifan    """Dependencies used in the implementation of `rules_rust`."""
50*d4726bddSHONG Yifan
51*d4726bddSHONG Yifan    maybe(
52*d4726bddSHONG Yifan        http_archive,
53*d4726bddSHONG Yifan        name = "platforms",
54*d4726bddSHONG Yifan        urls = [
55*d4726bddSHONG Yifan            "https://mirror.bazel.build/github.com/bazelbuild/platforms/releases/download/0.0.8/platforms-0.0.8.tar.gz",
56*d4726bddSHONG Yifan            "https://github.com/bazelbuild/platforms/releases/download/0.0.8/platforms-0.0.8.tar.gz",
57*d4726bddSHONG Yifan        ],
58*d4726bddSHONG Yifan        sha256 = "8150406605389ececb6da07cbcb509d5637a3ab9a24bc69b1101531367d89d74",
59*d4726bddSHONG Yifan    )
60*d4726bddSHONG Yifan    maybe(
61*d4726bddSHONG Yifan        http_archive,
62*d4726bddSHONG Yifan        name = "rules_cc",
63*d4726bddSHONG Yifan        urls = ["https://github.com/bazelbuild/rules_cc/releases/download/0.0.9/rules_cc-0.0.9.tar.gz"],
64*d4726bddSHONG Yifan        sha256 = "2037875b9a4456dce4a79d112a8ae885bbc4aad968e6587dca6e64f3a0900cdf",
65*d4726bddSHONG Yifan        strip_prefix = "rules_cc-0.0.9",
66*d4726bddSHONG Yifan    )
67*d4726bddSHONG Yifan    maybe(
68*d4726bddSHONG Yifan        http_archive,
69*d4726bddSHONG Yifan        name = "rules_license",
70*d4726bddSHONG Yifan        urls = [
71*d4726bddSHONG Yifan            "https://mirror.bazel.build/github.com/bazelbuild/rules_license/releases/download/0.0.8/rules_license-0.0.8.tar.gz",
72*d4726bddSHONG Yifan            "https://github.com/bazelbuild/rules_license/releases/download/0.0.8/rules_license-0.0.8.tar.gz",
73*d4726bddSHONG Yifan        ],
74*d4726bddSHONG Yifan        sha256 = "241b06f3097fd186ff468832150d6cc142247dc42a32aaefb56d0099895fd229",
75*d4726bddSHONG Yifan    )
76*d4726bddSHONG Yifan
77*d4726bddSHONG Yifan    maybe(
78*d4726bddSHONG Yifan        http_archive,
79*d4726bddSHONG Yifan        name = "bazel_skylib",
80*d4726bddSHONG Yifan        sha256 = "cd55a062e763b9349921f0f5db8c3933288dc8ba4f76dd9416aac68acee3cb94",
81*d4726bddSHONG Yifan        urls = [
82*d4726bddSHONG Yifan            "https://mirror.bazel.build/github.com/bazelbuild/bazel-skylib/releases/download/1.5.0/bazel-skylib-1.5.0.tar.gz",
83*d4726bddSHONG Yifan            "https://github.com/bazelbuild/bazel-skylib/releases/download/1.5.0/bazel-skylib-1.5.0.tar.gz",
84*d4726bddSHONG Yifan        ],
85*d4726bddSHONG Yifan    )
86*d4726bddSHONG Yifan
87*d4726bddSHONG Yifan    # Make the iOS simulator constraint available, which is referenced in abi_to_constraints()
88*d4726bddSHONG Yifan    # rules_rust does not require this dependency; it is just imported as a convenience for users.
89*d4726bddSHONG Yifan    maybe(
90*d4726bddSHONG Yifan        http_archive,
91*d4726bddSHONG Yifan        name = "build_bazel_apple_support",
92*d4726bddSHONG Yifan        sha256 = "1c4031e72b456a048d8177f59a5581808c07585fa9e255c6f5fefb8752af7e40",
93*d4726bddSHONG Yifan        url = "https://github.com/bazelbuild/apple_support/releases/download/1.13.0/apple_support.1.13.0.tar.gz",
94*d4726bddSHONG Yifan    )
95*d4726bddSHONG Yifan
96*d4726bddSHONG Yifan    # process_wrapper needs a low-dependency way to process json.
97*d4726bddSHONG Yifan    maybe(
98*d4726bddSHONG Yifan        http_archive,
99*d4726bddSHONG Yifan        **TINYJSON_KWARGS
100*d4726bddSHONG Yifan    )
101*d4726bddSHONG Yifan
102*d4726bddSHONG Yifan_RUST_TOOLCHAIN_VERSIONS = [
103*d4726bddSHONG Yifan    rust_common.default_version,
104*d4726bddSHONG Yifan    DEFAULT_NIGHTLY_VERSION,
105*d4726bddSHONG Yifan]
106*d4726bddSHONG Yifan
107*d4726bddSHONG Yifan# buildifier: disable=unnamed-macro
108*d4726bddSHONG Yifandef rust_register_toolchains(
109*d4726bddSHONG Yifan        dev_components = False,
110*d4726bddSHONG Yifan        edition = None,
111*d4726bddSHONG Yifan        allocator_library = None,
112*d4726bddSHONG Yifan        global_allocator_library = None,
113*d4726bddSHONG Yifan        iso_date = None,
114*d4726bddSHONG Yifan        register_toolchains = True,
115*d4726bddSHONG Yifan        rustfmt_version = None,
116*d4726bddSHONG Yifan        rust_analyzer_version = None,
117*d4726bddSHONG Yifan        sha256s = None,
118*d4726bddSHONG Yifan        extra_target_triples = DEFAULT_EXTRA_TARGET_TRIPLES,
119*d4726bddSHONG Yifan        extra_rustc_flags = None,
120*d4726bddSHONG Yifan        extra_exec_rustc_flags = None,
121*d4726bddSHONG Yifan        urls = DEFAULT_STATIC_RUST_URL_TEMPLATES,
122*d4726bddSHONG Yifan        version = None,
123*d4726bddSHONG Yifan        versions = []):
124*d4726bddSHONG Yifan    """Emits a default set of toolchains for Linux, MacOS, and Freebsd
125*d4726bddSHONG Yifan
126*d4726bddSHONG Yifan    Skip this macro and call the `rust_repository_set` macros directly if you need a compiler for \
127*d4726bddSHONG Yifan    other hosts or for additional target triples.
128*d4726bddSHONG Yifan
129*d4726bddSHONG Yifan    The `sha256s` attribute represents a dict associating tool subdirectories to sha256 hashes. As an example:
130*d4726bddSHONG Yifan    ```python
131*d4726bddSHONG Yifan    {
132*d4726bddSHONG Yifan        "rust-1.46.0-x86_64-unknown-linux-gnu": "e3b98bc3440fe92817881933f9564389eccb396f5f431f33d48b979fa2fbdcf5",
133*d4726bddSHONG Yifan        "rustfmt-1.4.12-x86_64-unknown-linux-gnu": "1894e76913303d66bf40885a601462844eec15fca9e76a6d13c390d7000d64b0",
134*d4726bddSHONG Yifan        "rust-std-1.46.0-x86_64-unknown-linux-gnu": "ac04aef80423f612c0079829b504902de27a6997214eb58ab0765d02f7ec1dbc",
135*d4726bddSHONG Yifan    }
136*d4726bddSHONG Yifan    ```
137*d4726bddSHONG Yifan    This would match for `exec_triple = "x86_64-unknown-linux-gnu"`.  If not specified, rules_rust pulls from a non-exhaustive \
138*d4726bddSHONG Yifan    list of known checksums..
139*d4726bddSHONG Yifan
140*d4726bddSHONG Yifan    See `load_arbitrary_tool` in `@rules_rust//rust:repositories.bzl` for more details.
141*d4726bddSHONG Yifan
142*d4726bddSHONG Yifan    Args:
143*d4726bddSHONG Yifan        dev_components (bool, optional): Whether to download the rustc-dev components (defaults to False). Requires version to be "nightly".
144*d4726bddSHONG Yifan        edition (str, optional): The rust edition to be used by default (2015, 2018, or 2021). If absent, every target is required to specify its `edition` attribute.
145*d4726bddSHONG Yifan        allocator_library (str, optional): Target that provides allocator functions when rust_library targets are embedded in a cc_binary.
146*d4726bddSHONG Yifan        global_allocator_library (str, optional): Target that provides allocator functions when global allocator is used with cc_common.link.
147*d4726bddSHONG Yifan        iso_date (str, optional):  **Deprecated**: Use `versions` instead.
148*d4726bddSHONG Yifan        register_toolchains (bool): If true, repositories will be generated to produce and register `rust_toolchain` targets.
149*d4726bddSHONG Yifan        rustfmt_version (str, optional): The version of rustfmt. If none is supplied and only a single version in `versions` is given, then this defaults to that version, otherwise will default to the default nightly version.
150*d4726bddSHONG Yifan        rust_analyzer_version (str, optional): The version of Rustc to pair with rust-analyzer.
151*d4726bddSHONG Yifan        sha256s (str, optional): A dict associating tool subdirectories to sha256 hashes.
152*d4726bddSHONG Yifan        extra_target_triples (list, optional): Additional rust-style targets that rust toolchains should support.
153*d4726bddSHONG Yifan        extra_rustc_flags (dict, list, optional): Dictionary of target triples to list of extra flags to pass to rustc in non-exec configuration.
154*d4726bddSHONG Yifan        extra_exec_rustc_flags (list, optional): Extra flags to pass to rustc in exec configuration.
155*d4726bddSHONG Yifan        urls (list, optional): 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).
156*d4726bddSHONG Yifan        version (str, optional): **Deprecated**: Use `versions` instead.
157*d4726bddSHONG Yifan        versions (list, optional): A list of toolchain versions to download. This paramter only accepts one versions
158*d4726bddSHONG Yifan            per channel. E.g. `["1.65.0", "nightly/2022-11-02", "beta/2020-12-30"]`.
159*d4726bddSHONG Yifan    """
160*d4726bddSHONG Yifan    if version:
161*d4726bddSHONG Yifan        # buildifier: disable=print
162*d4726bddSHONG Yifan        print("`rust_register.toolchains.version` is deprecated. Please use `versions` instead: https://bazelbuild.github.io/rules_rust/flatten.html#rust_register_toolchains-versions")
163*d4726bddSHONG Yifan
164*d4726bddSHONG Yifan    if iso_date:
165*d4726bddSHONG Yifan        # buildifier: disable=print
166*d4726bddSHONG Yifan        print("`rust_register.toolchains.iso_date` is deprecated. Please use `versions` instead: https://bazelbuild.github.io/rules_rust/flatten.html#rust_register_toolchains-versions")
167*d4726bddSHONG Yifan
168*d4726bddSHONG Yifan    if rustfmt_version in ("nightly", "beta"):
169*d4726bddSHONG Yifan        # buildifier: disable=print
170*d4726bddSHONG Yifan        print("`rust_register.toolchains.rustfmt_version` now requires iso date to be included in the string. E.g. `nightly/2022-12-15`. This version will be assumed until this value is updated")
171*d4726bddSHONG Yifan        rustfmt_version = "{}/{}".format(rustfmt_version, DEFAULT_NIGHTLY_ISO_DATE)
172*d4726bddSHONG Yifan
173*d4726bddSHONG Yifan    if not versions:
174*d4726bddSHONG Yifan        if version:
175*d4726bddSHONG Yifan            versions = [version]
176*d4726bddSHONG Yifan        else:
177*d4726bddSHONG Yifan            versions = _RUST_TOOLCHAIN_VERSIONS
178*d4726bddSHONG Yifan
179*d4726bddSHONG Yifan    if not rustfmt_version:
180*d4726bddSHONG Yifan        if len(versions) == 1:
181*d4726bddSHONG Yifan            rustfmt_version = versions[0]
182*d4726bddSHONG Yifan        else:
183*d4726bddSHONG Yifan            rustfmt_version = DEFAULT_NIGHTLY_VERSION
184*d4726bddSHONG Yifan
185*d4726bddSHONG Yifan    if dev_components:
186*d4726bddSHONG Yifan        has_nightly = False
187*d4726bddSHONG Yifan        for ver in versions:
188*d4726bddSHONG Yifan            if ver.startswith("nightly"):
189*d4726bddSHONG Yifan                has_nightly = True
190*d4726bddSHONG Yifan                break
191*d4726bddSHONG Yifan        if not has_nightly:
192*d4726bddSHONG Yifan            fail("rustc-dev components were requested but no \"nightly\" is being registered. Please update `versions` to include a nightly version.")
193*d4726bddSHONG Yifan
194*d4726bddSHONG Yifan    if not rust_analyzer_version:
195*d4726bddSHONG Yifan        rust_analyzer_version = select_rust_version(versions)
196*d4726bddSHONG Yifan
197*d4726bddSHONG Yifan    rust_analyzer_repo_name = "rust_analyzer_{}".format(rust_analyzer_version.replace("/", "-"))
198*d4726bddSHONG Yifan    rust_analyzer_iso_date = None
199*d4726bddSHONG Yifan    if rust_analyzer_version.startswith(("beta", "nightly")):
200*d4726bddSHONG Yifan        rust_analyzer_version, _, rust_analyzer_iso_date = rust_analyzer_version.partition("/")
201*d4726bddSHONG Yifan
202*d4726bddSHONG Yifan    toolchain_names = []
203*d4726bddSHONG Yifan    toolchain_labels = {}
204*d4726bddSHONG Yifan    toolchain_types = {}
205*d4726bddSHONG Yifan    exec_compatible_with_by_toolchain = {}
206*d4726bddSHONG Yifan    target_compatible_with_by_toolchain = {}
207*d4726bddSHONG Yifan
208*d4726bddSHONG Yifan    maybe(
209*d4726bddSHONG Yifan        rust_analyzer_toolchain_repository,
210*d4726bddSHONG Yifan        name = rust_analyzer_repo_name,
211*d4726bddSHONG Yifan        version = rust_analyzer_version,
212*d4726bddSHONG Yifan        urls = urls,
213*d4726bddSHONG Yifan        sha256s = sha256s,
214*d4726bddSHONG Yifan        iso_date = rust_analyzer_iso_date,
215*d4726bddSHONG Yifan    )
216*d4726bddSHONG Yifan
217*d4726bddSHONG Yifan    toolchain_names.append(rust_analyzer_repo_name)
218*d4726bddSHONG Yifan    toolchain_labels[rust_analyzer_repo_name] = "@{}_tools//:rust_analyzer_toolchain".format(
219*d4726bddSHONG Yifan        rust_analyzer_repo_name,
220*d4726bddSHONG Yifan    )
221*d4726bddSHONG Yifan    exec_compatible_with_by_toolchain[rust_analyzer_repo_name] = []
222*d4726bddSHONG Yifan    target_compatible_with_by_toolchain[rust_analyzer_repo_name] = []
223*d4726bddSHONG Yifan    toolchain_types[rust_analyzer_repo_name] = "@rules_rust//rust/rust_analyzer:toolchain_type"
224*d4726bddSHONG Yifan
225*d4726bddSHONG Yifan    if register_toolchains:
226*d4726bddSHONG Yifan        native.register_toolchains("@{}//:toolchain".format(
227*d4726bddSHONG Yifan            rust_analyzer_repo_name,
228*d4726bddSHONG Yifan        ))
229*d4726bddSHONG Yifan
230*d4726bddSHONG Yifan    rustfmt_iso_date = None
231*d4726bddSHONG Yifan    rustfmt_version_or_channel = rustfmt_version
232*d4726bddSHONG Yifan    if rustfmt_version.startswith(("beta", "nightly")):
233*d4726bddSHONG Yifan        rustfmt_version_or_channel, _, rustfmt_iso_date = rustfmt_version.partition("/")
234*d4726bddSHONG Yifan
235*d4726bddSHONG Yifan    for exec_triple, name in DEFAULT_TOOLCHAIN_TRIPLES.items():
236*d4726bddSHONG Yifan        maybe(
237*d4726bddSHONG Yifan            rust_repository_set,
238*d4726bddSHONG Yifan            name = name,
239*d4726bddSHONG Yifan            dev_components = dev_components,
240*d4726bddSHONG Yifan            edition = edition,
241*d4726bddSHONG Yifan            exec_triple = exec_triple,
242*d4726bddSHONG Yifan            extra_target_triples = extra_target_triples,
243*d4726bddSHONG Yifan            allocator_library = allocator_library,
244*d4726bddSHONG Yifan            global_allocator_library = global_allocator_library,
245*d4726bddSHONG Yifan            iso_date = iso_date,
246*d4726bddSHONG Yifan            register_toolchain = register_toolchains,
247*d4726bddSHONG Yifan            rustfmt_version = rustfmt_version,
248*d4726bddSHONG Yifan            extra_rustc_flags = extra_rustc_flags,
249*d4726bddSHONG Yifan            extra_exec_rustc_flags = extra_exec_rustc_flags,
250*d4726bddSHONG Yifan            sha256s = sha256s,
251*d4726bddSHONG Yifan            urls = urls,
252*d4726bddSHONG Yifan            version = version,
253*d4726bddSHONG Yifan            versions = versions,
254*d4726bddSHONG Yifan        )
255*d4726bddSHONG Yifan
256*d4726bddSHONG Yifan        rustfmt_repo_name = "rustfmt_{}__{}".format(rustfmt_version.replace("/", "-"), exec_triple)
257*d4726bddSHONG Yifan
258*d4726bddSHONG Yifan        maybe(
259*d4726bddSHONG Yifan            rustfmt_toolchain_repository,
260*d4726bddSHONG Yifan            name = rustfmt_repo_name,
261*d4726bddSHONG Yifan            version = rustfmt_version_or_channel,
262*d4726bddSHONG Yifan            urls = urls,
263*d4726bddSHONG Yifan            sha256s = sha256s,
264*d4726bddSHONG Yifan            iso_date = rustfmt_iso_date,
265*d4726bddSHONG Yifan            exec_triple = exec_triple,
266*d4726bddSHONG Yifan        )
267*d4726bddSHONG Yifan
268*d4726bddSHONG Yifan        if register_toolchains:
269*d4726bddSHONG Yifan            native.register_toolchains("@{}//:toolchain".format(
270*d4726bddSHONG Yifan                rustfmt_repo_name,
271*d4726bddSHONG Yifan            ))
272*d4726bddSHONG Yifan
273*d4726bddSHONG Yifan        for toolchain in _get_toolchain_repositories(name, exec_triple, extra_target_triples, versions, iso_date):
274*d4726bddSHONG Yifan            toolchain_names.append(toolchain.name)
275*d4726bddSHONG Yifan            toolchain_labels[toolchain.name] = "@{}//:{}".format(toolchain.name + "_tools", "rust_toolchain")
276*d4726bddSHONG Yifan            exec_compatible_with_by_toolchain[toolchain.name] = triple_to_constraint_set(exec_triple)
277*d4726bddSHONG Yifan            target_compatible_with_by_toolchain[toolchain.name] = triple_to_constraint_set(toolchain.target_triple)
278*d4726bddSHONG Yifan            toolchain_types[toolchain.name] = "@rules_rust//rust:toolchain"
279*d4726bddSHONG Yifan
280*d4726bddSHONG Yifan        toolchain_names.append(rustfmt_repo_name)
281*d4726bddSHONG Yifan        toolchain_labels[rustfmt_repo_name] = "@{}_tools//:rustfmt_toolchain".format(rustfmt_repo_name)
282*d4726bddSHONG Yifan        exec_compatible_with_by_toolchain[rustfmt_repo_name] = triple_to_constraint_set(exec_triple)
283*d4726bddSHONG Yifan        target_compatible_with_by_toolchain[rustfmt_repo_name] = []
284*d4726bddSHONG Yifan        toolchain_types[rustfmt_repo_name] = "@rules_rust//rust/rustfmt:toolchain_type"
285*d4726bddSHONG Yifan
286*d4726bddSHONG Yifan    toolchain_repository_hub(
287*d4726bddSHONG Yifan        name = "rust_toolchains",
288*d4726bddSHONG Yifan        toolchain_names = toolchain_names,
289*d4726bddSHONG Yifan        toolchain_labels = toolchain_labels,
290*d4726bddSHONG Yifan        toolchain_types = toolchain_types,
291*d4726bddSHONG Yifan        exec_compatible_with = exec_compatible_with_by_toolchain,
292*d4726bddSHONG Yifan        target_compatible_with = target_compatible_with_by_toolchain,
293*d4726bddSHONG Yifan    )
294*d4726bddSHONG Yifan
295*d4726bddSHONG Yifan# buildifier: disable=unnamed-macro
296*d4726bddSHONG Yifandef rust_repositories(**kwargs):
297*d4726bddSHONG Yifan    """**Deprecated**: Use [rules_rust_dependencies](#rules_rust_dependencies) \
298*d4726bddSHONG Yifan    and [rust_register_toolchains](#rust_register_toolchains) directly.
299*d4726bddSHONG Yifan
300*d4726bddSHONG Yifan    Args:
301*d4726bddSHONG Yifan        **kwargs (dict): Keyword arguments for the `rust_register_toolchains` macro.
302*d4726bddSHONG Yifan    """
303*d4726bddSHONG Yifan    rules_rust_dependencies()
304*d4726bddSHONG Yifan
305*d4726bddSHONG Yifan    rust_register_toolchains(**kwargs)
306*d4726bddSHONG Yifan
307*d4726bddSHONG Yifan_RUST_TOOLCHAIN_REPOSITORY_ATTRS = {
308*d4726bddSHONG Yifan    "allocator_library": attr.string(
309*d4726bddSHONG Yifan        doc = "Target that provides allocator functions when rust_library targets are embedded in a cc_binary.",
310*d4726bddSHONG Yifan        default = "@rules_rust//ffi/cc/allocator_library",
311*d4726bddSHONG Yifan    ),
312*d4726bddSHONG Yifan    "auth": attr.string_dict(
313*d4726bddSHONG Yifan        doc = (
314*d4726bddSHONG Yifan            "Auth object compatible with repository_ctx.download to use when downloading files. " +
315*d4726bddSHONG Yifan            "See [repository_ctx.download](https://docs.bazel.build/versions/main/skylark/lib/repository_ctx.html#download) for more details."
316*d4726bddSHONG Yifan        ),
317*d4726bddSHONG Yifan    ),
318*d4726bddSHONG Yifan    "auth_patterns": attr.string_list(
319*d4726bddSHONG Yifan        doc = "A list of patterns to match against urls for which the auth object should be used.",
320*d4726bddSHONG Yifan    ),
321*d4726bddSHONG Yifan    "dev_components": attr.bool(
322*d4726bddSHONG Yifan        doc = "Whether to download the rustc-dev components (defaults to False). Requires version to be \"nightly\".",
323*d4726bddSHONG Yifan        default = False,
324*d4726bddSHONG Yifan    ),
325*d4726bddSHONG Yifan    "edition": attr.string(
326*d4726bddSHONG Yifan        doc = (
327*d4726bddSHONG Yifan            "The rust edition to be used by default (2015, 2018, or 2021). " +
328*d4726bddSHONG Yifan            "If absent, every rule is required to specify its `edition` attribute."
329*d4726bddSHONG Yifan        ),
330*d4726bddSHONG Yifan    ),
331*d4726bddSHONG Yifan    "exec_triple": attr.string(
332*d4726bddSHONG Yifan        doc = "The Rust-style target that this compiler runs on",
333*d4726bddSHONG Yifan        mandatory = True,
334*d4726bddSHONG Yifan    ),
335*d4726bddSHONG Yifan    "extra_exec_rustc_flags": attr.string_list(
336*d4726bddSHONG Yifan        doc = "Extra flags to pass to rustc in exec configuration",
337*d4726bddSHONG Yifan    ),
338*d4726bddSHONG Yifan    "extra_rustc_flags": attr.string_list(
339*d4726bddSHONG Yifan        doc = "Extra flags to pass to rustc in non-exec configuration",
340*d4726bddSHONG Yifan    ),
341*d4726bddSHONG Yifan    "global_allocator_library": attr.string(
342*d4726bddSHONG Yifan        doc = "Target that provides allocator functions when a global allocator is used with cc_common.link.",
343*d4726bddSHONG Yifan        default = "@rules_rust//ffi/cc/global_allocator_library",
344*d4726bddSHONG Yifan    ),
345*d4726bddSHONG Yifan    "iso_date": attr.string(
346*d4726bddSHONG Yifan        doc = "The date of the tool (or None, if the version is a specific version).",
347*d4726bddSHONG Yifan    ),
348*d4726bddSHONG Yifan    "netrc": attr.string(
349*d4726bddSHONG Yifan        doc = ".netrc file to use for authentication; mirrors the eponymous attribute from http_archive",
350*d4726bddSHONG Yifan    ),
351*d4726bddSHONG Yifan    "opt_level": attr.string_dict(
352*d4726bddSHONG Yifan        doc = "Rustc optimization levels. For more details see the documentation for `rust_toolchain.opt_level`.",
353*d4726bddSHONG Yifan    ),
354*d4726bddSHONG Yifan    "rustfmt_version": attr.string(
355*d4726bddSHONG Yifan        doc = "The version of the tool among \"nightly\", \"beta\", or an exact version.",
356*d4726bddSHONG Yifan    ),
357*d4726bddSHONG Yifan    "sha256s": attr.string_dict(
358*d4726bddSHONG Yifan        doc = "A dict associating tool subdirectories to sha256 hashes. See [rust_register_toolchains](#rust_register_toolchains) for more details.",
359*d4726bddSHONG Yifan    ),
360*d4726bddSHONG Yifan    "target_triple": attr.string(
361*d4726bddSHONG Yifan        doc = "The Rust-style target that this compiler builds for.",
362*d4726bddSHONG Yifan        mandatory = True,
363*d4726bddSHONG Yifan    ),
364*d4726bddSHONG Yifan    "urls": attr.string_list(
365*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).",
366*d4726bddSHONG Yifan        default = DEFAULT_STATIC_RUST_URL_TEMPLATES,
367*d4726bddSHONG Yifan    ),
368*d4726bddSHONG Yifan    "version": attr.string(
369*d4726bddSHONG Yifan        doc = "The version of the tool among \"nightly\", \"beta\", or an exact version.",
370*d4726bddSHONG Yifan        mandatory = True,
371*d4726bddSHONG Yifan    ),
372*d4726bddSHONG Yifan}
373*d4726bddSHONG Yifan
374*d4726bddSHONG Yifandef _rust_toolchain_tools_repository_impl(ctx):
375*d4726bddSHONG Yifan    """The implementation of the rust toolchain tools repository rule."""
376*d4726bddSHONG Yifan    sha256s = dict(ctx.attr.sha256s)
377*d4726bddSHONG Yifan    iso_date = ctx.attr.iso_date
378*d4726bddSHONG Yifan    version = ctx.attr.version
379*d4726bddSHONG Yifan    version_array = version.split("/")
380*d4726bddSHONG Yifan    if len(version_array) > 1:
381*d4726bddSHONG Yifan        version = version_array[0]
382*d4726bddSHONG Yifan        iso_date = version_array[1]
383*d4726bddSHONG Yifan
384*d4726bddSHONG Yifan    check_version_valid(ctx.attr.version, iso_date)
385*d4726bddSHONG Yifan
386*d4726bddSHONG Yifan    exec_triple = triple(ctx.attr.exec_triple)
387*d4726bddSHONG Yifan
388*d4726bddSHONG Yifan    rustc_content, rustc_sha256 = load_rust_compiler(
389*d4726bddSHONG Yifan        ctx = ctx,
390*d4726bddSHONG Yifan        iso_date = iso_date,
391*d4726bddSHONG Yifan        target_triple = exec_triple,
392*d4726bddSHONG Yifan        version = version,
393*d4726bddSHONG Yifan    )
394*d4726bddSHONG Yifan    clippy_content, clippy_sha256 = load_clippy(
395*d4726bddSHONG Yifan        ctx = ctx,
396*d4726bddSHONG Yifan        iso_date = iso_date,
397*d4726bddSHONG Yifan        target_triple = exec_triple,
398*d4726bddSHONG Yifan        version = version,
399*d4726bddSHONG Yifan    )
400*d4726bddSHONG Yifan    cargo_content, cargo_sha256 = load_cargo(
401*d4726bddSHONG Yifan        ctx = ctx,
402*d4726bddSHONG Yifan        iso_date = iso_date,
403*d4726bddSHONG Yifan        target_triple = exec_triple,
404*d4726bddSHONG Yifan        version = version,
405*d4726bddSHONG Yifan    )
406*d4726bddSHONG Yifan
407*d4726bddSHONG Yifan    build_components = [
408*d4726bddSHONG Yifan        rustc_content,
409*d4726bddSHONG Yifan        clippy_content,
410*d4726bddSHONG Yifan        cargo_content,
411*d4726bddSHONG Yifan    ]
412*d4726bddSHONG Yifan    sha256s.update(rustc_sha256 | clippy_sha256 | cargo_sha256)
413*d4726bddSHONG Yifan
414*d4726bddSHONG Yifan    if ctx.attr.rustfmt_version:
415*d4726bddSHONG Yifan        rustfmt_version = ctx.attr.rustfmt_version
416*d4726bddSHONG Yifan        rustfmt_iso_date = None
417*d4726bddSHONG Yifan        if rustfmt_version in ("nightly", "beta"):
418*d4726bddSHONG Yifan            if iso_date:
419*d4726bddSHONG Yifan                rustfmt_iso_date = iso_date
420*d4726bddSHONG Yifan            else:
421*d4726bddSHONG Yifan                fail("`rustfmt_version` does not include an iso_date. The following reposiotry should either set `iso_date` or update `rustfmt_version` to include an iso_date suffix: {}".format(
422*d4726bddSHONG Yifan                    ctx.name,
423*d4726bddSHONG Yifan                ))
424*d4726bddSHONG Yifan        elif rustfmt_version.startswith(("nightly", "beta")):
425*d4726bddSHONG Yifan            rustfmt_version, _, rustfmt_iso_date = rustfmt_version.partition("/")
426*d4726bddSHONG Yifan        rustfmt_content, rustfmt_sha256 = load_rustfmt(
427*d4726bddSHONG Yifan            ctx = ctx,
428*d4726bddSHONG Yifan            target_triple = triple(ctx.attr.exec_triple),
429*d4726bddSHONG Yifan            version = rustfmt_version,
430*d4726bddSHONG Yifan            iso_date = rustfmt_iso_date,
431*d4726bddSHONG Yifan        )
432*d4726bddSHONG Yifan        build_components.append(rustfmt_content)
433*d4726bddSHONG Yifan        sha256s.update(rustfmt_sha256)
434*d4726bddSHONG Yifan
435*d4726bddSHONG Yifan    # Rust 1.45.0 and nightly builds after 2020-05-22 need the llvm-tools gzip to get the libLLVM dylib
436*d4726bddSHONG Yifan    include_llvm_tools = version >= "1.45.0" or (version == "nightly" and iso_date > "2020-05-22")
437*d4726bddSHONG Yifan    if include_llvm_tools:
438*d4726bddSHONG Yifan        llvm_tools_content, llvm_tools_sha256 = load_llvm_tools(
439*d4726bddSHONG Yifan            ctx = ctx,
440*d4726bddSHONG Yifan            target_triple = exec_triple,
441*d4726bddSHONG Yifan        )
442*d4726bddSHONG Yifan        build_components.append(llvm_tools_content)
443*d4726bddSHONG Yifan        sha256s.update(llvm_tools_sha256)
444*d4726bddSHONG Yifan
445*d4726bddSHONG Yifan    target_triple = triple(ctx.attr.target_triple)
446*d4726bddSHONG Yifan    rust_stdlib_content, rust_stdlib_sha256 = load_rust_stdlib(
447*d4726bddSHONG Yifan        ctx = ctx,
448*d4726bddSHONG Yifan        target_triple = target_triple,
449*d4726bddSHONG Yifan    )
450*d4726bddSHONG Yifan    build_components.append(rust_stdlib_content)
451*d4726bddSHONG Yifan    sha256s.update(rust_stdlib_sha256)
452*d4726bddSHONG Yifan
453*d4726bddSHONG Yifan    stdlib_linkflags = None
454*d4726bddSHONG Yifan    if "BAZEL_RUST_STDLIB_LINKFLAGS" in ctx.os.environ:
455*d4726bddSHONG Yifan        stdlib_linkflags = ctx.os.environ["BAZEL_RUST_STDLIB_LINKFLAGS"].split(":")
456*d4726bddSHONG Yifan
457*d4726bddSHONG Yifan    build_components.append(BUILD_for_rust_toolchain(
458*d4726bddSHONG Yifan        name = "rust_toolchain",
459*d4726bddSHONG Yifan        exec_triple = exec_triple,
460*d4726bddSHONG Yifan        allocator_library = ctx.attr.allocator_library,
461*d4726bddSHONG Yifan        global_allocator_library = ctx.attr.global_allocator_library,
462*d4726bddSHONG Yifan        target_triple = target_triple,
463*d4726bddSHONG Yifan        stdlib_linkflags = stdlib_linkflags,
464*d4726bddSHONG Yifan        default_edition = ctx.attr.edition,
465*d4726bddSHONG Yifan        include_rustfmt = not (not ctx.attr.rustfmt_version),
466*d4726bddSHONG Yifan        include_llvm_tools = include_llvm_tools,
467*d4726bddSHONG Yifan        extra_rustc_flags = ctx.attr.extra_rustc_flags,
468*d4726bddSHONG Yifan        extra_exec_rustc_flags = ctx.attr.extra_exec_rustc_flags,
469*d4726bddSHONG Yifan        opt_level = ctx.attr.opt_level if ctx.attr.opt_level else None,
470*d4726bddSHONG Yifan    ))
471*d4726bddSHONG Yifan
472*d4726bddSHONG Yifan    # Not all target triples are expected to have dev components
473*d4726bddSHONG Yifan    if ctx.attr.dev_components:
474*d4726bddSHONG Yifan        rustc_dev_sha256 = load_rustc_dev_nightly(ctx, target_triple)
475*d4726bddSHONG Yifan        sha256s.update(rustc_dev_sha256)
476*d4726bddSHONG Yifan
477*d4726bddSHONG Yifan    ctx.file("WORKSPACE.bazel", "")
478*d4726bddSHONG Yifan    ctx.file("BUILD.bazel", "\n".join(build_components))
479*d4726bddSHONG Yifan
480*d4726bddSHONG Yifan    repro = {"name": ctx.name}
481*d4726bddSHONG Yifan    for key in _RUST_TOOLCHAIN_REPOSITORY_ATTRS:
482*d4726bddSHONG Yifan        repro[key] = getattr(ctx.attr, key)
483*d4726bddSHONG Yifan    repro["sha256s"] = sha256s
484*d4726bddSHONG Yifan
485*d4726bddSHONG Yifan    return repro
486*d4726bddSHONG Yifan
487*d4726bddSHONG Yifanrust_toolchain_tools_repository = repository_rule(
488*d4726bddSHONG Yifan    doc = (
489*d4726bddSHONG Yifan        "Composes a single workspace containing the toolchain components for compiling on a given " +
490*d4726bddSHONG Yifan        "platform to a series of target platforms.\n" +
491*d4726bddSHONG Yifan        "\n" +
492*d4726bddSHONG Yifan        "A given instance of this rule should be accompanied by a toolchain_repository_proxy " +
493*d4726bddSHONG Yifan        "invocation to declare its toolchains to Bazel; the indirection allows separating toolchain " +
494*d4726bddSHONG Yifan        "selection from toolchain fetching."
495*d4726bddSHONG Yifan    ),
496*d4726bddSHONG Yifan    attrs = _RUST_TOOLCHAIN_REPOSITORY_ATTRS,
497*d4726bddSHONG Yifan    implementation = _rust_toolchain_tools_repository_impl,
498*d4726bddSHONG Yifan)
499*d4726bddSHONG Yifan
500*d4726bddSHONG Yifandef _toolchain_repository_proxy_impl(repository_ctx):
501*d4726bddSHONG Yifan    repository_ctx.file("WORKSPACE.bazel", """workspace(name = "{}")""".format(
502*d4726bddSHONG Yifan        repository_ctx.name,
503*d4726bddSHONG Yifan    ))
504*d4726bddSHONG Yifan
505*d4726bddSHONG Yifan    repository_ctx.file("BUILD.bazel", BUILD_for_toolchain(
506*d4726bddSHONG Yifan        name = "toolchain",
507*d4726bddSHONG Yifan        toolchain = repository_ctx.attr.toolchain,
508*d4726bddSHONG Yifan        target_settings = repository_ctx.attr.target_settings,
509*d4726bddSHONG Yifan        toolchain_type = repository_ctx.attr.toolchain_type,
510*d4726bddSHONG Yifan        target_compatible_with = repository_ctx.attr.target_compatible_with,
511*d4726bddSHONG Yifan        exec_compatible_with = repository_ctx.attr.exec_compatible_with,
512*d4726bddSHONG Yifan    ))
513*d4726bddSHONG Yifan
514*d4726bddSHONG Yifantoolchain_repository_proxy = repository_rule(
515*d4726bddSHONG Yifan    doc = (
516*d4726bddSHONG Yifan        "Generates a toolchain-bearing repository that declares the toolchains from some other " +
517*d4726bddSHONG Yifan        "rust_toolchain_repository."
518*d4726bddSHONG Yifan    ),
519*d4726bddSHONG Yifan    attrs = {
520*d4726bddSHONG Yifan        "exec_compatible_with": attr.string_list(
521*d4726bddSHONG Yifan            doc = "A list of constraints for the execution platform for this toolchain.",
522*d4726bddSHONG Yifan        ),
523*d4726bddSHONG Yifan        "target_compatible_with": attr.string_list(
524*d4726bddSHONG Yifan            doc = "A list of constraints for the target platform for this toolchain.",
525*d4726bddSHONG Yifan        ),
526*d4726bddSHONG Yifan        "target_settings": attr.string_list(
527*d4726bddSHONG Yifan            doc = "A list of config_settings that must be satisfied by the target configuration in order for this toolchain to be selected during toolchain resolution.",
528*d4726bddSHONG Yifan        ),
529*d4726bddSHONG Yifan        "toolchain": attr.string(
530*d4726bddSHONG Yifan            doc = "The name of the toolchain implementation target.",
531*d4726bddSHONG Yifan            mandatory = True,
532*d4726bddSHONG Yifan        ),
533*d4726bddSHONG Yifan        "toolchain_type": attr.string(
534*d4726bddSHONG Yifan            doc = "The toolchain type of the toolchain to declare",
535*d4726bddSHONG Yifan            mandatory = True,
536*d4726bddSHONG Yifan        ),
537*d4726bddSHONG Yifan    },
538*d4726bddSHONG Yifan    implementation = _toolchain_repository_proxy_impl,
539*d4726bddSHONG Yifan)
540*d4726bddSHONG Yifan
541*d4726bddSHONG Yifan# For legacy support
542*d4726bddSHONG Yifanrust_toolchain_repository_proxy = toolchain_repository_proxy
543*d4726bddSHONG Yifan
544*d4726bddSHONG Yifan# N.B. A "proxy repository" is needed to allow for registering the toolchain (with constraints)
545*d4726bddSHONG Yifan# without actually downloading the toolchain.
546*d4726bddSHONG Yifandef rust_toolchain_repository(
547*d4726bddSHONG Yifan        name,
548*d4726bddSHONG Yifan        version,
549*d4726bddSHONG Yifan        exec_triple,
550*d4726bddSHONG Yifan        target_triple,
551*d4726bddSHONG Yifan        exec_compatible_with = None,
552*d4726bddSHONG Yifan        target_compatible_with = None,
553*d4726bddSHONG Yifan        target_settings = [],
554*d4726bddSHONG Yifan        channel = None,
555*d4726bddSHONG Yifan        allocator_library = None,
556*d4726bddSHONG Yifan        global_allocator_library = None,
557*d4726bddSHONG Yifan        iso_date = None,
558*d4726bddSHONG Yifan        rustfmt_version = None,
559*d4726bddSHONG Yifan        edition = None,
560*d4726bddSHONG Yifan        dev_components = False,
561*d4726bddSHONG Yifan        extra_rustc_flags = None,
562*d4726bddSHONG Yifan        extra_exec_rustc_flags = None,
563*d4726bddSHONG Yifan        opt_level = None,
564*d4726bddSHONG Yifan        sha256s = None,
565*d4726bddSHONG Yifan        urls = DEFAULT_STATIC_RUST_URL_TEMPLATES,
566*d4726bddSHONG Yifan        auth = None,
567*d4726bddSHONG Yifan        netrc = None,
568*d4726bddSHONG Yifan        auth_patterns = None):
569*d4726bddSHONG Yifan    """Assembles a remote repository for the given toolchain params, produces a proxy repository \
570*d4726bddSHONG Yifan    to contain the toolchain declaration, and registers the toolchains.
571*d4726bddSHONG Yifan
572*d4726bddSHONG Yifan    Args:
573*d4726bddSHONG Yifan        name (str): The name of the generated repository
574*d4726bddSHONG Yifan        version (str): The version of the tool among "nightly", "beta", or an exact version.
575*d4726bddSHONG Yifan        exec_triple (str): The Rust-style target that this compiler runs on.
576*d4726bddSHONG Yifan        target_triple (str): The Rust-style target to build for.
577*d4726bddSHONG Yifan        channel (str, optional): The channel of the Rust toolchain.
578*d4726bddSHONG Yifan        exec_compatible_with (list, optional): A list of constraints for the execution platform for this toolchain.
579*d4726bddSHONG Yifan        target_compatible_with (list, optional): A list of constraints for the target platform for this toolchain.
580*d4726bddSHONG Yifan        target_settings (list, optional): A list of config_settings that must be satisfied by the target configuration in order for this toolchain to be selected during toolchain resolution.
581*d4726bddSHONG Yifan        allocator_library (str, optional): Target that provides allocator functions when rust_library targets are embedded in a cc_binary.
582*d4726bddSHONG Yifan        global_allocator_library (str, optional): Target that provides allocator functions when a global allocator is used with cc_common.link.
583*d4726bddSHONG Yifan        iso_date (str, optional): The date of the tool.
584*d4726bddSHONG Yifan        rustfmt_version (str, optional):  The version of rustfmt to be associated with the
585*d4726bddSHONG Yifan            toolchain.
586*d4726bddSHONG Yifan        edition (str, optional): The rust edition to be used by default (2015, 2018, or 2021). If absent, every rule is required to specify its `edition` attribute.
587*d4726bddSHONG Yifan        dev_components (bool, optional): Whether to download the rustc-dev components.
588*d4726bddSHONG Yifan            Requires version to be "nightly". Defaults to False.
589*d4726bddSHONG Yifan        extra_rustc_flags (list, optional): Extra flags to pass to rustc in non-exec configuration.
590*d4726bddSHONG Yifan        extra_exec_rustc_flags (list, optional): Extra flags to pass to rustc in exec configuration.
591*d4726bddSHONG Yifan        opt_level (dict, optional): Optimization level config for this toolchain.
592*d4726bddSHONG Yifan        sha256s (str, optional): A dict associating tool subdirectories to sha256 hashes. See
593*d4726bddSHONG Yifan            [rust_register_toolchains](#rust_register_toolchains) for more details.
594*d4726bddSHONG Yifan        urls (list, optional): 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). Defaults to ['https://static.rust-lang.org/dist/{}.tar.xz']
595*d4726bddSHONG Yifan        auth (dict): Auth object compatible with repository_ctx.download to use when downloading files.
596*d4726bddSHONG Yifan            See [repository_ctx.download](https://docs.bazel.build/versions/main/skylark/lib/repository_ctx.html#download) for more details.
597*d4726bddSHONG Yifan        netrc (str, optional): .netrc file to use for authentication; mirrors the eponymous attribute from http_archive
598*d4726bddSHONG Yifan        auth_patterns (list, optional): A list of patterns to match against urls for which the auth object should be used.
599*d4726bddSHONG Yifan
600*d4726bddSHONG Yifan    Returns:
601*d4726bddSHONG Yifan        str: The name of the registerable toolchain created by this rule.
602*d4726bddSHONG Yifan    """
603*d4726bddSHONG Yifan
604*d4726bddSHONG Yifan    if rustfmt_version in ("nightly", "beta"):
605*d4726bddSHONG Yifan        # buildifier: disable=print
606*d4726bddSHONG Yifan        print("`rust_toolchain_repository.rustfmt_version` now requires iso date to be included in the string. E.g. `nightly/2022-12-15`. This version will be assumed until this value is updated")
607*d4726bddSHONG Yifan        rustfmt_version = "{}/{}".format(rustfmt_version, DEFAULT_NIGHTLY_ISO_DATE)
608*d4726bddSHONG Yifan
609*d4726bddSHONG Yifan    if exec_compatible_with == None:
610*d4726bddSHONG Yifan        exec_compatible_with = triple_to_constraint_set(exec_triple)
611*d4726bddSHONG Yifan
612*d4726bddSHONG Yifan    if target_compatible_with == None:
613*d4726bddSHONG Yifan        target_compatible_with = triple_to_constraint_set(target_triple)
614*d4726bddSHONG Yifan
615*d4726bddSHONG Yifan    tools_repo_name = "{}_tools".format(name)
616*d4726bddSHONG Yifan
617*d4726bddSHONG Yifan    rust_toolchain_tools_repository(
618*d4726bddSHONG Yifan        name = tools_repo_name,
619*d4726bddSHONG Yifan        exec_triple = exec_triple,
620*d4726bddSHONG Yifan        allocator_library = allocator_library,
621*d4726bddSHONG Yifan        global_allocator_library = global_allocator_library,
622*d4726bddSHONG Yifan        target_triple = target_triple,
623*d4726bddSHONG Yifan        iso_date = iso_date,
624*d4726bddSHONG Yifan        version = version,
625*d4726bddSHONG Yifan        rustfmt_version = rustfmt_version,
626*d4726bddSHONG Yifan        edition = edition,
627*d4726bddSHONG Yifan        dev_components = dev_components,
628*d4726bddSHONG Yifan        extra_rustc_flags = extra_rustc_flags,
629*d4726bddSHONG Yifan        extra_exec_rustc_flags = extra_exec_rustc_flags,
630*d4726bddSHONG Yifan        opt_level = opt_level,
631*d4726bddSHONG Yifan        sha256s = sha256s,
632*d4726bddSHONG Yifan        urls = urls,
633*d4726bddSHONG Yifan        auth = auth,
634*d4726bddSHONG Yifan        netrc = netrc,
635*d4726bddSHONG Yifan        auth_patterns = auth_patterns,
636*d4726bddSHONG Yifan    )
637*d4726bddSHONG Yifan
638*d4726bddSHONG Yifan    channel_target_settings = ["@rules_rust//rust/toolchain/channel:{}".format(channel)] if channel else []
639*d4726bddSHONG Yifan
640*d4726bddSHONG Yifan    toolchain_repository_proxy(
641*d4726bddSHONG Yifan        name = name,
642*d4726bddSHONG Yifan        toolchain = "@{}//:rust_toolchain".format(tools_repo_name),
643*d4726bddSHONG Yifan        target_settings = channel_target_settings + target_settings,
644*d4726bddSHONG Yifan        toolchain_type = "@rules_rust//rust:toolchain",
645*d4726bddSHONG Yifan        exec_compatible_with = exec_compatible_with,
646*d4726bddSHONG Yifan        target_compatible_with = target_compatible_with,
647*d4726bddSHONG Yifan    )
648*d4726bddSHONG Yifan
649*d4726bddSHONG Yifan    return "@{name}//:toolchain".format(
650*d4726bddSHONG Yifan        name = name,
651*d4726bddSHONG Yifan    )
652*d4726bddSHONG Yifan
653*d4726bddSHONG Yifan_RUST_ANALYZER_TOOLCHAIN_TOOLS_REPOSITORY_ATTRS = {
654*d4726bddSHONG Yifan    "auth": attr.string_dict(
655*d4726bddSHONG Yifan        doc = (
656*d4726bddSHONG Yifan            "Auth object compatible with repository_ctx.download to use when downloading files. " +
657*d4726bddSHONG Yifan            "See [repository_ctx.download](https://docs.bazel.build/versions/main/skylark/lib/repository_ctx.html#download) for more details."
658*d4726bddSHONG Yifan        ),
659*d4726bddSHONG Yifan    ),
660*d4726bddSHONG Yifan    "auth_patterns": attr.string_list(
661*d4726bddSHONG Yifan        doc = "A list of patterns to match against urls for which the auth object should be used.",
662*d4726bddSHONG Yifan    ),
663*d4726bddSHONG Yifan    "iso_date": attr.string(
664*d4726bddSHONG Yifan        doc = "The date of the tool (or None, if the version is a specific version).",
665*d4726bddSHONG Yifan    ),
666*d4726bddSHONG Yifan    "netrc": attr.string(
667*d4726bddSHONG Yifan        doc = ".netrc file to use for authentication; mirrors the eponymous attribute from http_archive",
668*d4726bddSHONG Yifan    ),
669*d4726bddSHONG Yifan    "sha256s": attr.string_dict(
670*d4726bddSHONG Yifan        doc = "A dict associating tool subdirectories to sha256 hashes. See [rust_register_toolchains](#rust_register_toolchains) for more details.",
671*d4726bddSHONG Yifan    ),
672*d4726bddSHONG Yifan    "urls": attr.string_list(
673*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).",
674*d4726bddSHONG Yifan        default = DEFAULT_STATIC_RUST_URL_TEMPLATES,
675*d4726bddSHONG Yifan    ),
676*d4726bddSHONG Yifan    "version": attr.string(
677*d4726bddSHONG Yifan        doc = "The version of the tool among \"nightly\", \"beta\", or an exact version.",
678*d4726bddSHONG Yifan        mandatory = True,
679*d4726bddSHONG Yifan    ),
680*d4726bddSHONG Yifan}
681*d4726bddSHONG Yifan
682*d4726bddSHONG Yifandef _rust_analyzer_toolchain_tools_repository_impl(repository_ctx):
683*d4726bddSHONG Yifan    sha256s = dict(repository_ctx.attr.sha256s)
684*d4726bddSHONG Yifan
685*d4726bddSHONG Yifan    sha256s.update(load_rust_src(
686*d4726bddSHONG Yifan        ctx = repository_ctx,
687*d4726bddSHONG Yifan        iso_date = repository_ctx.attr.iso_date,
688*d4726bddSHONG Yifan        version = repository_ctx.attr.version,
689*d4726bddSHONG Yifan    ))
690*d4726bddSHONG Yifan
691*d4726bddSHONG Yifan    repository_ctx.file("WORKSPACE.bazel", """workspace(name = "{}")""".format(
692*d4726bddSHONG Yifan        repository_ctx.name,
693*d4726bddSHONG Yifan    ))
694*d4726bddSHONG Yifan
695*d4726bddSHONG Yifan    host_triple = get_host_triple(repository_ctx)
696*d4726bddSHONG Yifan    rustc_content, rustc_sha256 = load_rust_compiler(
697*d4726bddSHONG Yifan        ctx = repository_ctx,
698*d4726bddSHONG Yifan        iso_date = repository_ctx.attr.iso_date,
699*d4726bddSHONG Yifan        target_triple = host_triple,
700*d4726bddSHONG Yifan        version = repository_ctx.attr.version,
701*d4726bddSHONG Yifan    )
702*d4726bddSHONG Yifan    build_contents = [rustc_content]
703*d4726bddSHONG Yifan    sha256s.update(rustc_sha256)
704*d4726bddSHONG Yifan    rustc = "//:rustc"
705*d4726bddSHONG Yifan
706*d4726bddSHONG Yifan    proc_macro_srv = None
707*d4726bddSHONG Yifan    if includes_rust_analyzer_proc_macro_srv(repository_ctx.attr.version, repository_ctx.attr.iso_date):
708*d4726bddSHONG Yifan        build_contents.append(BUILD_for_rust_analyzer_proc_macro_srv(host_triple))
709*d4726bddSHONG Yifan        proc_macro_srv = "//:rust_analyzer_proc_macro_srv"
710*d4726bddSHONG Yifan
711*d4726bddSHONG Yifan    build_contents.append(BUILD_for_rust_analyzer_toolchain(
712*d4726bddSHONG Yifan        name = "rust_analyzer_toolchain",
713*d4726bddSHONG Yifan        rustc = rustc,
714*d4726bddSHONG Yifan        proc_macro_srv = proc_macro_srv,
715*d4726bddSHONG Yifan    ))
716*d4726bddSHONG Yifan
717*d4726bddSHONG Yifan    repository_ctx.file("BUILD.bazel", "\n".join(build_contents))
718*d4726bddSHONG Yifan    repository_ctx.file("WORKSPACE.bazel", """workspace(name = "{}")""".format(
719*d4726bddSHONG Yifan        repository_ctx.name,
720*d4726bddSHONG Yifan    ))
721*d4726bddSHONG Yifan
722*d4726bddSHONG Yifan    repro = {"name": repository_ctx.name}
723*d4726bddSHONG Yifan    for key in _RUST_ANALYZER_TOOLCHAIN_TOOLS_REPOSITORY_ATTRS:
724*d4726bddSHONG Yifan        repro[key] = getattr(repository_ctx.attr, key)
725*d4726bddSHONG Yifan    repro["sha256s"] = sha256s
726*d4726bddSHONG Yifan
727*d4726bddSHONG Yifan    return repro
728*d4726bddSHONG Yifan
729*d4726bddSHONG Yifanrust_analyzer_toolchain_tools_repository = repository_rule(
730*d4726bddSHONG Yifan    doc = "A repository rule for defining a rust_analyzer_toolchain with a `rust-src` artifact.",
731*d4726bddSHONG Yifan    implementation = _rust_analyzer_toolchain_tools_repository_impl,
732*d4726bddSHONG Yifan    attrs = _RUST_ANALYZER_TOOLCHAIN_TOOLS_REPOSITORY_ATTRS,
733*d4726bddSHONG Yifan)
734*d4726bddSHONG Yifan
735*d4726bddSHONG Yifandef rust_analyzer_toolchain_repository(
736*d4726bddSHONG Yifan        name,
737*d4726bddSHONG Yifan        version,
738*d4726bddSHONG Yifan        exec_compatible_with = [],
739*d4726bddSHONG Yifan        target_compatible_with = [],
740*d4726bddSHONG Yifan        iso_date = None,
741*d4726bddSHONG Yifan        sha256s = None,
742*d4726bddSHONG Yifan        urls = None,
743*d4726bddSHONG Yifan        auth = None,
744*d4726bddSHONG Yifan        netrc = None,
745*d4726bddSHONG Yifan        auth_patterns = None):
746*d4726bddSHONG Yifan    """Assemble a remote rust_analyzer_toolchain target based on the given params.
747*d4726bddSHONG Yifan
748*d4726bddSHONG Yifan    Args:
749*d4726bddSHONG Yifan        name (str): The name of the toolchain proxy repository contianing the registerable toolchain.
750*d4726bddSHONG Yifan        version (str): The version of the tool among "nightly", "beta', or an exact version.
751*d4726bddSHONG Yifan        exec_compatible_with (list, optional): A list of constraints for the execution platform for this toolchain.
752*d4726bddSHONG Yifan        target_compatible_with (list, optional): A list of constraints for the target platform for this toolchain.
753*d4726bddSHONG Yifan        iso_date (str, optional): The date of the tool.
754*d4726bddSHONG Yifan        sha256s (str, optional): A dict associating tool subdirectories to sha256 hashes. See
755*d4726bddSHONG Yifan            [rust_register_toolchains](#rust_register_toolchains) for more details.
756*d4726bddSHONG Yifan        urls (list, optional): 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). Defaults to ['https://static.rust-lang.org/dist/{}.tar.xz']
757*d4726bddSHONG Yifan        auth (dict): Auth object compatible with repository_ctx.download to use when downloading files.
758*d4726bddSHONG Yifan            See [repository_ctx.download](https://docs.bazel.build/versions/main/skylark/lib/repository_ctx.html#download) for more details.
759*d4726bddSHONG Yifan        netrc (str, optional): .netrc file to use for authentication; mirrors the eponymous attribute from http_archive
760*d4726bddSHONG Yifan        auth_patterns (dict, optional): Override mapping of hostnames to authorization patterns; mirrors the eponymous attribute from http_archive
761*d4726bddSHONG Yifan
762*d4726bddSHONG Yifan    Returns:
763*d4726bddSHONG Yifan        str: The name of a registerable rust_analyzer_toolchain.
764*d4726bddSHONG Yifan    """
765*d4726bddSHONG Yifan    rust_analyzer_toolchain_tools_repository(
766*d4726bddSHONG Yifan        name = name + "_tools",
767*d4726bddSHONG Yifan        version = version,
768*d4726bddSHONG Yifan        iso_date = iso_date,
769*d4726bddSHONG Yifan        sha256s = sha256s,
770*d4726bddSHONG Yifan        urls = urls,
771*d4726bddSHONG Yifan        auth = auth,
772*d4726bddSHONG Yifan        netrc = netrc,
773*d4726bddSHONG Yifan        auth_patterns = auth_patterns,
774*d4726bddSHONG Yifan    )
775*d4726bddSHONG Yifan
776*d4726bddSHONG Yifan    toolchain_repository_proxy(
777*d4726bddSHONG Yifan        name = name,
778*d4726bddSHONG Yifan        toolchain = "@{}//:{}".format(name + "_tools", "rust_analyzer_toolchain"),
779*d4726bddSHONG Yifan        toolchain_type = "@rules_rust//rust/rust_analyzer:toolchain_type",
780*d4726bddSHONG Yifan        exec_compatible_with = exec_compatible_with,
781*d4726bddSHONG Yifan        target_compatible_with = target_compatible_with,
782*d4726bddSHONG Yifan    )
783*d4726bddSHONG Yifan
784*d4726bddSHONG Yifan    return "@{}//:toolchain".format(
785*d4726bddSHONG Yifan        name,
786*d4726bddSHONG Yifan    )
787*d4726bddSHONG Yifan
788*d4726bddSHONG Yifan_RUSTFMT_TOOLCHAIN_TOOLS_ATTRS = {
789*d4726bddSHONG Yifan    "auth": attr.string_dict(
790*d4726bddSHONG Yifan        doc = (
791*d4726bddSHONG Yifan            "Auth object compatible with repository_ctx.download to use when downloading files. " +
792*d4726bddSHONG Yifan            "See [repository_ctx.download](https://docs.bazel.build/versions/main/skylark/lib/repository_ctx.html#download) for more details."
793*d4726bddSHONG Yifan        ),
794*d4726bddSHONG Yifan    ),
795*d4726bddSHONG Yifan    "auth_patterns": attr.string_dict(
796*d4726bddSHONG Yifan        doc = "Override mapping of hostnames to authorization patterns; mirrors the eponymous attribute from http_archive",
797*d4726bddSHONG Yifan    ),
798*d4726bddSHONG Yifan    "exec_triple": attr.string(
799*d4726bddSHONG Yifan        doc = "The Rust-style triple Rustfmt is expected to run on.",
800*d4726bddSHONG Yifan        mandatory = True,
801*d4726bddSHONG Yifan    ),
802*d4726bddSHONG Yifan    "iso_date": attr.string(
803*d4726bddSHONG Yifan        doc = "The date of the tool (or None, if the version is a specific version).",
804*d4726bddSHONG Yifan    ),
805*d4726bddSHONG Yifan    "netrc": attr.string(
806*d4726bddSHONG Yifan        doc = ".netrc file to use for authentication; mirrors the eponymous attribute from http_archive",
807*d4726bddSHONG Yifan    ),
808*d4726bddSHONG Yifan    "sha256s": attr.string_dict(
809*d4726bddSHONG Yifan        doc = "A dict associating tool subdirectories to sha256 hashes. See [rust_register_toolchains](#rust_register_toolchains) for more details.",
810*d4726bddSHONG Yifan    ),
811*d4726bddSHONG Yifan    "urls": attr.string_list(
812*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).",
813*d4726bddSHONG Yifan        default = DEFAULT_STATIC_RUST_URL_TEMPLATES,
814*d4726bddSHONG Yifan    ),
815*d4726bddSHONG Yifan    "version": attr.string(
816*d4726bddSHONG Yifan        doc = "The version of the tool among \"nightly\", \"beta\", or an exact version.",
817*d4726bddSHONG Yifan        mandatory = True,
818*d4726bddSHONG Yifan    ),
819*d4726bddSHONG Yifan}
820*d4726bddSHONG Yifan
821*d4726bddSHONG Yifandef _rustfmt_toolchain_tools_repository_impl(repository_ctx):
822*d4726bddSHONG Yifan    sha256s = dict(repository_ctx.attr.sha256s)
823*d4726bddSHONG Yifan    repository_ctx.file("WORKSPACE.bazel", """workspace(name = "{}")""".format(
824*d4726bddSHONG Yifan        repository_ctx.name,
825*d4726bddSHONG Yifan    ))
826*d4726bddSHONG Yifan
827*d4726bddSHONG Yifan    rustfmt = "//:rustfmt_bin"
828*d4726bddSHONG Yifan    rustc = "//:rustc"
829*d4726bddSHONG Yifan    rustc_lib = "//:rustc_lib"
830*d4726bddSHONG Yifan
831*d4726bddSHONG Yifan    exec_triple = triple(repository_ctx.attr.exec_triple)
832*d4726bddSHONG Yifan
833*d4726bddSHONG Yifan    rustc_content, rustc_sha256 = load_rust_compiler(
834*d4726bddSHONG Yifan        ctx = repository_ctx,
835*d4726bddSHONG Yifan        iso_date = repository_ctx.attr.iso_date,
836*d4726bddSHONG Yifan        target_triple = exec_triple,
837*d4726bddSHONG Yifan        version = repository_ctx.attr.version,
838*d4726bddSHONG Yifan    )
839*d4726bddSHONG Yifan    rustfmt_content, rustfmt_sha256 = load_rustfmt(
840*d4726bddSHONG Yifan        ctx = repository_ctx,
841*d4726bddSHONG Yifan        iso_date = repository_ctx.attr.iso_date,
842*d4726bddSHONG Yifan        target_triple = exec_triple,
843*d4726bddSHONG Yifan        version = repository_ctx.attr.version,
844*d4726bddSHONG Yifan    )
845*d4726bddSHONG Yifan
846*d4726bddSHONG Yifan    build_contents = [
847*d4726bddSHONG Yifan        rustc_content,
848*d4726bddSHONG Yifan        rustfmt_content,
849*d4726bddSHONG Yifan        BUILD_for_rustfmt_toolchain(
850*d4726bddSHONG Yifan            name = "rustfmt_toolchain",
851*d4726bddSHONG Yifan            rustfmt = rustfmt,
852*d4726bddSHONG Yifan            rustc = rustc,
853*d4726bddSHONG Yifan            rustc_lib = rustc_lib,
854*d4726bddSHONG Yifan        ),
855*d4726bddSHONG Yifan    ]
856*d4726bddSHONG Yifan    sha256s.update(rustc_sha256 | rustfmt_sha256)
857*d4726bddSHONG Yifan
858*d4726bddSHONG Yifan    repository_ctx.file("BUILD.bazel", "\n".join(build_contents))
859*d4726bddSHONG Yifan    repository_ctx.file("WORKSPACE.bazel", """workspace(name = "{}")""".format(
860*d4726bddSHONG Yifan        repository_ctx.name,
861*d4726bddSHONG Yifan    ))
862*d4726bddSHONG Yifan
863*d4726bddSHONG Yifan    repro = {"name": repository_ctx.name}
864*d4726bddSHONG Yifan    for key in _RUSTFMT_TOOLCHAIN_TOOLS_ATTRS:
865*d4726bddSHONG Yifan        repro[key] = getattr(repository_ctx.attr, key)
866*d4726bddSHONG Yifan    repro["sha256s"] = sha256s
867*d4726bddSHONG Yifan
868*d4726bddSHONG Yifan    return repro
869*d4726bddSHONG Yifan
870*d4726bddSHONG Yifanrustfmt_toolchain_tools_repository = repository_rule(
871*d4726bddSHONG Yifan    doc = "A repository rule for defining a rustfmt_toolchain.",
872*d4726bddSHONG Yifan    attrs = _RUSTFMT_TOOLCHAIN_TOOLS_ATTRS,
873*d4726bddSHONG Yifan    implementation = _rustfmt_toolchain_tools_repository_impl,
874*d4726bddSHONG Yifan)
875*d4726bddSHONG Yifan
876*d4726bddSHONG Yifandef rustfmt_toolchain_repository(
877*d4726bddSHONG Yifan        name,
878*d4726bddSHONG Yifan        version,
879*d4726bddSHONG Yifan        exec_triple,
880*d4726bddSHONG Yifan        exec_compatible_with = None,
881*d4726bddSHONG Yifan        target_compatible_with = None,
882*d4726bddSHONG Yifan        iso_date = None,
883*d4726bddSHONG Yifan        channel = None,
884*d4726bddSHONG Yifan        sha256s = None,
885*d4726bddSHONG Yifan        urls = None,
886*d4726bddSHONG Yifan        auth = None,
887*d4726bddSHONG Yifan        netrc = None,
888*d4726bddSHONG Yifan        auth_patterns = None):
889*d4726bddSHONG Yifan    """Assemble a remote rustfmt_toolchain target based on the given params.
890*d4726bddSHONG Yifan
891*d4726bddSHONG Yifan    Args:
892*d4726bddSHONG Yifan        name (str): The name of the toolchain proxy repository contianing the registerable toolchain.
893*d4726bddSHONG Yifan        version (str): The version of the tool among "nightly", "beta', or an exact version.
894*d4726bddSHONG Yifan        exec_triple (str): The platform triple Rustfmt is expected to run on.
895*d4726bddSHONG Yifan        exec_compatible_with (list, optional): A list of constraints for the execution platform for this toolchain.
896*d4726bddSHONG Yifan        target_compatible_with (list, optional): A list of constraints for the target platform for this toolchain.
897*d4726bddSHONG Yifan        iso_date (str, optional): The date of the tool.
898*d4726bddSHONG Yifan        channel (str, optional): The channel value to with which to constrain the toolchain.
899*d4726bddSHONG Yifan        sha256s (str, optional): A dict associating tool subdirectories to sha256 hashes. See
900*d4726bddSHONG Yifan            [rust_register_toolchains](#rust_register_toolchains) for more details.
901*d4726bddSHONG Yifan        urls (list, optional): 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). Defaults to ['https://static.rust-lang.org/dist/{}.tar.xz']
902*d4726bddSHONG Yifan        auth (dict): Auth object compatible with repository_ctx.download to use when downloading files.
903*d4726bddSHONG Yifan            See [repository_ctx.download](https://docs.bazel.build/versions/main/skylark/lib/repository_ctx.html#download) for more details.
904*d4726bddSHONG Yifan        netrc (str, optional): .netrc file to use for authentication; mirrors the eponymous attribute from http_archive
905*d4726bddSHONG Yifan        auth_patterns (dict, optional): Override mapping of hostnames to authorization patterns; mirrors the eponymous attribute from http_archive
906*d4726bddSHONG Yifan
907*d4726bddSHONG Yifan    Returns:
908*d4726bddSHONG Yifan        str: The name of a registerable rustfmt_toolchain.
909*d4726bddSHONG Yifan    """
910*d4726bddSHONG Yifan    if exec_compatible_with == None:
911*d4726bddSHONG Yifan        exec_compatible_with = triple_to_constraint_set(exec_triple)
912*d4726bddSHONG Yifan
913*d4726bddSHONG Yifan    rustfmt_toolchain_tools_repository(
914*d4726bddSHONG Yifan        name = name + "_tools",
915*d4726bddSHONG Yifan        version = version,
916*d4726bddSHONG Yifan        iso_date = iso_date,
917*d4726bddSHONG Yifan        sha256s = sha256s,
918*d4726bddSHONG Yifan        urls = urls,
919*d4726bddSHONG Yifan        auth = auth,
920*d4726bddSHONG Yifan        netrc = netrc,
921*d4726bddSHONG Yifan        auth_patterns = auth_patterns,
922*d4726bddSHONG Yifan        exec_triple = exec_triple,
923*d4726bddSHONG Yifan    )
924*d4726bddSHONG Yifan
925*d4726bddSHONG Yifan    toolchain_repository_proxy(
926*d4726bddSHONG Yifan        name = name,
927*d4726bddSHONG Yifan        toolchain = "@{}//:{}".format(name + "_tools", "rustfmt_toolchain"),
928*d4726bddSHONG Yifan        toolchain_type = "@rules_rust//rust/rustfmt:toolchain_type",
929*d4726bddSHONG Yifan        target_settings = ["@rules_rust//rust/toolchain/channel:{}".format(channel)] if channel else None,
930*d4726bddSHONG Yifan        exec_compatible_with = exec_compatible_with,
931*d4726bddSHONG Yifan        target_compatible_with = target_compatible_with,
932*d4726bddSHONG Yifan    )
933*d4726bddSHONG Yifan
934*d4726bddSHONG Yifan    return "@{}//:toolchain".format(
935*d4726bddSHONG Yifan        name,
936*d4726bddSHONG Yifan    )
937*d4726bddSHONG Yifan
938*d4726bddSHONG Yifandef _rust_toolchain_set_repository_impl(repository_ctx):
939*d4726bddSHONG Yifan    repository_ctx.file("WORKSPACE.bazel", """workspace(name = "{}")""".format(
940*d4726bddSHONG Yifan        repository_ctx.name,
941*d4726bddSHONG Yifan    ))
942*d4726bddSHONG Yifan
943*d4726bddSHONG Yifan    repository_ctx.file("BUILD.bazel", """exports_files(["defs.bzl"])""")
944*d4726bddSHONG Yifan    repository_ctx.file("defs.bzl", "ALL_TOOLCHAINS = {}\n".format(
945*d4726bddSHONG Yifan        json.encode_indent(repository_ctx.attr.toolchains, indent = " " * 4),
946*d4726bddSHONG Yifan    ))
947*d4726bddSHONG Yifan
948*d4726bddSHONG Yifanrust_toolchain_set_repository = repository_rule(
949*d4726bddSHONG Yifan    doc = (
950*d4726bddSHONG Yifan        "Generates a toolchain-bearing repository that declares the toolchains from some other " +
951*d4726bddSHONG Yifan        "rust_toolchain_repository."
952*d4726bddSHONG Yifan    ),
953*d4726bddSHONG Yifan    attrs = {
954*d4726bddSHONG Yifan        "toolchains": attr.string_list(
955*d4726bddSHONG Yifan            doc = "The list of all toolchains created by the current `rust_toolchain_set`",
956*d4726bddSHONG Yifan            mandatory = True,
957*d4726bddSHONG Yifan        ),
958*d4726bddSHONG Yifan    },
959*d4726bddSHONG Yifan    implementation = _rust_toolchain_set_repository_impl,
960*d4726bddSHONG Yifan)
961*d4726bddSHONG Yifan
962*d4726bddSHONG Yifandef _get_toolchain_repositories(name, exec_triple, extra_target_triples, versions, iso_date):
963*d4726bddSHONG Yifan    toolchain_repos = []
964*d4726bddSHONG Yifan
965*d4726bddSHONG Yifan    for target_triple in depset([exec_triple] + extra_target_triples).to_list():
966*d4726bddSHONG Yifan        # Parse all provided versions while checking for duplicates
967*d4726bddSHONG Yifan        channels = {}
968*d4726bddSHONG Yifan        for version in versions:
969*d4726bddSHONG Yifan            if version.startswith(("beta", "nightly")):
970*d4726bddSHONG Yifan                channel, _, date = version.partition("/")
971*d4726bddSHONG Yifan                ver = channel
972*d4726bddSHONG Yifan            else:
973*d4726bddSHONG Yifan                channel = "stable"
974*d4726bddSHONG Yifan                date = iso_date
975*d4726bddSHONG Yifan                ver = version
976*d4726bddSHONG Yifan
977*d4726bddSHONG Yifan            if channel in channels:
978*d4726bddSHONG Yifan                fail("Duplicate {} channels provided for {}: {}".format(channel, name, versions))
979*d4726bddSHONG Yifan
980*d4726bddSHONG Yifan            channels.update({channel: struct(
981*d4726bddSHONG Yifan                name = channel,
982*d4726bddSHONG Yifan                iso_date = date,
983*d4726bddSHONG Yifan                version = ver,
984*d4726bddSHONG Yifan            )})
985*d4726bddSHONG Yifan
986*d4726bddSHONG Yifan        # Define toolchains for each requested version
987*d4726bddSHONG Yifan        for channel in channels.values():
988*d4726bddSHONG Yifan            toolchain_repos.append(struct(
989*d4726bddSHONG Yifan                name = "{}__{}__{}".format(name, target_triple, channel.name),
990*d4726bddSHONG Yifan                target_triple = target_triple,
991*d4726bddSHONG Yifan                channel = channel,
992*d4726bddSHONG Yifan            ))
993*d4726bddSHONG Yifan
994*d4726bddSHONG Yifan    return toolchain_repos
995*d4726bddSHONG Yifan
996*d4726bddSHONG Yifandef rust_repository_set(
997*d4726bddSHONG Yifan        name,
998*d4726bddSHONG Yifan        exec_triple,
999*d4726bddSHONG Yifan        target_settings = [],
1000*d4726bddSHONG Yifan        version = None,
1001*d4726bddSHONG Yifan        versions = [],
1002*d4726bddSHONG Yifan        allocator_library = None,
1003*d4726bddSHONG Yifan        global_allocator_library = None,
1004*d4726bddSHONG Yifan        extra_target_triples = {},
1005*d4726bddSHONG Yifan        iso_date = None,
1006*d4726bddSHONG Yifan        rustfmt_version = None,
1007*d4726bddSHONG Yifan        edition = None,
1008*d4726bddSHONG Yifan        dev_components = False,
1009*d4726bddSHONG Yifan        extra_rustc_flags = None,
1010*d4726bddSHONG Yifan        extra_exec_rustc_flags = None,
1011*d4726bddSHONG Yifan        opt_level = None,
1012*d4726bddSHONG Yifan        sha256s = None,
1013*d4726bddSHONG Yifan        urls = DEFAULT_STATIC_RUST_URL_TEMPLATES,
1014*d4726bddSHONG Yifan        auth = None,
1015*d4726bddSHONG Yifan        netrc = None,
1016*d4726bddSHONG Yifan        auth_patterns = None,
1017*d4726bddSHONG Yifan        register_toolchain = True,
1018*d4726bddSHONG Yifan        exec_compatible_with = None,
1019*d4726bddSHONG Yifan        default_target_compatible_with = None):
1020*d4726bddSHONG Yifan    """Assembles a remote repository for the given toolchain params, produces a proxy repository \
1021*d4726bddSHONG Yifan    to contain the toolchain declaration, and registers the toolchains.
1022*d4726bddSHONG Yifan
1023*d4726bddSHONG Yifan    Args:
1024*d4726bddSHONG Yifan        name (str): The name of the generated repository
1025*d4726bddSHONG Yifan        exec_triple (str): The Rust-style target that this compiler runs on
1026*d4726bddSHONG Yifan        target_settings (list, optional): A list of config_settings that must be satisfied by the target configuration in order for this set of toolchains to be selected during toolchain resolution.
1027*d4726bddSHONG Yifan        version (str): The version of the tool among "nightly", "beta', or an exact version.
1028*d4726bddSHONG Yifan        versions (list, optional): A list of toolchain versions to download. This paramter only accepts one versions
1029*d4726bddSHONG Yifan            per channel. E.g. `["1.65.0", "nightly/2022-11-02", "beta/2020-12-30"]`.
1030*d4726bddSHONG Yifan        allocator_library (str, optional): Target that provides allocator functions when rust_library targets are
1031*d4726bddSHONG Yifan            embedded in a cc_binary.
1032*d4726bddSHONG Yifan        global_allocator_library (str, optional): Target that provides allocator functions a global allocator is used with cc_common.link.
1033*d4726bddSHONG Yifan        extra_target_triples (list or map, optional): Additional rust-style targets that this set of
1034*d4726bddSHONG Yifan            toolchains should support. If a map, values should be (optional) target_compatible_with lists for that particular target triple.
1035*d4726bddSHONG Yifan        iso_date (str, optional): The date of the tool.
1036*d4726bddSHONG Yifan        rustfmt_version (str, optional):  The version of rustfmt to be associated with the
1037*d4726bddSHONG Yifan            toolchain.
1038*d4726bddSHONG Yifan        edition (str, optional): The rust edition to be used by default (2015, 2018, or 2021). If absent, every rule is
1039*d4726bddSHONG Yifan            required to specify its `edition` attribute.
1040*d4726bddSHONG Yifan        dev_components (bool, optional): Whether to download the rustc-dev components.
1041*d4726bddSHONG Yifan            Requires version to be "nightly".
1042*d4726bddSHONG Yifan        extra_rustc_flags (dict, list, optional): Dictionary of target triples to list of extra flags to pass to rustc in non-exec configuration.
1043*d4726bddSHONG Yifan        extra_exec_rustc_flags (list, optional): Extra flags to pass to rustc in exec configuration.
1044*d4726bddSHONG Yifan        opt_level (dict, dict, optional): Dictionary of target triples to optimiztion config.
1045*d4726bddSHONG Yifan        sha256s (str, optional): A dict associating tool subdirectories to sha256 hashes. See
1046*d4726bddSHONG Yifan            [rust_register_toolchains](#rust_register_toolchains) for more details.
1047*d4726bddSHONG Yifan        urls (list, optional): A list of mirror urls containing the tools from the Rust-lang static file server. These
1048*d4726bddSHONG Yifan            must contain the '{}' used to substitute the tool being fetched (using .format).
1049*d4726bddSHONG Yifan        auth (dict): Auth object compatible with repository_ctx.download to use when downloading files.
1050*d4726bddSHONG Yifan            See [repository_ctx.download](https://docs.bazel.build/versions/main/skylark/lib/repository_ctx.html#download) for more details.
1051*d4726bddSHONG Yifan        netrc (str, optional): .netrc file to use for authentication; mirrors the eponymous attribute from http_archive
1052*d4726bddSHONG Yifan        auth_patterns (dict, optional): Override mapping of hostnames to authorization patterns; mirrors the eponymous attribute from http_archive
1053*d4726bddSHONG Yifan
1054*d4726bddSHONG Yifan        register_toolchain (bool): If True, the generated `rust_toolchain` target will become a registered toolchain.
1055*d4726bddSHONG Yifan        exec_compatible_with (list, optional): A list of constraints for the execution platform for this toolchain.
1056*d4726bddSHONG Yifan        default_target_compatible_with (list, optional): A list of constraints for the target platform for this toolchain when the exec platform is the same as the target platform.
1057*d4726bddSHONG Yifan    """
1058*d4726bddSHONG Yifan
1059*d4726bddSHONG Yifan    if version and versions:
1060*d4726bddSHONG Yifan        fail("`version` and `versions` attributes are mutually exclusive. Update {} to use one".format(
1061*d4726bddSHONG Yifan            name,
1062*d4726bddSHONG Yifan        ))
1063*d4726bddSHONG Yifan
1064*d4726bddSHONG Yifan    if not version and not versions:
1065*d4726bddSHONG Yifan        fail("`version` or `versions` attributes are required. Update {} to use one".format(
1066*d4726bddSHONG Yifan            name,
1067*d4726bddSHONG Yifan        ))
1068*d4726bddSHONG Yifan
1069*d4726bddSHONG Yifan    if version:
1070*d4726bddSHONG Yifan        # buildifier: disable=print
1071*d4726bddSHONG Yifan        print("`rust_repository_set.version` is deprecated. Instead use `rust_repository_set.versions`")
1072*d4726bddSHONG Yifan
1073*d4726bddSHONG Yifan    if version and not versions:
1074*d4726bddSHONG Yifan        versions = [version]
1075*d4726bddSHONG Yifan
1076*d4726bddSHONG Yifan    # extra_target_triples may be a dict or list - make a list we can pass to _get_toolchain_repositories
1077*d4726bddSHONG Yifan    extra_target_triples_list = []
1078*d4726bddSHONG Yifan    for extra_target_triple in extra_target_triples:
1079*d4726bddSHONG Yifan        extra_target_triples_list.append(extra_target_triple)
1080*d4726bddSHONG Yifan
1081*d4726bddSHONG Yifan    all_toolchain_names = []
1082*d4726bddSHONG Yifan    for toolchain in _get_toolchain_repositories(name, exec_triple, extra_target_triples_list, versions, iso_date):
1083*d4726bddSHONG Yifan        target_compatible_with = None
1084*d4726bddSHONG Yifan        if toolchain.target_triple == exec_triple:
1085*d4726bddSHONG Yifan            # The exec triple implicitly gets a toolchain with itself as a target - use default_target_compatible_with for it
1086*d4726bddSHONG Yifan            target_compatible_with = default_target_compatible_with
1087*d4726bddSHONG Yifan        elif type(extra_target_triples) == "dict":
1088*d4726bddSHONG Yifan            target_compatible_with = extra_target_triples.get(toolchain.target_triple)
1089*d4726bddSHONG Yifan
1090*d4726bddSHONG Yifan        # Infer toolchain-specific rustc flags depending on the type (list, dict, optional) of extra_rustc_flags
1091*d4726bddSHONG Yifan        if extra_rustc_flags == None:
1092*d4726bddSHONG Yifan            toolchain_extra_rustc_flags = []
1093*d4726bddSHONG Yifan        elif type(extra_rustc_flags) == "list":
1094*d4726bddSHONG Yifan            toolchain_extra_rustc_flags = extra_rustc_flags
1095*d4726bddSHONG Yifan        elif type(extra_rustc_flags) == "dict":
1096*d4726bddSHONG Yifan            toolchain_extra_rustc_flags = extra_rustc_flags.get(toolchain.target_triple)
1097*d4726bddSHONG Yifan        else:
1098*d4726bddSHONG Yifan            fail("extra_rustc_flags should be a list or a dict")
1099*d4726bddSHONG Yifan
1100*d4726bddSHONG Yifan        all_toolchain_names.append(rust_toolchain_repository(
1101*d4726bddSHONG Yifan            name = toolchain.name,
1102*d4726bddSHONG Yifan            allocator_library = allocator_library,
1103*d4726bddSHONG Yifan            global_allocator_library = global_allocator_library,
1104*d4726bddSHONG Yifan            auth = auth,
1105*d4726bddSHONG Yifan            netrc = netrc,
1106*d4726bddSHONG Yifan            auth_patterns = auth_patterns,
1107*d4726bddSHONG Yifan            channel = toolchain.channel.name,
1108*d4726bddSHONG Yifan            dev_components = dev_components,
1109*d4726bddSHONG Yifan            edition = edition,
1110*d4726bddSHONG Yifan            exec_triple = exec_triple,
1111*d4726bddSHONG Yifan            extra_exec_rustc_flags = extra_exec_rustc_flags,
1112*d4726bddSHONG Yifan            extra_rustc_flags = toolchain_extra_rustc_flags,
1113*d4726bddSHONG Yifan            opt_level = opt_level.get(toolchain.target_triple) if opt_level != None else None,
1114*d4726bddSHONG Yifan            target_settings = target_settings,
1115*d4726bddSHONG Yifan            iso_date = toolchain.channel.iso_date,
1116*d4726bddSHONG Yifan            rustfmt_version = rustfmt_version,
1117*d4726bddSHONG Yifan            sha256s = sha256s,
1118*d4726bddSHONG Yifan            target_triple = toolchain.target_triple,
1119*d4726bddSHONG Yifan            urls = urls,
1120*d4726bddSHONG Yifan            version = toolchain.channel.version,
1121*d4726bddSHONG Yifan            exec_compatible_with = exec_compatible_with,
1122*d4726bddSHONG Yifan            target_compatible_with = target_compatible_with,
1123*d4726bddSHONG Yifan        ))
1124*d4726bddSHONG Yifan
1125*d4726bddSHONG Yifan    # This repository exists to allow `rust_repository_set` to work with the `maybe` wrapper.
1126*d4726bddSHONG Yifan    rust_toolchain_set_repository(
1127*d4726bddSHONG Yifan        name = name,
1128*d4726bddSHONG Yifan        toolchains = all_toolchain_names,
1129*d4726bddSHONG Yifan    )
1130*d4726bddSHONG Yifan
1131*d4726bddSHONG Yifan    # Register toolchains
1132*d4726bddSHONG Yifan    if register_toolchain:
1133*d4726bddSHONG Yifan        native.register_toolchains(*all_toolchain_names)
1134*d4726bddSHONG Yifan        native.register_toolchains(str(Label("//rust/private/dummy_cc_toolchain:dummy_cc_wasm32_toolchain")))
1135