diff -r 60053dab7e2a -r 842a773e65f2 jamesa/generate_oby.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jamesa/generate_oby.py Wed Nov 04 17:40:17 2009 +0000 @@ -0,0 +1,212 @@ +# Copyright (c) 2009 Symbian Foundation Ltd +# This component and the accompanying materials are made available +# under the terms of the License "Eclipse Public License v1.0" +# which accompanies this distribution, and is available +# at the URL "http://www.eclipse.org/legal/epl-v10.html". +# +# Initial Contributors: +# Symbian Foundation Ltd - initial contribution. +# +# Contributors: +# +# Description: +# Create a barebones OBY file from a dependency report text file. + +"""Take a report generated by get_deps.py and attempt to create an OBY +file to build a ROM with the dependency list. +""" + +from build_graph import without_comments +from optparse import OptionParser + +import os +import re +import sys +import logging + +__author__ = 'James Aley' +__email__ = 'jamesa@symbian.org' +__version__ = '1.0' + +# Logging config +_LOG_FORMAT = '%(levelname)s: %(message)s' +logging.basicConfig(format=_LOG_FORMAT, level=logging.WARNING, stream=sys.stdout) + +# Regexes for bld.inf parsing +_RE_EXPORT_SECTION = '\\s*PRJ_EXPORTS\\s*' +_RE_OTHER_SECTION = '\\s*PRJ_[a-z]+\\s*' +_RE_IBY_OBY = '\\s*([^\\s]+\\.[oi]by)\\s+.*' +_p_export_section = re.compile(_RE_EXPORT_SECTION, re.I) +_p_other_section = re.compile(_RE_OTHER_SECTION, re.I) +_p_iby_oby = re.compile(_RE_IBY_OBY, re.I) + +# OBY output templates +_OBY_HEADER = """// OBY file generated by genereate_oby.py. +// The following includes are derived from the dependency report: %s + +""" + +_OBY_INCLUDE = """ +// Required for: %s +%s +""" + +_OBY_UNRESOLVED = """ + +// The following appear to be exported by this component, +// but were not found under the include directory: +%s +""" + +_OBY_NO_EXPORTS = """ + +// The following components are required in your dependency graph, but +// they appear not to export an IBY/OBY file. Your ROM will likely not +// build until you locate the correct include files for these. +%s +""" + +_INCLUDE_TEMPLATE = '#include <%s>' + +def bld_inf_list(report_path): + """Returna list of bld.inf files from the report + """ + bld_list = [] + report_file = None + try: + report_file = open(report_path) + except IOError, e: + logging.critical('Could not open report: %s' % (repr(e), )) + exit(1) + return filter(lambda x: x and not x.isspace(), [line.strip() for line in without_comments(report_file)]) + +def get_paths(bld_inf_file): + """Returns a list of referenced OBY or IBY files from a bld.inf file. + bld_inf_file is an open file handle, which will not be closed by this + function. + """ + oby_iby = [] + export_section = False + for line in without_comments(bld_inf_file): + if export_section: + match_iby_oby = _p_iby_oby.search(line) + if match_iby_oby: + file_name = match_iby_oby.groups()[0].strip() + oby_iby.append(file_name) + else: + match_other_section = _p_other_section.search(line) + if match_other_section: + export_section = False + else: + match_export_section = _p_export_section.search(line) + if match_export_section: + export_section = True + obys = filter(lambda x: x.lower().endswith('.oby'), oby_iby) + if len(obys) > 0: + return obys + return oby_iby + +def rom_file_list(bld_inf_paths): + """Iterate through a list of bld.inf file paths and extra the references + to OBY or IBY files where appropriate (OBY takes precedence). Return a + dictionary of relevant files in the format: + { 'component_bld_inf' : [ iby_file_list] } + """ + obys_ibys = {} + for path in bld_inf_paths: + bld_inf_file = None + try: + bld_inf_file = open(path) + except IOError, e: + logging.error('Unable to open bld.inf file: %s' % (repr(e), )) + continue + rom_file_paths = get_paths(bld_inf_file) + obys_ibys[path] = rom_file_paths + bld_inf_file.close() + return obys_ibys + +def iby_map(iby_dict, dir_name, file_names): + """Searches for the specified IBY/OBY file under the include_root path. + Returns the absolute path to the IBY/OBY if it was found, otherwise a blank string. + """ + for component in iby_dict.keys(): + # Map the file names for each component IBY file to a matching + # file name under the export directory, if it exists, otherwise + # keep the existing name for now - it might be matched later. + file_names = map(lambda x: x.lower(), file_names) + component_ibys = map(lambda x: os.path.basename(x).lower() in file_names \ + and os.path.join(dir_name, os.path.basename(x)) \ + or x, \ + iby_dict[component]) + iby_dict[component] = component_ibys + +def write_oby(out_path, iby_map, input_path, include_root): + """Write an OBY file to include the required IBY and OBY files for this + ROM specification, given by iby_map. + """ + out_file = None + try: + out_file = open(out_path, 'w') + except IOError, e: + logging.critical('Unable to write OBY file: %s' % repr(e)) + exit(1) + + # Write the header with the input file name included + out_file.write(_OBY_HEADER % (input_path, )) + + exports = filter(lambda x: len(iby_map[x]) > 0, iby_map.keys()) + no_exports = filter(lambda x: len(iby_map[x]) == 0, iby_map.keys()) + + # Write the includes and missing exports + for component in exports: + iby_list = iby_map[component] + exported = filter(lambda x: x.startswith(include_root), iby_list) + # Need relative paths for include, but os.path.relpath is added + # in Python 2.6, which isn't supported by other Symbian tools + # at present :-( + exported = map(lambda x: x[len(include_root) + 1:], exported) + exported.sort() + + missing = filter(lambda x: not x.startswith(include_root), iby_list) + missing = map(lambda x: os.path.basename(x), missing) + missing.sort() + + # Write the IBY file includes for this component + out_file.write(_OBY_INCLUDE % (component, '\n'.join([_INCLUDE_TEMPLATE % (iby, ) for iby in exported]), )) + + # Write the missing IBY reports + if len(missing) > 0: + out_file.write(_OBY_UNRESOLVED % ('\n'.join(['// %s' % (missed, ) for missed in missing]), )) + + # Write report for the IBY that appear not to export any ROM include files + out_file.write(_OBY_NO_EXPORTS % ('\n'.join(['// %s' % (path,) for path in no_exports]), )) + out_file.close() + +# Main +if __name__ == '__main__': + # Options config + parser = OptionParser() + parser.set_description(__doc__) + parser.add_option('-r', '--report', dest='report_path', + help='File name for the report generated by get_deps.py', + metavar='INPUT_FILE', default='dependencies.txt') + parser.add_option('-o', '--output', dest='output_file', + help='OBY ouput file to write to.', + metavar='OUT_FILE', default='generated.oby') + parser.add_option('-i', '--include_root', dest='include_root', + help='Environment ROM inlcude root.', + metavar='INCLUDE_ROOT', + default=os.path.sep.join(['epoc32', 'rom'])) + (options, args) = parser.parse_args() + + # Read the report and get a list of bld.inf files, then convert to + # a dictionary of bld_inf -> [IBY file list] mappings. + bld_infs = bld_inf_list(options.report_path) + bld_iby_map = rom_file_list(bld_infs) + + # Walk the include tree to find the exported IBYs. + os.path.walk(options.include_root, iby_map, bld_iby_map) + + # Write the OBY file + write_oby(options.output_file, bld_iby_map, options.report_path, options.include_root) +