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