]> git.proxmox.com Git - mirror_edk2.git/blame - BaseTools/Source/Python/Ecc/Ecc.py
MdeModulePkg: Fix build warning on Xhci driver with XCode 32 tool chain.
[mirror_edk2.git] / BaseTools / Source / Python / Ecc / Ecc.py
CommitLineData
30fdf114
LG
1## @file\r
2# This file is used to be the main entrance of ECC tool\r
3#\r
40d841f6
LG
4# Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>\r
5# This program and the accompanying materials\r
30fdf114
LG
6# are licensed and made available under the terms and conditions of the BSD License\r
7# which accompanies this distribution. The full text of the license may be found at\r
8# http://opensource.org/licenses/bsd-license.php\r
9#\r
10# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
12#\r
13\r
14##\r
15# Import Modules\r
16#\r
17import os, time, glob, sys\r
18import Common.EdkLogger as EdkLogger\r
19import Database\r
20import EccGlobalData\r
21from MetaDataParser import *\r
22from optparse import OptionParser\r
23from Configuration import Configuration\r
24from Check import Check\r
9508d0fa 25import Common.GlobalData as GlobalData\r
d0acc87a 26\r
30fdf114 27from Common.String import NormPath\r
b36d134f 28from Common.BuildVersion import gBUILD_VERSION\r
30fdf114 29from Common import BuildToolError\r
9508d0fa 30from Common.Misc import PathClass\r
d0acc87a
LG
31from MetaFileWorkspace.MetaFileParser import DscParser\r
32from MetaFileWorkspace.MetaFileParser import DecParser\r
33from MetaFileWorkspace.MetaFileParser import InfParser\r
34from MetaFileWorkspace.MetaFileParser import Fdf\r
35from MetaFileWorkspace.MetaFileTable import MetaFileStorage\r
30fdf114 36import c\r
fd171542 37import re, string\r
30fdf114
LG
38from Exception import *\r
39\r
40## Ecc\r
41#\r
42# This class is used to define Ecc main entrance\r
43#\r
44# @param object: Inherited from object class\r
45#\r
46class Ecc(object):\r
47 def __init__(self):\r
48 # Version and Copyright\r
b36d134f 49 self.VersionNumber = ("0.01" + " " + gBUILD_VERSION)\r
30fdf114 50 self.Version = "%prog Version " + self.VersionNumber\r
52302d4d 51 self.Copyright = "Copyright (c) 2009 - 2010, Intel Corporation All rights reserved."\r
30fdf114
LG
52\r
53 self.InitDefaultConfigIni()\r
54 self.OutputFile = 'output.txt'\r
55 self.ReportFile = 'Report.csv'\r
56 self.ExceptionFile = 'exception.xml'\r
57 self.IsInit = True\r
58 self.ScanSourceCode = True\r
59 self.ScanMetaData = True\r
d0acc87a 60 self.MetaFile = ''\r
fd171542 61\r
30fdf114
LG
62 # Parse the options and args\r
63 self.ParseOption()\r
9508d0fa
LG
64 \r
65 #\r
66 # Check EFI_SOURCE (Edk build convention). EDK_SOURCE will always point to ECP\r
67 #\r
68 WorkspaceDir = os.path.normcase(os.path.normpath(os.environ["WORKSPACE"]))\r
69 os.environ["WORKSPACE"] = WorkspaceDir\r
70 if "ECP_SOURCE" not in os.environ:\r
71 os.environ["ECP_SOURCE"] = os.path.join(WorkspaceDir, GlobalData.gEdkCompatibilityPkg)\r
72 if "EFI_SOURCE" not in os.environ:\r
73 os.environ["EFI_SOURCE"] = os.environ["ECP_SOURCE"]\r
74 if "EDK_SOURCE" not in os.environ:\r
75 os.environ["EDK_SOURCE"] = os.environ["ECP_SOURCE"]\r
76\r
77 #\r
78 # Unify case of characters on case-insensitive systems\r
79 #\r
80 EfiSourceDir = os.path.normcase(os.path.normpath(os.environ["EFI_SOURCE"]))\r
81 EdkSourceDir = os.path.normcase(os.path.normpath(os.environ["EDK_SOURCE"]))\r
82 EcpSourceDir = os.path.normcase(os.path.normpath(os.environ["ECP_SOURCE"]))\r
83 \r
84 os.environ["EFI_SOURCE"] = EfiSourceDir\r
85 os.environ["EDK_SOURCE"] = EdkSourceDir\r
86 os.environ["ECP_SOURCE"] = EcpSourceDir\r
87 \r
88 GlobalData.gWorkspace = WorkspaceDir\r
89 GlobalData.gEfiSource = EfiSourceDir\r
90 GlobalData.gEdkSource = EdkSourceDir\r
91 GlobalData.gEcpSource = EcpSourceDir\r
92\r
93 GlobalData.gGlobalDefines["WORKSPACE"] = WorkspaceDir\r
94 GlobalData.gGlobalDefines["EFI_SOURCE"] = EfiSourceDir\r
95 GlobalData.gGlobalDefines["EDK_SOURCE"] = EdkSourceDir\r
96 GlobalData.gGlobalDefines["ECP_SOURCE"] = EcpSourceDir\r
97 \r
98 \r
30fdf114
LG
99 # Generate checkpoints list\r
100 EccGlobalData.gConfig = Configuration(self.ConfigFile)\r
fd171542 101\r
30fdf114
LG
102 # Generate exception list\r
103 EccGlobalData.gException = ExceptionCheck(self.ExceptionFile)\r
fd171542 104\r
30fdf114
LG
105 # Init Ecc database\r
106 EccGlobalData.gDb = Database.Database(Database.DATABASE_PATH)\r
107 EccGlobalData.gDb.InitDatabase(self.IsInit)\r
fd171542 108\r
30fdf114
LG
109 # Build ECC database\r
110 self.BuildDatabase()\r
fd171542 111\r
30fdf114
LG
112 # Start to check\r
113 self.Check()\r
fd171542 114\r
30fdf114
LG
115 # Show report\r
116 self.GenReport()\r
fd171542 117\r
30fdf114
LG
118 # Close Database\r
119 EccGlobalData.gDb.Close()\r
120\r
121 def InitDefaultConfigIni(self):\r
122 paths = map(lambda p: os.path.join(p, 'Ecc', 'config.ini'), sys.path)\r
123 paths = (os.path.realpath('config.ini'),) + tuple(paths)\r
124 for path in paths:\r
125 if os.path.exists(path):\r
126 self.ConfigFile = path\r
127 return\r
128 self.ConfigFile = 'config.ini'\r
129\r
130 ## BuildDatabase\r
131 #\r
132 # Build the database for target\r
133 #\r
134 def BuildDatabase(self):\r
135 # Clean report table\r
136 EccGlobalData.gDb.TblReport.Drop()\r
137 EccGlobalData.gDb.TblReport.Create()\r
fd171542 138\r
30fdf114
LG
139 # Build database\r
140 if self.IsInit:\r
141 if self.ScanSourceCode:\r
142 EdkLogger.quiet("Building database for source code ...")\r
143 c.CollectSourceCodeDataIntoDB(EccGlobalData.gTarget)\r
144 if self.ScanMetaData:\r
145 EdkLogger.quiet("Building database for source code done!")\r
146 self.BuildMetaDataFileDatabase()\r
fd171542 147\r
30fdf114 148 EccGlobalData.gIdentifierTableList = GetTableList((MODEL_FILE_C, MODEL_FILE_H), 'Identifier', EccGlobalData.gDb)\r
e56468c0 149 EccGlobalData.gCFileList = GetFileList(MODEL_FILE_C, EccGlobalData.gDb)\r
150 EccGlobalData.gHFileList = GetFileList(MODEL_FILE_H, EccGlobalData.gDb)\r
fd171542 151\r
30fdf114
LG
152 ## BuildMetaDataFileDatabase\r
153 #\r
154 # Build the database for meta data files\r
155 #\r
156 def BuildMetaDataFileDatabase(self):\r
157 EdkLogger.quiet("Building database for meta data files ...")\r
158 Op = open(EccGlobalData.gConfig.MetaDataFileCheckPathOfGenerateFileList, 'w+')\r
159 #SkipDirs = Read from config file\r
160 SkipDirs = EccGlobalData.gConfig.SkipDirList\r
fd171542 161 SkipDirString = string.join(SkipDirs, '|')\r
162 p = re.compile(r'.*[\\/](?:%s)[\\/]?.*' % SkipDirString)\r
30fdf114 163 for Root, Dirs, Files in os.walk(EccGlobalData.gTarget):\r
fd171542 164 if p.match(Root.upper()):\r
165 continue\r
30fdf114
LG
166 for Dir in Dirs:\r
167 Dirname = os.path.join(Root, Dir)\r
168 if os.path.islink(Dirname):\r
169 Dirname = os.path.realpath(Dirname)\r
170 if os.path.isdir(Dirname):\r
171 # symlinks to directories are treated as directories\r
172 Dirs.remove(Dir)\r
173 Dirs.append(Dirname)\r
174\r
175 for File in Files:\r
176 if len(File) > 4 and File[-4:].upper() == ".DEC":\r
177 Filename = os.path.normpath(os.path.join(Root, File))\r
178 EdkLogger.quiet("Parsing %s" % Filename)\r
179 Op.write("%s\r" % Filename)\r
d0acc87a
LG
180 #Dec(Filename, True, True, EccGlobalData.gWorkspace, EccGlobalData.gDb)\r
181 self.MetaFile = DecParser(Filename, MODEL_FILE_DEC, EccGlobalData.gDb.TblDec)\r
182 self.MetaFile.Start()\r
30fdf114
LG
183 continue\r
184 if len(File) > 4 and File[-4:].upper() == ".DSC":\r
185 Filename = os.path.normpath(os.path.join(Root, File))\r
186 EdkLogger.quiet("Parsing %s" % Filename)\r
187 Op.write("%s\r" % Filename)\r
d0acc87a 188 #Dsc(Filename, True, True, EccGlobalData.gWorkspace, EccGlobalData.gDb)\r
9508d0fa 189 self.MetaFile = DscParser(PathClass(Filename, Root), MODEL_FILE_DSC, MetaFileStorage(EccGlobalData.gDb.TblDsc.Cur, Filename, MODEL_FILE_DSC, True))\r
d0acc87a
LG
190 # alwasy do post-process, in case of macros change\r
191 self.MetaFile.DoPostProcess()\r
192 self.MetaFile.Start()\r
193 self.MetaFile._PostProcess()\r
30fdf114
LG
194 continue\r
195 if len(File) > 4 and File[-4:].upper() == ".INF":\r
196 Filename = os.path.normpath(os.path.join(Root, File))\r
197 EdkLogger.quiet("Parsing %s" % Filename)\r
198 Op.write("%s\r" % Filename)\r
d0acc87a
LG
199 #Inf(Filename, True, True, EccGlobalData.gWorkspace, EccGlobalData.gDb)\r
200 self.MetaFile = InfParser(Filename, MODEL_FILE_INF, EccGlobalData.gDb.TblInf)\r
201 self.MetaFile.Start()\r
30fdf114
LG
202 continue\r
203 if len(File) > 4 and File[-4:].upper() == ".FDF":\r
204 Filename = os.path.normpath(os.path.join(Root, File))\r
205 EdkLogger.quiet("Parsing %s" % Filename)\r
206 Op.write("%s\r" % Filename)\r
fd171542 207 Fdf(Filename, True, EccGlobalData.gWorkspace, EccGlobalData.gDb)\r
30fdf114
LG
208 continue\r
209 Op.close()\r
fd171542 210\r
30fdf114
LG
211 # Commit to database\r
212 EccGlobalData.gDb.Conn.commit()\r
fd171542 213\r
30fdf114 214 EdkLogger.quiet("Building database for meta data files done!")\r
fd171542 215\r
30fdf114
LG
216 ##\r
217 #\r
218 # Check each checkpoint\r
219 #\r
220 def Check(self):\r
221 EdkLogger.quiet("Checking ...")\r
222 EccCheck = Check()\r
223 EccCheck.Check()\r
224 EdkLogger.quiet("Checking done!")\r
fd171542 225\r
30fdf114
LG
226 ##\r
227 #\r
228 # Generate the scan report\r
229 #\r
230 def GenReport(self):\r
231 EdkLogger.quiet("Generating report ...")\r
232 EccGlobalData.gDb.TblReport.ToCSV(self.ReportFile)\r
233 EdkLogger.quiet("Generating report done!")\r
fd171542 234\r
30fdf114
LG
235 def GetRealPathCase(self, path):\r
236 TmpPath = path.rstrip(os.sep)\r
237 PathParts = TmpPath.split(os.sep)\r
238 if len(PathParts) == 0:\r
239 return path\r
240 if len(PathParts) == 1:\r
241 if PathParts[0].strip().endswith(':'):\r
242 return PathParts[0].upper()\r
243 # Relative dir, list . current dir\r
244 Dirs = os.listdir('.')\r
245 for Dir in Dirs:\r
246 if Dir.upper() == PathParts[0].upper():\r
247 return Dir\r
fd171542 248\r
30fdf114
LG
249 if PathParts[0].strip().endswith(':'):\r
250 PathParts[0] = PathParts[0].upper()\r
251 ParentDir = PathParts[0]\r
252 RealPath = ParentDir\r
253 if PathParts[0] == '':\r
254 RealPath = os.sep\r
255 ParentDir = os.sep\r
fd171542 256\r
30fdf114
LG
257 PathParts.remove(PathParts[0]) # need to remove the parent\r
258 for Part in PathParts:\r
259 Dirs = os.listdir(ParentDir + os.sep)\r
260 for Dir in Dirs:\r
261 if Dir.upper() == Part.upper():\r
262 RealPath += os.sep\r
263 RealPath += Dir\r
264 break\r
265 ParentDir += os.sep\r
266 ParentDir += Dir\r
fd171542 267\r
30fdf114 268 return RealPath\r
fd171542 269\r
30fdf114
LG
270 ## ParseOption\r
271 #\r
272 # Parse options\r
273 #\r
274 def ParseOption(self):\r
275 EdkLogger.quiet("Loading ECC configuration ... done")\r
276 (Options, Target) = self.EccOptionParser()\r
fd171542 277\r
52302d4d
LG
278 if Options.Workspace:\r
279 os.environ["WORKSPACE"] = Options.Workspace\r
e56468c0 280\r
30fdf114
LG
281 # Check workspace envirnoment\r
282 if "WORKSPACE" not in os.environ:\r
fd171542 283 EdkLogger.error("ECC", BuildToolError.ATTRIBUTE_NOT_AVAILABLE, "Environment variable not found",\r
30fdf114
LG
284 ExtraData="WORKSPACE")\r
285 else:\r
286 EccGlobalData.gWorkspace = os.path.normpath(os.getenv("WORKSPACE"))\r
287 if not os.path.exists(EccGlobalData.gWorkspace):\r
288 EdkLogger.error("ECC", BuildToolError.FILE_NOT_FOUND, ExtraData="WORKSPACE = %s" % EccGlobalData.gWorkspace)\r
289 os.environ["WORKSPACE"] = EccGlobalData.gWorkspace\r
290 # Set log level\r
291 self.SetLogLevel(Options)\r
fd171542 292\r
30fdf114
LG
293 # Set other options\r
294 if Options.ConfigFile != None:\r
295 self.ConfigFile = Options.ConfigFile\r
296 if Options.OutputFile != None:\r
297 self.OutputFile = Options.OutputFile\r
298 if Options.ReportFile != None:\r
299 self.ReportFile = Options.ReportFile\r
52302d4d
LG
300 if Options.ExceptionFile != None:\r
301 self.ExceptionFile = Options.ExceptionFile\r
30fdf114
LG
302 if Options.Target != None:\r
303 if not os.path.isdir(Options.Target):\r
304 EdkLogger.error("ECC", BuildToolError.OPTION_VALUE_INVALID, ExtraData="Target [%s] does NOT exist" % Options.Target)\r
305 else:\r
306 EccGlobalData.gTarget = self.GetRealPathCase(os.path.normpath(Options.Target))\r
307 else:\r
308 EdkLogger.warn("Ecc", EdkLogger.ECC_ERROR, "The target source tree was not specified, using current WORKSPACE instead!")\r
309 EccGlobalData.gTarget = os.path.normpath(os.getenv("WORKSPACE"))\r
310 if Options.keepdatabase != None:\r
311 self.IsInit = False\r
312 if Options.metadata != None and Options.sourcecode != None:\r
313 EdkLogger.error("ECC", BuildToolError.OPTION_CONFLICT, ExtraData="-m and -s can't be specified at one time")\r
314 if Options.metadata != None:\r
315 self.ScanSourceCode = False\r
316 if Options.sourcecode != None:\r
317 self.ScanMetaData = False\r
fd171542 318\r
30fdf114
LG
319 ## SetLogLevel\r
320 #\r
321 # Set current log level of the tool based on args\r
322 #\r
fd171542 323 # @param Option: The option list including log level setting\r
30fdf114
LG
324 #\r
325 def SetLogLevel(self, Option):\r
326 if Option.verbose != None:\r
327 EdkLogger.SetLevel(EdkLogger.VERBOSE)\r
328 elif Option.quiet != None:\r
329 EdkLogger.SetLevel(EdkLogger.QUIET)\r
330 elif Option.debug != None:\r
331 EdkLogger.SetLevel(Option.debug + 1)\r
332 else:\r
333 EdkLogger.SetLevel(EdkLogger.INFO)\r
334\r
335 ## Parse command line options\r
336 #\r
337 # Using standard Python module optparse to parse command line option of this tool.\r
338 #\r
339 # @retval Opt A optparse.Values object containing the parsed options\r
340 # @retval Args Target of build command\r
341 #\r
342 def EccOptionParser(self):\r
343 Parser = OptionParser(description = self.Copyright, version = self.Version, prog = "Ecc.exe", usage = "%prog [options]")\r
344 Parser.add_option("-t", "--target sourcepath", action="store", type="string", dest='Target',\r
345 help="Check all files under the target workspace.")\r
346 Parser.add_option("-c", "--config filename", action="store", type="string", dest="ConfigFile",\r
347 help="Specify a configuration file. Defaultly use config.ini under ECC tool directory.")\r
348 Parser.add_option("-o", "--outfile filename", action="store", type="string", dest="OutputFile",\r
349 help="Specify the name of an output file, if and only if one filename was specified.")\r
350 Parser.add_option("-r", "--reportfile filename", action="store", type="string", dest="ReportFile",\r
351 help="Specify the name of an report file, if and only if one filename was specified.")\r
52302d4d
LG
352 Parser.add_option("-e", "--exceptionfile filename", action="store", type="string", dest="ExceptionFile",\r
353 help="Specify the name of an exception file, if and only if one filename was specified.")\r
30fdf114
LG
354 Parser.add_option("-m", "--metadata", action="store_true", type=None, help="Only scan meta-data files information if this option is specified.")\r
355 Parser.add_option("-s", "--sourcecode", action="store_true", type=None, help="Only scan source code files information if this option is specified.")\r
356 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
fd171542 357 Parser.add_option("-l", "--log filename", action="store", dest="LogFile", help="""If specified, the tool should emit the changes that\r
358 were made by the tool after printing the result message.\r
359 If filename, the emit to the file, otherwise emit to\r
360 standard output. If no modifications were made, then do not\r
30fdf114
LG
361 create a log file, or output a log message.""")\r
362 Parser.add_option("-q", "--quiet", action="store_true", type=None, help="Disable all messages except FATAL ERRORS.")\r
363 Parser.add_option("-v", "--verbose", action="store_true", type=None, help="Turn on verbose output with informational messages printed, "\\r
364 "including library instances selected, final dependency expression, "\\r
365 "and warning messages, etc.")\r
366 Parser.add_option("-d", "--debug", action="store", type="int", help="Enable debug messages at specified level.")\r
52302d4d 367 Parser.add_option("-w", "--workspace", action="store", type="string", dest='Workspace', help="Specify workspace.")\r
fd171542 368\r
30fdf114 369 (Opt, Args)=Parser.parse_args()\r
fd171542 370\r
30fdf114
LG
371 return (Opt, Args)\r
372\r
373##\r
374#\r
375# This acts like the main() function for the script, unless it is 'import'ed into another\r
376# script.\r
377#\r
378if __name__ == '__main__':\r
379 # Initialize log system\r
380 EdkLogger.Initialize()\r
381 EdkLogger.IsRaiseError = False\r
382 EdkLogger.quiet(time.strftime("%H:%M:%S, %b.%d %Y ", time.localtime()) + "[00:00]" + "\n")\r
383\r
384 StartTime = time.clock()\r
385 Ecc = Ecc()\r
386 FinishTime = time.clock()\r
387\r
388 BuildDuration = time.strftime("%M:%S", time.gmtime(int(round(FinishTime - StartTime))))\r
389 EdkLogger.quiet("\n%s [%s]" % (time.strftime("%H:%M:%S, %b.%d %Y", time.localtime()), BuildDuration))\r