Home | History | Annotate | Download | only in tools
      1 #!/usr/bin/env python
      2 
      3 # Copyright (c) 2012 Google Inc. All rights reserved.
      4 # Use of this source code is governed by a BSD-style license that can be
      5 # found in the LICENSE file.
      6 
      7 """Prints the information in a sln file in a diffable way.
      8 
      9    It first outputs each projects in alphabetical order with their
     10    dependencies.
     11 
     12    Then it outputs a possible build order.
     13 """
     14 
     15 __author__ = 'nsylvain (Nicolas Sylvain)'
     16 
     17 import os
     18 import re
     19 import sys
     20 import pretty_vcproj
     21 
     22 def BuildProject(project, built, projects, deps):
     23   # if all dependencies are done, we can build it, otherwise we try to build the
     24   # dependency.
     25   # This is not infinite-recursion proof.
     26   for dep in deps[project]:
     27     if dep not in built:
     28       BuildProject(dep, built, projects, deps)
     29   print project
     30   built.append(project)
     31 
     32 def ParseSolution(solution_file):
     33   # All projects, their clsid and paths.
     34   projects = dict()
     35 
     36   # A list of dependencies associated with a project.
     37   dependencies = dict()
     38 
     39   # Regular expressions that matches the SLN format.
     40   # The first line of a project definition.
     41   begin_project = re.compile(('^Project\("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942'
     42                               '}"\) = "(.*)", "(.*)", "(.*)"$'))
     43   # The last line of a project definition.
     44   end_project = re.compile('^EndProject$')
     45   # The first line of a dependency list.
     46   begin_dep = re.compile('ProjectSection\(ProjectDependencies\) = postProject$')
     47   # The last line of a dependency list.
     48   end_dep = re.compile('EndProjectSection$')
     49   # A line describing a dependency.
     50   dep_line = re.compile(' *({.*}) = ({.*})$')
     51 
     52   in_deps = False
     53   solution = open(solution_file)
     54   for line in solution:
     55     results = begin_project.search(line)
     56     if results:
     57       # Hack to remove icu because the diff is too different.
     58       if results.group(1).find('icu') != -1:
     59         continue
     60       # We remove "_gyp" from the names because it helps to diff them.
     61       current_project = results.group(1).replace('_gyp', '')
     62       projects[current_project] = [results.group(2).replace('_gyp', ''),
     63                                    results.group(3),
     64                                    results.group(2)]
     65       dependencies[current_project] = []
     66       continue
     67 
     68     results = end_project.search(line)
     69     if results:
     70       current_project = None
     71       continue
     72 
     73     results = begin_dep.search(line)
     74     if results:
     75       in_deps = True
     76       continue
     77 
     78     results = end_dep.search(line)
     79     if results:
     80       in_deps = False
     81       continue
     82 
     83     results = dep_line.search(line)
     84     if results and in_deps and current_project:
     85       dependencies[current_project].append(results.group(1))
     86       continue
     87 
     88   # Change all dependencies clsid to name instead.
     89   for project in dependencies:
     90     # For each dependencies in this project
     91     new_dep_array = []
     92     for dep in dependencies[project]:
     93       # Look for the project name matching this cldis
     94       for project_info in projects:
     95         if projects[project_info][1] == dep:
     96           new_dep_array.append(project_info)
     97     dependencies[project] = sorted(new_dep_array)
     98 
     99   return (projects, dependencies)
    100 
    101 def PrintDependencies(projects, deps):
    102   print "---------------------------------------"
    103   print "Dependencies for all projects"
    104   print "---------------------------------------"
    105   print "--                                   --"
    106 
    107   for (project, dep_list) in sorted(deps.items()):
    108     print "Project : %s" % project
    109     print "Path : %s" % projects[project][0]
    110     if dep_list:
    111       for dep in dep_list:
    112         print "  - %s" % dep
    113     print ""
    114 
    115   print "--                                   --"
    116 
    117 def PrintBuildOrder(projects, deps):
    118   print "---------------------------------------"
    119   print "Build order                            "
    120   print "---------------------------------------"
    121   print "--                                   --"
    122 
    123   built = []
    124   for (project, _) in sorted(deps.items()):
    125     if project not in built:
    126       BuildProject(project, built, projects, deps)
    127 
    128   print "--                                   --"
    129 
    130 def PrintVCProj(projects):
    131 
    132   for project in projects:
    133     print "-------------------------------------"
    134     print "-------------------------------------"
    135     print project
    136     print project
    137     print project
    138     print "-------------------------------------"
    139     print "-------------------------------------"
    140 
    141     project_path = os.path.abspath(os.path.join(os.path.dirname(sys.argv[1]),
    142                                                 projects[project][2]))
    143 
    144     pretty = pretty_vcproj
    145     argv = [ '',
    146              project_path,
    147              '$(SolutionDir)=%s\\' % os.path.dirname(sys.argv[1]),
    148            ]
    149     argv.extend(sys.argv[3:])
    150     pretty.main(argv)
    151 
    152 def main():
    153   # check if we have exactly 1 parameter.
    154   if len(sys.argv) < 2:
    155     print 'Usage: %s "c:\\path\\to\\project.sln"' % sys.argv[0]
    156     return 1
    157 
    158   (projects, deps) = ParseSolution(sys.argv[1])
    159   PrintDependencies(projects, deps)
    160   PrintBuildOrder(projects, deps)
    161 
    162   if '--recursive' in sys.argv:
    163     PrintVCProj(projects)
    164   return 0
    165 
    166 
    167 if __name__ == '__main__':
    168   sys.exit(main())
    169