1#!/usr/bin/env python
2# Copyright 2013 The Chromium 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"""Generator for C++ features from json files.
6
7Usage example:
8  features_compiler.py --destdir gen --root /home/Work/src _permissions.json
9"""
10
11import optparse
12import os
13
14from schema_loader import SchemaLoader
15from features_cc_generator import CCGenerator
16from features_h_generator import HGenerator
17from model import CreateFeature
18
19
20def _GenerateSchema(filename, root, destdir, namespace):
21  """Generates C++ features files from the json file |filename|.
22  """
23  # Load in the feature permissions from the JSON file.
24  schema = os.path.normpath(filename)
25  schema_loader = SchemaLoader(os.path.dirname(os.path.relpath(schema, root)),
26    os.path.dirname(schema))
27  schema_filename = os.path.splitext(schema)[0]
28  feature_defs = schema_loader.LoadSchema(schema)
29
30  # Generate a list of the features defined and a list of their models.
31  feature_list = []
32  for feature_def, feature in feature_defs.iteritems():
33    feature_list.append(CreateFeature(feature_def, feature))
34
35  source_file_dir, _ = os.path.split(schema)
36  relpath = os.path.relpath(os.path.normpath(source_file_dir), root)
37  full_path = os.path.join(relpath, schema)
38
39  generators = [
40      ('%s.cc' % schema_filename, CCGenerator()),
41      ('%s.h' % schema_filename, HGenerator())
42  ]
43
44  # Generate and output the code for all features.
45  output_code = []
46  for filename, generator in generators:
47    code = generator.Generate(feature_list, full_path, namespace).Render()
48    if destdir:
49      with open(os.path.join(destdir, relpath, filename), 'w') as f:
50        f.write(code)
51    output_code += [filename, '', code, '']
52
53  return '\n'.join(output_code)
54
55
56if __name__ == '__main__':
57  parser = optparse.OptionParser(
58      description='Generates a C++ features model from JSON schema',
59      usage='usage: %prog [option]... schema')
60  parser.add_option('-r', '--root', default='.',
61      help='logical include root directory. Path to schema files from '
62           'specified dir will be the include path.')
63  parser.add_option('-d', '--destdir',
64      help='root directory to output generated files.')
65  parser.add_option('-n', '--namespace', default='generated_features',
66      help='C++ namespace for generated files. e.g extensions::api.')
67  (opts, filenames) = parser.parse_args()
68
69  # Only one file is currently specified.
70  if len(filenames) != 1:
71    raise ValueError('One (and only one) file is required (for now).')
72
73  result = _GenerateSchema(filenames[0], opts.root, opts.destdir,
74                           opts.namespace)
75  if not opts.destdir:
76    print result
77