1#!/usr/bin/env python3 2# Copyright 2018 The Chromium OS Authors. All rights reserved. 3# Use of this source code is governed by a BSD-style license that can be 4# found in the LICENSE file. 5 6"""Generates bindings that are used gpu_renderer. 7 8A sysroot and virglrenderer source checkout is required. The defaults to the 9root directory. 10""" 11 12from __future__ import print_function 13import argparse 14import multiprocessing.pool 15import os 16import subprocess 17import sys 18import tempfile 19 20# Bright green. 21PASS_COLOR = '\033[1;32m' 22# Bright red. 23FAIL_COLOR = '\033[1;31m' 24# Default color. 25END_COLOR = '\033[0m' 26 27verbose = False 28 29def generate_module(module_name, allowlist, blocklist, header, clang_args, 30 lib_name, derive_default): 31 args = [ 32 'bindgen', 33 '--no-layout-tests', 34 '--allowlist-function', allowlist, 35 '--allowlist-var', allowlist, 36 '--allowlist-type', allowlist, 37 '--blocklist-function', blocklist, 38 '--blocklist-item', blocklist, 39 '--blocklist-type', blocklist, 40 '--no-prepend-enum-name', 41 '-o', module_name + '_bindings.rs', 42 ]; 43 44 if lib_name: 45 args.extend(['--raw-line', 46 '#[cfg(feature = \"{}\")]'.format(module_name)]) 47 args.extend(['--raw-line', 48 '#[link(name = "{}")] extern {{}}'.format(lib_name)]) 49 50 if derive_default: 51 args.append('--with-derive-default') 52 53 args.extend([header, '--']) 54 args.extend(clang_args) 55 56 if verbose: 57 print(' '.join(args)) 58 59 if subprocess.Popen(args).wait() == 0: 60 return 'pass' 61 else: 62 return 'bindgen failed' 63 64 65def download_virgl(src, dst, branch): 66 virgl_src = tempfile.TemporaryDirectory(prefix='virglrenderer-src') 67 68 args = ['git', 'clone'] 69 70 if branch: 71 args.extend(['-b', branch]) 72 73 args.extend([src, dst]) 74 75 if verbose: 76 print(' '.join(args)) 77 78 if subprocess.Popen(args).wait() == 0: 79 return True 80 else: 81 82 return False 83 84 85def get_parser(): 86 """Gets the argument parser""" 87 parser = argparse.ArgumentParser(description=__doc__) 88 parser.add_argument('--sysroot', 89 default='/', 90 help='sysroot directory (default=%(default)s)') 91 parser.add_argument('--virglrenderer', 92 help='virglrenderer src dir/repo (default=%(default)s)') 93 parser.add_argument('--virgl_branch', 94 default='master', 95 help='virglrenderer branch name (default=%(default)s)') 96 parser.add_argument('--verbose', '-v', 97 action='store_true', 98 help='enable verbose output (default=%(default)s)') 99 return parser 100 101 102def main(argv): 103 global verbose 104 os.chdir(os.path.dirname(sys.argv[0])) 105 opts = get_parser().parse_args(argv) 106 if opts.verbose: 107 verbose = True 108 109 if opts.virglrenderer: 110 if '://' in opts.virglrenderer: 111 virgl_src_dir_temp = tempfile.TemporaryDirectory(prefix='virglrenderer-src') 112 virgl_src_dir = virgl_src_dir_temp.name 113 if not download_virgl(opts.virglrenderer, virgl_src_dir, opts.virgl_branch): 114 print('failed to clone \'{}\' to \'{}\''.format(virgl_src_dir, 115 opts.virgl_branch)) 116 sys.exit(1) 117 else: 118 virgl_src_dir = opts.virglrenderer 119 120 header = os.path.join(virgl_src_dir, 'src/virglrenderer.h') 121 else: 122 header = os.path.join(opts.sysroot, 'usr/include/virgl/virglrenderer.h') 123 124 clang_args = ['-I', os.path.join(opts.sysroot, 'usr/include'), 125 '-D', 'VIRGL_RENDERER_UNSTABLE_APIS'] 126 127 modules = ( 128 ( 129 'virgl_renderer', 130 '(virgl|VIRGL)_.+', # allowlist 131 '.*(va_list|debug_callback).*', # blocklist 132 header, 133 clang_args, 134 'virglrenderer', 135 True, 136 ), 137 ) 138 139 pool = multiprocessing.pool.Pool(len(modules)) 140 results = pool.starmap(generate_module, modules, 1) 141 142 return_fail = False 143 print('---') 144 print('generate module summary:') 145 for module, result in zip(modules, results): 146 result_color = FAIL_COLOR 147 if result == 'pass': 148 result_color = PASS_COLOR 149 else: 150 return_fail = True 151 152 print('%15s: %s%s%s' % 153 (module[0], result_color, result, END_COLOR)) 154 155 if return_fail: 156 sys.exit(1) 157 158 with open('mod.rs', 'w') as f: 159 print('/* generated by generate.py */', file=f) 160 print('#![allow(dead_code)]', file=f) 161 print('#![allow(non_camel_case_types)]', file=f) 162 print('#![allow(non_snake_case)]', file=f) 163 print('#![allow(non_upper_case_globals)]', file=f) 164 print('pub mod virgl_debug_callback_bindings;', file=f) 165 for module in modules: 166 print('pub mod', module[0] + '_bindings;', file=f) 167 168 169if __name__ == '__main__': 170 sys.exit(main(sys.argv[1:])) 171