• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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