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 17import os 18import re 19import sys 20import pretty_vcproj 21 22def 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 32def 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 101def 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 117def 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 130def 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 152def 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 167if __name__ == '__main__': 168 sys.exit(main()) 169