]> git.proxmox.com Git - mirror_edk2.git/blobdiff - BaseTools/Source/Python/Ecc/Ecc.py
BaseTools-Source: Update displayed version information
[mirror_edk2.git] / BaseTools / Source / Python / Ecc / Ecc.py
index 4767645d0576e625330a0bce59534b20518cffcf..3fd4f2043bee6ea0b0d609832ae57699537cda08 100644 (file)
@@ -1,8 +1,8 @@
 ## @file\r
 # This file is used to be the main entrance of ECC tool\r
 #\r
-# Copyright (c) 2009, Intel Corporation\r
-# All rights reserved. This program and the accompanying materials\r
+# Copyright (c) 2009 - 2016, Intel Corporation. All rights reserved.<BR>
+# This program and the accompanying materials\r
 # are licensed and made available under the terms and conditions of the BSD License\r
 # which accompanies this distribution.  The full text of the license may be found at\r
 # http://opensource.org/licenses/bsd-license.php\r
@@ -14,7 +14,7 @@
 ##\r
 # Import Modules\r
 #\r
-import os, time, glob, sys\r
+import Common.LongFilePathOs as os, time, glob, sys\r
 import Common.EdkLogger as EdkLogger\r
 import Database\r
 import EccGlobalData\r
@@ -22,14 +22,23 @@ from MetaDataParser import *
 from optparse import OptionParser\r
 from Configuration import Configuration\r
 from Check import Check\r
-from Common.InfClassObject import Inf\r
-from Common.DecClassObject import Dec\r
-from Common.DscClassObject import Dsc\r
-from Common.FdfClassObject import Fdf\r
+import Common.GlobalData as GlobalData\r
+\r
 from Common.String import NormPath\r
+from Common.BuildVersion import gBUILD_VERSION\r
 from Common import BuildToolError\r
+from Common.Misc import PathClass\r
+from Common.Misc import DirCache\r
+from MetaFileWorkspace.MetaFileParser import DscParser\r
+from MetaFileWorkspace.MetaFileParser import DecParser\r
+from MetaFileWorkspace.MetaFileParser import InfParser\r
+from MetaFileWorkspace.MetaFileParser import Fdf\r
+from MetaFileWorkspace.MetaFileTable import MetaFileStorage\r
 import c\r
+import re, string\r
 from Exception import *\r
+from Common.LongFilePathSupport import OpenLongFilePath as open\r
+from Common.MultipleWorkspace import MultipleWorkspace as mws\r
 \r
 ## Ecc\r
 #\r
@@ -40,9 +49,9 @@ from Exception import *
 class Ecc(object):\r
     def __init__(self):\r
         # Version and Copyright\r
-        self.VersionNumber = "0.01"\r
+        self.VersionNumber = ("1.0" + " Build " + gBUILD_VERSION)
         self.Version = "%prog Version " + self.VersionNumber\r
-        self.Copyright = "Copyright (c) 2009, Intel Corporation  All rights reserved."\r
+        self.Copyright = "Copyright (c) 2009 - 2016, Intel Corporation  All rights reserved."
 \r
         self.InitDefaultConfigIni()\r
         self.OutputFile = 'output.txt'\r
@@ -51,29 +60,77 @@ class Ecc(object):
         self.IsInit = True\r
         self.ScanSourceCode = True\r
         self.ScanMetaData = True\r
-        \r
+        self.MetaFile = ''\r
+        self.OnlyScan = None\r
+\r
         # Parse the options and args\r
         self.ParseOption()\r
+        EdkLogger.info(time.strftime("%H:%M:%S, %b.%d %Y ", time.localtime()) + "[00:00]" + "\n")
+        \r
+        #\r
+        # Check EFI_SOURCE (Edk build convention). EDK_SOURCE will always point to ECP\r
+        #\r
+        WorkspaceDir = os.path.normcase(os.path.normpath(os.environ["WORKSPACE"]))\r
+        os.environ["WORKSPACE"] = WorkspaceDir\r
+        \r
+        # set multiple workspace\r
+        PackagesPath = os.getenv("PACKAGES_PATH")\r
+        mws.setWs(WorkspaceDir, PackagesPath)\r
+        \r
+        if "ECP_SOURCE" not in os.environ:\r
+            os.environ["ECP_SOURCE"] = mws.join(WorkspaceDir, GlobalData.gEdkCompatibilityPkg)\r
+        if "EFI_SOURCE" not in os.environ:\r
+            os.environ["EFI_SOURCE"] = os.environ["ECP_SOURCE"]\r
+        if "EDK_SOURCE" not in os.environ:\r
+            os.environ["EDK_SOURCE"] = os.environ["ECP_SOURCE"]\r
 \r
+        #\r
+        # Unify case of characters on case-insensitive systems\r
+        #\r
+        EfiSourceDir = os.path.normcase(os.path.normpath(os.environ["EFI_SOURCE"]))\r
+        EdkSourceDir = os.path.normcase(os.path.normpath(os.environ["EDK_SOURCE"]))\r
+        EcpSourceDir = os.path.normcase(os.path.normpath(os.environ["ECP_SOURCE"]))\r
+        \r
+        os.environ["EFI_SOURCE"] = EfiSourceDir\r
+        os.environ["EDK_SOURCE"] = EdkSourceDir\r
+        os.environ["ECP_SOURCE"] = EcpSourceDir\r
+        \r
+        GlobalData.gWorkspace = WorkspaceDir\r
+        GlobalData.gEfiSource = EfiSourceDir\r
+        GlobalData.gEdkSource = EdkSourceDir\r
+        GlobalData.gEcpSource = EcpSourceDir\r
+\r
+        GlobalData.gGlobalDefines["WORKSPACE"]  = WorkspaceDir\r
+        GlobalData.gGlobalDefines["EFI_SOURCE"] = EfiSourceDir\r
+        GlobalData.gGlobalDefines["EDK_SOURCE"] = EdkSourceDir\r
+        GlobalData.gGlobalDefines["ECP_SOURCE"] = EcpSourceDir\r
+        \r
+        EdkLogger.info("Loading ECC configuration ... done")
         # Generate checkpoints list\r
         EccGlobalData.gConfig = Configuration(self.ConfigFile)\r
-        \r
+\r
         # Generate exception list\r
         EccGlobalData.gException = ExceptionCheck(self.ExceptionFile)\r
-        \r
+\r
         # Init Ecc database\r
         EccGlobalData.gDb = Database.Database(Database.DATABASE_PATH)\r
         EccGlobalData.gDb.InitDatabase(self.IsInit)\r
-        \r
+\r
+        #\r
+        # Get files real name in workspace dir\r
+        #\r
+        GlobalData.gAllFiles = DirCache(GlobalData.gWorkspace)\r
+         \r
         # Build ECC database\r
-        self.BuildDatabase()\r
+#         self.BuildDatabase()\r
+        self.DetectOnlyScanDirs()\r
         \r
         # Start to check\r
         self.Check()\r
-        \r
+\r
         # Show report\r
         self.GenReport()\r
-        \r
+\r
         # Close Database\r
         EccGlobalData.gDb.Close()\r
 \r
@@ -86,81 +143,132 @@ class Ecc(object):
                 return\r
         self.ConfigFile = 'config.ini'\r
 \r
+\r
+    ## DetectOnlyScan\r
+    #\r
+    # Detect whether only scanned folders have been enabled\r
+    #\r
+    def DetectOnlyScanDirs(self):\r
+        if self.OnlyScan == True:\r
+            OnlyScanDirs = []\r
+            # Use regex here if multiple spaces or TAB exists in ScanOnlyDirList in config.ini file\r
+            for folder in re.finditer(r'\S+', EccGlobalData.gConfig.ScanOnlyDirList):\r
+                OnlyScanDirs.append(folder.group())\r
+            if len(OnlyScanDirs) != 0:\r
+                self.BuildDatabase(OnlyScanDirs)\r
+            else:\r
+                EdkLogger.error("ECC", BuildToolError.OPTION_VALUE_INVALID, ExtraData="Use -f option need to fill specific folders in config.ini file")\r
+        else:\r
+            self.BuildDatabase()\r
+            \r
+    \r
     ## BuildDatabase\r
     #\r
     # Build the database for target\r
     #\r
-    def BuildDatabase(self):\r
+    def BuildDatabase(self, SpeciDirs = None):\r
         # Clean report table\r
         EccGlobalData.gDb.TblReport.Drop()\r
         EccGlobalData.gDb.TblReport.Create()\r
-        \r
+\r
         # Build database\r
-        if self.IsInit:\r
-            if self.ScanSourceCode:\r
-                EdkLogger.quiet("Building database for source code ...")\r
-                c.CollectSourceCodeDataIntoDB(EccGlobalData.gTarget)\r
+        if self.IsInit:            \r
             if self.ScanMetaData:\r
-                EdkLogger.quiet("Building database for source code done!")\r
-                self.BuildMetaDataFileDatabase()\r
-        \r
+                EdkLogger.quiet("Building database for Meta Data File ...")\r
+                self.BuildMetaDataFileDatabase(SpeciDirs)\r
+            if self.ScanSourceCode:\r
+                EdkLogger.quiet("Building database for Meta Data File Done!")\r
+                if SpeciDirs == None:\r
+                    c.CollectSourceCodeDataIntoDB(EccGlobalData.gTarget)\r
+                else:\r
+                    for specificDir in SpeciDirs:\r
+                        c.CollectSourceCodeDataIntoDB(os.path.join(EccGlobalData.gTarget, specificDir))\r
+\r
         EccGlobalData.gIdentifierTableList = GetTableList((MODEL_FILE_C, MODEL_FILE_H), 'Identifier', EccGlobalData.gDb)\r
-    \r
+        EccGlobalData.gCFileList = GetFileList(MODEL_FILE_C, EccGlobalData.gDb)\r
+        EccGlobalData.gHFileList = GetFileList(MODEL_FILE_H, EccGlobalData.gDb)\r
+        EccGlobalData.gUFileList = GetFileList(MODEL_FILE_UNI, EccGlobalData.gDb)\r
+\r
     ## BuildMetaDataFileDatabase\r
     #\r
     # Build the database for meta data files\r
     #\r
-    def BuildMetaDataFileDatabase(self):\r
+    def BuildMetaDataFileDatabase(self, SpecificDirs = None):\r
+        ScanFolders = []\r
+        if SpecificDirs == None:\r
+            ScanFolders.append(EccGlobalData.gTarget)\r
+        else:\r
+            for specificDir in SpecificDirs:    \r
+                ScanFolders.append(os.path.join(EccGlobalData.gTarget, specificDir))\r
         EdkLogger.quiet("Building database for meta data files ...")\r
         Op = open(EccGlobalData.gConfig.MetaDataFileCheckPathOfGenerateFileList, 'w+')\r
         #SkipDirs = Read from config file\r
         SkipDirs = EccGlobalData.gConfig.SkipDirList\r
-        for Root, Dirs, Files in os.walk(EccGlobalData.gTarget):\r
-            for Dir in Dirs:\r
-                if Dir.upper() in SkipDirs:\r
-                    Dirs.remove(Dir)\r
-\r
-            for Dir in Dirs:\r
-                Dirname = os.path.join(Root, Dir)\r
-                if os.path.islink(Dirname):\r
-                    Dirname = os.path.realpath(Dirname)\r
-                    if os.path.isdir(Dirname):\r
-                        # symlinks to directories are treated as directories\r
-                        Dirs.remove(Dir)\r
-                        Dirs.append(Dirname)\r
-\r
-            for File in Files:\r
-                if len(File) > 4 and File[-4:].upper() == ".DEC":\r
-                    Filename = os.path.normpath(os.path.join(Root, File))\r
-                    EdkLogger.quiet("Parsing %s" % Filename)\r
-                    Op.write("%s\r" % Filename)\r
-                    Dec(Filename, True, True, EccGlobalData.gWorkspace, EccGlobalData.gDb)\r
-                    continue\r
-                if len(File) > 4 and File[-4:].upper() == ".DSC":\r
-                    Filename = os.path.normpath(os.path.join(Root, File))\r
-                    EdkLogger.quiet("Parsing %s" % Filename)\r
-                    Op.write("%s\r" % Filename)\r
-                    Dsc(Filename, True, True, EccGlobalData.gWorkspace, EccGlobalData.gDb)\r
-                    continue\r
-                if len(File) > 4 and File[-4:].upper() == ".INF":\r
-                    Filename = os.path.normpath(os.path.join(Root, File))\r
-                    EdkLogger.quiet("Parsing %s" % Filename)\r
-                    Op.write("%s\r" % Filename)\r
-                    Inf(Filename, True, True, EccGlobalData.gWorkspace, EccGlobalData.gDb)\r
-                    continue\r
-                if len(File) > 4 and File[-4:].upper() == ".FDF":\r
-                    Filename = os.path.normpath(os.path.join(Root, File))\r
-                    EdkLogger.quiet("Parsing %s" % Filename)\r
-                    Op.write("%s\r" % Filename)\r
-                    Fdf(Filename, True, EccGlobalData.gWorkspace, EccGlobalData.gDb)                    \r
+        SkipDirString = string.join(SkipDirs, '|')\r
+#         p = re.compile(r'.*[\\/](?:%s)[\\/]?.*' % SkipDirString)\r
+        p = re.compile(r'.*[\\/](?:%s^\S)[\\/]?.*' % SkipDirString)\r
+        for scanFolder in ScanFolders:\r
+            for Root, Dirs, Files in os.walk(scanFolder):\r
+                if p.match(Root.upper()):\r
                     continue\r
+                for Dir in Dirs:\r
+                    Dirname = os.path.join(Root, Dir)\r
+                    if os.path.islink(Dirname):\r
+                        Dirname = os.path.realpath(Dirname)\r
+                        if os.path.isdir(Dirname):\r
+                            # symlinks to directories are treated as directories\r
+                            Dirs.remove(Dir)\r
+                            Dirs.append(Dirname)\r
+    \r
+                for File in Files:\r
+                    if len(File) > 4 and File[-4:].upper() == ".DEC":\r
+                        Filename = os.path.normpath(os.path.join(Root, File))\r
+                        EdkLogger.quiet("Parsing %s" % Filename)\r
+                        Op.write("%s\r" % Filename)\r
+                        #Dec(Filename, True, True, EccGlobalData.gWorkspace, EccGlobalData.gDb)\r
+                        self.MetaFile = DecParser(Filename, MODEL_FILE_DEC, EccGlobalData.gDb.TblDec)\r
+                        self.MetaFile.Start()\r
+                        continue\r
+                    if len(File) > 4 and File[-4:].upper() == ".DSC":\r
+                        Filename = os.path.normpath(os.path.join(Root, File))\r
+                        EdkLogger.quiet("Parsing %s" % Filename)\r
+                        Op.write("%s\r" % Filename)\r
+                        #Dsc(Filename, True, True, EccGlobalData.gWorkspace, EccGlobalData.gDb)\r
+                        self.MetaFile = DscParser(PathClass(Filename, Root), MODEL_FILE_DSC, MetaFileStorage(EccGlobalData.gDb.TblDsc.Cur, Filename, MODEL_FILE_DSC, True))\r
+                        # alwasy do post-process, in case of macros change\r
+                        self.MetaFile.DoPostProcess()\r
+                        self.MetaFile.Start()\r
+                        self.MetaFile._PostProcess()\r
+                        continue\r
+                    if len(File) > 4 and File[-4:].upper() == ".INF":\r
+                        Filename = os.path.normpath(os.path.join(Root, File))\r
+                        EdkLogger.quiet("Parsing %s" % Filename)\r
+                        Op.write("%s\r" % Filename)\r
+                        #Inf(Filename, True, True, EccGlobalData.gWorkspace, EccGlobalData.gDb)\r
+                        self.MetaFile = InfParser(Filename, MODEL_FILE_INF, EccGlobalData.gDb.TblInf)\r
+                        self.MetaFile.Start()\r
+                        continue\r
+                    if len(File) > 4 and File[-4:].upper() == ".FDF":\r
+                        Filename = os.path.normpath(os.path.join(Root, File))\r
+                        EdkLogger.quiet("Parsing %s" % Filename)\r
+                        Op.write("%s\r" % Filename)\r
+                        Fdf(Filename, True, EccGlobalData.gWorkspace, EccGlobalData.gDb)\r
+                        continue\r
+                    if len(File) > 4 and File[-4:].upper() == ".UNI":\r
+                        Filename = os.path.normpath(os.path.join(Root, File))\r
+                        EdkLogger.quiet("Parsing %s" % Filename)\r
+                        Op.write("%s\r" % Filename)\r
+                        FileID = EccGlobalData.gDb.TblFile.InsertFile(Filename, MODEL_FILE_UNI)\r
+                        EccGlobalData.gDb.TblReport.UpdateBelongsToItemByFile(FileID, File)\r
+                        continue\r
+\r
         Op.close()\r
-        \r
+\r
         # Commit to database\r
         EccGlobalData.gDb.Conn.commit()\r
-        \r
+\r
         EdkLogger.quiet("Building database for meta data files done!")\r
-    \r
+\r
     ##\r
     #\r
     # Check each checkpoint\r
@@ -170,7 +278,7 @@ class Ecc(object):
         EccCheck = Check()\r
         EccCheck.Check()\r
         EdkLogger.quiet("Checking  done!")\r
-    \r
+\r
     ##\r
     #\r
     # Generate the scan report\r
@@ -179,7 +287,7 @@ class Ecc(object):
         EdkLogger.quiet("Generating report ...")\r
         EccGlobalData.gDb.TblReport.ToCSV(self.ReportFile)\r
         EdkLogger.quiet("Generating report done!")\r
-        \r
+\r
     def GetRealPathCase(self, path):\r
         TmpPath = path.rstrip(os.sep)\r
         PathParts = TmpPath.split(os.sep)\r
@@ -193,7 +301,7 @@ class Ecc(object):
             for Dir in Dirs:\r
                 if Dir.upper() == PathParts[0].upper():\r
                     return Dir\r
-        \r
+\r
         if PathParts[0].strip().endswith(':'):\r
             PathParts[0] = PathParts[0].upper()\r
         ParentDir = PathParts[0]\r
@@ -201,7 +309,7 @@ class Ecc(object):
         if PathParts[0] == '':\r
             RealPath = os.sep\r
             ParentDir = os.sep\r
-        \r
+\r
         PathParts.remove(PathParts[0])    # need to remove the parent\r
         for Part in PathParts:\r
             Dirs = os.listdir(ParentDir + os.sep)\r
@@ -212,20 +320,22 @@ class Ecc(object):
                     break\r
             ParentDir += os.sep\r
             ParentDir += Dir\r
-            \r
+\r
         return RealPath\r
-        \r
+\r
     ## ParseOption\r
     #\r
     # Parse options\r
     #\r
     def ParseOption(self):\r
-        EdkLogger.quiet("Loading ECC configuration ... done")\r
         (Options, Target) = self.EccOptionParser()\r
-        \r
+\r
+        if Options.Workspace:\r
+            os.environ["WORKSPACE"] = Options.Workspace\r
+\r
         # Check workspace envirnoment\r
         if "WORKSPACE" not in os.environ:\r
-            EdkLogger.error("ECC", BuildToolError.ATTRIBUTE_NOT_AVAILABLE, "Environment variable not found", \r
+            EdkLogger.error("ECC", BuildToolError.ATTRIBUTE_NOT_AVAILABLE, "Environment variable not found",\r
                             ExtraData="WORKSPACE")\r
         else:\r
             EccGlobalData.gWorkspace = os.path.normpath(os.getenv("WORKSPACE"))\r
@@ -234,7 +344,7 @@ class Ecc(object):
             os.environ["WORKSPACE"] = EccGlobalData.gWorkspace\r
         # Set log level\r
         self.SetLogLevel(Options)\r
-        \r
+\r
         # Set other options\r
         if Options.ConfigFile != None:\r
             self.ConfigFile = Options.ConfigFile\r
@@ -242,6 +352,8 @@ class Ecc(object):
             self.OutputFile = Options.OutputFile\r
         if Options.ReportFile != None:\r
             self.ReportFile = Options.ReportFile\r
+        if Options.ExceptionFile != None:\r
+            self.ExceptionFile = Options.ExceptionFile\r
         if Options.Target != None:\r
             if not os.path.isdir(Options.Target):\r
                 EdkLogger.error("ECC", BuildToolError.OPTION_VALUE_INVALID, ExtraData="Target [%s] does NOT exist" % Options.Target)\r
@@ -258,12 +370,14 @@ class Ecc(object):
             self.ScanSourceCode = False\r
         if Options.sourcecode != None:\r
             self.ScanMetaData = False\r
-        \r
+        if Options.folders != None:\r
+            self.OnlyScan = True\r
+\r
     ## SetLogLevel\r
     #\r
     # Set current log level of the tool based on args\r
     #\r
-    # @param Option:  The option list including log level setting \r
+    # @param Option:  The option list including log level setting\r
     #\r
     def SetLogLevel(self, Option):\r
         if Option.verbose != None:\r
@@ -292,22 +406,26 @@ class Ecc(object):
             help="Specify the name of an output file, if and only if one filename was specified.")\r
         Parser.add_option("-r", "--reportfile filename", action="store", type="string", dest="ReportFile",\r
             help="Specify the name of an report file, if and only if one filename was specified.")\r
+        Parser.add_option("-e", "--exceptionfile filename", action="store", type="string", dest="ExceptionFile",\r
+            help="Specify the name of an exception file, if and only if one filename was specified.")\r
         Parser.add_option("-m", "--metadata", action="store_true", type=None, help="Only scan meta-data files information if this option is specified.")\r
         Parser.add_option("-s", "--sourcecode", action="store_true", type=None, help="Only scan source code files information if this option is specified.")\r
         Parser.add_option("-k", "--keepdatabase", action="store_true", type=None, help="The existing Ecc database will not be cleaned except report information if this option is specified.")\r
-        Parser.add_option("-l", "--log filename", action="store", dest="LogFile", help="""If specified, the tool should emit the changes that \r
-                                                                                          were made by the tool after printing the result message. \r
-                                                                                          If filename, the emit to the file, otherwise emit to \r
-                                                                                          standard output. If no modifications were made, then do not \r
+        Parser.add_option("-l", "--log filename", action="store", dest="LogFile", help="""If specified, the tool should emit the changes that\r
+                                                                                          were made by the tool after printing the result message.\r
+                                                                                          If filename, the emit to the file, otherwise emit to\r
+                                                                                          standard output. If no modifications were made, then do not\r
                                                                                           create a log file, or output a log message.""")\r
         Parser.add_option("-q", "--quiet", action="store_true", type=None, help="Disable all messages except FATAL ERRORS.")\r
         Parser.add_option("-v", "--verbose", action="store_true", type=None, help="Turn on verbose output with informational messages printed, "\\r
                                                                                    "including library instances selected, final dependency expression, "\\r
                                                                                    "and warning messages, etc.")\r
         Parser.add_option("-d", "--debug", action="store", type="int", help="Enable debug messages at specified level.")\r
-    \r
+        Parser.add_option("-w", "--workspace", action="store", type="string", dest='Workspace', help="Specify workspace.")\r
+        Parser.add_option("-f", "--folders", action="store_true", type=None, help="Only scanning specified folders which are recorded in config.ini file.")\r
+\r
         (Opt, Args)=Parser.parse_args()\r
-        \r
+\r
         return (Opt, Args)\r
 \r
 ##\r
@@ -319,7 +437,6 @@ if __name__ == '__main__':
     # Initialize log system\r
     EdkLogger.Initialize()\r
     EdkLogger.IsRaiseError = False\r
-    EdkLogger.quiet(time.strftime("%H:%M:%S, %b.%d %Y ", time.localtime()) + "[00:00]" + "\n")\r
 \r
     StartTime = time.clock()\r
     Ecc = Ecc()\r