|
1 # Copyright (c) 2009 Symbian Foundation Ltd |
|
2 # This component and the accompanying materials are made available |
|
3 # under the terms of the License "Eclipse Public License v1.0" |
|
4 # which accompanies this distribution, and is available |
|
5 # at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
6 # |
|
7 # Initial Contributors: |
|
8 # Symbian Foundation Ltd - initial contribution. |
|
9 # |
|
10 # Contributors: |
|
11 # |
|
12 # Description: |
|
13 # Create a barebones OBY file from a dependency report text file. |
|
14 |
|
15 """Take a report generated by get_deps.py and attempt to create an OBY |
|
16 file to build a ROM with the dependency list. |
|
17 """ |
|
18 |
|
19 from build_graph import without_comments |
|
20 from optparse import OptionParser |
|
21 |
|
22 import os |
|
23 import re |
|
24 import sys |
|
25 import logging |
|
26 |
|
27 __author__ = 'James Aley' |
|
28 __email__ = 'jamesa@symbian.org' |
|
29 __version__ = '1.0' |
|
30 |
|
31 # Logging config |
|
32 _LOG_FORMAT = '%(levelname)s: %(message)s' |
|
33 logging.basicConfig(format=_LOG_FORMAT, level=logging.WARNING, stream=sys.stdout) |
|
34 |
|
35 # Regexes for bld.inf parsing |
|
36 _RE_EXPORT_SECTION = '\\s*PRJ_EXPORTS\\s*' |
|
37 _RE_OTHER_SECTION = '\\s*PRJ_[a-z]+\\s*' |
|
38 _RE_IBY_OBY = '\\s*([^\\s]+\\.[oi]by)\\s+.*' |
|
39 _p_export_section = re.compile(_RE_EXPORT_SECTION, re.I) |
|
40 _p_other_section = re.compile(_RE_OTHER_SECTION, re.I) |
|
41 _p_iby_oby = re.compile(_RE_IBY_OBY, re.I) |
|
42 |
|
43 # OBY output templates |
|
44 _OBY_HEADER = """// OBY file generated by genereate_oby.py. |
|
45 // The following includes are derived from the dependency report: %s |
|
46 |
|
47 """ |
|
48 |
|
49 _OBY_INCLUDE = """ |
|
50 // Required for: %s |
|
51 %s |
|
52 """ |
|
53 |
|
54 _OBY_UNRESOLVED = """ |
|
55 |
|
56 // The following appear to be exported by this component, |
|
57 // but were not found under the include directory: |
|
58 %s |
|
59 """ |
|
60 |
|
61 _OBY_NO_EXPORTS = """ |
|
62 |
|
63 // The following components are required in your dependency graph, but |
|
64 // they appear not to export an IBY/OBY file. Your ROM will likely not |
|
65 // build until you locate the correct include files for these. |
|
66 %s |
|
67 """ |
|
68 |
|
69 _INCLUDE_TEMPLATE = '#include <%s>' |
|
70 |
|
71 def bld_inf_list(report_path): |
|
72 """Returna list of bld.inf files from the report |
|
73 """ |
|
74 bld_list = [] |
|
75 report_file = None |
|
76 try: |
|
77 report_file = open(report_path) |
|
78 except IOError, e: |
|
79 logging.critical('Could not open report: %s' % (repr(e), )) |
|
80 exit(1) |
|
81 return filter(lambda x: x and not x.isspace(), [line.strip() for line in without_comments(report_file)]) |
|
82 |
|
83 def get_paths(bld_inf_file): |
|
84 """Returns a list of referenced OBY or IBY files from a bld.inf file. |
|
85 bld_inf_file is an open file handle, which will not be closed by this |
|
86 function. |
|
87 """ |
|
88 oby_iby = [] |
|
89 export_section = False |
|
90 for line in without_comments(bld_inf_file): |
|
91 if export_section: |
|
92 match_iby_oby = _p_iby_oby.search(line) |
|
93 if match_iby_oby: |
|
94 file_name = match_iby_oby.groups()[0].strip() |
|
95 oby_iby.append(file_name) |
|
96 else: |
|
97 match_other_section = _p_other_section.search(line) |
|
98 if match_other_section: |
|
99 export_section = False |
|
100 else: |
|
101 match_export_section = _p_export_section.search(line) |
|
102 if match_export_section: |
|
103 export_section = True |
|
104 obys = filter(lambda x: x.lower().endswith('.oby'), oby_iby) |
|
105 if len(obys) > 0: |
|
106 return obys |
|
107 return oby_iby |
|
108 |
|
109 def rom_file_list(bld_inf_paths): |
|
110 """Iterate through a list of bld.inf file paths and extra the references |
|
111 to OBY or IBY files where appropriate (OBY takes precedence). Return a |
|
112 dictionary of relevant files in the format: |
|
113 { 'component_bld_inf' : [ iby_file_list] } |
|
114 """ |
|
115 obys_ibys = {} |
|
116 for path in bld_inf_paths: |
|
117 bld_inf_file = None |
|
118 try: |
|
119 bld_inf_file = open(path) |
|
120 except IOError, e: |
|
121 logging.error('Unable to open bld.inf file: %s' % (repr(e), )) |
|
122 continue |
|
123 rom_file_paths = get_paths(bld_inf_file) |
|
124 obys_ibys[path] = rom_file_paths |
|
125 bld_inf_file.close() |
|
126 return obys_ibys |
|
127 |
|
128 def iby_map(iby_dict, dir_name, file_names): |
|
129 """Searches for the specified IBY/OBY file under the include_root path. |
|
130 Returns the absolute path to the IBY/OBY if it was found, otherwise a blank string. |
|
131 """ |
|
132 for component in iby_dict.keys(): |
|
133 # Map the file names for each component IBY file to a matching |
|
134 # file name under the export directory, if it exists, otherwise |
|
135 # keep the existing name for now - it might be matched later. |
|
136 file_names = map(lambda x: x.lower(), file_names) |
|
137 component_ibys = map(lambda x: os.path.basename(x).lower() in file_names \ |
|
138 and os.path.join(dir_name, os.path.basename(x)) \ |
|
139 or x, \ |
|
140 iby_dict[component]) |
|
141 iby_dict[component] = component_ibys |
|
142 |
|
143 def write_oby(out_path, iby_map, input_path, include_root): |
|
144 """Write an OBY file to include the required IBY and OBY files for this |
|
145 ROM specification, given by iby_map. |
|
146 """ |
|
147 out_file = None |
|
148 try: |
|
149 out_file = open(out_path, 'w') |
|
150 except IOError, e: |
|
151 logging.critical('Unable to write OBY file: %s' % repr(e)) |
|
152 exit(1) |
|
153 |
|
154 # Write the header with the input file name included |
|
155 out_file.write(_OBY_HEADER % (input_path, )) |
|
156 |
|
157 exports = filter(lambda x: len(iby_map[x]) > 0, iby_map.keys()) |
|
158 no_exports = filter(lambda x: len(iby_map[x]) == 0, iby_map.keys()) |
|
159 |
|
160 # Write the includes and missing exports |
|
161 for component in exports: |
|
162 iby_list = iby_map[component] |
|
163 exported = filter(lambda x: x.startswith(include_root), iby_list) |
|
164 # Need relative paths for include, but os.path.relpath is added |
|
165 # in Python 2.6, which isn't supported by other Symbian tools |
|
166 # at present :-( |
|
167 exported = map(lambda x: x[len(include_root) + 1:], exported) |
|
168 exported.sort() |
|
169 |
|
170 missing = filter(lambda x: not x.startswith(include_root), iby_list) |
|
171 missing = map(lambda x: os.path.basename(x), missing) |
|
172 missing.sort() |
|
173 |
|
174 # Write the IBY file includes for this component |
|
175 out_file.write(_OBY_INCLUDE % (component, '\n'.join([_INCLUDE_TEMPLATE % (iby, ) for iby in exported]), )) |
|
176 |
|
177 # Write the missing IBY reports |
|
178 if len(missing) > 0: |
|
179 out_file.write(_OBY_UNRESOLVED % ('\n'.join(['// %s' % (missed, ) for missed in missing]), )) |
|
180 |
|
181 # Write report for the IBY that appear not to export any ROM include files |
|
182 out_file.write(_OBY_NO_EXPORTS % ('\n'.join(['// %s' % (path,) for path in no_exports]), )) |
|
183 out_file.close() |
|
184 |
|
185 # Main |
|
186 if __name__ == '__main__': |
|
187 # Options config |
|
188 parser = OptionParser() |
|
189 parser.set_description(__doc__) |
|
190 parser.add_option('-r', '--report', dest='report_path', |
|
191 help='File name for the report generated by get_deps.py', |
|
192 metavar='INPUT_FILE', default='dependencies.txt') |
|
193 parser.add_option('-o', '--output', dest='output_file', |
|
194 help='OBY ouput file to write to.', |
|
195 metavar='OUT_FILE', default='generated.oby') |
|
196 parser.add_option('-i', '--include_root', dest='include_root', |
|
197 help='Environment ROM inlcude root.', |
|
198 metavar='INCLUDE_ROOT', |
|
199 default=os.path.sep.join(['epoc32', 'rom'])) |
|
200 (options, args) = parser.parse_args() |
|
201 |
|
202 # Read the report and get a list of bld.inf files, then convert to |
|
203 # a dictionary of bld_inf -> [IBY file list] mappings. |
|
204 bld_infs = bld_inf_list(options.report_path) |
|
205 bld_iby_map = rom_file_list(bld_infs) |
|
206 |
|
207 # Walk the include tree to find the exported IBYs. |
|
208 os.path.walk(options.include_root, iby_map, bld_iby_map) |
|
209 |
|
210 # Write the OBY file |
|
211 write_oby(options.output_file, bld_iby_map, options.report_path, options.include_root) |
|
212 |