build/buildutils/checkwarnings.py
changeset 21 2a9601315dfc
child 23 98ccebc37403
equal deleted inserted replaced
18:e8e63152f320 21:2a9601315dfc
       
     1 #!/usr/bin/python
       
     2 #
       
     3 # Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     4 # All rights reserved.
       
     5 # This component and the accompanying materials are made available
       
     6 # under the terms of "Eclipse Public License v1.0"
       
     7 # which accompanies this distribution, and is available
       
     8 # at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     9 #
       
    10 # Initial Contributors:
       
    11 # Nokia Corporation - initial contribution.
       
    12 #
       
    13 # Contributors:
       
    14 #
       
    15 # Description: This script checks the build logs for warnings and categorizes
       
    16 # them into various categories. Returns 1 if there are BAD warnings. 
       
    17 #
       
    18 
       
    19 import sys
       
    20 from optparse import OptionParser
       
    21 
       
    22 
       
    23 class WarningHandler:
       
    24 
       
    25     # Counters for various warnings
       
    26     totalWarnings = 0
       
    27     badOnes = 0
       
    28     deprecatedWarnings = 0
       
    29     compilerWarnings = 0
       
    30     linkerWarnings = 0
       
    31     postlinkerWarnings = 0
       
    32     flmWarnings = 0
       
    33 
       
    34     # Constants for matching warnings related to deprecation
       
    35     deprecatedStart = "warning: preprocessor #warning directive"
       
    36     deprecatedSecondLine = "warning: #warning This header file has been deprecated. Will be removed in one of the next SDK releases."
       
    37     deprecatedOptionalThirdLine = "warning: (included from:"
       
    38     deprecatedOptionalRest = "warning:  "
       
    39 
       
    40     # This list includes strings from which the BAD warnings can be recognized.
       
    41     # Note that these must be in lower case!
       
    42     badWarnings = [
       
    43         "#111-d", "#1166-d", "#117-d", "#128-d", "#1293-d", "#1441-d", "#170-d", 
       
    44         "#174-d", "#175-d", "#185-d", "#186-d", "#223-d", "#231-d", "#257-d", 
       
    45         "#284-d", "#368-d", "#414-d", "#430-d", "#47-d", "#514-d", "#546-d",
       
    46         "#68-d", "#69-d", "#830-d", "#940-d", "c2874w", "c4127", "c4355", "c4530",
       
    47         "c4702", "c4786", "lnk4049", "#836-d", "a1495e", "l6318w" ]
       
    48 
       
    49         
       
    50     def IsBadWarning(self, lowerCasedLine):
       
    51         for bad in self.badWarnings:
       
    52             if bad in lowerCasedLine:
       
    53                 return True
       
    54         return False
       
    55         
       
    56     
       
    57     def PrintResults(self):
       
    58         print "\n-------------------------------\n"
       
    59         print "Total warnings:", self.totalWarnings
       
    60         print "Bad ones:      ", self.badOnes
       
    61         print ""
       
    62         print "Details:"
       
    63         print "  FLM warnings:            ", self.flmWarnings
       
    64         print "  Use of deprecated api:   ", self.deprecatedWarnings
       
    65         print "  Other compiler warnings: ", self.compilerWarnings
       
    66         print "  Linker warnings:         ", self.linkerWarnings
       
    67         print "  Post-linker warnings:    ", self.postlinkerWarnings
       
    68 
       
    69     
       
    70 
       
    71 class PrintSettings:
       
    72     """Class parsing and maintaining the printing settings related to warnings"""
       
    73   
       
    74     printDeprecatedWarnings = False
       
    75     printCompilerWarnings = False
       
    76     printLinkerWarnings = False
       
    77     printFlmWarnings = False
       
    78  
       
    79     def parseArgs(self):
       
    80         parser = OptionParser(
       
    81             usage = "python -u %prog [options] <logfile>",
       
    82             description = "Analyzes warnings from the given log file. " + \
       
    83                 "By default prints only BAD warnings and statistics.")
       
    84         parser.add_option("--printall", dest="printall", action="store_true", 
       
    85             default=False, help="Prints all the warnings")
       
    86         parser.add_option("--pc", dest="printcompilerwarnings", action="store_true", 
       
    87             default=False, help="Prints compiler warnings")
       
    88         parser.add_option("--pl", dest="printlinkerwarnings", action="store_true", 
       
    89             default=False, help="Prints linker warnings")
       
    90         parser.add_option("--pd", dest="printdeprecatedwarnings", action="store_true", 
       
    91             default=False, help="Prints deprecation warnings")
       
    92         parser.add_option("--pf", dest="printflmwarnings", action="store_true", 
       
    93             default=False, help="Prints FLM warnings")
       
    94         (opts, args) = parser.parse_args()
       
    95 
       
    96         if len(args) != 1:
       
    97             parser.print_help()
       
    98             sys.exit(-1)
       
    99             
       
   100         if opts.printall:
       
   101             self.printDeprecatedWarnings = True
       
   102             self.printCompilerWarnings = True
       
   103             self.printLinkerWarnings = True
       
   104             self.printFlmWarnings = True
       
   105         else:
       
   106             self.printDeprecatedWarnings = opts.printdeprecatedwarnings
       
   107             self.printCompilerWarnings = opts.printcompilerwarnings
       
   108             self.printLinkerWarnings = opts.printlinkerwarnings
       
   109             self.printFlmWarnings = opts.printflmwarnings
       
   110         
       
   111         return args[0]
       
   112 
       
   113         
       
   114  
       
   115 # Calculates the number of various warnings from the given file containing 
       
   116 # the console output from a Raptor build. 
       
   117 #
       
   118 # BAD warnings are those warnings that are considered so important that builds
       
   119 # should have always zero of them. The related log message strings are defined
       
   120 # in the variable badWarnings above.
       
   121 #
       
   122 # The warnings are further categorized as deprecated API warnings, compiler
       
   123 # warnings, linker, and post-linker warnings.
       
   124 #
       
   125 def main():
       
   126 
       
   127     # Parse command line options and log file name.
       
   128     settings = PrintSettings()
       
   129     path = settings.parseArgs()
       
   130 
       
   131     # Read in the lines
       
   132     f = open(path)
       
   133     lines = f.readlines()
       
   134     f.close()
       
   135     
       
   136     # Initialize the warning handler
       
   137     wh = WarningHandler()
       
   138     
       
   139     # Initial state for the state machine, see the method stateMachine for
       
   140     # information about the other states
       
   141     state = 0
       
   142     underCompilation = ""
       
   143     
       
   144     # Check all the lines for possible warnings
       
   145     for line in lines:
       
   146     
       
   147         # Reset the target always when having line of form " xyz"
       
   148         # Works also with empty lines as the newline is counted in
       
   149         if line[0] == ' ' and line[1] != ' ':
       
   150             underCompilation = line
       
   151             state = 1;
       
   152             continue
       
   153 
       
   154         state = stateMachine(state, line, underCompilation, settings, wh)
       
   155 
       
   156     # Done with the parsing, just dump the statistics
       
   157     wh.PrintResults()
       
   158     
       
   159     if wh.badOnes > 0:
       
   160         sys.exit(1)
       
   161     else:
       
   162         sys.exit(0)
       
   163         
       
   164 
       
   165 # The state machine function doing the actual work
       
   166 def stateMachine(state, line, underCompilation, settings, wh):
       
   167 
       
   168     # Looking for any warning related to the current target
       
   169     if state == 1:
       
   170     
       
   171         # Check first for the start of a multiline deprecation warning
       
   172         if wh.deprecatedStart in line:
       
   173             if settings.printDeprecatedWarnings:
       
   174                 print underCompilation,
       
   175                 print line,
       
   176             wh.deprecatedWarnings += 1
       
   177             wh.totalWarnings += 1
       
   178             return 2
       
   179             
       
   180         else:
       
   181         
       
   182             # Then check for all the other warnings
       
   183             lowerCasedLine = line.lower()
       
   184             if "warning:" in lowerCasedLine:
       
   185                 wh.totalWarnings += 1
       
   186 
       
   187                 # Check for bad warnings
       
   188                 isBad = wh.IsBadWarning(lowerCasedLine)
       
   189                 if isBad:
       
   190                     wh.badOnes += 1                    
       
   191 
       
   192                 # Categorize and print the warning (BAD warnings are printed always)
       
   193                 if ("mwldsym2.exe: warning" in lowerCasedLine):
       
   194                     wh.linkerWarnings += 1
       
   195                     if settings.printLinkerWarnings or isBad:
       
   196                         print underCompilation,
       
   197                         print line,
       
   198                 elif ("elf2e32: warning:" in lowerCasedLine):
       
   199                     wh.postlinkerWarnings += 1
       
   200                     if settings.printLinkerWarnings or isBad:
       
   201                         print underCompilation,
       
   202                         print line,
       
   203                 elif ("makedef warning:" in lowerCasedLine):
       
   204                     wh.postlinkerWarnings += 1
       
   205                     if settings.printLinkerWarnings:
       
   206                         print underCompilation,
       
   207                         print line,
       
   208                     return 5   # find the rest of the lines
       
   209                 elif ("warning: overriding commands for target" in lowerCasedLine or
       
   210                        "warning: ignoring old commands for target" in lowerCasedLine):
       
   211                     wh.flmWarnings += 1
       
   212                     if settings.printFlmWarnings or isBad:
       
   213                         print underCompilation,
       
   214                         print line,                    
       
   215                 elif (": warning:" in lowerCasedLine):
       
   216                     wh.compilerWarnings += 1
       
   217                     if settings.printCompilerWarnings or isBad:
       
   218                         print underCompilation,
       
   219                         print line,
       
   220                     
       
   221             return 1
       
   222     
       
   223     # Looking for the second line of the multiline deprecation warning
       
   224     if state == 2:
       
   225         if wh.deprecatedSecondLine in line:
       
   226             if settings.printDeprecatedWarnings:
       
   227                 print line,
       
   228             return 3
       
   229         else:
       
   230             print "Missing second line"
       
   231             return 1           
       
   232     
       
   233     # Looking for the optional third line of the multiline deprecation warning
       
   234     if state == 3:
       
   235         if wh.deprecatedOptionalThirdLine in line:
       
   236             if settings.printDeprecatedWarnings:
       
   237                 print line,
       
   238             return 4
       
   239         else:
       
   240             # Hmm... went one line too far -> need to check the current line again
       
   241             # but now in the state 1
       
   242             return stateMachine(1, line, underCompilation, settings, wh)            
       
   243 
       
   244     # Looking for the optional trailing lines of the multiline deprecation warning
       
   245     if state == 4:
       
   246         if wh.deprecatedOptionalRest in line:
       
   247             if settings.printDeprecatedWarnings:
       
   248                 print line,
       
   249             return 4
       
   250         else:
       
   251             # Hmm... went one line too far -> need to check the current line again
       
   252             # but now in the state 1           
       
   253             return stateMachine(1, line, underCompilation, settings, wh)
       
   254                     
       
   255     # Looking for MAKEDEF detailed information lines
       
   256     if state == 5:
       
   257         if settings.printLinkerWarnings:
       
   258             print line,
       
   259         return 1
       
   260 
       
   261                             
       
   262 
       
   263 if __name__ == "__main__":
       
   264     main()