1*8975f5c5SAndroid Build Coastguard Worker#!/usr/bin/env python3 2*8975f5c5SAndroid Build Coastguard Worker 3*8975f5c5SAndroid Build Coastguard Worker# Copyright 2022 The Chromium Authors 4*8975f5c5SAndroid Build Coastguard Worker# Use of this source code is governed by a BSD-style license that can be 5*8975f5c5SAndroid Build Coastguard Worker# found in the LICENSE file. 6*8975f5c5SAndroid Build Coastguard Worker 7*8975f5c5SAndroid Build Coastguard Workerimport argparse 8*8975f5c5SAndroid Build Coastguard Workerimport contextlib 9*8975f5c5SAndroid Build Coastguard Workerimport os 10*8975f5c5SAndroid Build Coastguard Workerimport subprocess 11*8975f5c5SAndroid Build Coastguard Workerimport sys 12*8975f5c5SAndroid Build Coastguard Worker 13*8975f5c5SAndroid Build Coastguard Worker# Set up path to be able to import action_helpers. 14*8975f5c5SAndroid Build Coastguard Workersys.path.append( 15*8975f5c5SAndroid Build Coastguard Worker os.path.join(os.path.dirname(os.path.abspath(__file__)), os.pardir, 16*8975f5c5SAndroid Build Coastguard Worker os.pardir, 'build')) 17*8975f5c5SAndroid Build Coastguard Workerimport action_helpers 18*8975f5c5SAndroid Build Coastguard Worker 19*8975f5c5SAndroid Build Coastguard Workerfrom filter_clang_args import filter_clang_args 20*8975f5c5SAndroid Build Coastguard Worker 21*8975f5c5SAndroid Build Coastguard Worker 22*8975f5c5SAndroid Build Coastguard Workerdef main(): 23*8975f5c5SAndroid Build Coastguard Worker parser = argparse.ArgumentParser("run_bindgen.py") 24*8975f5c5SAndroid Build Coastguard Worker parser.add_argument("--exe", help="Path to bindgen", required=True), 25*8975f5c5SAndroid Build Coastguard Worker parser.add_argument("--header", 26*8975f5c5SAndroid Build Coastguard Worker help="C header file to generate bindings for", 27*8975f5c5SAndroid Build Coastguard Worker required=True) 28*8975f5c5SAndroid Build Coastguard Worker parser.add_argument("--depfile", 29*8975f5c5SAndroid Build Coastguard Worker help="depfile to output with header dependencies") 30*8975f5c5SAndroid Build Coastguard Worker parser.add_argument("--output", help="output .rs bindings", required=True) 31*8975f5c5SAndroid Build Coastguard Worker parser.add_argument( 32*8975f5c5SAndroid Build Coastguard Worker "--wrap-static-fns", 33*8975f5c5SAndroid Build Coastguard Worker help="output source file for `static` and `static inline` functions") 34*8975f5c5SAndroid Build Coastguard Worker parser.add_argument("--ld-library-path", 35*8975f5c5SAndroid Build Coastguard Worker help="LD_LIBRARY_PATH (or DYLD_LIBRARY_PATH on Mac) to " 36*8975f5c5SAndroid Build Coastguard Worker "set") 37*8975f5c5SAndroid Build Coastguard Worker parser.add_argument("--libclang-path", 38*8975f5c5SAndroid Build Coastguard Worker help="Path to the libclang shared libray.") 39*8975f5c5SAndroid Build Coastguard Worker parser.add_argument("-I", "--include", help="include path", action="append") 40*8975f5c5SAndroid Build Coastguard Worker parser.add_argument("--bindgen-flags", 41*8975f5c5SAndroid Build Coastguard Worker help="flags to pass to bindgen", 42*8975f5c5SAndroid Build Coastguard Worker nargs="*") 43*8975f5c5SAndroid Build Coastguard Worker parser.add_argument( 44*8975f5c5SAndroid Build Coastguard Worker "clangargs", 45*8975f5c5SAndroid Build Coastguard Worker metavar="CLANGARGS", 46*8975f5c5SAndroid Build Coastguard Worker help="arguments to pass to libclang (see " 47*8975f5c5SAndroid Build Coastguard Worker "https://docs.rs/bindgen/latest/bindgen/struct.Builder.html#method.clang_args)", 48*8975f5c5SAndroid Build Coastguard Worker nargs="*") 49*8975f5c5SAndroid Build Coastguard Worker args = parser.parse_args() 50*8975f5c5SAndroid Build Coastguard Worker 51*8975f5c5SAndroid Build Coastguard Worker # Abort if `TARGET` exists in the environment. Cargo sets `TARGET` when 52*8975f5c5SAndroid Build Coastguard Worker # running build scripts and bindgen will try to be helpful by using that value 53*8975f5c5SAndroid Build Coastguard Worker # if it's set. In practice we've seen a case where someone had the value set 54*8975f5c5SAndroid Build Coastguard Worker # in their build environment with no intention of it reaching bindgen, leading 55*8975f5c5SAndroid Build Coastguard Worker # to a hard-to-debug build error. 56*8975f5c5SAndroid Build Coastguard Worker if 'TARGET' in os.environ: 57*8975f5c5SAndroid Build Coastguard Worker sys.exit('ERROR: saw TARGET in environment, remove to avoid bindgen' 58*8975f5c5SAndroid Build Coastguard Worker ' failures') 59*8975f5c5SAndroid Build Coastguard Worker 60*8975f5c5SAndroid Build Coastguard Worker with contextlib.ExitStack() as stack: 61*8975f5c5SAndroid Build Coastguard Worker # Args passed to the actual bindgen cli 62*8975f5c5SAndroid Build Coastguard Worker genargs = [] 63*8975f5c5SAndroid Build Coastguard Worker genargs.append('--no-layout-tests') 64*8975f5c5SAndroid Build Coastguard Worker if args.bindgen_flags is not None: 65*8975f5c5SAndroid Build Coastguard Worker for flag in args.bindgen_flags: 66*8975f5c5SAndroid Build Coastguard Worker genargs.append("--" + flag) 67*8975f5c5SAndroid Build Coastguard Worker 68*8975f5c5SAndroid Build Coastguard Worker # TODO(danakj): We need to point bindgen to 69*8975f5c5SAndroid Build Coastguard Worker # //third_party/rust-toolchain/bin/rustfmt. 70*8975f5c5SAndroid Build Coastguard Worker genargs.append('--no-rustfmt-bindings') 71*8975f5c5SAndroid Build Coastguard Worker genargs += ['--rust-target', 'nightly'] 72*8975f5c5SAndroid Build Coastguard Worker 73*8975f5c5SAndroid Build Coastguard Worker if args.depfile: 74*8975f5c5SAndroid Build Coastguard Worker depfile = stack.enter_context(action_helpers.atomic_output(args.depfile)) 75*8975f5c5SAndroid Build Coastguard Worker genargs.append('--depfile') 76*8975f5c5SAndroid Build Coastguard Worker genargs.append(depfile.name) 77*8975f5c5SAndroid Build Coastguard Worker # Ideally we would use action_helpers.atomic_output for the output file, but 78*8975f5c5SAndroid Build Coastguard Worker # this would put the wrong name in the depfile. 79*8975f5c5SAndroid Build Coastguard Worker genargs.append('--output') 80*8975f5c5SAndroid Build Coastguard Worker genargs.append(args.output) 81*8975f5c5SAndroid Build Coastguard Worker 82*8975f5c5SAndroid Build Coastguard Worker # The GN rules know what path to find the system headers in, and we want to 83*8975f5c5SAndroid Build Coastguard Worker # use the headers we specify, instead of non-hermetic headers from elsewhere 84*8975f5c5SAndroid Build Coastguard Worker # in the system. 85*8975f5c5SAndroid Build Coastguard Worker genargs.append('--no-include-path-detection') 86*8975f5c5SAndroid Build Coastguard Worker 87*8975f5c5SAndroid Build Coastguard Worker if args.wrap_static_fns: 88*8975f5c5SAndroid Build Coastguard Worker wrap_static_fns = stack.enter_context( 89*8975f5c5SAndroid Build Coastguard Worker action_helpers.atomic_output(args.wrap_static_fns)) 90*8975f5c5SAndroid Build Coastguard Worker genargs.append('--experimental') 91*8975f5c5SAndroid Build Coastguard Worker genargs.append('--wrap-static-fns') 92*8975f5c5SAndroid Build Coastguard Worker genargs.append('--wrap-static-fns-path') 93*8975f5c5SAndroid Build Coastguard Worker genargs.append(wrap_static_fns.name) 94*8975f5c5SAndroid Build Coastguard Worker genargs.append(args.header) 95*8975f5c5SAndroid Build Coastguard Worker genargs.append('--') 96*8975f5c5SAndroid Build Coastguard Worker genargs.extend(filter_clang_args(args.clangargs)) 97*8975f5c5SAndroid Build Coastguard Worker env = os.environ 98*8975f5c5SAndroid Build Coastguard Worker if args.ld_library_path: 99*8975f5c5SAndroid Build Coastguard Worker if sys.platform == 'darwin': 100*8975f5c5SAndroid Build Coastguard Worker env["DYLD_LIBRARY_PATH"] = args.ld_library_path 101*8975f5c5SAndroid Build Coastguard Worker else: 102*8975f5c5SAndroid Build Coastguard Worker env["LD_LIBRARY_PATH"] = args.ld_library_path 103*8975f5c5SAndroid Build Coastguard Worker if args.libclang_path: 104*8975f5c5SAndroid Build Coastguard Worker env["LIBCLANG_PATH"] = args.libclang_path 105*8975f5c5SAndroid Build Coastguard Worker try: 106*8975f5c5SAndroid Build Coastguard Worker subprocess.check_call([args.exe, *genargs], env=env) 107*8975f5c5SAndroid Build Coastguard Worker except: 108*8975f5c5SAndroid Build Coastguard Worker # Make sure we don't emit anything if bindgen failed. The other files use 109*8975f5c5SAndroid Build Coastguard Worker # action_helpers for this. 110*8975f5c5SAndroid Build Coastguard Worker try: 111*8975f5c5SAndroid Build Coastguard Worker os.remove(args.output) 112*8975f5c5SAndroid Build Coastguard Worker except FileNotFoundError: 113*8975f5c5SAndroid Build Coastguard Worker pass 114*8975f5c5SAndroid Build Coastguard Worker raise 115*8975f5c5SAndroid Build Coastguard Worker 116*8975f5c5SAndroid Build Coastguard Worker 117*8975f5c5SAndroid Build Coastguard Workerif __name__ == '__main__': 118*8975f5c5SAndroid Build Coastguard Worker main() 119