~christof-mroz/hipl/hipfw-performance

3486.1.23 by Tim Just
Applied modularization concept on tiny branch.
1
#!/usr/bin/python
3486.1.195 by Tim Just
Added command line arguments and main function to process_modules.py
2
import getopt, glob, os, sys, xml.dom.minidom
3
3486.1.23 by Tim Just
Applied modularization concept on tiny branch.
4
### Constants ###
5
APPLICATION_TAG_NAME  = 'application'
6
APPLICATION_ATTR_NAME = 'name'
7
APPLICATION_PATH_NAME = 'path'
8
9
MODULES_DIR      = 'modules'
10
MODULE_INFO_FILE = 'module_info.xml'
11
12
HEADER_FILE_DIR    = MODULES_DIR
13
HEADER_FILE_SUFFIX = '_modules.h'
14
3486.1.275 by Tim Just
Improved dependency check on daemon startup.
15
WARNING_STRING = 'WARNING This file was generated by ' + __file__ + ' - '
16
WARNING_STRING += 'DO NOT EDIT!'
3486.1.23 by Tim Just
Applied modularization concept on tiny branch.
17
18
# Parses the XML document at 'path' and returns a dictionary with module info
3486.1.275 by Tim Just
Improved dependency check on daemon startup.
19
def parse_xml_info(path):
3486.1.195 by Tim Just
Added command line arguments and main function to process_modules.py
20
3486.1.23 by Tim Just
Applied modularization concept on tiny branch.
21
    file = open(path, "r")
22
    dom = xml.dom.minidom.parse(file)
23
    file.close()
3486.1.195 by Tim Just
Added command line arguments and main function to process_modules.py
24
3486.1.23 by Tim Just
Applied modularization concept on tiny branch.
25
    module_info = {}
3486.1.195 by Tim Just
Added command line arguments and main function to process_modules.py
26
3486.1.23 by Tim Just
Applied modularization concept on tiny branch.
27
    module_name = str(dom.getElementsByTagName('module')[0].attributes['name'].value)
28
    module_info['version'] = str(dom.getElementsByTagName('module')[0].attributes['version'].value)
3486.1.195 by Tim Just
Added command line arguments and main function to process_modules.py
29
3486.1.23 by Tim Just
Applied modularization concept on tiny branch.
30
    module_info['requires'] = []
31
    if 0 < len(dom.getElementsByTagName('requires')):
32
        for node in dom.getElementsByTagName('requires')[0].getElementsByTagName('module'):
33
            current_req = {}
34
            current_req['name'] = str(node.attributes['name'].value)
35
            if 'minversion' in node.attributes.keys():
36
                current_req['minversion'] = str(node.attributes['minversion'].value)
37
            if 'maxversion' in node.attributes.keys():
38
                current_req['maxversion'] = str(node.attributes['maxversion'].value)
3486.1.195 by Tim Just
Added command line arguments and main function to process_modules.py
39
3486.1.23 by Tim Just
Applied modularization concept on tiny branch.
40
            module_info['requires'].append(current_req)
3486.1.195 by Tim Just
Added command line arguments and main function to process_modules.py
41
3486.1.23 by Tim Just
Applied modularization concept on tiny branch.
42
    module_info['conflicts'] = []
43
    if 0 < len(dom.getElementsByTagName('conflicts')):
44
        for node in dom.getElementsByTagName('conflicts')[0].getElementsByTagName('module'):
45
            current_con = {}
46
            current_con['name'] = str(node.attributes['name'].value)
47
            if 'minversion' in node.attributes.keys():
48
                current_con['minversion'] = str(node.attributes['minversion'].value)
49
            if 'maxversion' in node.attributes.keys():
50
                current_con['maxversion'] = str(node.attributes['maxversion'].value)
3486.1.195 by Tim Just
Added command line arguments and main function to process_modules.py
51
3486.1.23 by Tim Just
Applied modularization concept on tiny branch.
52
            module_info['conflicts'].append(current_con)
3486.1.195 by Tim Just
Added command line arguments and main function to process_modules.py
53
3486.1.23 by Tim Just
Applied modularization concept on tiny branch.
54
    module_info['application'] = {}
55
    if 0 == len(dom.getElementsByTagName('application')):
56
        print '|\n|    WARNING in configuration of ' + module_name + ':',
57
        print 'no application tag found'
58
        print '|    Please check configuration file'
59
        raise Error()
3486.1.195 by Tim Just
Added command line arguments and main function to process_modules.py
60
3486.1.23 by Tim Just
Applied modularization concept on tiny branch.
61
    for current_app in dom.getElementsByTagName('application'):
62
        app_info = {}
63
        name = str(current_app.attributes['name'].value)
64
        app_info['header_file'] = str(current_app.attributes['header_file'].value)
65
        app_info['init_function'] = str(current_app.attributes['init_function'].value)
66
        module_info['application'][name] = app_info
3486.1.195 by Tim Just
Added command line arguments and main function to process_modules.py
67
3486.1.275 by Tim Just
Improved dependency check on daemon startup.
68
    return (module_name, module_info)
3486.1.195 by Tim Just
Added command line arguments and main function to process_modules.py
69
70
# Tries to read the XML configuration files for all sub-folders in the given
3486.1.23 by Tim Just
Applied modularization concept on tiny branch.
71
# directory and returns a dictionary containing the module information
3486.1.254 by Tim Just
Removed project_info.xml and added some missing files to EXTRA_DIST.
72
def read_module_info(MODULES_DIR, disabled_modules):
3486.1.195 by Tim Just
Added command line arguments and main function to process_modules.py
73
3486.1.23 by Tim Just
Applied modularization concept on tiny branch.
74
    # Initialize output variable
75
    module_info = {}
3486.1.195 by Tim Just
Added command line arguments and main function to process_modules.py
76
3486.1.23 by Tim Just
Applied modularization concept on tiny branch.
77
    # Iterate through all sub directories in MODULES_DIR
78
    for current_module in glob.glob(MODULES_DIR + '/*/'):
79
        cont = False
3486.1.254 by Tim Just
Removed project_info.xml and added some missing files to EXTRA_DIST.
80
        print '|    found module: ' + current_module
3486.1.23 by Tim Just
Applied modularization concept on tiny branch.
81
        # Check if current_module is disabled
82
        for disabled in disabled_modules:
83
            if current_module == os.path.join(MODULES_DIR, disabled) + '/':
84
                cont = True
3486.1.206 by Tim Just
Improved ouput of process_modules.
85
                print '|    state:        ' + 'DISABLED'
3486.1.254 by Tim Just
Removed project_info.xml and added some missing files to EXTRA_DIST.
86
                print '|    (ignoring this directory)\n|'
3486.1.23 by Tim Just
Applied modularization concept on tiny branch.
87
        if True == cont:
88
            continue
3486.1.195 by Tim Just
Added command line arguments and main function to process_modules.py
89
3486.1.23 by Tim Just
Applied modularization concept on tiny branch.
90
        try:
91
            path = os.path.join(current_module, MODULE_INFO_FILE)
3486.1.275 by Tim Just
Improved dependency check on daemon startup.
92
            (module_name, info) = parse_xml_info(path)
3486.1.206 by Tim Just
Improved ouput of process_modules.
93
            print '|    state:        ' + 'ENABLED'
94
            print '|    version:      ' + info['version'] + '\n|'
3486.1.254 by Tim Just
Removed project_info.xml and added some missing files to EXTRA_DIST.
95
            module_info[module_name] = info
3486.1.23 by Tim Just
Applied modularization concept on tiny branch.
96
        except:
97
            print '|\n|    WARNING parsing of module info file',
98
            print '\'' + path + '\' failed!'
99
            print '|    ...ignoring this directory\n|'
3486.1.195 by Tim Just
Added command line arguments and main function to process_modules.py
100
3486.1.275 by Tim Just
Improved dependency check on daemon startup.
101
    return (module_info)
3486.1.23 by Tim Just
Applied modularization concept on tiny branch.
102
103
# Checks the module_info data structure for missing dependencies and conflicts
3486.1.195 by Tim Just
Added command line arguments and main function to process_modules.py
104
# between modules. Returns a
3486.1.275 by Tim Just
Improved dependency check on daemon startup.
105
def check_dependencies(module_info):
3486.1.195 by Tim Just
Added command line arguments and main function to process_modules.py
106
3486.1.23 by Tim Just
Applied modularization concept on tiny branch.
107
    for current_module in module_info.keys():
108
        # Check for dependencies
109
        for require in module_info[current_module]['requires']:
110
            if False == (require['name'] in module_info.keys()):
111
                print '|\n|    ERROR ' + current_module,
112
                print 'requires module ' + require['name']
113
                sys.exit('|    ...abort current run. Please check module configuration\n|')
114
            else:
115
                req_version = module_info[require['name']]['version']
3486.1.195 by Tim Just
Added command line arguments and main function to process_modules.py
116
3486.1.23 by Tim Just
Applied modularization concept on tiny branch.
117
                if require.has_key('minversion') and req_version < require['minversion']:
118
                    print '|\n|    ERROR ' + current_module + ' requires module',
119
                    print require['name'] + ' at least in version ' + require['minversion']
120
                    sys.exit('|    ...abort current run. Please check module configuration\n|')
121
                if require.has_key('maxversion') and req_version > require['maxversion']:
122
                    print '|\n|    ERROR ' + current_module + ' requires module',
123
                    print require['name'] + ' at most in version ' + require['maxversion']
124
                    sys.exit('|    ...abort current run. Please check module configuration\n|')
3486.1.195 by Tim Just
Added command line arguments and main function to process_modules.py
125
3486.1.23 by Tim Just
Applied modularization concept on tiny branch.
126
        # Check for conflicts
127
        for conflict in module_info[current_module]['conflicts']:
128
            if conflict['name'] in module_info.keys():
129
                con_version = module_info[conflict['name']]['version']
3486.1.195 by Tim Just
Added command line arguments and main function to process_modules.py
130
131
                if False == ((conflict.has_key('minversion') and
132
                              con_version < conflict['minversion']) or
133
                             (conflict.has_key('maxversion') and
3486.1.23 by Tim Just
Applied modularization concept on tiny branch.
134
                              con_version > conflict['maxversion'])):
135
                    print '|    ERROR ' + current_module + ' conflicts with module ' + conflict['name'] + ' (version ' + con_version + ')'
136
                    sys.exit('|    ...abort current run. Please check module configuration\n|')
137
138
# Creates a C header file with the given filename an the needed includes,
139
# the number of init functions per application and an array of function
140
# pointers for each application
3486.1.275 by Tim Just
Improved dependency check on daemon startup.
141
def create_header_files(applications, module_info):
3486.1.195 by Tim Just
Added command line arguments and main function to process_modules.py
142
3486.1.275 by Tim Just
Improved dependency check on daemon startup.
143
    if False == os.path.isdir(HEADER_FILE_DIR):
144
        os.mkdir(HEADER_FILE_DIR)
3486.1.198 by Tim Just
Fixed bug in process_modules.py
145
3486.1.254 by Tim Just
Removed project_info.xml and added some missing files to EXTRA_DIST.
146
    for current_app in applications:
3486.1.195 by Tim Just
Added command line arguments and main function to process_modules.py
147
3486.1.275 by Tim Just
Improved dependency check on daemon startup.
148
        hdr_file_path = os.path.join(HEADER_FILE_DIR,
149
                                     current_app + HEADER_FILE_SUFFIX)
3486.1.202 by Tim Just
process_modules.py now returns errors and these are handled by configure.
150
151
        try:
152
            hdr_file = open(hdr_file_path, 'w')
153
            try:
3486.1.259 by Tim Just
Added warning to files generated by process_modules.py.
154
                app_string = 'HIP_MODULES_' + current_app.upper() + '_MODULES_H'
155
                hdr_file.write('/* ' + WARNING_STRING + ' */\n')
3486.1.202 by Tim Just
process_modules.py now returns errors and these are handled by configure.
156
                hdr_file.write('#ifndef ' + app_string + '\n')
157
                hdr_file.write('#define ' + app_string + '\n')
158
3486.1.275 by Tim Just
Improved dependency check on daemon startup.
159
                info_string  = 'struct module_info ' + current_app
160
                info_string += '_modules[] = {'
161
                first_loop           = True
162
                num_spaces           = len(info_string)
163
                num_modules          = 0
164
                max_required_modules = 0
165
166
                for current_module in module_info:
167
                    if module_info[current_module]['application'].has_key(current_app):
168
                        app_info = module_info[current_module]['application'][current_app]
169
                        num_modules += 1
170
                        hdr_file.write('\n#include \"' + app_info['header_file'] + '\"')
171
172
                        num_required_modules = len(module_info[current_module]['requires'])
173
                        if num_required_modules > max_required_modules:
174
                            max_required_modules = num_required_modules
175
                        if first_loop != True:
176
                            info_string += ',\n'
177
                            for i in range(num_spaces):
178
                                info_string += ' '
179
                        info_string += '{"' + current_module + '", '
180
                        info_string += str(num_required_modules) + ', '
181
182
                        first_loop_1 = True
183
                        info_string += '{'
184
                        for required_module in module_info[current_module]['requires']:
185
                            if first_loop_1 != True:
186
                                info_string += ', '
187
                            info_string += '"' + required_module['name'] + '"'
188
                            first_loop_1 = False
189
                        info_string += '}'
190
                        info_string += ', &' + app_info['init_function'] + '}'
191
                        first_loop = False
192
193
                info_string += '};'
194
195
                info_struct  = '\n\n#define MAX_REQUIRED_MODULES '
196
                info_struct += str(max_required_modules)
197
                info_struct += '\n\nstruct module_info {\n'
198
                info_struct += '    const char *name;\n'
199
                info_struct += '    const int   num_required_moduels;\n'
200
                info_struct += '    const char *required_modules_hipd['
201
                info_struct += 'MAX_REQUIRED_MODULES];\n'
202
                info_struct += '    int       (*init_function)(void);\n'
203
                info_struct += '};\n\n'
204
                hdr_file.write(info_struct)
205
                hdr_file.write('/* Number of modules - determined during build process. */')
206
                hdr_file.write('\nconst int ' + current_app + '_num_modules')
207
                hdr_file.write(' = ' + str(num_modules) + ';\n\n')
208
209
                hdr_file.write(info_string)
3486.1.202 by Tim Just
process_modules.py now returns errors and these are handled by configure.
210
3486.1.241 by Tim Just
Uses commas instead of spaces for separation of modules.
211
                hdr_file.write('\n\n#endif /* ' + app_string + ' */\n')
3486.1.202 by Tim Just
process_modules.py now returns errors and these are handled by configure.
212
                print '|    created file: ' + hdr_file_path
213
            finally:
214
                hdr_file.close()
215
        except IOError:
216
            sys.exit('Error on creating header files')
3486.1.23 by Tim Just
Applied modularization concept on tiny branch.
217
218
### Main program ###
3486.1.195 by Tim Just
Added command line arguments and main function to process_modules.py
219
def main():
220
    srcdir = None
221
    disabled_modules = None
3486.1.261 by Tim Just
Fixed build with all modules disabled.
222
    applications = set(['hipd'])
3486.1.195 by Tim Just
Added command line arguments and main function to process_modules.py
223
224
    try:
225
        opts, args = getopt.getopt(sys.argv[1:],
226
                                   "s:d:",
227
                                   ["srcdir=", "disabled_modules="])
228
    except getopt.GetoptError, err:
229
        print str(err)
230
        sys.exit(2)
231
    for o, a in opts:
232
        if o in ("-s", "--srcdir"):
233
            srcdir = a
234
        elif o in ("-d", "--disabled_modules"):
235
            disabled_modules = a
236
        else:
237
            assert False, "unhandled option"
238
3486.1.198 by Tim Just
Fixed bug in process_modules.py
239
    if disabled_modules:
3486.1.241 by Tim Just
Uses commas instead of spaces for separation of modules.
240
        disabled_modules = disabled_modules.rsplit(',')
3486.1.195 by Tim Just
Added command line arguments and main function to process_modules.py
241
3486.1.275 by Tim Just
Improved dependency check on daemon startup.
242
    (module_info) = read_module_info(os.path.join(srcdir, MODULES_DIR),
243
                                     disabled_modules)
244
245
    check_dependencies(module_info)
246
247
    create_header_files(applications, module_info)
3486.1.195 by Tim Just
Added command line arguments and main function to process_modules.py
248
249
if __name__ == "__main__":
250
    main()