Home | History | Annotate | Download | only in scripts
      1 #!/usr/bin/python
      2 #
      3 # Copyright (C) 2009 Google Inc. All rights reserved.
      4 #
      5 # Redistribution and use in source and binary forms, with or without
      6 # modification, are permitted provided that the following conditions are
      7 # met:
      8 #
      9 #     * Redistributions of source code must retain the above copyright
     10 # notice, this list of conditions and the following disclaimer.
     11 #     * Redistributions in binary form must reproduce the above
     12 # copyright notice, this list of conditions and the following disclaimer
     13 # in the documentation and/or other materials provided with the
     14 # distribution.
     15 #     * Neither the name of Google Inc. nor the names of its
     16 # contributors may be used to endorse or promote products derived from
     17 # this software without specific prior written permission.
     18 #
     19 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     20 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     21 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     22 # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     23 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     24 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     25 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     26 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     27 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     28 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     29 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     30 #
     31 # Copyright (c) 2009 The Chromium Authors. All rights reserved.
     32 # Use of this source code is governed by a BSD-style license that can be
     33 # found in the LICENSE file.
     34 
     35 # action_derivedsourceslist.py generates a single cpp file that includes
     36 # all v8 bindings cpp files generated from idls. Files can be assigned into
     37 # multiple output files, to reduce maximum compilation unit size and allow
     38 # parallel compilation.
     39 #
     40 # usage: action_derivedsourceslist.py IDL_FILES_LIST -- OUTPUT_FILE1 OUTPUT_FILE2 ...
     41 #
     42 # Note that IDL_FILES_LIST is a text file containing the IDL file paths.
     43 
     44 import errno
     45 import os
     46 import os.path
     47 import re
     48 import subprocess
     49 import sys
     50 
     51 # A regexp for finding Conditional attributes in interface definitions.
     52 conditionalPattern = re.compile('interface[\s]*\[[^\]]*Conditional=([\_0-9a-zA-Z&|]*)')
     53 
     54 copyrightTemplate = """/*
     55  * THIS FILE WAS AUTOMATICALLY GENERATED, DO NOT EDIT.
     56  *
     57  * This file was generated by the make_jni_lists.py script.
     58  *
     59  * Copyright (C) 2009 Google Inc.  All rights reserved.
     60  *
     61  * Redistribution and use in source and binary forms, with or without
     62  * modification, are permitted provided that the following conditions
     63  * are met:
     64  * 1. Redistributions of source code must retain the above copyright
     65  *    notice, this list of conditions and the following disclaimer.
     66  * 2. Redistributions in binary form must reproduce the above copyright
     67  *    notice, this list of conditions and the following disclaimer in the
     68  *    documentation and/or other materials provided with the distribution.
     69  *
     70  * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
     71  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     72  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     73  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
     74  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     75  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     76  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
     77  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
     78  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     79  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     80  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     81  */
     82 """
     83 
     84 
     85 # Wraps conditional with ENABLE() and replace '&','|' with '&&','||' if more than one conditional is specified.
     86 def formatConditional(conditional):
     87     def wrapWithEnable(s):
     88         if re.match('[|&]$', s):
     89             return s * 2
     90         return 'ENABLE(' + s + ')'
     91     return ' '.join(map(wrapWithEnable, conditional))
     92 
     93 
     94 # Find the conditional interface attribute.
     95 def extractConditional(idlFilePath):
     96     conditional = None
     97 
     98     # Read file and look for "interface [ Conditional=XXX ]".
     99     idlFile = open(idlFilePath)
    100     idlContents = idlFile.read().replace('\n', '')
    101     idlFile.close()
    102 
    103     match = conditionalPattern.search(idlContents)
    104     if match:
    105         conditional = match.group(1)
    106         conditional = re.split('([|&])', conditional)
    107 
    108     return conditional
    109 
    110 # Extracts conditional and interface name from each IDL file.
    111 def extractMetaData(filePaths):
    112     metaDataList = []
    113 
    114     for f in filePaths:
    115         metaData = {}
    116         if len(f) == 0:
    117             continue
    118         if not os.path.exists(f):
    119             print 'WARNING: file not found: "%s"' % f
    120             continue
    121 
    122         # Extract type name from file name
    123         (parentPath, fileName) = os.path.split(f)
    124         (interfaceName, ext) = os.path.splitext(fileName)
    125 
    126         if not ext == '.idl':
    127             continue
    128 
    129         metaData = {
    130             'conditional': extractConditional(f),
    131             'name': interfaceName,
    132         }
    133 
    134         metaDataList.append(metaData)
    135 
    136     return metaDataList
    137 
    138 
    139 def generateContent(filesMetaData, partition, totalPartitions):
    140     # Sort files by conditionals.
    141     filesMetaData.sort()
    142 
    143     output = []
    144 
    145     # Add fixed content.
    146     output.append(copyrightTemplate)
    147     output.append('#define NO_IMPLICIT_ATOMICSTRING\n\n')
    148 
    149     # List all includes segmented by if and endif.
    150     prevConditional = None
    151     for metaData in filesMetaData:
    152         name = metaData['name']
    153         if (hash(name) % totalPartitions) != partition:
    154             continue
    155         conditional = metaData['conditional']
    156 
    157         if prevConditional and prevConditional != conditional:
    158             output.append('#endif\n')
    159         if conditional and prevConditional != conditional:
    160             output.append('\n#if %s\n' % formatConditional(conditional))
    161 
    162         output.append('#include "bindings/V8%s.cpp"\n' % name)
    163 
    164         prevConditional = conditional
    165 
    166     if prevConditional:
    167         output.append('#endif\n')
    168 
    169     return ''.join(output)
    170 
    171 
    172 def writeContent(content, outputFileName):
    173     (parentPath, fileName) = os.path.split(outputFileName)
    174     if not os.path.exists(parentPath):
    175         print parentPath
    176         os.mkdir(parentPath)
    177     f = open(outputFileName, 'w')
    178     f.write(content)
    179     f.close()
    180 
    181 
    182 def main(args):
    183     assert(len(args) > 3)
    184     inOutBreakIndex = args.index('--')
    185     inputFileName = args[1]
    186     outputFileNames = args[inOutBreakIndex+1:]
    187 
    188     inputFile = open(inputFileName, 'r')
    189     idlFileNames = inputFile.read().split('\n')
    190     inputFile.close()
    191 
    192     filesMetaData = extractMetaData(idlFileNames)
    193     for fileName in outputFileNames:
    194         print 'Generating derived sources list into %s...' % fileName
    195         partition = outputFileNames.index(fileName)
    196         fileContents = generateContent(filesMetaData, partition, len(outputFileNames))
    197         writeContent(fileContents, fileName)
    198 
    199     return 0
    200 
    201 
    202 if __name__ == '__main__':
    203     sys.exit(main(sys.argv))
    204