1#!/usr/bin/python 2# Copyright (C) 2013 Google Inc. All rights reserved. 3# 4# Redistribution and use in source and binary forms, with or without 5# modification, are permitted provided that the following conditions are 6# met: 7# 8# * Redistributions of source code must retain the above copyright 9# notice, this list of conditions and the following disclaimer. 10# * Redistributions in binary form must reproduce the above 11# copyright notice, this list of conditions and the following disclaimer 12# in the documentation and/or other materials provided with the 13# distribution. 14# * Neither the name of Google Inc. nor the names of its 15# contributors may be used to endorse or promote products derived from 16# this software without specific prior written permission. 17# 18# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 30"""Compile an .idl file to Blink V8 bindings (.h and .cpp files). 31 32FIXME: Not currently used in build. 33This is a rewrite of the Perl IDL compiler in Python, but is not complete. 34Once it is complete, we will switch all IDL files over to Python at once. 35Until then, please work on the Perl IDL compiler. 36For details, see bug http://crbug.com/239771 37""" 38 39import optparse 40import os 41import pickle 42import posixpath 43import shlex 44import sys 45 46import code_generator_v8 47import idl_reader 48 49module_path, _ = os.path.split(__file__) 50source_path = os.path.normpath(os.path.join(module_path, os.pardir, os.pardir, os.pardir)) 51 52 53def parse_options(): 54 parser = optparse.OptionParser() 55 parser.add_option('--additional-idl-files') 56 # FIXME: The --dump-json-and-pickle option is only for debugging and will 57 # be removed once we complete migrating all IDL files from the Perl flow to 58 # the Python flow. 59 parser.add_option('--dump-json-and-pickle', action='store_true', default=False) 60 parser.add_option('--idl-attributes-file') 61 parser.add_option('--include', dest='idl_directories', action='append') 62 parser.add_option('--output-directory') 63 parser.add_option('--interface-dependencies-file') 64 parser.add_option('--verbose', action='store_true', default=False) 65 parser.add_option('--write-file-only-if-changed', type='int') 66 # ensure output comes last, so command line easy to parse via regexes 67 parser.disable_interspersed_args() 68 69 options, args = parser.parse_args() 70 if options.output_directory is None: 71 parser.error('Must specify output directory using --output-directory.') 72 if options.additional_idl_files is None: 73 options.additional_idl_files = [] 74 else: 75 # additional_idl_files is passed as a string with varied (shell-style) 76 # quoting, hence needs parsing. 77 options.additional_idl_files = shlex.split(options.additional_idl_files) 78 if len(args) != 1: 79 parser.error('Must specify exactly 1 input file as argument, but %d given.' % len(args)) 80 options.idl_filename = os.path.realpath(args[0]) 81 return options 82 83 84def get_relative_dir_posix(filename): 85 """Returns directory of a local file relative to Source, in POSIX format.""" 86 relative_path_local = os.path.relpath(filename, source_path) 87 relative_dir_local = os.path.dirname(relative_path_local) 88 return relative_dir_local.replace(os.path.sep, posixpath.sep) 89 90 91def write_json_and_pickle(definitions, interface_name, output_directory): 92 json_string = definitions.to_json() 93 json_basename = interface_name + '.json' 94 json_filename = os.path.join(output_directory, json_basename) 95 with open(json_filename, 'w') as json_file: 96 json_file.write(json_string) 97 pickle_basename = interface_name + '.pkl' 98 pickle_filename = os.path.join(output_directory, pickle_basename) 99 with open(pickle_filename, 'wb') as pickle_file: 100 pickle.dump(definitions, pickle_file) 101 102 103def main(): 104 options = parse_options() 105 idl_filename = options.idl_filename 106 basename = os.path.basename(idl_filename) 107 interface_name, _ = os.path.splitext(basename) 108 output_directory = options.output_directory 109 verbose = options.verbose 110 if verbose: 111 print idl_filename 112 relative_dir_posix = get_relative_dir_posix(idl_filename) 113 114 reader = idl_reader.IdlReader(options.interface_dependencies_file, options.additional_idl_files, options.idl_attributes_file, output_directory, verbose) 115 definitions = reader.read_idl_definitions(idl_filename) 116 code_generator = code_generator_v8.CodeGeneratorV8(definitions, interface_name, options.output_directory, relative_dir_posix, options.idl_directories, verbose) 117 if not definitions: 118 # We generate dummy .h and .cpp files just to tell build scripts 119 # that outputs have been created. 120 code_generator.write_dummy_header_and_cpp() 121 return 122 if options.dump_json_and_pickle: 123 write_json_and_pickle(definitions, interface_name, output_directory) 124 return 125 code_generator.write_header_and_cpp() 126 127 128if __name__ == '__main__': 129 sys.exit(main()) 130