Home | History | Annotate | Download | only in grit
      1 #!/usr/bin/env python
      2 # Copyright (c) 2012 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 
      6 '''Tool to determine inputs and outputs of a grit file.
      7 '''
      8 
      9 import optparse
     10 import os
     11 import posixpath
     12 import sys
     13 
     14 from grit import grd_reader
     15 from grit import util
     16 
     17 class WrongNumberOfArguments(Exception):
     18   pass
     19 
     20 
     21 def Outputs(filename, defines, ids_file):
     22   grd = grd_reader.Parse(
     23       filename, defines=defines, tags_to_ignore=set(['messages']),
     24       first_ids_file=ids_file)
     25 
     26   target = []
     27   lang_folders = {}
     28   # Add all explicitly-specified output files
     29   for output in grd.GetOutputFiles():
     30     path = output.GetFilename()
     31     target.append(path)
     32 
     33     if path.endswith('.h'):
     34       path, filename = os.path.split(path)
     35     if output.attrs['lang']:
     36       lang_folders[output.attrs['lang']] = os.path.dirname(path)
     37 
     38   # Add all generated files, once for each output language.
     39   for node in grd:
     40     if node.name == 'structure':
     41       with node:
     42         # TODO(joi) Should remove the "if sconsdep is true" thing as it is a
     43         # hack - see grit/node/structure.py
     44         if node.HasFileForLanguage() and node.attrs['sconsdep'] == 'true':
     45           for lang in lang_folders:
     46             path = node.FileForLanguage(lang, lang_folders[lang],
     47                                         create_file=False,
     48                                         return_if_not_generated=False)
     49             if path:
     50               target.append(path)
     51 
     52   return [t.replace('\\', '/') for t in target]
     53 
     54 
     55 def GritSourceFiles():
     56   files = []
     57   grit_root_dir = os.path.relpath(os.path.dirname(__file__), os.getcwd())
     58   for root, dirs, filenames in os.walk(grit_root_dir):
     59     grit_src = [os.path.join(root, f) for f in filenames
     60                 if f.endswith('.py')]
     61     files.extend(grit_src)
     62   return sorted(files)
     63 
     64 
     65 def Inputs(filename, defines, ids_file, target_platform):
     66   grd = grd_reader.Parse(
     67       filename, debug=False, defines=defines, tags_to_ignore=set(['message']),
     68       first_ids_file=ids_file, target_platform=target_platform)
     69   files = set()
     70   for lang, ctx in grd.GetConfigurations():
     71     grd.SetOutputLanguage(lang or grd.GetSourceLanguage())
     72     grd.SetOutputContext(ctx)
     73     for node in grd.ActiveDescendants():
     74       with node:
     75         if (node.name == 'structure' or node.name == 'skeleton' or
     76             (node.name == 'file' and node.parent and
     77              node.parent.name == 'translations')):
     78           files.add(grd.ToRealPath(node.GetInputPath()))
     79           # If it's a flattened node, grab inlined resources too.
     80           if node.name == 'structure' and node.attrs['flattenhtml'] == 'true':
     81             node.RunPreSubstitutionGatherer()
     82             files.update(node.GetHtmlResourceFilenames())
     83         elif node.name == 'grit':
     84           first_ids_file = node.GetFirstIdsFile()
     85           if first_ids_file:
     86             files.add(first_ids_file)
     87         elif node.name == 'include':
     88           files.add(grd.ToRealPath(node.GetInputPath()))
     89           # If it's a flattened node, grab inlined resources too.
     90           if node.attrs['flattenhtml'] == 'true':
     91             files.update(node.GetHtmlResourceFilenames())
     92         elif node.name == 'part':
     93           files.add(util.normpath(os.path.join(os.path.dirname(filename),
     94                                                node.GetInputPath())))
     95 
     96   cwd = os.getcwd()
     97   return [os.path.relpath(f, cwd) for f in sorted(files)]
     98 
     99 
    100 def PrintUsage():
    101   print 'USAGE: ./grit_info.py --inputs [-D foo] [-f resource_ids] <grd-file>'
    102   print ('       ./grit_info.py --outputs [-D foo] [-f resource_ids] ' +
    103       '<out-prefix> <grd-file>')
    104 
    105 
    106 def DoMain(argv):
    107   parser = optparse.OptionParser()
    108   parser.add_option("--inputs", action="store_true", dest="inputs")
    109   parser.add_option("--outputs", action="store_true", dest="outputs")
    110   parser.add_option("-D", action="append", dest="defines", default=[])
    111   # grit build also supports '-E KEY=VALUE', support that to share command
    112   # line flags.
    113   parser.add_option("-E", action="append", dest="build_env", default=[])
    114   parser.add_option("-w", action="append", dest="whitelist_files", default=[])
    115   parser.add_option("-f", dest="ids_file",
    116                     default="GRIT_DIR/../gritsettings/resource_ids")
    117   parser.add_option("-t", dest="target_platform", default=None)
    118 
    119   options, args = parser.parse_args(argv)
    120 
    121   defines = {}
    122   for define in options.defines:
    123     name, val = util.ParseDefine(define)
    124     defines[name] = val
    125 
    126   for env_pair in options.build_env:
    127     (env_name, env_value) = env_pair.split('=', 1)
    128     os.environ[env_name] = env_value
    129 
    130   if options.inputs:
    131     if len(args) > 1:
    132       raise WrongNumberOfArguments("Expected 0 or 1 arguments for --inputs.")
    133 
    134     inputs = []
    135     if len(args) == 1:
    136       filename = args[0]
    137       inputs = Inputs(filename, defines, options.ids_file,
    138                       options.target_platform)
    139 
    140     # Add in the grit source files.  If one of these change, we want to re-run
    141     # grit.
    142     inputs.extend(GritSourceFiles())
    143     inputs = [f.replace('\\', '/') for f in inputs]
    144 
    145     if len(args) == 1:
    146       # Include grd file as second input (works around gyp expecting it).
    147       inputs.insert(1, args[0])
    148     if options.whitelist_files:
    149       inputs.extend(options.whitelist_files)
    150     return '\n'.join(inputs)
    151   elif options.outputs:
    152     if len(args) != 2:
    153       raise WrongNumberOfArguments(
    154           "Expected exactly 2 arguments for --outputs.")
    155 
    156     prefix, filename = args
    157     outputs = [posixpath.join(prefix, f)
    158                for f in Outputs(filename, defines, options.ids_file)]
    159     return '\n'.join(outputs)
    160   else:
    161     raise WrongNumberOfArguments("Expected --inputs or --outputs.")
    162 
    163 
    164 def main(argv):
    165   if sys.version_info < (2, 6):
    166     print "GRIT requires Python 2.6 or later."
    167     return 1
    168 
    169   try:
    170     result = DoMain(argv[1:])
    171   except WrongNumberOfArguments, e:
    172     PrintUsage()
    173     print e
    174     return 1
    175   print result
    176   return 0
    177 
    178 
    179 if __name__ == '__main__':
    180   sys.exit(main(sys.argv))
    181