tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

run_rs_bindings_from_cc.py (5052B)


      1 #!/usr/bin/env python3
      2 
      3 # Copyright 2022 The Chromium Authors
      4 # Use of this source code is governed by a BSD-style license that can be
      5 # found in the LICENSE file.
      6 
      7 import argparse
      8 import json
      9 import os
     10 import subprocess
     11 import sys
     12 
     13 THIS_DIR = os.path.dirname(os.path.abspath(__file__))
     14 CHROMIUM_SRC_DIR = os.path.relpath(os.path.join(THIS_DIR, os.pardir, os.pardir))
     15 sys.path.append(THIS_DIR)
     16 from run_bindgen import filter_clang_args
     17 
     18 RUST_TOOLCHAIN_DIR = os.path.join(CHROMIUM_SRC_DIR, "third_party",
     19                                  "rust-toolchain")
     20 RUSTFMT_EXE_PATH = os.path.join(RUST_TOOLCHAIN_DIR, "bin", "rustfmt")
     21 RUSTFMT_CONFIG_PATH = os.path.join(CHROMIUM_SRC_DIR, ".rustfmt.toml")
     22 RS_BINDINGS_FROM_CC_EXE_PATH = os.path.join(RUST_TOOLCHAIN_DIR, "bin",
     23                                            "rs_bindings_from_cc")
     24 
     25 
     26 def format_cmdline(args):
     27  def quote_arg(x):
     28    if ' ' not in x: return x
     29    x = x.replace('"', '\\"')
     30    return f"\"{x}\""
     31 
     32  return " ".join([quote_arg(x) for x in args])
     33 
     34 
     35 def main():
     36  parser = argparse.ArgumentParser()
     37  parser.add_argument("--targets_and_args_from_gn",
     38                      metavar="FILE",
     39                      help="File parsed into --targets_and_args Crubit arg",
     40                      required=True),
     41  parser.add_argument("--public_headers",
     42                      metavar="FILE",
     43                      help="Passed through to Crubit",
     44                      required=True),
     45  parser.add_argument("--rs_out",
     46                      metavar="FILE",
     47                      help="Passed through to Crubit",
     48                      required=True),
     49  parser.add_argument("--cc_out",
     50                      metavar="FILE",
     51                      help="Passed through to Crubit",
     52                      required=True),
     53  parser.add_argument("clang_args",
     54                      metavar="CLANGARGS",
     55                      help="Arguments to forward to clang libraries",
     56                      nargs=argparse.REMAINDER)
     57  args = parser.parse_args()
     58 
     59  # Output paths
     60  generator_args = []
     61  generator_args.append("--rs_out={0}".format(os.path.relpath(args.rs_out)))
     62  generator_args.append("--cc_out={0}".format(os.path.relpath(args.cc_out)))
     63  if "CRUBIT_DEBUG" in os.environ:
     64    generator_args.append("--ir_out={0}".format(
     65        os.path.relpath(args.rs_out).replace(".rs", ".ir")))
     66 
     67  # Public headers.
     68  generator_args.append("--public_headers={0}".format(",".join(
     69      [os.path.relpath(hdr) for hdr in args.public_headers.split(",")])))
     70 
     71  # Targets to headers map.
     72  with open(args.targets_and_args_from_gn, "r") as f:
     73    targets_and_args = json.load(f)
     74  for entry in targets_and_args:
     75    entry["f"] = ["supported"]
     76    hdrs = entry["h"]
     77    for i in range(len(hdrs)):
     78      hdrs[i] = os.path.relpath(hdrs[i])
     79  generator_args.append("--targets_and_args={0}".format(
     80      json.dumps(targets_and_args)))
     81 
     82  # All Crubit invocations in Chromium share the following cmdline args.
     83  generator_args.append(f"--rustfmt_exe_path={RUSTFMT_EXE_PATH}")
     84  generator_args.append(f"--rustfmt_config_path={RUSTFMT_CONFIG_PATH}")
     85  generator_args.append(
     86      "--crubit_support_path=third_party/crubit/src/rs_bindings_from_cc/support"
     87  )
     88 
     89  # Long cmdlines may not work - work around that by using Abseil's `--flagfile`
     90  # https://abseil.io/docs/python/guides/flags#a-note-about---flagfile
     91  #
     92  # Note that `clang_args` are not written to the flag file, because Abseil's
     93  # flag parsing code is only aware of `ABSL_FLAG`-declared flags and doesn't
     94  # know about Clang args (e.g. `-W...` or `-I...`).
     95  params_file_path = os.path.relpath(args.rs_out).replace(".rs", ".params")
     96  with open(params_file_path, "w") as f:
     97    for line in generator_args:
     98      print(line, file=f)
     99 
    100  # Clang arguments.
    101  #
    102  # The call to `filter_clang_args` is needed to avoid the following error:
    103  # error: unable to find plugin 'find-bad-constructs'
    104  clang_args = []
    105  clang_args.extend(filter_clang_args(args.clang_args))
    106  # TODO(crbug.com/40226863): This warning needs to be suppressed, because
    107  # otherwise Crubit/Clang complains as follows:
    108  #     error: .../third_party/rust-toolchain/bin/rs_bindings_from_cc:
    109  #     'linker' input unused [-Werror,-Wunused-command-line-argument]
    110  # Maybe `build/rust/rs_bindings_from_cc.gni` gives too much in `args`?  But
    111  # then `{{cflags}}` seems perfectly reasonable...
    112  clang_args += ["-Wno-unused-command-line-argument"]
    113 
    114  # Print a copy&pastable final cmdline when asked for debugging help.
    115  cmdline = [RS_BINDINGS_FROM_CC_EXE_PATH, f"--flagfile={params_file_path}"]
    116  cmdline.extend(clang_args)
    117  if "CRUBIT_DEBUG" in os.environ:
    118    pretty_cmdline = format_cmdline(cmdline)
    119    print(f"CRUBIT_DEBUG: CMDLINE: {pretty_cmdline}", file=sys.stderr)
    120 
    121  # TODO(crbug.com/40226863): run_bindgen.py removes the outputs when the tool
    122  # fails.  Maybe we need to do something similar here?  OTOH in most failure
    123  # modes Crubit will fail *before* generating its outputs...
    124  return subprocess.run(cmdline).returncode
    125 
    126 
    127 if __name__ == '__main__':
    128  sys.exit(main())