xref: /aosp_15_r20/external/pigweed/pw_toolchain/rust/extensions.bzl (revision 61c4878ac05f98d0ceed94b57d316916de578985)
1*61c4878aSAndroid Build Coastguard Worker# Copyright 2024 The Pigweed Authors
2*61c4878aSAndroid Build Coastguard Worker#
3*61c4878aSAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License"); you may not
4*61c4878aSAndroid Build Coastguard Worker# use this file except in compliance with the License. You may obtain a copy of
5*61c4878aSAndroid Build Coastguard Worker# the License at
6*61c4878aSAndroid Build Coastguard Worker#
7*61c4878aSAndroid Build Coastguard Worker#     https://www.apache.org/licenses/LICENSE-2.0
8*61c4878aSAndroid Build Coastguard Worker#
9*61c4878aSAndroid Build Coastguard Worker# Unless required by applicable law or agreed to in writing, software
10*61c4878aSAndroid Build Coastguard Worker# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11*61c4878aSAndroid Build Coastguard Worker# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12*61c4878aSAndroid Build Coastguard Worker# License for the specific language governing permissions and limitations under
13*61c4878aSAndroid Build Coastguard Worker# the License.
14*61c4878aSAndroid Build Coastguard Worker"""Extension for declaring Pigweed Rust toolchains."""
15*61c4878aSAndroid Build Coastguard Worker
16*61c4878aSAndroid Build Coastguard Workerload("//pw_env_setup/bazel/cipd_setup:cipd_rules.bzl", "cipd_repository")
17*61c4878aSAndroid Build Coastguard Workerload(":templates.bzl", "rust_analyzer_toolchain_template", "rust_toolchain_template", "toolchain_template")
18*61c4878aSAndroid Build Coastguard Workerload(":toolchains.bzl", "CHANNELS", "EXTRA_TARGETS", "HOSTS")
19*61c4878aSAndroid Build Coastguard Worker
20*61c4878aSAndroid Build Coastguard Workerdef _module_cipd_tag(module):
21*61c4878aSAndroid Build Coastguard Worker    """\
22*61c4878aSAndroid Build Coastguard Worker    Returns the `cipd_tag` tag for the given module.
23*61c4878aSAndroid Build Coastguard Worker
24*61c4878aSAndroid Build Coastguard Worker    Latter delcations will take precedence of ealier ones.
25*61c4878aSAndroid Build Coastguard Worker    """
26*61c4878aSAndroid Build Coastguard Worker    cipd_tag = None
27*61c4878aSAndroid Build Coastguard Worker    for toolchain in module.tags.toolchain:
28*61c4878aSAndroid Build Coastguard Worker        cipd_tag = toolchain.cipd_tag
29*61c4878aSAndroid Build Coastguard Worker
30*61c4878aSAndroid Build Coastguard Worker    return cipd_tag
31*61c4878aSAndroid Build Coastguard Worker
32*61c4878aSAndroid Build Coastguard Workerdef _find_cipd_tag(ctx):
33*61c4878aSAndroid Build Coastguard Worker    """\
34*61c4878aSAndroid Build Coastguard Worker    Returns the CIPD tag specified in either the root or pigweed modules.
35*61c4878aSAndroid Build Coastguard Worker
36*61c4878aSAndroid Build Coastguard Worker    The tag from the root module will take priority over the tag from the
37*61c4878aSAndroid Build Coastguard Worker    pigweed module.
38*61c4878aSAndroid Build Coastguard Worker    """
39*61c4878aSAndroid Build Coastguard Worker
40*61c4878aSAndroid Build Coastguard Worker    pigweed_module = None
41*61c4878aSAndroid Build Coastguard Worker    root_tag = None
42*61c4878aSAndroid Build Coastguard Worker
43*61c4878aSAndroid Build Coastguard Worker    for module in ctx.modules:
44*61c4878aSAndroid Build Coastguard Worker        if module.is_root:
45*61c4878aSAndroid Build Coastguard Worker            root_tag = _module_cipd_tag(module)
46*61c4878aSAndroid Build Coastguard Worker        if module.name == "pigweed":
47*61c4878aSAndroid Build Coastguard Worker            pigweed_module = module
48*61c4878aSAndroid Build Coastguard Worker
49*61c4878aSAndroid Build Coastguard Worker    if pigweed_module == None:
50*61c4878aSAndroid Build Coastguard Worker        fail("Unable to find pigweed module")
51*61c4878aSAndroid Build Coastguard Worker
52*61c4878aSAndroid Build Coastguard Worker    return root_tag or _module_cipd_tag(pigweed_module)
53*61c4878aSAndroid Build Coastguard Worker
54*61c4878aSAndroid Build Coastguard Workerdef _normalize_os_to_cipd(os):
55*61c4878aSAndroid Build Coastguard Worker    """\
56*61c4878aSAndroid Build Coastguard Worker    Translate a bazel OS name to one used by CIPD.
57*61c4878aSAndroid Build Coastguard Worker    """
58*61c4878aSAndroid Build Coastguard Worker    if os == "macos":
59*61c4878aSAndroid Build Coastguard Worker        return "mac"
60*61c4878aSAndroid Build Coastguard Worker
61*61c4878aSAndroid Build Coastguard Worker    return os
62*61c4878aSAndroid Build Coastguard Worker
63*61c4878aSAndroid Build Coastguard Workerdef _pw_rust_impl(ctx):
64*61c4878aSAndroid Build Coastguard Worker    cipd_tag = _find_cipd_tag(ctx)
65*61c4878aSAndroid Build Coastguard Worker
66*61c4878aSAndroid Build Coastguard Worker    # Register CIPD repositories for toolchain binaries
67*61c4878aSAndroid Build Coastguard Worker    for host in HOSTS:
68*61c4878aSAndroid Build Coastguard Worker        cipd_os = _normalize_os_to_cipd(host["os"])
69*61c4878aSAndroid Build Coastguard Worker
70*61c4878aSAndroid Build Coastguard Worker        cipd_repository(
71*61c4878aSAndroid Build Coastguard Worker            name = "rust_toolchain_host_{}_{}".format(host["os"], host["cpu"]),
72*61c4878aSAndroid Build Coastguard Worker            build_file = "//pw_toolchain/rust:rust_toolchain.BUILD",
73*61c4878aSAndroid Build Coastguard Worker            path = "fuchsia/third_party/rust/host/{}-{}".format(cipd_os, host["cipd_arch"]),
74*61c4878aSAndroid Build Coastguard Worker            tag = cipd_tag,
75*61c4878aSAndroid Build Coastguard Worker        )
76*61c4878aSAndroid Build Coastguard Worker
77*61c4878aSAndroid Build Coastguard Worker        cipd_repository(
78*61c4878aSAndroid Build Coastguard Worker            name = "rust_toolchain_target_{}_{}".format(host["triple"], host["cpu"]),
79*61c4878aSAndroid Build Coastguard Worker            build_file = "//pw_toolchain/rust:rust_stdlib.BUILD",
80*61c4878aSAndroid Build Coastguard Worker            path = "fuchsia/third_party/rust/target/{}".format(host["triple"]),
81*61c4878aSAndroid Build Coastguard Worker            tag = cipd_tag,
82*61c4878aSAndroid Build Coastguard Worker        )
83*61c4878aSAndroid Build Coastguard Worker
84*61c4878aSAndroid Build Coastguard Worker    for target in EXTRA_TARGETS:
85*61c4878aSAndroid Build Coastguard Worker        cipd_repository(
86*61c4878aSAndroid Build Coastguard Worker            name = "rust_toolchain_target_{}_{}".format(target["triple"], target["cpu"]),
87*61c4878aSAndroid Build Coastguard Worker            build_file = "//pw_toolchain/rust:rust_stdlib.BUILD",
88*61c4878aSAndroid Build Coastguard Worker            path = "fuchsia/third_party/rust/target/{}".format(target["triple"]),
89*61c4878aSAndroid Build Coastguard Worker            tag = cipd_tag,
90*61c4878aSAndroid Build Coastguard Worker        )
91*61c4878aSAndroid Build Coastguard Worker
92*61c4878aSAndroid Build Coastguard Worker    _toolchain_repository_hub(name = "pw_rust_toolchains")
93*61c4878aSAndroid Build Coastguard Worker
94*61c4878aSAndroid Build Coastguard Worker_RUST_TOOLCHAIN_TAG = tag_class(
95*61c4878aSAndroid Build Coastguard Worker    attrs = dict(
96*61c4878aSAndroid Build Coastguard Worker        cipd_tag = attr.string(
97*61c4878aSAndroid Build Coastguard Worker            doc = "The CIPD tag to use when fetching the Rust toolchain.",
98*61c4878aSAndroid Build Coastguard Worker        ),
99*61c4878aSAndroid Build Coastguard Worker    ),
100*61c4878aSAndroid Build Coastguard Worker)
101*61c4878aSAndroid Build Coastguard Worker
102*61c4878aSAndroid Build Coastguard Workerpw_rust = module_extension(
103*61c4878aSAndroid Build Coastguard Worker    implementation = _pw_rust_impl,
104*61c4878aSAndroid Build Coastguard Worker    tag_classes = {
105*61c4878aSAndroid Build Coastguard Worker        "toolchain": _RUST_TOOLCHAIN_TAG,
106*61c4878aSAndroid Build Coastguard Worker    },
107*61c4878aSAndroid Build Coastguard Worker    doc = """Generate a repository for all Pigweed Rust toolchains.
108*61c4878aSAndroid Build Coastguard Worker
109*61c4878aSAndroid Build Coastguard Worker        Declares a suite of Rust toolchains that may be registered in a
110*61c4878aSAndroid Build Coastguard Worker        MODULE.bazel file. If you would like to use the Toolchains provided
111*61c4878aSAndroid Build Coastguard Worker        by Pigweed, add these lines to your MOUDLE.bazel:
112*61c4878aSAndroid Build Coastguard Worker        ```
113*61c4878aSAndroid Build Coastguard Worker        pw_rust = use_extension("@pigweed//pw_toolchain/rust:extensions.bzl", "pw_rust")
114*61c4878aSAndroid Build Coastguard Worker        use_repo(pw_rust, "pw_rust_toolchains")
115*61c4878aSAndroid Build Coastguard Worker        register_toolchains(
116*61c4878aSAndroid Build Coastguard Worker            "@pw_rust_toolchains//:all",
117*61c4878aSAndroid Build Coastguard Worker            dev_dependency = True,
118*61c4878aSAndroid Build Coastguard Worker        )
119*61c4878aSAndroid Build Coastguard Worker        ```
120*61c4878aSAndroid Build Coastguard Worker
121*61c4878aSAndroid Build Coastguard Worker        If you would like to override the rust compiler version, you can specify a
122*61c4878aSAndroid Build Coastguard Worker        CIPD version for an alternative toolchain to use in your project. Note that
123*61c4878aSAndroid Build Coastguard Worker        only the root module's specification of this tag is applied, and that if no
124*61c4878aSAndroid Build Coastguard Worker        version tag is specified Pigweed's value will be used as a fallback.
125*61c4878aSAndroid Build Coastguard Worker        ```
126*61c4878aSAndroid Build Coastguard Worker        pw_rust = use_extension("@pigweed//pw_toolchain/rust:extensions.bzl", "pw_rust")
127*61c4878aSAndroid Build Coastguard Worker        pw_rust.toolchain(cipd_tag = "rust_revision:bf9c7a64ad222b85397573668b39e6d1ab9f4a72")
128*61c4878aSAndroid Build Coastguard Worker        use_repo(pw_rust, "pw_rust_toolchains")
129*61c4878aSAndroid Build Coastguard Worker        register_toolchains(
130*61c4878aSAndroid Build Coastguard Worker            "@pw_rust_toolchains//:all",
131*61c4878aSAndroid Build Coastguard Worker            dev_dependency = True,
132*61c4878aSAndroid Build Coastguard Worker        )
133*61c4878aSAndroid Build Coastguard Worker        ```
134*61c4878aSAndroid Build Coastguard Worker    """,
135*61c4878aSAndroid Build Coastguard Worker)
136*61c4878aSAndroid Build Coastguard Worker
137*61c4878aSAndroid Build Coastguard Workerdef _pw_rust_toolchain(
138*61c4878aSAndroid Build Coastguard Worker        name,
139*61c4878aSAndroid Build Coastguard Worker        exec_triple,
140*61c4878aSAndroid Build Coastguard Worker        target_triple,
141*61c4878aSAndroid Build Coastguard Worker        toolchain_repo,
142*61c4878aSAndroid Build Coastguard Worker        target_repo,
143*61c4878aSAndroid Build Coastguard Worker        dylib_ext,
144*61c4878aSAndroid Build Coastguard Worker        exec_compatible_with,
145*61c4878aSAndroid Build Coastguard Worker        target_compatible_with,
146*61c4878aSAndroid Build Coastguard Worker        target_settings,
147*61c4878aSAndroid Build Coastguard Worker        extra_rustc_flags,
148*61c4878aSAndroid Build Coastguard Worker        analyzer_toolchain_name = None):
149*61c4878aSAndroid Build Coastguard Worker    build_file = rust_toolchain_template(
150*61c4878aSAndroid Build Coastguard Worker        name = name,
151*61c4878aSAndroid Build Coastguard Worker        exec_compatible_with = exec_compatible_with,
152*61c4878aSAndroid Build Coastguard Worker        target_compatible_with = target_compatible_with,
153*61c4878aSAndroid Build Coastguard Worker        dylib_ext = dylib_ext,
154*61c4878aSAndroid Build Coastguard Worker        target_repo = target_repo,
155*61c4878aSAndroid Build Coastguard Worker        toolchain_repo = toolchain_repo,
156*61c4878aSAndroid Build Coastguard Worker        exec_triple = exec_triple,
157*61c4878aSAndroid Build Coastguard Worker        target_triple = target_triple,
158*61c4878aSAndroid Build Coastguard Worker        extra_rustc_flags = extra_rustc_flags,
159*61c4878aSAndroid Build Coastguard Worker    )
160*61c4878aSAndroid Build Coastguard Worker
161*61c4878aSAndroid Build Coastguard Worker    build_file += toolchain_template(
162*61c4878aSAndroid Build Coastguard Worker        name = name,
163*61c4878aSAndroid Build Coastguard Worker        exec_compatible_with = exec_compatible_with,
164*61c4878aSAndroid Build Coastguard Worker        target_compatible_with = target_compatible_with,
165*61c4878aSAndroid Build Coastguard Worker        target_settings = target_settings,
166*61c4878aSAndroid Build Coastguard Worker    )
167*61c4878aSAndroid Build Coastguard Worker
168*61c4878aSAndroid Build Coastguard Worker    if analyzer_toolchain_name:
169*61c4878aSAndroid Build Coastguard Worker        build_file += rust_analyzer_toolchain_template(
170*61c4878aSAndroid Build Coastguard Worker            name = analyzer_toolchain_name,
171*61c4878aSAndroid Build Coastguard Worker            toolchain_repo = toolchain_repo,
172*61c4878aSAndroid Build Coastguard Worker            exec_compatible_with = exec_compatible_with,
173*61c4878aSAndroid Build Coastguard Worker            target_compatible_with = target_compatible_with,
174*61c4878aSAndroid Build Coastguard Worker            target_settings = target_settings,
175*61c4878aSAndroid Build Coastguard Worker        )
176*61c4878aSAndroid Build Coastguard Worker
177*61c4878aSAndroid Build Coastguard Worker    return build_file
178*61c4878aSAndroid Build Coastguard Worker
179*61c4878aSAndroid Build Coastguard Workerdef _BUILD_for_toolchain_repo():
180*61c4878aSAndroid Build Coastguard Worker    # Declare rust toolchains
181*61c4878aSAndroid Build Coastguard Worker    build_file = """load("@rules_rust//rust:toolchain.bzl", "rust_analyzer_toolchain", "rust_toolchain")\n"""
182*61c4878aSAndroid Build Coastguard Worker    for channel in CHANNELS:
183*61c4878aSAndroid Build Coastguard Worker        for host in HOSTS:
184*61c4878aSAndroid Build Coastguard Worker            build_file += _pw_rust_toolchain(
185*61c4878aSAndroid Build Coastguard Worker                name = "host_rust_toolchain_{}_{}_{}".format(host["os"], host["cpu"], channel["name"]),
186*61c4878aSAndroid Build Coastguard Worker                analyzer_toolchain_name = "host_rust_analyzer_toolchain_{}_{}_{}".format(host["os"], host["cpu"], channel["name"]),
187*61c4878aSAndroid Build Coastguard Worker                exec_compatible_with = [
188*61c4878aSAndroid Build Coastguard Worker                    "@platforms//cpu:{}".format(host["cpu"]),
189*61c4878aSAndroid Build Coastguard Worker                    "@platforms//os:{}".format(host["os"]),
190*61c4878aSAndroid Build Coastguard Worker                ],
191*61c4878aSAndroid Build Coastguard Worker                target_compatible_with = [
192*61c4878aSAndroid Build Coastguard Worker                    "@platforms//cpu:{}".format(host["cpu"]),
193*61c4878aSAndroid Build Coastguard Worker                    "@platforms//os:{}".format(host["os"]),
194*61c4878aSAndroid Build Coastguard Worker                ],
195*61c4878aSAndroid Build Coastguard Worker                target_settings = channel["target_settings"],
196*61c4878aSAndroid Build Coastguard Worker                dylib_ext = host["dylib_ext"],
197*61c4878aSAndroid Build Coastguard Worker                target_repo = "@rust_toolchain_target_{}_{}".format(host["triple"], host["cpu"]),
198*61c4878aSAndroid Build Coastguard Worker                toolchain_repo = "@rust_toolchain_host_{}_{}".format(host["os"], host["cpu"]),
199*61c4878aSAndroid Build Coastguard Worker                exec_triple = host["triple"],
200*61c4878aSAndroid Build Coastguard Worker                target_triple = host["triple"],
201*61c4878aSAndroid Build Coastguard Worker                extra_rustc_flags = channel["extra_rustc_flags"],
202*61c4878aSAndroid Build Coastguard Worker            )
203*61c4878aSAndroid Build Coastguard Worker
204*61c4878aSAndroid Build Coastguard Worker            for target in EXTRA_TARGETS:
205*61c4878aSAndroid Build Coastguard Worker                build_file += _pw_rust_toolchain(
206*61c4878aSAndroid Build Coastguard Worker                    name = "{}_{}_rust_toolchain_{}_{}_{}".format(host["os"], host["cpu"], target["triple"], target["cpu"], channel["name"]),
207*61c4878aSAndroid Build Coastguard Worker                    exec_triple = host["triple"],
208*61c4878aSAndroid Build Coastguard Worker                    target_triple = target["triple"],
209*61c4878aSAndroid Build Coastguard Worker                    target_repo = "@rust_toolchain_target_{}_{}".format(target["triple"], target["cpu"]),
210*61c4878aSAndroid Build Coastguard Worker                    toolchain_repo = "@rust_toolchain_host_{}_{}".format(host["os"], host["cpu"]),
211*61c4878aSAndroid Build Coastguard Worker                    dylib_ext = "*.so",
212*61c4878aSAndroid Build Coastguard Worker                    exec_compatible_with = [
213*61c4878aSAndroid Build Coastguard Worker                        "@platforms//cpu:{}".format(host["cpu"]),
214*61c4878aSAndroid Build Coastguard Worker                        "@platforms//os:{}".format(host["os"]),
215*61c4878aSAndroid Build Coastguard Worker                    ],
216*61c4878aSAndroid Build Coastguard Worker                    target_compatible_with = [
217*61c4878aSAndroid Build Coastguard Worker                        "@platforms//cpu:{}".format(target["cpu"]),
218*61c4878aSAndroid Build Coastguard Worker                    ],
219*61c4878aSAndroid Build Coastguard Worker                    target_settings = channel["target_settings"],
220*61c4878aSAndroid Build Coastguard Worker                    extra_rustc_flags = channel["extra_rustc_flags"],
221*61c4878aSAndroid Build Coastguard Worker                )
222*61c4878aSAndroid Build Coastguard Worker    return build_file
223*61c4878aSAndroid Build Coastguard Worker
224*61c4878aSAndroid Build Coastguard Workerdef _toolchain_repository_hub_impl(repository_ctx):
225*61c4878aSAndroid Build Coastguard Worker    repository_ctx.file("WORKSPACE.bazel", """workspace(name = "{}")""".format(
226*61c4878aSAndroid Build Coastguard Worker        repository_ctx.name,
227*61c4878aSAndroid Build Coastguard Worker    ))
228*61c4878aSAndroid Build Coastguard Worker
229*61c4878aSAndroid Build Coastguard Worker    repository_ctx.file("BUILD.bazel", _BUILD_for_toolchain_repo())
230*61c4878aSAndroid Build Coastguard Worker
231*61c4878aSAndroid Build Coastguard Worker_toolchain_repository_hub = repository_rule(
232*61c4878aSAndroid Build Coastguard Worker    doc = "A repository of Pigweed Rust toolchains",
233*61c4878aSAndroid Build Coastguard Worker    implementation = _toolchain_repository_hub_impl,
234*61c4878aSAndroid Build Coastguard Worker)
235