xref: /aosp_15_r20/external/pigweed/pw_toolchain/rust/defs.bzl (revision 61c4878ac05f98d0ceed94b57d316916de578985)
1# Copyright 2023 The Pigweed Authors
2#
3# Licensed under the Apache License, Version 2.0 (the "License"); you may not
4# use this file except in compliance with the License. You may obtain a copy of
5# the License at
6#
7#     https://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12# License for the specific language governing permissions and limitations under
13# the License.
14"""Utilities for declaring Rust toolchains that are compatible with Arm gcc."""
15
16load("@rules_rust//rust:toolchain.bzl", "rust_analyzer_toolchain", "rust_toolchain")
17load("//pw_env_setup/bazel/cipd_setup:cipd_rules.bzl", "cipd_repository")
18load(":toolchains.bzl", "CHANNELS", "EXTRA_TARGETS", "HOSTS")
19
20_rust_toolchain_repo_template = """\
21load("{pigweed_repo_name}//pw_toolchain/rust:defs.bzl", "pw_rust_declare_toolchain_targets")
22
23package(default_visibility = ["//visibility:public"])
24
25licenses(["notice"])
26
27pw_rust_declare_toolchain_targets()
28"""
29
30def _rust_toolchain_repo_impl(ctx):
31    ctx.file("BUILD", _rust_toolchain_repo_template.format(pigweed_repo_name = ctx.attr.pigweed_repo_name))
32    pass
33
34_rust_toolchain_repo = repository_rule(
35    _rust_toolchain_repo_impl,
36    attrs = {
37        "pigweed_repo_name": attr.string(
38            doc = "The name of the pigweed used to reference build files for the registered repositories.",
39        ),
40    },
41)
42
43# buildifier: disable=unnamed-macro
44def pw_rust_register_toolchain_and_target_repos(cipd_tag, pigweed_repo_name = "@pigweed"):
45    """Declare and register CIPD repos for Rust toolchain and target rupport.
46
47    Args:
48      cipd_tag: Tag with which to select specific package versions.
49      pigweed_repo_name: The name of the pigweed used to reference build files
50        for the registered repositories.  Defaults to "@pigweed".
51    """
52    toolchain_repo_name = "{}_rust_toolchain_repo".format(pigweed_repo_name).lstrip("@")
53    _rust_toolchain_repo(name = toolchain_repo_name, pigweed_repo_name = pigweed_repo_name)
54    for host in HOSTS:
55        cipd_os = host["os"]
56        if cipd_os == "macos":
57            cipd_os = "mac"
58
59        cipd_repository(
60            name = "rust_toolchain_host_{}_{}".format(host["os"], host["cpu"]),
61            build_file = "{}//pw_toolchain/rust:rust_toolchain.BUILD".format(pigweed_repo_name),
62            path = "fuchsia/third_party/rust/host/{}-{}".format(cipd_os, host["cipd_arch"]),
63            tag = cipd_tag,
64        )
65
66        cipd_repository(
67            name = "rust_toolchain_target_{}".format(host["triple"]),
68            build_file = "{}//pw_toolchain/rust:rust_stdlib.BUILD".format(pigweed_repo_name),
69            path = "fuchsia/third_party/rust/target/{}".format(host["triple"]),
70            tag = cipd_tag,
71        )
72
73    for target in EXTRA_TARGETS:
74        cipd_repository(
75            name = "rust_toolchain_target_{}".format(target["triple"]),
76            build_file = "{}//pw_toolchain/rust:rust_stdlib.BUILD".format(pigweed_repo_name),
77            path = "fuchsia/third_party/rust/target/{}".format(target["triple"]),
78            tag = cipd_tag,
79        )
80
81# buildifier: disable=unnamed-macro
82def pw_rust_register_toolchains(pigweed_repo_name = "@pigweed"):
83    """Register Rust Toolchains
84
85    Args:
86      pigweed_repo_name: The name of the pigweed used to reference build files
87        for the registered repositories.  Defaults to "@pigweed".
88
89    For this registration to be valid one must
90    1. Call `pw_rust_register_toolchain_and_target_repos(tag)` pervisouly in the
91       WORKSPACE file.
92    2. Call `pw_rust_declare_toolchain_targets()` from
93       `//pw_toolchain/rust/BUILD.bazel`.
94    """
95
96    toolchain_repo = "{}_rust_toolchain_repo".format(pigweed_repo_name)
97
98    for channel in CHANNELS:
99        for host in HOSTS:
100            native.register_toolchains(
101                "{}//:host_rust_toolchain_{}_{}_{}".format(toolchain_repo, host["os"], host["cpu"], channel["name"]),
102                "{}//:host_rust_analyzer_toolchain_{}_{}_{}".format(toolchain_repo, host["os"], host["cpu"], channel["name"]),
103            )
104            for target in EXTRA_TARGETS:
105                native.register_toolchains(
106                    "{}//:{}_{}_rust_toolchain_{}_{}_{}".format(toolchain_repo, host["os"], host["cpu"], target["triple"], target["cpu"], channel["name"]),
107                )
108
109# buildifier: disable=unnamed-macro
110def pw_rust_declare_toolchain_targets():
111    """Declare rust toolchain targets"""
112    for channel in CHANNELS:
113        for host in HOSTS:
114            _pw_rust_host_toolchain(
115                name = "host_rust_toolchain_{}_{}_{}".format(host["os"], host["cpu"], channel["name"]),
116                analyzer_toolchain_name = "host_rust_analyzer_toolchain_{}_{}_{}".format(host["os"], host["cpu"], channel["name"]),
117                compatible_with = [
118                    "@platforms//cpu:{}".format(host["cpu"]),
119                    "@platforms//os:{}".format(host["os"]),
120                ],
121                target_settings = channel["target_settings"],
122                dylib_ext = host["dylib_ext"],
123                target_repo = "@rust_toolchain_target_{}".format(host["triple"]),
124                toolchain_repo = "@rust_toolchain_host_{}_{}".format(host["os"], host["cpu"]),
125                triple = host["triple"],
126                extra_rustc_flags = channel["extra_rustc_flags"],
127            )
128            for target in EXTRA_TARGETS:
129                _pw_rust_toolchain(
130                    name = "{}_{}_rust_toolchain_{}_{}_{}".format(host["os"], host["cpu"], target["triple"], target["cpu"], channel["name"]),
131                    exec_triple = host["triple"],
132                    target_triple = target["triple"],
133                    target_repo = "@rust_toolchain_target_{}".format(target["triple"]),
134                    toolchain_repo = "@rust_toolchain_host_{}_{}".format(host["os"], host["cpu"]),
135                    dylib_ext = "*.so",
136                    exec_compatible_with = [
137                        "@platforms//cpu:{}".format(host["cpu"]),
138                        "@platforms//os:{}".format(host["os"]),
139                    ],
140                    target_compatible_with = [
141                        "@platforms//cpu:{}".format(target["cpu"]),
142                    ],
143                    target_settings = channel["target_settings"],
144                    extra_rustc_flags = channel["extra_rustc_flags"],
145                )
146
147def _pw_rust_toolchain(
148        name,
149        exec_triple,
150        target_triple,
151        toolchain_repo,
152        target_repo,
153        dylib_ext,
154        exec_compatible_with,
155        target_compatible_with,
156        target_settings,
157        extra_rustc_flags):
158    rust_toolchain(
159        name = "{}_rust_toolchain".format(name),
160        binary_ext = "",
161        clippy_driver = "{}//:bin/clippy-driver".format(toolchain_repo),
162        default_edition = "2021",
163        dylib_ext = dylib_ext,
164        exec_compatible_with = exec_compatible_with,
165        exec_triple = exec_triple,
166        rust_doc = "{}//:bin/rustdoc".format(toolchain_repo),
167        rust_std = "{}//:rust_std".format(target_repo),
168        rustc = "{}//:bin/rustc".format(toolchain_repo),
169        rustc_lib = "{}//:rustc_lib".format(toolchain_repo),
170        staticlib_ext = ".a",
171        stdlib_linkflags = [],
172        target_compatible_with = target_compatible_with,
173        target_triple = target_triple,
174        extra_rustc_flags = extra_rustc_flags,
175        extra_exec_rustc_flags = extra_rustc_flags,
176        # TODO: https://pwbug.dev/342695883 - Works around confusing
177        # target_compatible_with semantics in rust_toolchain. Figure out how to
178        # do better.
179        tags = ["manual"],
180    )
181    native.toolchain(
182        name = name,
183        exec_compatible_with = exec_compatible_with,
184        target_compatible_with = target_compatible_with,
185        target_settings = target_settings,
186        toolchain = ":{}_rust_toolchain".format(name),
187        toolchain_type = "@rules_rust//rust:toolchain",
188    )
189
190def _pw_rust_host_toolchain(
191        name,
192        analyzer_toolchain_name,
193        triple,
194        toolchain_repo,
195        target_repo,
196        dylib_ext,
197        compatible_with,
198        target_settings,
199        extra_rustc_flags):
200    _pw_rust_toolchain(
201        name = name,
202        exec_triple = triple,
203        target_triple = triple,
204        toolchain_repo = toolchain_repo,
205        target_repo = target_repo,
206        dylib_ext = dylib_ext,
207        exec_compatible_with = compatible_with,
208        target_compatible_with = compatible_with,
209        target_settings = target_settings,
210        extra_rustc_flags = extra_rustc_flags,
211    )
212
213    rust_analyzer_toolchain(
214        name = "{}_rust_analyzer_toolchain".format(analyzer_toolchain_name),
215        exec_compatible_with = compatible_with,
216        proc_macro_srv = "{}//:libexec/rust-analyzer-proc-macro-srv".format(toolchain_repo),
217        rustc = "{}//:bin/rustc".format(toolchain_repo),
218        rustc_srcs = "{}//:rustc_srcs".format(toolchain_repo),
219        target_compatible_with = compatible_with,
220        visibility = ["//visibility:public"],
221    )
222
223    native.toolchain(
224        name = analyzer_toolchain_name,
225        exec_compatible_with = compatible_with,
226        target_compatible_with = compatible_with,
227        target_settings = target_settings,
228        toolchain = ":{}_rust_analyzer_toolchain".format(analyzer_toolchain_name),
229        toolchain_type = "@rules_rust//rust/rust_analyzer:toolchain_type",
230    )
231