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