File: WhatModulesVTK.py

package info (click to toggle)
vtk6 6.3.0%2Bdfsg2-8.1
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 118,972 kB
  • sloc: cpp: 1,442,790; ansic: 113,395; python: 72,383; tcl: 46,998; xml: 8,119; yacc: 4,525; java: 4,239; perl: 3,108; lex: 1,694; sh: 1,093; asm: 154; makefile: 68; objc: 17
file content (305 lines) | stat: -rwxr-xr-x 10,401 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
#!/usr/bin/env python
import os, sys
import re

RENDERING_BACKENDS = ['OpenGL', 'OpenGL2']

def displayHelp():
    print """
Usage: WhatModulesVTK.py vtkSourceTree applicationFile|applicationFolder
  Generate a FindPackage(VTK COMPONENTS) that lists all modules
    referenced by a set of files.
  Additionally, two extra find_package( VTK COMPONENTS) lists of modules
  are produced. One is a minimal set and the other chases down all the
  dependencies to produce a maximal set of modules. This is done by
  parsing the module.cmake files.

    For example:
      Running from the VTK source,
        ./Utilities/Maintenance/WhatModulesVTK.py . Filters/Modeling/Testing/Cxx/TestRotationalExtrusion.cxx
      Produces
        Modules and their dependencies:
        find_package(VTK COMPONENTS
          vtkCommonComputationalGeometry
          vtkCommonCore
          vtkCommonDataModel
          vtkCommonExecutionModel
          vtkCommonMath
          vtkCommonMisc
          vtkCommonSystem
          vtkCommonTransforms
          vtkFiltersCore
          vtkFiltersGeneral
          vtkFiltersModeling
          vtkFiltersSources
          vtkImagingCore
          vtkRenderingCore
          vtkRenderingOpenGL
          vtkTestingCore
          vtkTestingRendering
        )
        Your application code includes 17 of 170 vtk modules.

        All modules referenced in the files:
        find_package(VTK COMPONENTS
          vtkCommonCore
          vtkFiltersCore
          vtkFiltersModeling
          vtkFiltersSources
          vtkRenderingCore
          vtkRenderingOpenGL
          vtkTestingCore
          vtkTestingRendering
        )
        Your application code includes 8 of 170 vtk modules.

        Minimal set of modules:
        find_package(VTK COMPONENTS
          vtkCommonCore
          vtkFiltersCore
          vtkFiltersModeling
          vtkRenderingOpenGL
          vtkTestingRendering
        )
        Your application code includes 5 of 170 vtk modules.

"""
    exit(0)

def EndsWithBackendName(moduleName):
    '''
    Return ``True`` if ``moduleName`` ends with any of the RENDERING_BACKENDS.
    '''
    for backend in RENDERING_BACKENDS:
        if moduleName.endswith(backend):
            return True
    return False

def ExcludeModuleName(moduleName, renderingBackend):
   '''
   Return ``True`` if ``moduleName`` should not be considered.
   '''
   return EndsWithBackendName(moduleName) and not moduleName.endswith(renderingBackend)

def IncludesToPaths(path, renderingBackend='OpenGL'):
    '''
    Build a dict that maps include files to paths.
    '''
    includeToPath = dict()
    prog = re.compile(r"(vtk.*\.h)")
    for root, dirs, files in os.walk(path):
        for f in files:
            if prog.match(f):
                includeFile = prog.findall(f)[0]
                parts = root.split("/")
                module = parts[len(parts)-2] + parts[len(parts)-1]
                if ExcludeModuleName(module, renderingBackend):
                    continue
                includeToPath[includeFile] = module
    return includeToPath

def FindModules(path, renderingBackend='OpenGL'):
    '''
    Build a dict that maps paths to modules.
    '''
    pathToModule = dict()
    fileProg = re.compile(r"module.cmake")
    moduleProg = re.compile(r".*module[^(]*\(\s*(\w*)",re.S)
    for root, dirs, files in os.walk(path):
        for f in files:
            if fileProg.match(f):
                fid = open(os.path.join(root, f), "r")
                contents = fid.read()
                m = moduleProg.match(contents)
                if m:
                    moduleName = m.group(1)
                    if ExcludeModuleName(moduleName, renderingBackend):
                        continue
                    parts = root.split("/")
                    pathToModule[parts[len(parts)-2] + parts[len(parts)-1]] = moduleName
                fid.close()
    return pathToModule

def FindIncludes(path):
    '''
    Build a set that contains vtk includes.
    '''
    includes = set()
    includeProg = re.compile(r"(vtk.*\.h)")
    fid = open(path, "r")
    contents = fid.read()
    incs = includeProg.findall(contents)
    includes.update(incs)
    fid.close()
    return includes

def FindModuleFiles(path, renderingBackend='OpenGL'):
    '''
    Get a list of module files in the VTK directory.
    '''
    moduleFiles = [os.path.join(root, name)
                 for root, dirs, files in os.walk(path)
                 for name in files
                 if name == ("module.cmake")
                 and not ExcludeModuleName(name, renderingBackend)]
    return moduleFiles

def ParseModuleFile(fileName, renderingBackend='OpenGL'):
    '''
    Read each module file returning the module name and what
    it depends on or implements.
    '''
    fh = open(fileName, 'rb')
    lines = []
    for line in fh:
        line = line.strip()
        if line.startswith('$'): # Skip CMake variable names
            continue
        if line.startswith('#'):
            continue
        line = line.split('#')[0].strip() # inline comments
        if line == "":
            continue
        line = line.split(')')[0].strip() # closing brace with no space
        if line == "":
            continue
        for l in line.split(" "):
            lines.append(l)
    languages = ['PYTHON', 'TCL', 'JAVA']
    keywords = ['BACKEND', 'COMPILE_DEPENDS', 'DEPENDS', 'EXCLUDE_FROM_ALL',
                'EXCLUDE_FROM_WRAPPING', 'GROUPS', 'IMPLEMENTS', 'KIT',
                'PRIVATE_DEPENDS', 'TEST_DEPENDS'] + \
               map(lambda l: 'EXCLUDE_FROM_%s_WRAPPING' % l, languages)
    moduleName = ""
    depends = []
    implements = []
    state = "START";
    for item in lines:
        if state == "START" and item.startswith("vtk_module("):
            moduleName = item.split("(")[1]
            continue
        if item in keywords:
            state = item
            continue
        if state == 'DEPENDS' and item !=  ')':
            item = item.replace("${VTK_RENDERING_BACKEND}", renderingBackend)
            depends.append(item)
            continue
        if state == 'IMPLEMENTS' and item !=  ')':
            implements.append(item)
            continue
    return [moduleName, depends + implements]

def FindMinimalSetOfModules(modules, moduleDepencencies):
    '''
    Find the minimal set of modules needed.
    '''
    dependencies = set()
    for m in modules:
        dependencies = dependencies | set(moduleDepencencies[m]) # Set union
    return modules - dependencies # Set difference


def FindAllNeededModules(modules, foundModules, moduleDepencencies):
    '''
    Recursively search moduleDependencies finding all modules.
    '''
    if modules != None and len(modules) > 0:
        for m in modules:
            foundModules.add(m)
            foundModules = foundModules | set(moduleDepencencies[m]) # Set union
            foundModules = FindAllNeededModules(moduleDepencencies[m],
                                                foundModules,moduleDepencencies)
    return foundModules

def MakeFindPackage(modules):
    '''
    Make a useful find_package command.
    '''
    # Print a useful cmake command
    res = "find_package(VTK COMPONENTS\n"
    for module in sorted(modules):
        res +=  "  " + module + "\n"
    res +=  ")"
    return res

from pprint import pprint as pp

def main(vtkSourceDir, sourceFiles, renderingBackend='OpenGL'):
    '''
    Start the program
    '''
    # Generate dict's for mapping includes to modules
    includesToPaths = IncludesToPaths(vtkSourceDir + "/", renderingBackend)
    pathsToModules = FindModules(vtkSourceDir + "/", renderingBackend)

    # Test to see if VTK source is provided
    if len(pathsToModules) == 0:
        raise IOError, vtkSourceDir +\
        " is not a VTK source directory. It does not contain any module.cmake files."

    # Parse the module files making a dictionary of each module and its
    # dependencies or what it implements.
    moduleDepencencies = dict()
    moduleFiles = FindModuleFiles(vtkSourceDir + "/", renderingBackend)

    for fname in moduleFiles:
        m = ParseModuleFile(fname, renderingBackend)
        moduleDepencencies[m[0]] = m[1]

    # Build a set of includes for all command line files
    allIncludes = set()
    for f in sourceFiles:
        if os.path.isfile(f):
            allIncludes.update(FindIncludes(f))
        else:
            # We have a folder so look through all the files.
            for path, dirs, files in os.walk(f):
                for fn in files:
                    allIncludes.update(FindIncludes(os.path.join(path,fn)))
    if len(allIncludes) == 0:
        raise IOError, f + " does not exist"

    # Build a set that contains all modules referenced in command line files
    allModules = set()
    for inc in allIncludes:
        if inc in includesToPaths:
            module = includesToPaths[inc]
            if module in pathsToModules:
                allModules.add(pathsToModules[includesToPaths[inc]])

    # Add vtkInteractionStyle if required.
    if "vtkRenderWindowInteractor.h" in allIncludes:
        allModules.add("vtkInteractionStyle")

    # Add OpenGL factory classes if required.
    if "vtkRenderingFreeType" in allModules:
        allModules.add("vtkRenderingFreeTypeFontConfig")
    if "vtkRenderingCore" in allModules:
        allModules.add("vtkRendering%s" % renderingBackend)
    if "vtkRenderingVolume" in allModules:
        allModules.add("vtkRenderingVolume%s" % renderingBackend)

    # Find the minimal set of modules.
    minimalSetOfModules =\
        FindMinimalSetOfModules(allModules, moduleDepencencies)
    # Find all the modules, chasing down all the dependencies.
    allNeededModules =\
        FindAllNeededModules(minimalSetOfModules, set(), moduleDepencencies)

    modules = {'All modules referenced in the files:': allModules,
                'Minimal set of modules:': minimalSetOfModules,
                'Modules and their dependencies:': allNeededModules
              }
    for k, v in modules.iteritems():
        print k
        print MakeFindPackage(v)
        print "Your application code includes " + str(len(v)) +\
              " of " + str(len(pathsToModules)) + " vtk modules.\n"
    print

if __name__ == '__main__':
    if len(sys.argv) != 3:
      displayHelp()
      exit(0)
    main(sys.argv[1], sys.argv[2:])