File: run_rs_bindings_from_cc.py

package info (click to toggle)
chromium 138.0.7204.157-1
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 6,071,864 kB
  • sloc: cpp: 34,936,859; ansic: 7,176,967; javascript: 4,110,704; python: 1,419,953; asm: 946,768; xml: 739,967; pascal: 187,324; sh: 89,623; perl: 88,663; objc: 79,944; sql: 50,304; cs: 41,786; fortran: 24,137; makefile: 21,806; php: 13,980; tcl: 13,166; yacc: 8,925; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (128 lines) | stat: -rwxr-xr-x 5,052 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
#!/usr/bin/env python3

# Copyright 2022 The Chromium Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

import argparse
import json
import os
import subprocess
import sys

THIS_DIR = os.path.dirname(os.path.abspath(__file__))
CHROMIUM_SRC_DIR = os.path.relpath(os.path.join(THIS_DIR, os.pardir, os.pardir))
sys.path.append(THIS_DIR)
from run_bindgen import filter_clang_args

RUST_TOOLCHAIN_DIR = os.path.join(CHROMIUM_SRC_DIR, "third_party",
                                  "rust-toolchain")
RUSTFMT_EXE_PATH = os.path.join(RUST_TOOLCHAIN_DIR, "bin", "rustfmt")
RUSTFMT_CONFIG_PATH = os.path.join(CHROMIUM_SRC_DIR, ".rustfmt.toml")
RS_BINDINGS_FROM_CC_EXE_PATH = os.path.join(RUST_TOOLCHAIN_DIR, "bin",
                                            "rs_bindings_from_cc")


def format_cmdline(args):
  def quote_arg(x):
    if ' ' not in x: return x
    x = x.replace('"', '\\"')
    return f"\"{x}\""

  return " ".join([quote_arg(x) for x in args])


def main():
  parser = argparse.ArgumentParser()
  parser.add_argument("--targets_and_args_from_gn",
                      metavar="FILE",
                      help="File parsed into --targets_and_args Crubit arg",
                      required=True),
  parser.add_argument("--public_headers",
                      metavar="FILE",
                      help="Passed through to Crubit",
                      required=True),
  parser.add_argument("--rs_out",
                      metavar="FILE",
                      help="Passed through to Crubit",
                      required=True),
  parser.add_argument("--cc_out",
                      metavar="FILE",
                      help="Passed through to Crubit",
                      required=True),
  parser.add_argument("clang_args",
                      metavar="CLANGARGS",
                      help="Arguments to forward to clang libraries",
                      nargs=argparse.REMAINDER)
  args = parser.parse_args()

  # Output paths
  generator_args = []
  generator_args.append("--rs_out={0}".format(os.path.relpath(args.rs_out)))
  generator_args.append("--cc_out={0}".format(os.path.relpath(args.cc_out)))
  if "CRUBIT_DEBUG" in os.environ:
    generator_args.append("--ir_out={0}".format(
        os.path.relpath(args.rs_out).replace(".rs", ".ir")))

  # Public headers.
  generator_args.append("--public_headers={0}".format(",".join(
      [os.path.relpath(hdr) for hdr in args.public_headers.split(",")])))

  # Targets to headers map.
  with open(args.targets_and_args_from_gn, "r") as f:
    targets_and_args = json.load(f)
  for entry in targets_and_args:
    entry["f"] = ["supported"]
    hdrs = entry["h"]
    for i in range(len(hdrs)):
      hdrs[i] = os.path.relpath(hdrs[i])
  generator_args.append("--targets_and_args={0}".format(
      json.dumps(targets_and_args)))

  # All Crubit invocations in Chromium share the following cmdline args.
  generator_args.append(f"--rustfmt_exe_path={RUSTFMT_EXE_PATH}")
  generator_args.append(f"--rustfmt_config_path={RUSTFMT_CONFIG_PATH}")
  generator_args.append(
      "--crubit_support_path=third_party/crubit/src/rs_bindings_from_cc/support"
  )

  # Long cmdlines may not work - work around that by using Abseil's `--flagfile`
  # https://abseil.io/docs/python/guides/flags#a-note-about---flagfile
  #
  # Note that `clang_args` are not written to the flag file, because Abseil's
  # flag parsing code is only aware of `ABSL_FLAG`-declared flags and doesn't
  # know about Clang args (e.g. `-W...` or `-I...`).
  params_file_path = os.path.relpath(args.rs_out).replace(".rs", ".params")
  with open(params_file_path, "w") as f:
    for line in generator_args:
      print(line, file=f)

  # Clang arguments.
  #
  # The call to `filter_clang_args` is needed to avoid the following error:
  # error: unable to find plugin 'find-bad-constructs'
  clang_args = []
  clang_args.extend(filter_clang_args(args.clang_args))
  # TODO(crbug.com/40226863): This warning needs to be suppressed, because
  # otherwise Crubit/Clang complains as follows:
  #     error: .../third_party/rust-toolchain/bin/rs_bindings_from_cc:
  #     'linker' input unused [-Werror,-Wunused-command-line-argument]
  # Maybe `build/rust/rs_bindings_from_cc.gni` gives too much in `args`?  But
  # then `{{cflags}}` seems perfectly reasonable...
  clang_args += ["-Wno-unused-command-line-argument"]

  # Print a copy&pastable final cmdline when asked for debugging help.
  cmdline = [RS_BINDINGS_FROM_CC_EXE_PATH, f"--flagfile={params_file_path}"]
  cmdline.extend(clang_args)
  if "CRUBIT_DEBUG" in os.environ:
    pretty_cmdline = format_cmdline(cmdline)
    print(f"CRUBIT_DEBUG: CMDLINE: {pretty_cmdline}", file=sys.stderr)

  # TODO(crbug.com/40226863): run_bindgen.py removes the outputs when the tool
  # fails.  Maybe we need to do something similar here?  OTOH in most failure
  # modes Crubit will fail *before* generating its outputs...
  return subprocess.run(cmdline).returncode


if __name__ == '__main__':
  sys.exit(main())