• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# -*- bazel-starlark -*-
2# Copyright 2023 The Chromium Authors
3# Use of this source code is governed by a BSD-style license that can be
4# found in the LICENSE file.
5"""Siso configuration for rust/linux."""
6
7load("@builtin//lib/gn.star", "gn")
8load("@builtin//path.star", "path")
9load("@builtin//runtime.star", "runtime")
10load("@builtin//struct.star", "module")
11load("./ar.star", "ar")
12load("./config.star", "config")
13load("./fuchsia.star", "fuchsia")
14load("./win_sdk.star", "win_sdk")
15
16def __filegroups(ctx):
17    fg = {
18        "third_party/rust-toolchain:toolchain": {
19            "type": "glob",
20            "includes": [
21                "bin/rustc",
22                "lib/*.so",
23                "lib/libclang.so.*",
24                "lib/rustlib/src/rust/library/std/src/lib.rs",
25                "lib/rustlib/x86_64-unknown-linux-gnu/lib/*",
26            ],
27        },
28        "third_party/rust:rustlib": {
29            "type": "glob",
30            "includes": [
31                "*.rs",
32            ],
33        },
34        "build/linux/debian_bullseye_amd64-sysroot:rustlink": {
35            "type": "glob",
36            "includes": [
37                "*.so",
38                "*.so.*",
39                "*.o",
40                "*.a",
41            ],
42        },
43        "third_party/llvm-build/Release+Asserts:rustlink": {
44            "type": "glob",
45            "includes": [
46                "bin/*lld*",
47                "bin/clang",
48                "bin/clang++",
49                "lib/clang/*/share/cfi_ignorelist.txt",
50                "libclang*.a",
51            ],
52        },
53    }
54    if fuchsia.enabled(ctx):
55        fg.update(fuchsia.filegroups(ctx))
56    return fg
57
58def __rust_link_handler(ctx, cmd):
59    inputs = []
60    use_android_toolchain = None
61    target = None
62    args = cmd.args
63
64    # there is a case that command line sets environment variable
65    # like `TOOL_VERSION=xxxx "python3" ..`
66    if args[0] == "/bin/sh":
67        args = args[2].split(" ")
68    for i, arg in enumerate(args):
69        if arg.startswith("--sysroot=../../third_party/fuchsia-sdk/sdk"):
70            sysroot = ctx.fs.canonpath(arg.removeprefix("--sysroot="))
71            libpath = path.join(path.dir(sysroot), "lib")
72            inputs.extend([
73                sysroot + ":link",
74                libpath + ":link",
75            ])
76        elif arg.startswith("--sysroot=../../third_party/android_toolchain/ndk/toolchains/llvm/prebuilt/linux-x86_64/sysroot"):
77            use_android_toolchain = True
78            inputs.append("third_party/android_toolchain/ndk/toolchains/llvm/prebuilt/linux-x86_64/sysroot:headers")
79        if arg == "-isysroot":
80            sysroot = ctx.fs.canonpath(args[i + 1])
81            inputs.extend([
82                sysroot + ":link",
83            ])
84        if arg.startswith("--target="):
85            target = arg.removeprefix("--target=")
86        if arg.startswith("-Clinker="):
87            linker = arg.removeprefix("-Clinker=")
88            if linker.startswith("\""):
89                linker = linker[1:len(linker) - 1]
90            linker_base = path.dir(path.dir(linker))
91
92            # TODO(crbug.com/380798907): expand input_deps, instead of using label?
93            inputs.append(ctx.fs.canonpath(linker_base) + ":link")
94    if use_android_toolchain and target:
95        # e.g. target=aarch64-linux-android26
96        android_ver = ""
97        i = target.find("android")
98        if i >= 0:
99            android_ver = target[i:].removeprefix("android").removeprefix("eabi")
100        if android_ver:
101            android_arch = target.removesuffix(android_ver)
102            filegroup = "third_party/android_toolchain/ndk/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/%s/%s:link" % (android_arch, android_ver)
103            inputs.append(filegroup)
104
105    # Replace thin archives (.lib) with -start-lib ... -end-lib in rsp file for
106    # Windows builds.
107    new_rspfile_content = None
108    is_windows = None
109    if "args.gn" in ctx.metadata:
110        gn_args = gn.args(ctx)
111        if gn_args.get("target_os") == '"win"':
112            is_windows = True
113    if runtime.os == "windows":
114        is_windows = True
115    if is_windows:
116        new_lines = []
117        for line in str(cmd.rspfile_content).split("\n"):
118            new_elems = []
119            for elem in line.split(" "):
120                # Parse only .lib files.
121                if not elem.endswith(".lib"):
122                    new_elems.append(elem)
123                    continue
124
125                # Parse files under the out dir.
126                fname = ctx.fs.canonpath(elem.removeprefix("-Clink-arg="))
127                if not ctx.fs.exists(fname):
128                    new_elems.append(elem)
129                    continue
130
131                # Check if the library is generated or not.
132                # The source libs are not under the build dir.
133                build_dir = ctx.fs.canonpath("./")
134                if path.rel(build_dir, fname).startswith("../../"):
135                    new_elems.append(elem)
136                    continue
137
138                ents = ar.entries(ctx, fname, build_dir)
139                if not ents:
140                    new_elems.append(elem)
141                    continue
142
143                new_elems.append("-Clink-arg=-start-lib")
144                new_elems.extend(["-Clink-arg=" + e for e in ents])
145                new_elems.append("-Clink-arg=-end-lib")
146            new_lines.append(" ".join(new_elems))
147        new_rspfile_content = "\n".join(new_lines)
148
149    ctx.actions.fix(inputs = cmd.inputs + inputs, rspfile_content = new_rspfile_content or cmd.rspfile_content)
150
151def __rust_build_handler(ctx, cmd):
152    inputs = []
153    for i, arg in enumerate(cmd.args):
154        if arg == "--src-dir":
155            inputs.append(ctx.fs.canonpath(cmd.args[i + 1]))
156    ctx.actions.fix(inputs = cmd.inputs + inputs)
157
158__handlers = {
159    "rust_link_handler": __rust_link_handler,
160    "rust_build_handler": __rust_build_handler,
161}
162
163def __step_config(ctx, step_config):
164    platform_ref = "large"  # Rust actions run faster on large workers.
165
166    remote = True
167    if runtime.os != "linux":
168        remote = False
169    clang_inputs = [
170        "build/linux/debian_bullseye_amd64-sysroot:rustlink",
171        "third_party/llvm-build/Release+Asserts:rustlink",
172    ]
173    if win_sdk.enabled(ctx):
174        clang_inputs.append(win_sdk.toolchain_dir(ctx) + ":libs")
175
176    rust_toolchain = [
177        # TODO(b/285225184): use precomputed subtree
178        "third_party/rust-toolchain:toolchain",
179    ]
180    rust_inputs = [
181        "build/action_helpers.py",
182        "build/gn_helpers.py",
183        "build/rust/rustc_wrapper.py",
184    ] + rust_toolchain
185    rust_indirect_inputs = {
186        "includes": [
187            "*.h",
188            "*.o",
189            "*.rlib",
190            "*.rs",
191            "*.so",
192        ],
193    }
194    step_config["rules"].extend([
195        {
196            "name": "rust_bin",
197            "action": "(.*_)?rust_bin",
198            "inputs": rust_inputs + clang_inputs,
199            "indirect_inputs": rust_indirect_inputs,
200            "handler": "rust_link_handler",
201            "deps": "none",  # disable gcc scandeps
202            "remote": remote,
203            # "canonicalize_dir": True,  # TODO(b/300352286)
204            "timeout": "2m",
205            "platform_ref": platform_ref,
206        },
207        {
208            "name": "rust_cdylib",
209            "action": "(.*_)?rust_cdylib",
210            "inputs": rust_inputs + clang_inputs,
211            "indirect_inputs": rust_indirect_inputs,
212            "handler": "rust_link_handler",
213            "deps": "none",  # disable gcc scandeps
214            "remote": remote,
215            # "canonicalize_dir": True,  # TODO(b/300352286)
216            "timeout": "2m",
217            "platform_ref": platform_ref,
218        },
219        {
220            "name": "rust_macro",
221            "action": "(.*_)?rust_macro",
222            "inputs": rust_inputs + clang_inputs,
223            "indirect_inputs": rust_indirect_inputs,
224            "handler": "rust_link_handler",
225            "deps": "none",  # disable gcc scandeps
226            # "canonicalize_dir": True,  # TODO(b/300352286)
227            "remote": remote,
228            "timeout": "2m",
229            "platform_ref": platform_ref,
230        },
231        {
232            "name": "rust_rlib",
233            "action": "(.*_)?rust_rlib",
234            "inputs": rust_inputs,
235            "indirect_inputs": rust_indirect_inputs,
236            "deps": "none",  # disable gcc scandeps
237            "remote": remote,
238            # "canonicalize_dir": True,  # TODO(b/300352286)
239            "timeout": "2m",
240            "platform_ref": platform_ref,
241        },
242        {
243            "name": "rust_staticlib",
244            "action": "(.*_)?rust_staticlib",
245            "inputs": rust_inputs,
246            "indirect_inputs": rust_indirect_inputs,
247            "deps": "none",  # disable gcc scandeps
248            "remote": remote,
249            # "canonicalize_dir": True,  # TODO(b/300352286)
250            "timeout": "2m",
251            "platform_ref": platform_ref,
252        },
253        {
254            "name": "rust/run_build_script",
255            "command_prefix": "python3 ../../build/rust/run_build_script.py",
256            "inputs": [
257                "third_party/rust-toolchain:toolchain",
258                "third_party/rust:rustlib",
259            ],
260            "handler": "rust_build_handler",
261            "remote": remote and config.get(ctx, "cog"),
262            "input_root_absolute_path": True,
263            "timeout": "2m",
264        },
265        {
266            "name": "rust/find_std_rlibs",
267            "command_prefix": "python3 ../../build/rust/std/find_std_rlibs.py",
268            "inputs": [
269                "third_party/rust-toolchain:toolchain",
270                "third_party/rust-toolchain/lib/rustlib:rlib",
271            ],
272            "remote": remote and config.get(ctx, "cog"),
273            "input_root_absolute_path": True,
274            "timeout": "2m",
275        },
276        {
277            # rust/bindgen fails remotely when *.d does not exist.
278            # TODO(b/356496947): need to run scandeps?
279            "name": "rust/bindgen",
280            "command_prefix": "python3 ../../build/rust/run_bindgen.py",
281            "inputs": rust_toolchain + clang_inputs,
282            "remote": False,
283            "timeout": "2m",
284        },
285    ])
286    return step_config
287
288rust = module(
289    "rust",
290    filegroups = __filegroups,
291    handlers = __handlers,
292    step_config = __step_config,
293)
294