File: WhatModulesVTK.py

package info (click to toggle)
vtk9 9.5.2%2Bdfsg4-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 206,616 kB
  • sloc: cpp: 2,340,827; ansic: 327,116; python: 114,881; yacc: 4,104; java: 3,977; sh: 3,032; xml: 2,771; perl: 2,189; lex: 1,787; javascript: 1,261; makefile: 189; objc: 153; tcl: 59
file content (209 lines) | stat: -rwxr-xr-x 7,849 bytes parent folder | download | duplicates (5)
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
#!/usr/bin/env python3

import re
from collections import defaultdict
from pathlib import Path


def get_program_parameters():
    import argparse
    description = 'Generate a find_package(VTK COMPONENTS ...) that lists all modules referenced by a set of files.'
    epilogue = '''
This uses the VTK source folder to determine the modules and headers.
Then the user files/folders are looked at to find the headers being used.
Finally a find_package() is output with the modules you need for
 inclusion in your CMakeLists.txt file.

Note:
1) If include file(s) are not found when building your application.
    You may need to search the VTK source to find where the file is.
    Then look at contents of vtk.module in that folder and add the
     module name to the find_package statement.
2) If linking fails, it usually means that the needed module has not been
     built, so you may need to add it to your VTK build and rebuild VTK.
3) More modules than strictly necessary may be included.
    '''
    parser = argparse.ArgumentParser(description=description, epilog=epilogue,
                                     formatter_class=argparse.RawDescriptionHelpFormatter)
    parser.add_argument('vtk_path', help='The path to the VTK source tree.')
    parser.add_argument('application', nargs='+', help='Paths to the application files or folders.')
    args = parser.parse_args()
    return args.vtk_path, args.application


def check_paths(vtk_src_dir, application_srcs):
    """
    Check that the paths are valid.

    :param vtk_src_dir: The path to the VTK source.
    :param application_srcs: The user source files to be scanned for modules.
    :return: True if paths, files exist.
    """
    ok = True
    if not Path(vtk_src_dir).is_dir():
        print('The path to your VTK Source folder does not exist.')
        print(Path(vtk_src_dir))
        ok = False
    bad_paths = list()
    for f in application_srcs:
        p = Path(f)
        if not (p.is_dir() or p.is_file()):
            bad_paths.append(p)
    if bad_paths:
        print('These application paths or files do not exist.')
        for p in bad_paths:
            print(p)
            ok = False
    return ok


def find_vtk_modules(vtk_src_dir):
    """
    Build a dict of the VTK Module name, library name(if it exists) and any header files.

    :param vtk_src_dir: The path to the VTK source folder
    :return: Module name, library name and headers.
    """
    vtk_modules = defaultdict(dict)
    modules = [f for f in Path(vtk_src_dir).rglob('vtk.module')]
    # Includes in the module path
    file_patterns = ['vtk*.h', 'vtk*.h.in', 'QVTK*.h', '*QtQuick.h']
    for module in modules:
        content = module.read_text()
        args = content.split('\n')
        #  Assuming NAME is always there.
        if 'NAME' in args:
            name = args[args.index('NAME') + 1].strip()
            if 'LIBRARY_NAME' in args:
                library_name = args[args.index('LIBRARY_NAME') + 1].strip()
            else:
                library_name = None
            headers = list()
            for pattern in file_patterns:
                if pattern == 'vtk*.h.in':
                    # These files will be converted to header files in the build folder of VTK.
                    headers.extend([f.with_suffix('').name for f in module.parent.glob(pattern)])
                else:
                    headers.extend([f.name for f in module.parent.glob(pattern)])
            vtk_modules[name]['library_name'] = library_name
            vtk_modules[name]['headers'] = headers
    return vtk_modules


def build_headers_modules(modules):
    """
    Make a dictionary whose key is the header filename and value is the module.

    :param modules: The modules.
    :return: Headers and their corresponding module.
    """
    # The headers should be unique to a module, however we will not assume this.
    headers_modules = defaultdict(set)
    for k, v in modules.items():
        if 'headers' in v:
            for k1 in v['headers']:
                headers_modules[k1].add(k)
    return headers_modules


def find_application_includes(path):
    """
    Build a set that contains the vtk includes found in the file.

    :param path: The path to the application file.
    :return: The includes that were found.
    """
    includes = set()
    include_hdr1 = re.compile(r'((?:vtk|QVTK).*\.h)')
    include_hdr2 = re.compile(r'(\w+QtQuick\.h)')
    content = path.read_text()
    incs = include_hdr1.findall(content)
    includes.update(incs)
    incs = include_hdr2.findall(content)
    includes.update(incs)
    return includes


def generate_find_package(vtk_src_dir, application_srcs):
    """
    Generate the find_package statement.

    :param vtk_src_dir: The VTK source folder.
    :param application_srcs: A list of application folders and or files.
    :return: The find_package statement.
    """
    vtk_modules = find_vtk_modules(vtk_src_dir)
    # Test to see if VTK source is provided
    if len(vtk_modules) == 0:
        print(vtk_src_dir, 'is not a VTK source directory. It does not contain any vtk.module files.')
        return None
    vtk_headers_modules = build_headers_modules(vtk_modules)

    valid_extensions = ['.h', '.hxx', '.txx', '.cpp', '.cxx', '.cc']

    # Build a set of includes for all command line files
    all_includes = set()
    for app_src in application_srcs:
        p = Path(app_src)
        if p.is_file():
            if p.suffix in valid_extensions:
                all_includes.update(find_application_includes(p))
        elif p.is_dir():
            paths = list()
            for ext in valid_extensions:
                paths.extend([f for f in p.rglob('*' + ext) if f.is_file()])
            for path in paths:
                all_includes.update(find_application_includes(path))
    if len(all_includes) == 0:
        print('No VTK includes found in the application files.')
        return None

    # Build a set that contains all modules referenced in the user files.
    all_modules = set()
    for inc in all_includes:
        if inc in vtk_headers_modules:
            for m in vtk_headers_modules[inc]:
                all_modules.add(m)

    if 'VTK::RenderingCore' in all_modules:
        all_modules.add('VTK::RenderingOpenGL2')
        all_modules.add('VTK::InteractionStyle')
        all_modules.add('VTK::RenderingFreeType')
        all_modules.add('VTK::RenderingGL2PSOpenGL2')
        all_modules.add('VTK::RenderingContextOpenGL2')
    if 'VTK::DomainsChemistry' in all_modules:
        all_modules.add('VTK::DomainsChemistryOpenGL2')
    if 'VTK::RenderingVolume' in all_modules:
        all_modules.add('VTK::RenderingVolumeOpenGL2')
    if 'VTK::RenderingContext2D' in all_modules:
        all_modules.add('VTK::RenderingContextOpenGL2')
    if 'VTK::IOExport' in all_modules:
        all_modules.add('VTK::RenderingContextOpenGL2')
        all_modules.add('VTK::IOExportOpenGL2')
        all_modules.add('VTK::IOExportPDF')
        all_modules.add('VTK::RenderingContextOpenGL2')

    res = ['All modules referenced in your files:', 'find_package(VTK', ' COMPONENTS']
    for m in sorted(all_modules):
        res.append(' ' * 2 + m.replace('VTK::', ''))
    res.append(')')
    res.append(
        'Your application code includes ' + str(len(all_modules)) + ' of ' + str(
            len(vtk_modules)) + ' vtk modules.')
    return res


def main():
    vtk_src_dir, application_srcs = get_program_parameters()
    if not check_paths(vtk_src_dir, application_srcs):
        return

    res = generate_find_package(vtk_src_dir, application_srcs)
    if res:
        print('\n'.join(res))


if __name__ == '__main__':
    print('If you have built VTK and\n modules.json is available in the build folder.')
    print(' Please consider using FindNeededModules.py instead.')
    main()