diff -r d6dafc5d983f -r 1627c337e51e build/buildutils/armsize.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/build/buildutils/armsize.py Fri Oct 29 11:49:32 2010 +0300 @@ -0,0 +1,186 @@ +#!/usr/bin/python +# +# Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). +# All rights reserved. +# This component and the accompanying materials are made available +# under the terms of "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: +# Nokia Corporation - initial contribution. +# +# Contributors: +# +# Description: +# This utility is used to find out the size in disk of files +# written to ROM images (or compiled). Script finds out Symbian +# build enviornment binary file paths based on iby-file(s) or +# mmp-files, and prints out file sizes. +# +# Run the script with option --help to see the parameters + +import os.path, fnmatch, re, subprocess, glob +from optparse import OptionParser +from itertools import chain + +RE_MMP_TARGET = re.compile(r"\s*TARGET\s+(\S+)", re.IGNORECASE) +RE_DEFINE = re.compile(r"^define\s*(\S+)\s+(\S+)\s*$", re.IGNORECASE) +RE_IBYTARGET = re.compile(r"^(?:file|data)=(\S+)\s+\S+\s*$", re.IGNORECASE) + +# Base defines used in IBY files +BASE_DEFINES = [("ABI_DIR", r"\epoc32\release\armv5"), + ("BUILD_DIR", r"urel"), + ("DATAZ_", r"\epoc32\data\z"), + ("RESOURCE_FILES_DIR", r"resource"), + ("ZRESOURCE", r"DATAZ_\resource"), + ("ZSYSTEM", r"DATAZ_\system"), + ("ZPRIVATE", r"DATAZ_\private")] + +def flatten(listOfLists): + return list(chain(*listOfLists)) + +def cppFile(source, cppDefines = None, include = None): + ''' Preprocess source with epoc32/include, and return preprocessed lines ''' + includePaths = [r"/epoc32/include"] + + if cppDefines: + cppDefines = " ".join(["-D%s" % d for d in cppDefines]) + else: + cppDefines = "" + if include: + path, filename = os.path.split(include) + includePaths.append(path) + + include = "-include " + include + + else: + include = "" + + drive, tail = os.path.splitdrive(source) + command = r'cpp %s %s %s "%s"' % (" ".join(["-I %s" % i for i in includePaths]), + cppDefines, include, source) + process = subprocess.Popen(command, + shell = True, + cwd = "%s\\" % drive, + stdout = subprocess.PIPE) + for line in process.stdout.readlines(): + yield line + +def replaceDefines(line, defines): + ''' Replace the macro definitions recursively ''' + oldLine = None + while oldLine != line: + oldLine = line + for search, replace in defines: + line = line.replace(search, replace) + return line + +def parseIby(lines): + ''' Parse IBY file lines, using defines ''' + defines = BASE_DEFINES[:] + for l in lines: + defineMatch = RE_DEFINE.match(l) + if defineMatch: + search, replace = defineMatch.groups() + defines.append((search, replace)) + else: + yield replaceDefines(l, defines) + +def getIbySources(ibyfile, cppDefines = None, include = None): + ''' Get IBY file source files''' + drive, tail = os.path.splitdrive(ibyfile) + for l in parseIby(cppFile(ibyfile, cppDefines, include)): + match = RE_IBYTARGET.match(l) + if match: + yield drive + match.group(1) + +def findFiles(root, pattern): + ''' Find files recursively ''' + for path, dirs, files in os.walk(root): + for f in fnmatch.filter(files, pattern): + yield os.path.join(path, f) + +def getMmpTarget(mmpfile): + ''' Get the target binary name from mmp-file ''' + for l in open(mmpfile, "r").readlines(): + match = RE_MMP_TARGET.search(l) + if match: + return match.group(1) + return None + +def getMmpTargets(mmpRoot): + ''' Get the target binary paths of all mmp-files found under root ''' + drive, tail = os.path.splitdrive(mmpRoot) + + totalSize = 0 + for mmp in findFiles(mmpRoot, "*.mmp"): + target = getMmpTarget(mmp) + if not target: + continue + binPath = drive + "/epoc32/release/armv5/urel/" + target + if os.path.exists(binPath): + yield binPath + +def getSizes(binaries): + ''' Get the sizes of given files, return list of tuples (size|None, file) ''' + for binPath in binaries: + if not os.path.exists(binPath): + yield None, binPath + else: + yield os.path.getsize(binPath), binPath + +def printSizes(sizes): + ''' Print file sizes and a total ''' + totalSize = 0 + for size, binPath in sizes: + if size: + totalSize = totalSize + size + + print "%s\t%s" % (size, binPath) + + print "%d\tTotal" % totalSize + +def main(): + parser = OptionParser() + parser.add_option( + "--mmproot", dest = "mmproot", + help = "root for searching mmp-files (whose target is used for filenames)") + parser.add_option( + "--ibyfile", dest = "ibyfile", + help = "ibyfile(s) which are processed to find out target file paths") + parser.add_option( + "--sortname", dest = "sortname", action = "store_true", default = False, + help = "sort files by name") + parser.add_option( + "--sortsize", dest = "sortsize", action = "store_true", default = False, + help = "sort files by size") + parser.add_option( + "--cppdefines", dest = "cppdefines", + help = "cpp defines for iby, e.g. --cppdefines __JAVA,__JAVA_MIDP20") + parser.add_option( + "--include", dest = "include", + help = "Include file for iby cpp, e.g. --include /epoc32/include/config/ncp52/bldpublic.hrh") + (options, args) = parser.parse_args() + + if options.mmproot: + binaries = getMmpTargets(options.mmproot) + + elif options.ibyfile: + cppdefines = options.cppdefines and options.cppdefines.split(",") + + ibys = glob.glob(options.ibyfile) + binaries = flatten([getIbySources(iby, cppdefines, options.include) + for iby in ibys]) + + sizes = getSizes(binaries) + + if options.sortsize: + sizes = sorted(sizes) + if options.sortname: + sizes = sorted(sizes, cmp=lambda x,y: cmp(x[1], y[1])) + + printSizes(sizes) + +if __name__ == "__main__": + main()