• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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