build/buildutils/armsize.py
author hgs
Fri, 29 Oct 2010 11:49:32 +0300
changeset 87 1627c337e51e
permissions -rw-r--r--
v2.2.21_1
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
87
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
     1
#!/usr/bin/python
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
     2
#
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
     3
# Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
     4
# All rights reserved.
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
     5
# This component and the accompanying materials are made available
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
     6
# under the terms of "Eclipse Public License v1.0"
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
     7
# which accompanies this distribution, and is available
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
     8
# at the URL "http://www.eclipse.org/legal/epl-v10.html".
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
     9
#
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
    10
# Initial Contributors:
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
    11
# Nokia Corporation - initial contribution.
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
    12
#
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
    13
# Contributors:
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
    14
#
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
    15
# Description: 
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
    16
#  This utility is used to find out the size in disk of files 
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
    17
#  written to ROM images (or compiled). Script finds out Symbian 
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
    18
#  build enviornment binary file paths based on iby-file(s) or 
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
    19
#  mmp-files, and prints out file sizes.
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
    20
#
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
    21
#  Run the script with option --help to see the parameters
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
    22
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
    23
import os.path, fnmatch, re, subprocess, glob
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
    24
from optparse import OptionParser
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
    25
from itertools import chain
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
    26
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
    27
RE_MMP_TARGET = re.compile(r"\s*TARGET\s+(\S+)", re.IGNORECASE)
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
    28
RE_DEFINE = re.compile(r"^define\s*(\S+)\s+(\S+)\s*$", re.IGNORECASE)
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
    29
RE_IBYTARGET = re.compile(r"^(?:file|data)=(\S+)\s+\S+\s*$", re.IGNORECASE)
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
    30
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
    31
# Base defines used in IBY files
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
    32
BASE_DEFINES = [("ABI_DIR", r"\epoc32\release\armv5"),
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
    33
                ("BUILD_DIR", r"urel"),
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
    34
                ("DATAZ_", r"\epoc32\data\z"),
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
    35
                ("RESOURCE_FILES_DIR", r"resource"),
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
    36
                ("ZRESOURCE", r"DATAZ_\resource"),
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
    37
                ("ZSYSTEM", r"DATAZ_\system"),
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
    38
                ("ZPRIVATE", r"DATAZ_\private")]
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
    39
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
    40
def flatten(listOfLists):
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
    41
    return list(chain(*listOfLists))
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
    42
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
    43
def cppFile(source, cppDefines = None, include = None):
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
    44
    ''' Preprocess source with epoc32/include, and return preprocessed lines '''
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
    45
    includePaths = [r"/epoc32/include"]
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
    46
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
    47
    if cppDefines:
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
    48
        cppDefines = " ".join(["-D%s" % d for d in cppDefines])
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
    49
    else:
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
    50
        cppDefines = ""
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
    51
    if include:
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
    52
        path, filename = os.path.split(include)
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
    53
        includePaths.append(path)
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
    54
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
    55
        include = "-include " + include
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
    56
        
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
    57
    else:
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
    58
        include = ""
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
    59
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
    60
    drive, tail = os.path.splitdrive(source)
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
    61
    command = r'cpp %s %s %s "%s"' % (" ".join(["-I %s" % i for i in includePaths]),
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
    62
                                      cppDefines, include, source)
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
    63
    process = subprocess.Popen(command, 
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
    64
                               shell = True,
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
    65
                               cwd = "%s\\" % drive,
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
    66
                               stdout = subprocess.PIPE)
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
    67
    for line in process.stdout.readlines():
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
    68
        yield line
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
    69
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
    70
def replaceDefines(line, defines):
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
    71
    ''' Replace the macro definitions recursively '''
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
    72
    oldLine = None
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
    73
    while oldLine != line:
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
    74
        oldLine = line
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
    75
        for search, replace in defines:
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
    76
            line = line.replace(search, replace)
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
    77
    return line
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
    78
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
    79
def parseIby(lines):
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
    80
    ''' Parse IBY file lines, using defines '''
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
    81
    defines = BASE_DEFINES[:]
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
    82
    for l in lines:
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
    83
        defineMatch = RE_DEFINE.match(l)
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
    84
        if defineMatch:
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
    85
            search, replace = defineMatch.groups()
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
    86
            defines.append((search, replace))
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
    87
        else:
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
    88
            yield replaceDefines(l, defines)
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
    89
            
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
    90
def getIbySources(ibyfile, cppDefines = None, include = None):
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
    91
    ''' Get IBY file source files'''
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
    92
    drive, tail = os.path.splitdrive(ibyfile)
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
    93
    for l in parseIby(cppFile(ibyfile, cppDefines, include)):
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
    94
        match = RE_IBYTARGET.match(l)
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
    95
        if match:
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
    96
            yield drive + match.group(1)
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
    97
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
    98
def findFiles(root, pattern):
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
    99
    ''' Find files recursively '''
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
   100
    for path, dirs, files in os.walk(root):
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
   101
        for f in fnmatch.filter(files, pattern):
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
   102
            yield os.path.join(path, f)
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
   103
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
   104
def getMmpTarget(mmpfile):
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
   105
    ''' Get the target binary name from mmp-file '''
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
   106
    for l in open(mmpfile, "r").readlines():
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
   107
        match = RE_MMP_TARGET.search(l)
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
   108
        if match:
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
   109
            return match.group(1)
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
   110
    return None
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
   111
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
   112
def getMmpTargets(mmpRoot):
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
   113
    ''' Get the target binary paths of all mmp-files found under root '''
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
   114
    drive, tail = os.path.splitdrive(mmpRoot)
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
   115
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
   116
    totalSize = 0
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
   117
    for mmp in findFiles(mmpRoot, "*.mmp"):
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
   118
        target = getMmpTarget(mmp)
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
   119
        if not target:
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
   120
            continue
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
   121
        binPath = drive + "/epoc32/release/armv5/urel/" + target
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
   122
        if os.path.exists(binPath):
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
   123
            yield binPath
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
   124
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
   125
def getSizes(binaries):
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
   126
    ''' Get the sizes of given files, return list of tuples (size|None, file) '''
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
   127
    for binPath in binaries:
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
   128
        if not os.path.exists(binPath):
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
   129
            yield None, binPath
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
   130
        else:
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
   131
            yield os.path.getsize(binPath), binPath
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
   132
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
   133
def printSizes(sizes):
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
   134
    ''' Print file sizes and a total '''
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
   135
    totalSize = 0
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
   136
    for size, binPath in sizes:
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
   137
        if size:
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
   138
            totalSize = totalSize + size
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
   139
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
   140
        print "%s\t%s" % (size, binPath)
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
   141
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
   142
    print "%d\tTotal" % totalSize
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
   143
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
   144
def main():
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
   145
    parser = OptionParser()
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
   146
    parser.add_option(
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
   147
        "--mmproot", dest = "mmproot",
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
   148
        help = "root for searching mmp-files (whose target is used for filenames)")
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
   149
    parser.add_option(
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
   150
        "--ibyfile", dest = "ibyfile",
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
   151
        help = "ibyfile(s) which are processed to find out target file paths")
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
   152
    parser.add_option(
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
   153
        "--sortname", dest = "sortname", action = "store_true", default = False,
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
   154
        help = "sort files by name")
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
   155
    parser.add_option(
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
   156
        "--sortsize", dest = "sortsize", action = "store_true", default = False,
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
   157
        help = "sort files by size")
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
   158
    parser.add_option(
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
   159
        "--cppdefines", dest = "cppdefines",
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
   160
        help = "cpp defines for iby, e.g. --cppdefines __JAVA,__JAVA_MIDP20")
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
   161
    parser.add_option(
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
   162
        "--include", dest = "include",
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
   163
        help = "Include file for iby cpp, e.g. --include /epoc32/include/config/ncp52/bldpublic.hrh")
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
   164
    (options, args) = parser.parse_args()
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
   165
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
   166
    if options.mmproot:
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
   167
        binaries = getMmpTargets(options.mmproot)
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
   168
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
   169
    elif options.ibyfile:
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
   170
        cppdefines = options.cppdefines and options.cppdefines.split(",")
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
   171
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
   172
        ibys = glob.glob(options.ibyfile)
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
   173
        binaries = flatten([getIbySources(iby, cppdefines, options.include) 
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
   174
                            for iby in ibys])
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
   175
        
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
   176
    sizes = getSizes(binaries)
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
   177
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
   178
    if options.sortsize:
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
   179
        sizes = sorted(sizes)
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
   180
    if options.sortname:
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
   181
        sizes = sorted(sizes, cmp=lambda x,y: cmp(x[1], y[1]))
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
   182
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
   183
    printSizes(sizes)
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
   184
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
   185
if __name__ == "__main__":
1627c337e51e v2.2.21_1
hgs
parents:
diff changeset
   186
    main()