Fix build error.
[mirror_edk2.git] / BaseTools / Source / Python / AutoGen / AutoGen.py
CommitLineData
52302d4d
LG
1## @file\r
2# Generate AutoGen.h, AutoGen.c and *.depex files\r
3#\r
40d841f6
LG
4# Copyright (c) 2007 - 2010, Intel Corporation. All rights reserved.<BR>\r
5# This program and the accompanying materials\r
52302d4d
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## Import Modules\r
15#\r
16import os\r
17import re\r
18import os.path as path\r
19import copy\r
20\r
21import GenC\r
22import GenMake\r
23import GenDepex\r
24from StringIO import StringIO\r
25\r
26from StrGather import *\r
27from BuildEngine import BuildRule\r
28\r
29from Common.BuildToolError import *\r
30from Common.DataType import *\r
31from Common.Misc import *\r
32from Common.String import *\r
33import Common.GlobalData as GlobalData\r
34from GenFds.FdfParser import *\r
35from CommonDataClass.CommonClass import SkuInfoClass\r
36from Workspace.BuildClassObject import *\r
e56468c0 37import Common.VpdInfoFile as VpdInfoFile\r
52302d4d
LG
38\r
39## Regular expression for splitting Dependency Expression stirng into tokens\r
40gDepexTokenPattern = re.compile("(\(|\)|\w+| \S+\.inf)")\r
41\r
42## Mapping Makefile type\r
43gMakeTypeMap = {"MSFT":"nmake", "GCC":"gmake"}\r
44\r
45\r
46## Build rule configuration file\r
47gBuildRuleFile = 'Conf/build_rule.txt'\r
48\r
49## default file name for AutoGen\r
50gAutoGenCodeFileName = "AutoGen.c"\r
51gAutoGenHeaderFileName = "AutoGen.h"\r
52gAutoGenStringFileName = "%(module_name)sStrDefs.h"\r
53gAutoGenStringFormFileName = "%(module_name)sStrDefs.hpk"\r
54gAutoGenDepexFileName = "%(module_name)s.depex"\r
55\r
56## Base class for AutoGen\r
57#\r
58# This class just implements the cache mechanism of AutoGen objects.\r
59#\r
60class AutoGen(object):\r
61 # database to maintain the objects of xxxAutoGen\r
62 _CACHE_ = {} # (BuildTarget, ToolChain) : {ARCH : {platform file: AutoGen object}}}\r
63\r
64 ## Factory method\r
65 #\r
66 # @param Class class object of real AutoGen class\r
67 # (WorkspaceAutoGen, ModuleAutoGen or PlatformAutoGen)\r
68 # @param Workspace Workspace directory or WorkspaceAutoGen object\r
69 # @param MetaFile The path of meta file\r
70 # @param Target Build target\r
71 # @param Toolchain Tool chain name\r
72 # @param Arch Target arch\r
73 # @param *args The specific class related parameters\r
74 # @param **kwargs The specific class related dict parameters\r
75 #\r
76 def __new__(Class, Workspace, MetaFile, Target, Toolchain, Arch, *args, **kwargs):\r
77 # check if the object has been created\r
78 Key = (Target, Toolchain)\r
79 if Key not in Class._CACHE_ or Arch not in Class._CACHE_[Key] \\r
80 or MetaFile not in Class._CACHE_[Key][Arch]:\r
81 AutoGenObject = super(AutoGen, Class).__new__(Class)\r
82 # call real constructor\r
83 if not AutoGenObject._Init(Workspace, MetaFile, Target, Toolchain, Arch, *args, **kwargs):\r
84 return None\r
85 if Key not in Class._CACHE_:\r
86 Class._CACHE_[Key] = {}\r
87 if Arch not in Class._CACHE_[Key]:\r
88 Class._CACHE_[Key][Arch] = {}\r
89 Class._CACHE_[Key][Arch][MetaFile] = AutoGenObject\r
90 else:\r
91 AutoGenObject = Class._CACHE_[Key][Arch][MetaFile]\r
92\r
93 return AutoGenObject\r
94\r
95 ## hash() operator\r
96 #\r
97 # The file path of platform file will be used to represent hash value of this object\r
98 #\r
99 # @retval int Hash value of the file path of platform file\r
100 #\r
101 def __hash__(self):\r
102 return hash(self.MetaFile)\r
103\r
104 ## str() operator\r
105 #\r
106 # The file path of platform file will be used to represent this object\r
107 #\r
108 # @retval string String of platform file path\r
109 #\r
110 def __str__(self):\r
111 return str(self.MetaFile)\r
112\r
113 ## "==" operator\r
114 def __eq__(self, Other):\r
115 return Other and self.MetaFile == Other\r
116\r
117## Workspace AutoGen class\r
118#\r
119# This class is used mainly to control the whole platform build for different\r
120# architecture. This class will generate top level makefile.\r
121#\r
122class WorkspaceAutoGen(AutoGen):\r
123 ## Real constructor of WorkspaceAutoGen\r
124 #\r
125 # This method behaves the same as __init__ except that it needs explict invoke\r
126 # (in super class's __new__ method)\r
127 #\r
128 # @param WorkspaceDir Root directory of workspace\r
129 # @param ActivePlatform Meta-file of active platform\r
130 # @param Target Build target\r
131 # @param Toolchain Tool chain name\r
132 # @param ArchList List of architecture of current build\r
133 # @param MetaFileDb Database containing meta-files\r
134 # @param BuildConfig Configuration of build\r
135 # @param ToolDefinition Tool chain definitions\r
136 # @param FlashDefinitionFile File of flash definition\r
137 # @param Fds FD list to be generated\r
138 # @param Fvs FV list to be generated\r
139 # @param SkuId SKU id from command line\r
140 #\r
141 def _Init(self, WorkspaceDir, ActivePlatform, Target, Toolchain, ArchList, MetaFileDb,\r
f3decdc3 142 BuildConfig, ToolDefinition, FlashDefinitionFile='', Fds=[], Fvs=[], SkuId='', UniFlag=None):\r
52302d4d
LG
143 self.MetaFile = ActivePlatform.MetaFile\r
144 self.WorkspaceDir = WorkspaceDir\r
145 self.Platform = ActivePlatform\r
146 self.BuildTarget = Target\r
147 self.ToolChain = Toolchain\r
148 self.ArchList = ArchList\r
149 self.SkuId = SkuId\r
f3decdc3 150 self.UniFlag = UniFlag\r
52302d4d
LG
151\r
152 self.BuildDatabase = MetaFileDb\r
153 self.TargetTxt = BuildConfig\r
154 self.ToolDef = ToolDefinition\r
155 self.FdfFile = FlashDefinitionFile\r
156 self.FdTargetList = Fds\r
157 self.FvTargetList = Fvs\r
158 self.AutoGenObjectList = []\r
159\r
160 # there's many relative directory operations, so ...\r
161 os.chdir(self.WorkspaceDir)\r
162\r
163 # parse FDF file to get PCDs in it, if any\r
164 if self.FdfFile != None and self.FdfFile != '':\r
08dd311f
LG
165 #\r
166 # Make global macros available when parsing FDF file\r
167 #\r
168 InputMacroDict.update(self.BuildDatabase.WorkspaceDb._GlobalMacros)\r
52302d4d
LG
169 Fdf = FdfParser(self.FdfFile.Path)\r
170 Fdf.ParseFile()\r
171 PcdSet = Fdf.Profile.PcdDict\r
172 ModuleList = Fdf.Profile.InfList\r
173 self.FdfProfile = Fdf.Profile\r
174 else:\r
175 PcdSet = {}\r
176 ModuleList = []\r
177 self.FdfProfile = None\r
178 \r
179 # apply SKU and inject PCDs from Flash Definition file\r
180 for Arch in self.ArchList:\r
181 Platform = self.BuildDatabase[self.MetaFile, Arch]\r
182 Platform.SkuName = self.SkuId\r
183 for Name, Guid in PcdSet:\r
184 Platform.AddPcd(Name, Guid, PcdSet[Name, Guid])\r
185\r
186 Pa = PlatformAutoGen(self, self.MetaFile, Target, Toolchain, Arch)\r
187 #\r
188 # Explicitly collect platform's dynamic PCDs\r
189 #\r
190 Pa.CollectPlatformDynamicPcds()\r
191 self.AutoGenObjectList.append(Pa)\r
192\r
193 self._BuildDir = None\r
194 self._FvDir = None\r
195 self._MakeFileDir = None\r
196 self._BuildCommand = None\r
197\r
198 return True\r
199\r
200 def __repr__(self):\r
201 return "%s [%s]" % (self.MetaFile, ", ".join(self.ArchList))\r
202\r
203 ## Return the directory to store FV files\r
204 def _GetFvDir(self):\r
205 if self._FvDir == None:\r
206 self._FvDir = path.join(self.BuildDir, 'FV')\r
207 return self._FvDir\r
208\r
209 ## Return the directory to store all intermediate and final files built\r
210 def _GetBuildDir(self):\r
211 return self.AutoGenObjectList[0].BuildDir\r
212\r
213 ## Return the build output directory platform specifies\r
214 def _GetOutputDir(self):\r
215 return self.Platform.OutputDirectory\r
216\r
217 ## Return platform name\r
218 def _GetName(self):\r
219 return self.Platform.PlatformName\r
220\r
221 ## Return meta-file GUID\r
222 def _GetGuid(self):\r
223 return self.Platform.Guid\r
224\r
225 ## Return platform version\r
226 def _GetVersion(self):\r
227 return self.Platform.Version\r
228\r
229 ## Return paths of tools\r
230 def _GetToolDefinition(self):\r
231 return self.AutoGenObjectList[0].ToolDefinition\r
232\r
233 ## Return directory of platform makefile\r
234 #\r
235 # @retval string Makefile directory\r
236 #\r
237 def _GetMakeFileDir(self):\r
238 if self._MakeFileDir == None:\r
239 self._MakeFileDir = self.BuildDir\r
240 return self._MakeFileDir\r
241\r
242 ## Return build command string\r
243 #\r
244 # @retval string Build command string\r
245 #\r
246 def _GetBuildCommand(self):\r
247 if self._BuildCommand == None:\r
248 # BuildCommand should be all the same. So just get one from platform AutoGen\r
249 self._BuildCommand = self.AutoGenObjectList[0].BuildCommand\r
250 return self._BuildCommand\r
251\r
e56468c0 252 ## Create makefile for the platform and modules in it\r
52302d4d
LG
253 #\r
254 # @param CreateDepsMakeFile Flag indicating if the makefile for\r
255 # modules will be created as well\r
256 #\r
257 def CreateMakeFile(self, CreateDepsMakeFile=False):\r
258 # create makefile for platform\r
259 Makefile = GenMake.TopLevelMakefile(self)\r
260 if Makefile.Generate():\r
261 EdkLogger.debug(EdkLogger.DEBUG_9, "Generated makefile for platform [%s] %s\n" %\r
262 (self.MetaFile, self.ArchList))\r
263 else:\r
264 EdkLogger.debug(EdkLogger.DEBUG_9, "Skipped the generation of makefile for platform [%s] %s\n" %\r
265 (self.MetaFile, self.ArchList))\r
266\r
267 if CreateDepsMakeFile:\r
268 for Pa in self.AutoGenObjectList:\r
269 Pa.CreateMakeFile(CreateDepsMakeFile)\r
270\r
271 ## Create autogen code for platform and modules\r
272 #\r
273 # Since there's no autogen code for platform, this method will do nothing\r
274 # if CreateModuleCodeFile is set to False.\r
275 #\r
276 # @param CreateDepsCodeFile Flag indicating if creating module's\r
277 # autogen code file or not\r
278 #\r
279 def CreateCodeFile(self, CreateDepsCodeFile=False):\r
280 if not CreateDepsCodeFile:\r
281 return\r
282 for Pa in self.AutoGenObjectList:\r
283 Pa.CreateCodeFile(CreateDepsCodeFile)\r
284\r
285 Name = property(_GetName)\r
286 Guid = property(_GetGuid)\r
287 Version = property(_GetVersion)\r
288 OutputDir = property(_GetOutputDir)\r
289\r
290 ToolDefinition = property(_GetToolDefinition) # toolcode : tool path\r
291\r
292 BuildDir = property(_GetBuildDir)\r
293 FvDir = property(_GetFvDir)\r
294 MakeFileDir = property(_GetMakeFileDir)\r
295 BuildCommand = property(_GetBuildCommand)\r
296\r
297## AutoGen class for platform\r
298#\r
299# PlatformAutoGen class will process the original information in platform\r
300# file in order to generate makefile for platform.\r
301#\r
302class PlatformAutoGen(AutoGen):\r
303 #\r
304 # Used to store all PCDs for both PEI and DXE phase, in order to generate \r
305 # correct PCD database\r
306 # \r
307 _DynaPcdList_ = []\r
308 _NonDynaPcdList_ = []\r
309\r
310 ## The real constructor of PlatformAutoGen\r
311 #\r
312 # This method is not supposed to be called by users of PlatformAutoGen. It's\r
313 # only used by factory method __new__() to do real initialization work for an\r
314 # object of PlatformAutoGen\r
315 #\r
316 # @param Workspace WorkspaceAutoGen object\r
317 # @param PlatformFile Platform file (DSC file)\r
318 # @param Target Build target (DEBUG, RELEASE)\r
319 # @param Toolchain Name of tool chain\r
320 # @param Arch arch of the platform supports\r
321 #\r
322 def _Init(self, Workspace, PlatformFile, Target, Toolchain, Arch):\r
323 EdkLogger.debug(EdkLogger.DEBUG_9, "AutoGen platform [%s] [%s]" % (PlatformFile, Arch))\r
324 GlobalData.gProcessingFile = "%s [%s, %s, %s]" % (PlatformFile, Arch, Toolchain, Target)\r
325\r
326 self.MetaFile = PlatformFile\r
327 self.Workspace = Workspace\r
328 self.WorkspaceDir = Workspace.WorkspaceDir\r
329 self.ToolChain = Toolchain\r
330 self.BuildTarget = Target\r
331 self.Arch = Arch\r
332 self.SourceDir = PlatformFile.SubDir\r
333 self.SourceOverrideDir = None\r
334 self.FdTargetList = self.Workspace.FdTargetList\r
335 self.FvTargetList = self.Workspace.FvTargetList\r
336 self.AllPcdList = []\r
337\r
338 # flag indicating if the makefile/C-code file has been created or not\r
339 self.IsMakeFileCreated = False\r
340 self.IsCodeFileCreated = False\r
341\r
342 self._Platform = None\r
343 self._Name = None\r
344 self._Guid = None\r
345 self._Version = None\r
346\r
347 self._BuildRule = None\r
348 self._SourceDir = None\r
349 self._BuildDir = None\r
350 self._OutputDir = None\r
351 self._FvDir = None\r
352 self._MakeFileDir = None\r
353 self._FdfFile = None\r
354\r
355 self._PcdTokenNumber = None # (TokenCName, TokenSpaceGuidCName) : GeneratedTokenNumber\r
356 self._DynamicPcdList = None # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]\r
357 self._NonDynamicPcdList = None # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]\r
358\r
359 self._ToolDefinitions = None\r
360 self._ToolDefFile = None # toolcode : tool path\r
361 self._ToolChainFamily = None\r
362 self._BuildRuleFamily = None\r
363 self._BuildOption = None # toolcode : option\r
364 self._EdkBuildOption = None # edktoolcode : option\r
365 self._EdkIIBuildOption = None # edkiitoolcode : option\r
366 self._PackageList = None\r
367 self._ModuleAutoGenList = None\r
368 self._LibraryAutoGenList = None\r
369 self._BuildCommand = None\r
370\r
371 # get the original module/package/platform objects\r
372 self.BuildDatabase = Workspace.BuildDatabase\r
373 return True\r
374\r
375 def __repr__(self):\r
376 return "%s [%s]" % (self.MetaFile, self.Arch)\r
377\r
378 ## Create autogen code for platform and modules\r
379 #\r
380 # Since there's no autogen code for platform, this method will do nothing\r
381 # if CreateModuleCodeFile is set to False.\r
382 #\r
383 # @param CreateModuleCodeFile Flag indicating if creating module's\r
384 # autogen code file or not\r
385 #\r
386 def CreateCodeFile(self, CreateModuleCodeFile=False):\r
387 # only module has code to be greated, so do nothing if CreateModuleCodeFile is False\r
388 if self.IsCodeFileCreated or not CreateModuleCodeFile:\r
389 return\r
390\r
391 for Ma in self.ModuleAutoGenList:\r
392 Ma.CreateCodeFile(True)\r
393\r
394 # don't do this twice\r
395 self.IsCodeFileCreated = True\r
396\r
397 ## Create makefile for the platform and mdoules in it\r
398 #\r
399 # @param CreateModuleMakeFile Flag indicating if the makefile for\r
400 # modules will be created as well\r
401 #\r
402 def CreateMakeFile(self, CreateModuleMakeFile=False):\r
403 if CreateModuleMakeFile:\r
404 for ModuleFile in self.Platform.Modules:\r
405 Ma = ModuleAutoGen(self.Workspace, ModuleFile, self.BuildTarget,\r
406 self.ToolChain, self.Arch, self.MetaFile)\r
407 Ma.CreateMakeFile(True)\r
408\r
409 # no need to create makefile for the platform more than once\r
410 if self.IsMakeFileCreated:\r
411 return\r
412\r
413 # create makefile for platform\r
414 Makefile = GenMake.PlatformMakefile(self)\r
415 if Makefile.Generate():\r
416 EdkLogger.debug(EdkLogger.DEBUG_9, "Generated makefile for platform [%s] [%s]\n" %\r
417 (self.MetaFile, self.Arch))\r
418 else:\r
419 EdkLogger.debug(EdkLogger.DEBUG_9, "Skipped the generation of makefile for platform [%s] [%s]\n" %\r
420 (self.MetaFile, self.Arch))\r
421 self.IsMakeFileCreated = True\r
422\r
423 ## Collect dynamic PCDs\r
424 #\r
425 # Gather dynamic PCDs list from each module and their settings from platform\r
426 # This interface should be invoked explicitly when platform action is created.\r
427 #\r
428 def CollectPlatformDynamicPcds(self):\r
429 # for gathering error information\r
430 NoDatumTypePcdList = set()\r
431\r
432 self._GuidValue = {}\r
433 for F in self.Platform.Modules.keys():\r
434 M = ModuleAutoGen(self.Workspace, F, self.BuildTarget, self.ToolChain, self.Arch, self.MetaFile)\r
435 #GuidValue.update(M.Guids)\r
436 \r
437 self.Platform.Modules[F].M = M\r
438 \r
439 for PcdFromModule in M.ModulePcdList+M.LibraryPcdList:\r
440 # make sure that the "VOID*" kind of datum has MaxDatumSize set\r
441 if PcdFromModule.DatumType == "VOID*" and PcdFromModule.MaxDatumSize == None:\r
442 NoDatumTypePcdList.add("%s.%s [%s]" % (PcdFromModule.TokenSpaceGuidCName, PcdFromModule.TokenCName, F))\r
443\r
444 if PcdFromModule.Type in GenC.gDynamicPcd or PcdFromModule.Type in GenC.gDynamicExPcd:\r
445 #\r
446 # If a dynamic PCD used by a PEM module/PEI module & DXE module,\r
447 # it should be stored in Pcd PEI database, If a dynamic only\r
448 # used by DXE module, it should be stored in DXE PCD database.\r
449 # The default Phase is DXE\r
450 #\r
451 if M.ModuleType in ["PEIM", "PEI_CORE"]:\r
452 PcdFromModule.Phase = "PEI"\r
453 if PcdFromModule not in self._DynaPcdList_:\r
454 self._DynaPcdList_.append(PcdFromModule)\r
455 elif PcdFromModule.Phase == 'PEI':\r
456 # overwrite any the same PCD existing, if Phase is PEI\r
457 Index = self._DynaPcdList_.index(PcdFromModule)\r
458 self._DynaPcdList_[Index] = PcdFromModule\r
459 elif PcdFromModule not in self._NonDynaPcdList_:\r
460 self._NonDynaPcdList_.append(PcdFromModule)\r
461\r
462 # print out error information and break the build, if error found\r
463 if len(NoDatumTypePcdList) > 0:\r
464 NoDatumTypePcdListString = "\n\t\t".join(NoDatumTypePcdList)\r
465 EdkLogger.error("build", AUTOGEN_ERROR, "PCD setting error",\r
466 File=self.MetaFile,\r
467 ExtraData="\n\tPCD(s) without MaxDatumSize:\n\t\t%s\n"\r
468 % NoDatumTypePcdListString)\r
469 self._NonDynamicPcdList = self._NonDynaPcdList_\r
470 self._DynamicPcdList = self._DynaPcdList_\r
471 self.AllPcdList = self._NonDynamicPcdList + self._DynamicPcdList\r
472 \r
473 #\r
474 # Sort dynamic PCD list to:\r
475 # 1) If PCD's datum type is VOID* and value is unicode string which starts with L, the PCD item should \r
476 # try to be put header of dynamicd List\r
477 # 2) If PCD is HII type, the PCD item should be put after unicode type PCD\r
478 #\r
479 # The reason of sorting is make sure the unicode string is in double-byte alignment in string table.\r
480 #\r
481 UnicodePcdArray = []\r
482 HiiPcdArray = []\r
483 OtherPcdArray = []\r
e56468c0 484 VpdFile = VpdInfoFile.VpdInfoFile()\r
485 NeedProcessVpdMapFile = False \r
486 \r
487 if (self.Workspace.ArchList[-1] == self.Arch): \r
488 for Pcd in self._DynamicPcdList:\r
489\r
490 # just pick the a value to determine whether is unicode string type\r
491 Sku = Pcd.SkuInfoList[Pcd.SkuInfoList.keys()[0]]\r
492 Sku.VpdOffset = Sku.VpdOffset.strip()\r
493 \r
494 PcdValue = Sku.DefaultValue\r
495 if Pcd.DatumType == 'VOID*' and PcdValue.startswith("L"):\r
496 # if found PCD which datum value is unicode string the insert to left size of UnicodeIndex\r
497 UnicodePcdArray.append(Pcd)\r
498 elif len(Sku.VariableName) > 0:\r
499 # if found HII type PCD then insert to right of UnicodeIndex\r
500 HiiPcdArray.append(Pcd)\r
501 else:\r
502 OtherPcdArray.append(Pcd)\r
503 \r
504 if Pcd.Type in [TAB_PCDS_DYNAMIC_VPD, TAB_PCDS_DYNAMIC_EX_VPD]:\r
505 if not (self.Platform.VpdToolGuid == None or self.Platform.VpdToolGuid == ''):\r
506 #\r
507 # Fix the optional data of VPD PCD.\r
508 #\r
509 if (Pcd.DatumType.strip() != "VOID*"):\r
510 if Sku.DefaultValue == '':\r
511 Pcd.SkuInfoList[Pcd.SkuInfoList.keys()[0]].DefaultValue = Pcd.MaxDatumSize\r
512 Pcd.MaxDatumSize = None\r
513 else:\r
514 EdkLogger.error("build", AUTOGEN_ERROR, "PCD setting error",\r
515 File=self.MetaFile,\r
516 ExtraData="\n\tPCD: %s.%s format incorrect in DSC: %s\n\t\t\n"\r
517 % (Pcd.TokenSpaceGuidCName, Pcd.TokenCName, self.Platform.MetaFile.Path)) \r
518 \r
519 VpdFile.Add(Pcd, Sku.VpdOffset)\r
520 # if the offset of a VPD is *, then it need to be fixed up by third party tool.\r
521 if not NeedProcessVpdMapFile and Sku.VpdOffset == "*":\r
522 NeedProcessVpdMapFile = True\r
523 \r
524 #\r
525 # Fix the PCDs define in VPD PCD section that never referenced by module.\r
526 # An example is PCD for signature usage.\r
527 # \r
528 for DscPcd in self.Platform.Pcds:\r
529 DscPcdEntry = self.Platform.Pcds[DscPcd]\r
530 if DscPcdEntry.Type in [TAB_PCDS_DYNAMIC_VPD, TAB_PCDS_DYNAMIC_EX_VPD]:\r
531 if not (self.Platform.VpdToolGuid == None or self.Platform.VpdToolGuid == ''):\r
532 FoundFlag = False\r
533 for VpdPcd in VpdFile._VpdArray.keys():\r
534 # This PCD has been referenced by module\r
535 if (VpdPcd.TokenSpaceGuidCName == DscPcdEntry.TokenSpaceGuidCName) and \\r
536 (VpdPcd.TokenCName == DscPcdEntry.TokenCName):\r
537 FoundFlag = True\r
538 \r
539 # Not found, it should be signature\r
540 if not FoundFlag :\r
541 # just pick the a value to determine whether is unicode string type\r
542 Sku = DscPcdEntry.SkuInfoList[DscPcdEntry.SkuInfoList.keys()[0]]\r
543 Sku.VpdOffset = Sku.VpdOffset.strip() \r
544 \r
545 # Need to iterate DEC pcd information to get the value & datumtype\r
546 for eachDec in self.PackageList:\r
547 for DecPcd in eachDec.Pcds:\r
548 DecPcdEntry = eachDec.Pcds[DecPcd]\r
549 if (DecPcdEntry.TokenSpaceGuidCName == DscPcdEntry.TokenSpaceGuidCName) and \\r
550 (DecPcdEntry.TokenCName == DscPcdEntry.TokenCName):\r
08dd311f
LG
551 # Print warning message to let the developer make a determine.\r
552 EdkLogger.warn("build", "Unreferenced vpd pcd used!",\r
553 File=self.MetaFile, \\r
554 ExtraData = "PCD: %s.%s used in the DSC file %s is unreferenced." \\r
555 %(DscPcdEntry.TokenSpaceGuidCName, DscPcdEntry.TokenCName, self.Platform.MetaFile.Path)) \r
556 \r
e56468c0 557 DscPcdEntry.DatumType = DecPcdEntry.DatumType\r
558 DscPcdEntry.DefaultValue = DecPcdEntry.DefaultValue\r
08dd311f
LG
559 # Only fix the value while no value provided in DSC file.\r
560 if (Sku.DefaultValue == "" or Sku.DefaultValue==None):\r
561 DscPcdEntry.SkuInfoList[DscPcdEntry.SkuInfoList.keys()[0]].DefaultValue = DecPcdEntry.DefaultValue\r
562 \r
e56468c0 563 \r
564 VpdFile.Add(DscPcdEntry, Sku.VpdOffset)\r
565 # if the offset of a VPD is *, then it need to be fixed up by third party tool.\r
566 if not NeedProcessVpdMapFile and Sku.VpdOffset == "*":\r
567 NeedProcessVpdMapFile = True \r
568 \r
569 \r
570 if (self.Platform.FlashDefinition == None or self.Platform.FlashDefinition == '') and \\r
571 VpdFile.GetCount() != 0:\r
572 EdkLogger.error("build", ATTRIBUTE_NOT_AVAILABLE, \r
573 "Fail to get FLASH_DEFINITION definition in DSC file %s which is required when DSC contains VPD PCD." % str(self.Platform.MetaFile))\r
574 \r
575 if VpdFile.GetCount() != 0:\r
576 WorkspaceDb = self.BuildDatabase.WorkspaceDb\r
577 DscTimeStamp = WorkspaceDb.GetTimeStamp(WorkspaceDb.GetFileId(str(self.Platform.MetaFile)))\r
578 FvPath = os.path.join(self.BuildDir, "FV")\r
579 if not os.path.exists(FvPath):\r
580 try:\r
581 os.makedirs(FvPath)\r
582 except:\r
583 EdkLogger.error("build", FILE_WRITE_FAILURE, "Fail to create FV folder under %s" % self.BuildDir)\r
584 \r
08dd311f
LG
585 \r
586 VpdFilePath = os.path.join(FvPath, "%s.txt" % self.Platform.VpdToolGuid)\r
587\r
e56468c0 588 \r
589 if not os.path.exists(VpdFilePath) or os.path.getmtime(VpdFilePath) < DscTimeStamp:\r
590 VpdFile.Write(VpdFilePath)\r
591 \r
592 # retrieve BPDG tool's path from tool_def.txt according to VPD_TOOL_GUID defined in DSC file.\r
593 BPDGToolName = None\r
594 for ToolDef in self.ToolDefinition.values():\r
595 if ToolDef.has_key("GUID") and ToolDef["GUID"] == self.Platform.VpdToolGuid:\r
596 if not ToolDef.has_key("PATH"):\r
597 EdkLogger.error("build", ATTRIBUTE_NOT_AVAILABLE, "PATH attribute was not provided for BPDG guid tool %s in tools_def.txt" % self.Platform.VpdToolGuid)\r
598 BPDGToolName = ToolDef["PATH"]\r
599 break\r
600 # Call third party GUID BPDG tool.\r
601 if BPDGToolName != None:\r
08dd311f 602 VpdInfoFile.CallExtenalBPDGTool(BPDGToolName, VpdFilePath)\r
e56468c0 603 else:\r
604 EdkLogger.error("Build", FILE_NOT_FOUND, "Fail to find third-party BPDG tool to process VPD PCDs. BPDG Guid tool need to be defined in tools_def.txt and VPD_TOOL_GUID need to be provided in DSC file.")\r
605 \r
606 # Process VPD map file generated by third party BPDG tool\r
607 if NeedProcessVpdMapFile:\r
08dd311f 608 VpdMapFilePath = os.path.join(self.BuildDir, "FV", "%s.map" % self.Platform.VpdToolGuid)\r
e56468c0 609 if os.path.exists(VpdMapFilePath):\r
610 VpdFile.Read(VpdMapFilePath)\r
611 \r
612 # Fixup "*" offset\r
613 for Pcd in self._DynamicPcdList:\r
614 # just pick the a value to determine whether is unicode string type\r
615 Sku = Pcd.SkuInfoList[Pcd.SkuInfoList.keys()[0]] \r
616 if Sku.VpdOffset == "*":\r
617 Sku.VpdOffset = VpdFile.GetOffset(Pcd)[0]\r
618 else:\r
619 EdkLogger.error("build", FILE_READ_FAILURE, "Can not find VPD map file %s to fix up VPD offset." % VpdMapFilePath)\r
620 \r
621 # Delete the DynamicPcdList At the last time enter into this function \r
622 del self._DynamicPcdList[:] \r
52302d4d
LG
623 self._DynamicPcdList.extend(UnicodePcdArray)\r
624 self._DynamicPcdList.extend(HiiPcdArray)\r
625 self._DynamicPcdList.extend(OtherPcdArray)\r
626 \r
627 \r
628 ## Return the platform build data object\r
629 def _GetPlatform(self):\r
630 if self._Platform == None:\r
631 self._Platform = self.BuildDatabase[self.MetaFile, self.Arch]\r
632 return self._Platform\r
633\r
634 ## Return platform name\r
635 def _GetName(self):\r
636 return self.Platform.PlatformName\r
637\r
638 ## Return the meta file GUID\r
639 def _GetGuid(self):\r
640 return self.Platform.Guid\r
641\r
642 ## Return the platform version\r
643 def _GetVersion(self):\r
644 return self.Platform.Version\r
645\r
646 ## Return the FDF file name\r
647 def _GetFdfFile(self):\r
648 if self._FdfFile == None:\r
649 if self.Workspace.FdfFile != "":\r
650 self._FdfFile= path.join(self.WorkspaceDir, self.Workspace.FdfFile)\r
651 else:\r
652 self._FdfFile = ''\r
653 return self._FdfFile\r
654\r
655 ## Return the build output directory platform specifies\r
656 def _GetOutputDir(self):\r
657 return self.Platform.OutputDirectory\r
658\r
659 ## Return the directory to store all intermediate and final files built\r
660 def _GetBuildDir(self):\r
661 if self._BuildDir == None:\r
662 if os.path.isabs(self.OutputDir):\r
663 self._BuildDir = path.join(\r
664 path.abspath(self.OutputDir),\r
665 self.BuildTarget + "_" + self.ToolChain,\r
666 )\r
667 else:\r
668 self._BuildDir = path.join(\r
669 self.WorkspaceDir,\r
670 self.OutputDir,\r
671 self.BuildTarget + "_" + self.ToolChain,\r
672 )\r
673 return self._BuildDir\r
674\r
675 ## Return directory of platform makefile\r
676 #\r
677 # @retval string Makefile directory\r
678 #\r
679 def _GetMakeFileDir(self):\r
680 if self._MakeFileDir == None:\r
681 self._MakeFileDir = path.join(self.BuildDir, self.Arch)\r
682 return self._MakeFileDir\r
683\r
684 ## Return build command string\r
685 #\r
686 # @retval string Build command string\r
687 #\r
688 def _GetBuildCommand(self):\r
689 if self._BuildCommand == None:\r
690 self._BuildCommand = []\r
691 if "MAKE" in self.ToolDefinition and "PATH" in self.ToolDefinition["MAKE"]:\r
692 self._BuildCommand += SplitOption(self.ToolDefinition["MAKE"]["PATH"])\r
693 if "FLAGS" in self.ToolDefinition["MAKE"]:\r
694 NewOption = self.ToolDefinition["MAKE"]["FLAGS"].strip()\r
695 if NewOption != '':\r
696 self._BuildCommand += SplitOption(NewOption)\r
697 return self._BuildCommand\r
698\r
699 ## Get tool chain definition\r
700 #\r
701 # Get each tool defition for given tool chain from tools_def.txt and platform\r
702 #\r
703 def _GetToolDefinition(self):\r
704 if self._ToolDefinitions == None:\r
705 ToolDefinition = self.Workspace.ToolDef.ToolsDefTxtDictionary\r
706 if TAB_TOD_DEFINES_COMMAND_TYPE not in self.Workspace.ToolDef.ToolsDefTxtDatabase:\r
707 EdkLogger.error('build', RESOURCE_NOT_AVAILABLE, "No tools found in configuration",\r
708 ExtraData="[%s]" % self.MetaFile)\r
709 self._ToolDefinitions = {}\r
710 DllPathList = set()\r
711 for Def in ToolDefinition:\r
712 Target, Tag, Arch, Tool, Attr = Def.split("_")\r
713 if Target != self.BuildTarget or Tag != self.ToolChain or Arch != self.Arch:\r
714 continue\r
715\r
716 Value = ToolDefinition[Def]\r
717 # don't record the DLL\r
718 if Attr == "DLL":\r
719 DllPathList.add(Value)\r
720 continue\r
721\r
722 if Tool not in self._ToolDefinitions:\r
723 self._ToolDefinitions[Tool] = {}\r
724 self._ToolDefinitions[Tool][Attr] = Value\r
725\r
726 ToolsDef = ''\r
727 MakePath = ''\r
728 if GlobalData.gOptions.SilentMode and "MAKE" in self._ToolDefinitions:\r
729 if "FLAGS" not in self._ToolDefinitions["MAKE"]:\r
730 self._ToolDefinitions["MAKE"]["FLAGS"] = ""\r
731 self._ToolDefinitions["MAKE"]["FLAGS"] += " -s"\r
732 MakeFlags = ''\r
733 for Tool in self._ToolDefinitions:\r
734 for Attr in self._ToolDefinitions[Tool]:\r
735 Value = self._ToolDefinitions[Tool][Attr]\r
736 if Tool in self.BuildOption and Attr in self.BuildOption[Tool]:\r
737 # check if override is indicated\r
738 if self.BuildOption[Tool][Attr].startswith('='):\r
739 Value = self.BuildOption[Tool][Attr][1:]\r
740 else:\r
741 Value += " " + self.BuildOption[Tool][Attr]\r
742\r
743 if Attr == "PATH":\r
744 # Don't put MAKE definition in the file\r
745 if Tool == "MAKE":\r
746 MakePath = Value\r
747 else:\r
748 ToolsDef += "%s = %s\n" % (Tool, Value)\r
749 elif Attr != "DLL":\r
750 # Don't put MAKE definition in the file\r
751 if Tool == "MAKE":\r
752 if Attr == "FLAGS":\r
753 MakeFlags = Value\r
754 else:\r
755 ToolsDef += "%s_%s = %s\n" % (Tool, Attr, Value)\r
756 ToolsDef += "\n"\r
757\r
758 SaveFileOnChange(self.ToolDefinitionFile, ToolsDef)\r
759 for DllPath in DllPathList:\r
760 os.environ["PATH"] = DllPath + os.pathsep + os.environ["PATH"]\r
761 os.environ["MAKE_FLAGS"] = MakeFlags\r
762\r
763 return self._ToolDefinitions\r
764\r
765 ## Return the paths of tools\r
766 def _GetToolDefFile(self):\r
767 if self._ToolDefFile == None:\r
768 self._ToolDefFile = os.path.join(self.MakeFileDir, "TOOLS_DEF." + self.Arch)\r
769 return self._ToolDefFile\r
770\r
771 ## Retrieve the toolchain family of given toolchain tag. Default to 'MSFT'.\r
772 def _GetToolChainFamily(self):\r
773 if self._ToolChainFamily == None:\r
774 ToolDefinition = self.Workspace.ToolDef.ToolsDefTxtDatabase\r
775 if TAB_TOD_DEFINES_FAMILY not in ToolDefinition \\r
776 or self.ToolChain not in ToolDefinition[TAB_TOD_DEFINES_FAMILY] \\r
777 or not ToolDefinition[TAB_TOD_DEFINES_FAMILY][self.ToolChain]:\r
778 EdkLogger.verbose("No tool chain family found in configuration for %s. Default to MSFT." \\r
779 % self.ToolChain)\r
780 self._ToolChainFamily = "MSFT"\r
781 else:\r
782 self._ToolChainFamily = ToolDefinition[TAB_TOD_DEFINES_FAMILY][self.ToolChain]\r
783 return self._ToolChainFamily\r
784\r
785 def _GetBuildRuleFamily(self):\r
786 if self._BuildRuleFamily == None:\r
787 ToolDefinition = self.Workspace.ToolDef.ToolsDefTxtDatabase\r
788 if TAB_TOD_DEFINES_BUILDRULEFAMILY not in ToolDefinition \\r
789 or self.ToolChain not in ToolDefinition[TAB_TOD_DEFINES_BUILDRULEFAMILY] \\r
790 or not ToolDefinition[TAB_TOD_DEFINES_BUILDRULEFAMILY][self.ToolChain]:\r
791 EdkLogger.verbose("No tool chain family found in configuration for %s. Default to MSFT." \\r
792 % self.ToolChain)\r
793 self._BuildRuleFamily = "MSFT"\r
794 else:\r
795 self._BuildRuleFamily = ToolDefinition[TAB_TOD_DEFINES_BUILDRULEFAMILY][self.ToolChain]\r
796 return self._BuildRuleFamily\r
797\r
798 ## Return the build options specific for all modules in this platform\r
799 def _GetBuildOptions(self):\r
800 if self._BuildOption == None:\r
801 self._BuildOption = self._ExpandBuildOption(self.Platform.BuildOptions)\r
802 return self._BuildOption\r
803\r
804 ## Return the build options specific for EDK modules in this platform\r
805 def _GetEdkBuildOptions(self):\r
806 if self._EdkBuildOption == None:\r
807 self._EdkBuildOption = self._ExpandBuildOption(self.Platform.BuildOptions, EDK_NAME)\r
808 return self._EdkBuildOption\r
809\r
810 ## Return the build options specific for EDKII modules in this platform\r
811 def _GetEdkIIBuildOptions(self):\r
812 if self._EdkIIBuildOption == None:\r
813 self._EdkIIBuildOption = self._ExpandBuildOption(self.Platform.BuildOptions, EDKII_NAME)\r
814 return self._EdkIIBuildOption\r
815\r
816 ## Parse build_rule.txt in $(WORKSPACE)/Conf/build_rule.txt\r
817 #\r
818 # @retval BuildRule object\r
819 #\r
820 def _GetBuildRule(self):\r
821 if self._BuildRule == None:\r
822 BuildRuleFile = None\r
823 if TAB_TAT_DEFINES_BUILD_RULE_CONF in self.Workspace.TargetTxt.TargetTxtDictionary:\r
824 BuildRuleFile = self.Workspace.TargetTxt.TargetTxtDictionary[TAB_TAT_DEFINES_BUILD_RULE_CONF]\r
825 if BuildRuleFile in [None, '']:\r
826 BuildRuleFile = gBuildRuleFile\r
827 self._BuildRule = BuildRule(BuildRuleFile)\r
828 return self._BuildRule\r
829\r
830 ## Summarize the packages used by modules in this platform\r
831 def _GetPackageList(self):\r
832 if self._PackageList == None:\r
833 self._PackageList = set()\r
834 for La in self.LibraryAutoGenList:\r
835 self._PackageList.update(La.DependentPackageList)\r
836 for Ma in self.ModuleAutoGenList:\r
837 self._PackageList.update(Ma.DependentPackageList)\r
838 self._PackageList = list(self._PackageList)\r
839 return self._PackageList\r
840\r
841 ## Get list of non-dynamic PCDs\r
842 def _GetNonDynamicPcdList(self):\r
e56468c0 843 if self._NonDynamicPcdList == None:\r
844 self.CollectPlatformDynamicPcds()\r
52302d4d
LG
845 return self._NonDynamicPcdList\r
846\r
847 ## Get list of dynamic PCDs\r
848 def _GetDynamicPcdList(self):\r
e56468c0 849 if self._DynamicPcdList == None:\r
850 self.CollectPlatformDynamicPcds()\r
52302d4d
LG
851 return self._DynamicPcdList\r
852\r
853 ## Generate Token Number for all PCD\r
854 def _GetPcdTokenNumbers(self):\r
855 if self._PcdTokenNumber == None:\r
856 self._PcdTokenNumber = sdict()\r
857 TokenNumber = 1\r
858 for Pcd in self.DynamicPcdList:\r
859 if Pcd.Phase == "PEI":\r
860 EdkLogger.debug(EdkLogger.DEBUG_5, "%s %s (%s) -> %d" % (Pcd.TokenCName, Pcd.TokenSpaceGuidCName, Pcd.Phase, TokenNumber))\r
861 self._PcdTokenNumber[Pcd.TokenCName, Pcd.TokenSpaceGuidCName] = TokenNumber\r
862 TokenNumber += 1\r
863\r
864 for Pcd in self.DynamicPcdList:\r
865 if Pcd.Phase == "DXE":\r
866 EdkLogger.debug(EdkLogger.DEBUG_5, "%s %s (%s) -> %d" % (Pcd.TokenCName, Pcd.TokenSpaceGuidCName, Pcd.Phase, TokenNumber))\r
867 self._PcdTokenNumber[Pcd.TokenCName, Pcd.TokenSpaceGuidCName] = TokenNumber\r
868 TokenNumber += 1\r
869\r
870 for Pcd in self.NonDynamicPcdList:\r
871 self._PcdTokenNumber[Pcd.TokenCName, Pcd.TokenSpaceGuidCName] = TokenNumber\r
872 TokenNumber += 1\r
873 return self._PcdTokenNumber\r
874\r
875 ## Summarize ModuleAutoGen objects of all modules/libraries to be built for this platform\r
876 def _GetAutoGenObjectList(self):\r
877 self._ModuleAutoGenList = []\r
878 self._LibraryAutoGenList = []\r
879 for ModuleFile in self.Platform.Modules:\r
880 Ma = ModuleAutoGen(\r
881 self.Workspace,\r
882 ModuleFile,\r
883 self.BuildTarget,\r
884 self.ToolChain,\r
885 self.Arch,\r
886 self.MetaFile\r
887 )\r
888 if Ma not in self._ModuleAutoGenList:\r
889 self._ModuleAutoGenList.append(Ma)\r
890 for La in Ma.LibraryAutoGenList:\r
891 if La not in self._LibraryAutoGenList:\r
892 self._LibraryAutoGenList.append(La)\r
893\r
894 ## Summarize ModuleAutoGen objects of all modules to be built for this platform\r
895 def _GetModuleAutoGenList(self):\r
896 if self._ModuleAutoGenList == None:\r
897 self._GetAutoGenObjectList()\r
898 return self._ModuleAutoGenList\r
899\r
900 ## Summarize ModuleAutoGen objects of all libraries to be built for this platform\r
901 def _GetLibraryAutoGenList(self):\r
902 if self._LibraryAutoGenList == None:\r
903 self._GetAutoGenObjectList()\r
904 return self._LibraryAutoGenList\r
905\r
906 ## Test if a module is supported by the platform\r
907 #\r
908 # An error will be raised directly if the module or its arch is not supported\r
909 # by the platform or current configuration\r
910 #\r
911 def ValidModule(self, Module):\r
912 return Module in self.Platform.Modules or Module in self.Platform.LibraryInstances\r
913\r
914 ## Resolve the library classes in a module to library instances\r
915 #\r
916 # This method will not only resolve library classes but also sort the library\r
917 # instances according to the dependency-ship.\r
918 #\r
919 # @param Module The module from which the library classes will be resolved\r
920 #\r
921 # @retval library_list List of library instances sorted\r
922 #\r
923 def ApplyLibraryInstance(self, Module):\r
924 ModuleType = Module.ModuleType\r
925\r
926 # for overridding library instances with module specific setting\r
927 PlatformModule = self.Platform.Modules[str(Module)]\r
928\r
929 # add forced library instances (specified under LibraryClasses sections)\r
930 for LibraryClass in self.Platform.LibraryClasses.GetKeys():\r
931 if LibraryClass.startswith("NULL"):\r
932 Module.LibraryClasses[LibraryClass] = self.Platform.LibraryClasses[LibraryClass]\r
933\r
934 # add forced library instances (specified in module overrides)\r
935 for LibraryClass in PlatformModule.LibraryClasses:\r
936 if LibraryClass.startswith("NULL"):\r
937 Module.LibraryClasses[LibraryClass] = PlatformModule.LibraryClasses[LibraryClass]\r
938\r
939 # R9 module\r
940 LibraryConsumerList = [Module]\r
941 Constructor = []\r
942 ConsumedByList = sdict()\r
943 LibraryInstance = sdict()\r
944\r
945 EdkLogger.verbose("")\r
946 EdkLogger.verbose("Library instances of module [%s] [%s]:" % (str(Module), self.Arch))\r
947 while len(LibraryConsumerList) > 0:\r
948 M = LibraryConsumerList.pop()\r
949 for LibraryClassName in M.LibraryClasses:\r
950 if LibraryClassName not in LibraryInstance:\r
951 # override library instance for this module\r
952 if LibraryClassName in PlatformModule.LibraryClasses:\r
953 LibraryPath = PlatformModule.LibraryClasses[LibraryClassName]\r
954 else:\r
955 LibraryPath = self.Platform.LibraryClasses[LibraryClassName, ModuleType]\r
956 if LibraryPath == None or LibraryPath == "":\r
957 LibraryPath = M.LibraryClasses[LibraryClassName]\r
958 if LibraryPath == None or LibraryPath == "":\r
959 EdkLogger.error("build", RESOURCE_NOT_AVAILABLE,\r
960 "Instance of library class [%s] is not found" % LibraryClassName,\r
961 File=self.MetaFile,\r
962 ExtraData="in [%s] [%s]\n\tconsumed by module [%s]" % (str(M), self.Arch, str(Module)))\r
963\r
964 LibraryModule = self.BuildDatabase[LibraryPath, self.Arch]\r
965 # for those forced library instance (NULL library), add a fake library class\r
966 if LibraryClassName.startswith("NULL"):\r
967 LibraryModule.LibraryClass.append(LibraryClassObject(LibraryClassName, [ModuleType]))\r
968 elif LibraryModule.LibraryClass == None \\r
969 or len(LibraryModule.LibraryClass) == 0 \\r
970 or (ModuleType != 'USER_DEFINED'\r
971 and ModuleType not in LibraryModule.LibraryClass[0].SupModList):\r
972 # only USER_DEFINED can link against any library instance despite of its SupModList\r
973 EdkLogger.error("build", OPTION_MISSING,\r
974 "Module type [%s] is not supported by library instance [%s]" \\r
975 % (ModuleType, LibraryPath), File=self.MetaFile,\r
976 ExtraData="consumed by [%s]" % str(Module))\r
977\r
978 LibraryInstance[LibraryClassName] = LibraryModule\r
979 LibraryConsumerList.append(LibraryModule)\r
980 EdkLogger.verbose("\t" + str(LibraryClassName) + " : " + str(LibraryModule))\r
981 else:\r
982 LibraryModule = LibraryInstance[LibraryClassName]\r
983\r
984 if LibraryModule == None:\r
985 continue\r
986\r
987 if LibraryModule.ConstructorList != [] and LibraryModule not in Constructor:\r
988 Constructor.append(LibraryModule)\r
989\r
990 if LibraryModule not in ConsumedByList:\r
991 ConsumedByList[LibraryModule] = []\r
992 # don't add current module itself to consumer list\r
993 if M != Module:\r
994 if M in ConsumedByList[LibraryModule]:\r
995 continue\r
996 ConsumedByList[LibraryModule].append(M)\r
997 #\r
998 # Initialize the sorted output list to the empty set\r
999 #\r
1000 SortedLibraryList = []\r
1001 #\r
1002 # Q <- Set of all nodes with no incoming edges\r
1003 #\r
1004 LibraryList = [] #LibraryInstance.values()\r
1005 Q = []\r
1006 for LibraryClassName in LibraryInstance:\r
1007 M = LibraryInstance[LibraryClassName]\r
1008 LibraryList.append(M)\r
1009 if ConsumedByList[M] == []:\r
1010 Q.append(M)\r
1011\r
1012 #\r
1013 # start the DAG algorithm\r
1014 #\r
1015 while True:\r
1016 EdgeRemoved = True\r
1017 while Q == [] and EdgeRemoved:\r
1018 EdgeRemoved = False\r
1019 # for each node Item with a Constructor\r
1020 for Item in LibraryList:\r
1021 if Item not in Constructor:\r
1022 continue\r
1023 # for each Node without a constructor with an edge e from Item to Node\r
1024 for Node in ConsumedByList[Item]:\r
1025 if Node in Constructor:\r
1026 continue\r
1027 # remove edge e from the graph if Node has no constructor\r
1028 ConsumedByList[Item].remove(Node)\r
1029 EdgeRemoved = True\r
1030 if ConsumedByList[Item] == []:\r
1031 # insert Item into Q\r
1032 Q.insert(0, Item)\r
1033 break\r
1034 if Q != []:\r
1035 break\r
1036 # DAG is done if there's no more incoming edge for all nodes\r
1037 if Q == []:\r
1038 break\r
1039\r
1040 # remove node from Q\r
1041 Node = Q.pop()\r
1042 # output Node\r
1043 SortedLibraryList.append(Node)\r
1044\r
1045 # for each node Item with an edge e from Node to Item do\r
1046 for Item in LibraryList:\r
1047 if Node not in ConsumedByList[Item]:\r
1048 continue\r
1049 # remove edge e from the graph\r
1050 ConsumedByList[Item].remove(Node)\r
1051\r
1052 if ConsumedByList[Item] != []:\r
1053 continue\r
1054 # insert Item into Q, if Item has no other incoming edges\r
1055 Q.insert(0, Item)\r
1056\r
1057 #\r
1058 # if any remaining node Item in the graph has a constructor and an incoming edge, then the graph has a cycle\r
1059 #\r
1060 for Item in LibraryList:\r
1061 if ConsumedByList[Item] != [] and Item in Constructor and len(Constructor) > 1:\r
1062 ErrorMessage = "\tconsumed by " + "\n\tconsumed by ".join([str(L) for L in ConsumedByList[Item]])\r
1063 EdkLogger.error("build", BUILD_ERROR, 'Library [%s] with constructors has a cycle' % str(Item),\r
1064 ExtraData=ErrorMessage, File=self.MetaFile)\r
1065 if Item not in SortedLibraryList:\r
1066 SortedLibraryList.append(Item)\r
1067\r
1068 #\r
1069 # Build the list of constructor and destructir names\r
1070 # The DAG Topo sort produces the destructor order, so the list of constructors must generated in the reverse order\r
1071 #\r
1072 SortedLibraryList.reverse()\r
1073 return SortedLibraryList\r
1074\r
1075\r
1076 ## Override PCD setting (type, value, ...)\r
1077 #\r
1078 # @param ToPcd The PCD to be overrided\r
1079 # @param FromPcd The PCD overrideing from\r
1080 #\r
1081 def _OverridePcd(self, ToPcd, FromPcd, Module=""):\r
1082 #\r
1083 # in case there's PCDs coming from FDF file, which have no type given.\r
1084 # at this point, ToPcd.Type has the type found from dependent\r
1085 # package\r
1086 #\r
1087 if FromPcd != None:\r
1088 if ToPcd.Pending and FromPcd.Type not in [None, '']:\r
1089 ToPcd.Type = FromPcd.Type\r
e56468c0 1090 elif (ToPcd.Type not in [None, '']) and (FromPcd.Type not in [None, ''])\\r
1091 and (ToPcd.Type != FromPcd.Type) and (ToPcd.Type in FromPcd.Type):\r
1092 if ToPcd.Type.strip() == "DynamicEx":\r
1093 ToPcd.Type = FromPcd.Type \r
52302d4d
LG
1094 elif ToPcd.Type not in [None, ''] and FromPcd.Type not in [None, ''] \\r
1095 and ToPcd.Type != FromPcd.Type:\r
1096 EdkLogger.error("build", OPTION_CONFLICT, "Mismatched PCD type",\r
1097 ExtraData="%s.%s is defined as [%s] in module %s, but as [%s] in platform."\\r
1098 % (ToPcd.TokenSpaceGuidCName, ToPcd.TokenCName,\r
1099 ToPcd.Type, Module, FromPcd.Type),\r
1100 File=self.MetaFile)\r
1101\r
1102 if FromPcd.MaxDatumSize not in [None, '']:\r
1103 ToPcd.MaxDatumSize = FromPcd.MaxDatumSize\r
1104 if FromPcd.DefaultValue not in [None, '']:\r
1105 ToPcd.DefaultValue = FromPcd.DefaultValue\r
1106 if FromPcd.TokenValue not in [None, '']:\r
1107 ToPcd.TokenValue = FromPcd.TokenValue\r
1108 if FromPcd.MaxDatumSize not in [None, '']:\r
1109 ToPcd.MaxDatumSize = FromPcd.MaxDatumSize\r
1110 if FromPcd.DatumType not in [None, '']:\r
1111 ToPcd.DatumType = FromPcd.DatumType\r
1112 if FromPcd.SkuInfoList not in [None, '', []]:\r
1113 ToPcd.SkuInfoList = FromPcd.SkuInfoList\r
1114\r
1115 # check the validation of datum\r
1116 IsValid, Cause = CheckPcdDatum(ToPcd.DatumType, ToPcd.DefaultValue)\r
1117 if not IsValid:\r
1118 EdkLogger.error('build', FORMAT_INVALID, Cause, File=self.MetaFile,\r
1119 ExtraData="%s.%s" % (ToPcd.TokenSpaceGuidCName, ToPcd.TokenCName))\r
1120\r
1121 if ToPcd.DatumType == "VOID*" and ToPcd.MaxDatumSize in ['', None]:\r
1122 EdkLogger.debug(EdkLogger.DEBUG_9, "No MaxDatumSize specified for PCD %s.%s" \\r
1123 % (ToPcd.TokenSpaceGuidCName, ToPcd.TokenCName))\r
1124 Value = ToPcd.DefaultValue\r
1125 if Value in [None, '']:\r
1126 ToPcd.MaxDatumSize = 1\r
1127 elif Value[0] == 'L':\r
1128 ToPcd.MaxDatumSize = str(len(Value) * 2)\r
1129 elif Value[0] == '{':\r
1130 ToPcd.MaxDatumSize = str(len(Value.split(',')))\r
1131 else:\r
1132 ToPcd.MaxDatumSize = str(len(Value))\r
1133\r
1134 # apply default SKU for dynamic PCDS if specified one is not available\r
1135 if (ToPcd.Type in PCD_DYNAMIC_TYPE_LIST or ToPcd.Type in PCD_DYNAMIC_EX_TYPE_LIST) \\r
1136 and ToPcd.SkuInfoList in [None, {}, '']:\r
1137 if self.Platform.SkuName in self.Platform.SkuIds:\r
1138 SkuName = self.Platform.SkuName\r
1139 else:\r
1140 SkuName = 'DEFAULT'\r
1141 ToPcd.SkuInfoList = {\r
1142 SkuName : SkuInfoClass(SkuName, self.Platform.SkuIds[SkuName], '', '', '', '', '', ToPcd.DefaultValue)\r
1143 }\r
1144\r
1145 ## Apply PCD setting defined platform to a module\r
1146 #\r
1147 # @param Module The module from which the PCD setting will be overrided\r
1148 #\r
1149 # @retval PCD_list The list PCDs with settings from platform\r
1150 #\r
1151 def ApplyPcdSetting(self, Module, Pcds):\r
1152 # for each PCD in module\r
1153 for Name,Guid in Pcds:\r
1154 PcdInModule = Pcds[Name,Guid]\r
1155 # find out the PCD setting in platform\r
1156 if (Name,Guid) in self.Platform.Pcds:\r
1157 PcdInPlatform = self.Platform.Pcds[Name,Guid]\r
1158 else:\r
1159 PcdInPlatform = None\r
1160 # then override the settings if any\r
1161 self._OverridePcd(PcdInModule, PcdInPlatform, Module)\r
1162 # resolve the VariableGuid value\r
1163 for SkuId in PcdInModule.SkuInfoList:\r
1164 Sku = PcdInModule.SkuInfoList[SkuId]\r
1165 if Sku.VariableGuid == '': continue\r
1166 Sku.VariableGuidValue = GuidValue(Sku.VariableGuid, self.PackageList)\r
1167 if Sku.VariableGuidValue == None:\r
1168 PackageList = "\n\t".join([str(P) for P in self.PackageList])\r
1169 EdkLogger.error(\r
1170 'build',\r
1171 RESOURCE_NOT_AVAILABLE,\r
1172 "Value of GUID [%s] is not found in" % Sku.VariableGuid,\r
1173 ExtraData=PackageList + "\n\t(used with %s.%s from module %s)" \\r
1174 % (Guid, Name, str(Module)),\r
1175 File=self.MetaFile\r
1176 )\r
1177\r
1178 # override PCD settings with module specific setting\r
1179 if Module in self.Platform.Modules:\r
1180 PlatformModule = self.Platform.Modules[str(Module)]\r
1181 for Key in PlatformModule.Pcds:\r
1182 if Key in Pcds:\r
1183 self._OverridePcd(Pcds[Key], PlatformModule.Pcds[Key], Module)\r
1184 return Pcds.values()\r
1185\r
1186 ## Resolve library names to library modules\r
1187 #\r
1188 # (for R8.x modules)\r
1189 #\r
1190 # @param Module The module from which the library names will be resolved\r
1191 #\r
1192 # @retval library_list The list of library modules\r
1193 #\r
1194 def ResolveLibraryReference(self, Module):\r
1195 EdkLogger.verbose("")\r
1196 EdkLogger.verbose("Library instances of module [%s] [%s]:" % (str(Module), self.Arch))\r
1197 LibraryConsumerList = [Module]\r
1198\r
1199 # "CompilerStub" is a must for R8 modules\r
1200 if Module.Libraries:\r
1201 Module.Libraries.append("CompilerStub")\r
1202 LibraryList = []\r
1203 while len(LibraryConsumerList) > 0:\r
1204 M = LibraryConsumerList.pop()\r
1205 for LibraryName in M.Libraries:\r
1206 Library = self.Platform.LibraryClasses[LibraryName, ':dummy:']\r
1207 if Library == None:\r
1208 for Key in self.Platform.LibraryClasses.data.keys():\r
1209 if LibraryName.upper() == Key.upper():\r
1210 Library = self.Platform.LibraryClasses[Key, ':dummy:']\r
1211 break\r
1212 if Library == None:\r
1213 EdkLogger.warn("build", "Library [%s] is not found" % LibraryName, File=str(M),\r
1214 ExtraData="\t%s [%s]" % (str(Module), self.Arch))\r
1215 continue\r
1216\r
1217 if Library not in LibraryList:\r
1218 LibraryList.append(Library)\r
1219 LibraryConsumerList.append(Library)\r
1220 EdkLogger.verbose("\t" + LibraryName + " : " + str(Library) + ' ' + str(type(Library)))\r
1221 return LibraryList\r
1222\r
1223 ## Expand * in build option key\r
1224 #\r
1225 # @param Options Options to be expanded\r
1226 #\r
1227 # @retval options Options expanded\r
1228 #\r
1229 def _ExpandBuildOption(self, Options, ModuleStyle=None):\r
1230 BuildOptions = {}\r
1231 FamilyMatch = False\r
1232 FamilyIsNull = True\r
1233 for Key in Options:\r
1234 if ModuleStyle != None and len (Key) > 2:\r
1235 # Check Module style is EDK or EDKII.\r
1236 # Only append build option for the matched style module.\r
1237 if ModuleStyle == EDK_NAME and Key[2] != EDK_NAME:\r
1238 continue\r
1239 elif ModuleStyle == EDKII_NAME and Key[2] != EDKII_NAME:\r
1240 continue\r
1241 Family = Key[0]\r
1242 Target, Tag, Arch, Tool, Attr = Key[1].split("_")\r
1243 # if tool chain family doesn't match, skip it\r
1244 if Tool in self.ToolDefinition and Family != "":\r
1245 FamilyIsNull = False\r
1246 if self.ToolDefinition[Tool].get(TAB_TOD_DEFINES_BUILDRULEFAMILY, "") != "":\r
1247 if Family != self.ToolDefinition[Tool][TAB_TOD_DEFINES_BUILDRULEFAMILY]:\r
1248 continue\r
1249 elif Family != self.ToolDefinition[Tool][TAB_TOD_DEFINES_FAMILY]:\r
1250 continue\r
1251 FamilyMatch = True\r
1252 # expand any wildcard\r
1253 if Target == "*" or Target == self.BuildTarget:\r
1254 if Tag == "*" or Tag == self.ToolChain:\r
1255 if Arch == "*" or Arch == self.Arch:\r
1256 if Tool not in BuildOptions:\r
1257 BuildOptions[Tool] = {}\r
1258 if Attr != "FLAGS" or Attr not in BuildOptions[Tool]:\r
1259 BuildOptions[Tool][Attr] = Options[Key]\r
1260 else:\r
1261 # append options for the same tool\r
1262 BuildOptions[Tool][Attr] += " " + Options[Key]\r
1263 # Build Option Family has been checked, which need't to be checked again for family.\r
1264 if FamilyMatch or FamilyIsNull:\r
1265 return BuildOptions\r
1266 \r
1267 for Key in Options:\r
1268 if ModuleStyle != None and len (Key) > 2:\r
1269 # Check Module style is EDK or EDKII.\r
1270 # Only append build option for the matched style module.\r
1271 if ModuleStyle == EDK_NAME and Key[2] != EDK_NAME:\r
1272 continue\r
1273 elif ModuleStyle == EDKII_NAME and Key[2] != EDKII_NAME:\r
1274 continue\r
1275 Family = Key[0]\r
1276 Target, Tag, Arch, Tool, Attr = Key[1].split("_")\r
1277 # if tool chain family doesn't match, skip it\r
1278 if Tool not in self.ToolDefinition or Family =="":\r
1279 continue\r
1280 # option has been added before\r
1281 if Family != self.ToolDefinition[Tool][TAB_TOD_DEFINES_FAMILY]:\r
1282 continue\r
1283\r
1284 # expand any wildcard\r
1285 if Target == "*" or Target == self.BuildTarget:\r
1286 if Tag == "*" or Tag == self.ToolChain:\r
1287 if Arch == "*" or Arch == self.Arch:\r
1288 if Tool not in BuildOptions:\r
1289 BuildOptions[Tool] = {}\r
1290 if Attr != "FLAGS" or Attr not in BuildOptions[Tool]:\r
1291 BuildOptions[Tool][Attr] = Options[Key]\r
1292 else:\r
1293 # append options for the same tool\r
1294 BuildOptions[Tool][Attr] += " " + Options[Key]\r
1295 return BuildOptions\r
1296\r
1297 ## Append build options in platform to a module\r
1298 #\r
1299 # @param Module The module to which the build options will be appened\r
1300 #\r
1301 # @retval options The options appended with build options in platform\r
1302 #\r
1303 def ApplyBuildOption(self, Module):\r
1304 # Get the different options for the different style module\r
1305 if Module.AutoGenVersion < 0x00010005:\r
1306 PlatformOptions = self.EdkBuildOption\r
1307 else:\r
1308 PlatformOptions = self.EdkIIBuildOption\r
1309 ModuleOptions = self._ExpandBuildOption(Module.BuildOptions)\r
1310 if Module in self.Platform.Modules:\r
1311 PlatformModule = self.Platform.Modules[str(Module)]\r
1312 PlatformModuleOptions = self._ExpandBuildOption(PlatformModule.BuildOptions)\r
1313 else:\r
1314 PlatformModuleOptions = {}\r
1315\r
1316 AllTools = set(ModuleOptions.keys() + PlatformOptions.keys() + PlatformModuleOptions.keys() + self.ToolDefinition.keys())\r
1317 BuildOptions = {}\r
1318 for Tool in AllTools:\r
1319 if Tool not in BuildOptions:\r
1320 BuildOptions[Tool] = {}\r
1321\r
1322 for Options in [self.ToolDefinition, ModuleOptions, PlatformOptions, PlatformModuleOptions]:\r
1323 if Tool not in Options:\r
1324 continue\r
1325 for Attr in Options[Tool]:\r
1326 Value = Options[Tool][Attr]\r
1327 if Attr not in BuildOptions[Tool]:\r
1328 BuildOptions[Tool][Attr] = ""\r
1329 # check if override is indicated\r
1330 if Value.startswith('='):\r
1331 BuildOptions[Tool][Attr] = Value[1:]\r
1332 else:\r
1333 BuildOptions[Tool][Attr] += " " + Value\r
f3decdc3
LG
1334 if Module.AutoGenVersion < 0x00010005 and self.Workspace.UniFlag != None:\r
1335 #\r
1336 # Override UNI flag only for EDK module.\r
1337 #\r
1338 if 'BUILD' not in BuildOptions:\r
1339 BuildOptions['BUILD'] = {}\r
1340 BuildOptions['BUILD']['FLAGS'] = self.Workspace.UniFlag\r
52302d4d
LG
1341 return BuildOptions\r
1342\r
1343 Platform = property(_GetPlatform)\r
1344 Name = property(_GetName)\r
1345 Guid = property(_GetGuid)\r
1346 Version = property(_GetVersion)\r
1347\r
1348 OutputDir = property(_GetOutputDir)\r
1349 BuildDir = property(_GetBuildDir)\r
1350 MakeFileDir = property(_GetMakeFileDir)\r
1351 FdfFile = property(_GetFdfFile)\r
1352\r
1353 PcdTokenNumber = property(_GetPcdTokenNumbers) # (TokenCName, TokenSpaceGuidCName) : GeneratedTokenNumber\r
1354 DynamicPcdList = property(_GetDynamicPcdList) # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]\r
1355 NonDynamicPcdList = property(_GetNonDynamicPcdList) # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]\r
1356 PackageList = property(_GetPackageList)\r
1357\r
1358 ToolDefinition = property(_GetToolDefinition) # toolcode : tool path\r
1359 ToolDefinitionFile = property(_GetToolDefFile) # toolcode : lib path\r
1360 ToolChainFamily = property(_GetToolChainFamily)\r
1361 BuildRuleFamily = property(_GetBuildRuleFamily)\r
1362 BuildOption = property(_GetBuildOptions) # toolcode : option\r
1363 EdkBuildOption = property(_GetEdkBuildOptions) # edktoolcode : option\r
1364 EdkIIBuildOption = property(_GetEdkIIBuildOptions) # edkiitoolcode : option\r
1365\r
1366 BuildCommand = property(_GetBuildCommand)\r
1367 BuildRule = property(_GetBuildRule)\r
1368 ModuleAutoGenList = property(_GetModuleAutoGenList)\r
1369 LibraryAutoGenList = property(_GetLibraryAutoGenList)\r
1370\r
1371## ModuleAutoGen class\r
1372#\r
1373# This class encapsules the AutoGen behaviors for the build tools. In addition to\r
1374# the generation of AutoGen.h and AutoGen.c, it will generate *.depex file according\r
1375# to the [depex] section in module's inf file.\r
1376#\r
1377class ModuleAutoGen(AutoGen):\r
1378 ## The real constructor of ModuleAutoGen\r
1379 #\r
1380 # This method is not supposed to be called by users of ModuleAutoGen. It's\r
1381 # only used by factory method __new__() to do real initialization work for an\r
1382 # object of ModuleAutoGen\r
1383 #\r
1384 # @param Workspace EdkIIWorkspaceBuild object\r
1385 # @param ModuleFile The path of module file\r
1386 # @param Target Build target (DEBUG, RELEASE)\r
1387 # @param Toolchain Name of tool chain\r
1388 # @param Arch The arch the module supports\r
1389 # @param PlatformFile Platform meta-file\r
1390 #\r
1391 def _Init(self, Workspace, ModuleFile, Target, Toolchain, Arch, PlatformFile):\r
1392 EdkLogger.debug(EdkLogger.DEBUG_9, "AutoGen module [%s] [%s]" % (ModuleFile, Arch))\r
1393 GlobalData.gProcessingFile = "%s [%s, %s, %s]" % (ModuleFile, Arch, Toolchain, Target)\r
1394\r
1395 self.Workspace = Workspace\r
1396 self.WorkspaceDir = Workspace.WorkspaceDir\r
1397\r
1398 self.MetaFile = ModuleFile\r
1399 self.PlatformInfo = PlatformAutoGen(Workspace, PlatformFile, Target, Toolchain, Arch)\r
1400 # check if this module is employed by active platform\r
1401 if not self.PlatformInfo.ValidModule(self.MetaFile):\r
1402 EdkLogger.verbose("Module [%s] for [%s] is not employed by active platform\n" \\r
1403 % (self.MetaFile, Arch))\r
1404 return False\r
1405\r
1406 self.SourceDir = self.MetaFile.SubDir\r
1407 self.SourceOverrideDir = None\r
1408 # use overrided path defined in DSC file\r
1409 if self.MetaFile.Key in GlobalData.gOverrideDir:\r
1410 self.SourceOverrideDir = GlobalData.gOverrideDir[self.MetaFile.Key]\r
1411\r
1412 self.ToolChain = Toolchain\r
1413 self.BuildTarget = Target\r
1414 self.Arch = Arch\r
1415 self.ToolChainFamily = self.PlatformInfo.ToolChainFamily\r
1416 self.BuildRuleFamily = self.PlatformInfo.BuildRuleFamily\r
1417\r
1418 self.IsMakeFileCreated = False\r
1419 self.IsCodeFileCreated = False\r
1420\r
1421 self.BuildDatabase = self.Workspace.BuildDatabase\r
1422\r
1423 self._Module = None\r
1424 self._Name = None\r
1425 self._Guid = None\r
1426 self._Version = None\r
1427 self._ModuleType = None\r
1428 self._ComponentType = None\r
1429 self._PcdIsDriver = None\r
1430 self._AutoGenVersion = None\r
1431 self._LibraryFlag = None\r
1432 self._CustomMakefile = None\r
1433 self._Macro = None\r
1434\r
1435 self._BuildDir = None\r
1436 self._OutputDir = None\r
1437 self._DebugDir = None\r
1438 self._MakeFileDir = None\r
1439\r
1440 self._IncludePathList = None\r
1441 self._AutoGenFileList = None\r
1442 self._UnicodeFileList = None\r
1443 self._SourceFileList = None\r
1444 self._ObjectFileList = None\r
1445 self._BinaryFileList = None\r
1446\r
1447 self._DependentPackageList = None\r
1448 self._DependentLibraryList = None\r
1449 self._LibraryAutoGenList = None\r
1450 self._DerivedPackageList = None\r
1451 self._ModulePcdList = None\r
1452 self._LibraryPcdList = None\r
1453 self._GuidList = None\r
1454 self._ProtocolList = None\r
1455 self._PpiList = None\r
1456 self._DepexList = None\r
1457 self._DepexExpressionList = None\r
1458 self._BuildOption = None\r
1459 self._BuildTargets = None\r
1460 self._IntroBuildTargetList = None\r
1461 self._FinalBuildTargetList = None\r
1462 self._FileTypes = None\r
1463 self._BuildRules = None\r
1464\r
1465 return True\r
1466\r
1467 def __repr__(self):\r
1468 return "%s [%s]" % (self.MetaFile, self.Arch)\r
1469\r
1470 # Macros could be used in build_rule.txt (also Makefile)\r
1471 def _GetMacros(self):\r
1472 if self._Macro == None:\r
1473 self._Macro = sdict()\r
1474 self._Macro["WORKSPACE" ] = self.WorkspaceDir\r
1475 self._Macro["MODULE_NAME" ] = self.Name\r
1476 self._Macro["MODULE_GUID" ] = self.Guid\r
1477 self._Macro["MODULE_VERSION" ] = self.Version\r
1478 self._Macro["MODULE_TYPE" ] = self.ModuleType\r
1479 self._Macro["MODULE_FILE" ] = str(self.MetaFile)\r
1480 self._Macro["MODULE_FILE_BASE_NAME" ] = self.MetaFile.BaseName\r
1481 self._Macro["MODULE_RELATIVE_DIR" ] = self.SourceDir\r
1482 self._Macro["MODULE_DIR" ] = self.SourceDir\r
1483\r
1484 self._Macro["BASE_NAME" ] = self.Name\r
1485\r
1486 self._Macro["ARCH" ] = self.Arch\r
1487 self._Macro["TOOLCHAIN" ] = self.ToolChain\r
1488 self._Macro["TOOLCHAIN_TAG" ] = self.ToolChain\r
1489 self._Macro["TARGET" ] = self.BuildTarget\r
1490\r
1491 self._Macro["BUILD_DIR" ] = self.PlatformInfo.BuildDir\r
1492 self._Macro["BIN_DIR" ] = os.path.join(self.PlatformInfo.BuildDir, self.Arch)\r
1493 self._Macro["LIB_DIR" ] = os.path.join(self.PlatformInfo.BuildDir, self.Arch)\r
1494 self._Macro["MODULE_BUILD_DIR" ] = self.BuildDir\r
1495 self._Macro["OUTPUT_DIR" ] = self.OutputDir\r
1496 self._Macro["DEBUG_DIR" ] = self.DebugDir\r
1497 return self._Macro\r
1498\r
1499 ## Return the module build data object\r
1500 def _GetModule(self):\r
1501 if self._Module == None:\r
1502 self._Module = self.Workspace.BuildDatabase[self.MetaFile, self.Arch]\r
1503 return self._Module\r
1504\r
1505 ## Return the module name\r
1506 def _GetBaseName(self):\r
1507 return self.Module.BaseName\r
1508\r
1509 ## Return the module SourceOverridePath\r
1510 def _GetSourceOverridePath(self):\r
1511 return self.Module.SourceOverridePath\r
1512\r
1513 ## Return the module meta-file GUID\r
1514 def _GetGuid(self):\r
1515 return self.Module.Guid\r
1516\r
1517 ## Return the module version\r
1518 def _GetVersion(self):\r
1519 return self.Module.Version\r
1520\r
1521 ## Return the module type\r
1522 def _GetModuleType(self):\r
1523 return self.Module.ModuleType\r
1524\r
1525 ## Return the component type (for R8.x style of module)\r
1526 def _GetComponentType(self):\r
1527 return self.Module.ComponentType\r
1528\r
1529 ## Return the build type\r
1530 def _GetBuildType(self):\r
1531 return self.Module.BuildType\r
1532\r
1533 ## Return the PCD_IS_DRIVER setting\r
1534 def _GetPcdIsDriver(self):\r
1535 return self.Module.PcdIsDriver\r
1536\r
1537 ## Return the autogen version, i.e. module meta-file version\r
1538 def _GetAutoGenVersion(self):\r
1539 return self.Module.AutoGenVersion\r
1540\r
1541 ## Check if the module is library or not\r
1542 def _IsLibrary(self):\r
1543 if self._LibraryFlag == None:\r
1544 if self.Module.LibraryClass != None and self.Module.LibraryClass != []:\r
1545 self._LibraryFlag = True\r
1546 else:\r
1547 self._LibraryFlag = False\r
1548 return self._LibraryFlag\r
1549\r
1550 ## Return the directory to store intermediate files of the module\r
1551 def _GetBuildDir(self):\r
1552 if self._BuildDir == None:\r
1553 self._BuildDir = path.join(\r
1554 self.PlatformInfo.BuildDir,\r
1555 self.Arch,\r
1556 self.SourceDir,\r
1557 self.MetaFile.BaseName\r
1558 )\r
1559 CreateDirectory(self._BuildDir)\r
1560 return self._BuildDir\r
1561\r
1562 ## Return the directory to store the intermediate object files of the mdoule\r
1563 def _GetOutputDir(self):\r
1564 if self._OutputDir == None:\r
1565 self._OutputDir = path.join(self.BuildDir, "OUTPUT")\r
1566 CreateDirectory(self._OutputDir)\r
1567 return self._OutputDir\r
1568\r
1569 ## Return the directory to store auto-gened source files of the mdoule\r
1570 def _GetDebugDir(self):\r
1571 if self._DebugDir == None:\r
1572 self._DebugDir = path.join(self.BuildDir, "DEBUG")\r
1573 CreateDirectory(self._DebugDir)\r
1574 return self._DebugDir\r
1575\r
1576 ## Return the path of custom file\r
1577 def _GetCustomMakefile(self):\r
1578 if self._CustomMakefile == None:\r
1579 self._CustomMakefile = {}\r
1580 for Type in self.Module.CustomMakefile:\r
1581 if Type in gMakeTypeMap:\r
1582 MakeType = gMakeTypeMap[Type]\r
1583 else:\r
1584 MakeType = 'nmake'\r
1585 if self.SourceOverrideDir != None:\r
1586 File = os.path.join(self.SourceOverrideDir, self.Module.CustomMakefile[Type])\r
1587 if not os.path.exists(File):\r
1588 File = os.path.join(self.SourceDir, self.Module.CustomMakefile[Type])\r
1589 else:\r
1590 File = os.path.join(self.SourceDir, self.Module.CustomMakefile[Type])\r
1591 self._CustomMakefile[MakeType] = File\r
1592 return self._CustomMakefile\r
1593\r
1594 ## Return the directory of the makefile\r
1595 #\r
1596 # @retval string The directory string of module's makefile\r
1597 #\r
1598 def _GetMakeFileDir(self):\r
1599 return self.BuildDir\r
1600\r
1601 ## Return build command string\r
1602 #\r
1603 # @retval string Build command string\r
1604 #\r
1605 def _GetBuildCommand(self):\r
1606 return self.PlatformInfo.BuildCommand\r
1607\r
1608 ## Get object list of all packages the module and its dependent libraries belong to\r
1609 #\r
1610 # @retval list The list of package object\r
1611 #\r
1612 def _GetDerivedPackageList(self):\r
1613 PackageList = []\r
1614 for M in [self.Module] + self.DependentLibraryList:\r
1615 for Package in M.Packages:\r
1616 if Package in PackageList:\r
1617 continue\r
1618 PackageList.append(Package)\r
1619 return PackageList\r
1620\r
1621 ## Merge dependency expression\r
1622 #\r
1623 # @retval list The token list of the dependency expression after parsed\r
1624 #\r
1625 def _GetDepexTokenList(self):\r
1626 if self._DepexList == None:\r
1627 self._DepexList = {}\r
1628 if self.IsLibrary or TAB_DEPENDENCY_EXPRESSION_FILE in self.FileTypes:\r
1629 return self._DepexList\r
1630\r
1631 self._DepexList[self.ModuleType] = []\r
1632\r
1633 for ModuleType in self._DepexList:\r
1634 DepexList = self._DepexList[ModuleType]\r
1635 #\r
1636 # Append depex from dependent libraries, if not "BEFORE", "AFTER" expresion\r
1637 #\r
1638 for M in [self.Module] + self.DependentLibraryList:\r
1639 Inherited = False\r
1640 for D in M.Depex[self.Arch, ModuleType]:\r
1641 if DepexList != []:\r
1642 DepexList.append('AND')\r
1643 DepexList.append('(')\r
1644 DepexList.extend(D)\r
1645 if DepexList[-1] == 'END': # no need of a END at this time\r
1646 DepexList.pop()\r
1647 DepexList.append(')')\r
1648 Inherited = True\r
1649 if Inherited:\r
1650 EdkLogger.verbose("DEPEX[%s] (+%s) = %s" % (self.Name, M.BaseName, DepexList))\r
1651 if 'BEFORE' in DepexList or 'AFTER' in DepexList:\r
1652 break\r
1653 if len(DepexList) > 0:\r
1654 EdkLogger.verbose('')\r
1655 return self._DepexList\r
1656\r
1657 ## Merge dependency expression\r
1658 #\r
1659 # @retval list The token list of the dependency expression after parsed\r
1660 #\r
1661 def _GetDepexExpressionTokenList(self):\r
1662 if self._DepexExpressionList == None:\r
1663 self._DepexExpressionList = {}\r
1664 if self.IsLibrary or TAB_DEPENDENCY_EXPRESSION_FILE in self.FileTypes:\r
1665 return self._DepexExpressionList\r
1666\r
1667 self._DepexExpressionList[self.ModuleType] = ''\r
1668\r
1669 for ModuleType in self._DepexExpressionList:\r
1670 DepexExpressionList = self._DepexExpressionList[ModuleType]\r
1671 #\r
1672 # Append depex from dependent libraries, if not "BEFORE", "AFTER" expresion\r
1673 #\r
1674 for M in [self.Module] + self.DependentLibraryList:\r
1675 Inherited = False\r
1676 for D in M.DepexExpression[self.Arch, ModuleType]:\r
1677 if DepexExpressionList != '':\r
1678 DepexExpressionList += ' AND '\r
1679 DepexExpressionList += '('\r
1680 DepexExpressionList += D\r
1681 DepexExpressionList = DepexExpressionList.rstrip('END').strip()\r
1682 DepexExpressionList += ')'\r
1683 Inherited = True\r
1684 if Inherited:\r
1685 EdkLogger.verbose("DEPEX[%s] (+%s) = %s" % (self.Name, M.BaseName, DepexExpressionList))\r
1686 if 'BEFORE' in DepexExpressionList or 'AFTER' in DepexExpressionList:\r
1687 break\r
1688 if len(DepexExpressionList) > 0:\r
1689 EdkLogger.verbose('')\r
1690 self._DepexExpressionList[ModuleType] = DepexExpressionList\r
1691 return self._DepexExpressionList\r
1692\r
1693 ## Return the list of specification version required for the module\r
1694 #\r
1695 # @retval list The list of specification defined in module file\r
1696 #\r
1697 def _GetSpecification(self):\r
1698 return self.Module.Specification\r
1699\r
1700 ## Tool option for the module build\r
1701 #\r
1702 # @param PlatformInfo The object of PlatformBuildInfo\r
1703 # @retval dict The dict containing valid options\r
1704 #\r
1705 def _GetModuleBuildOption(self):\r
1706 if self._BuildOption == None:\r
1707 self._BuildOption = self.PlatformInfo.ApplyBuildOption(self.Module)\r
1708 return self._BuildOption\r
1709\r
1710 ## Return a list of files which can be built from source\r
1711 #\r
1712 # What kind of files can be built is determined by build rules in\r
1713 # $(WORKSPACE)/Conf/build_rule.txt and toolchain family.\r
1714 #\r
1715 def _GetSourceFileList(self):\r
1716 if self._SourceFileList == None:\r
1717 self._SourceFileList = []\r
1718 for F in self.Module.Sources:\r
1719 # match tool chain\r
08dd311f 1720 if F.TagName not in ("", "*", self.ToolChain):\r
52302d4d
LG
1721 EdkLogger.debug(EdkLogger.DEBUG_9, "The toolchain [%s] for processing file [%s] is found, "\r
1722 "but [%s] is needed" % (F.TagName, str(F), self.ToolChain))\r
1723 continue\r
1724 # match tool chain family\r
08dd311f 1725 if F.ToolChainFamily not in ("", "*", self.ToolChainFamily):\r
52302d4d
LG
1726 EdkLogger.debug(\r
1727 EdkLogger.DEBUG_0,\r
1728 "The file [%s] must be built by tools of [%s], " \\r
1729 "but current toolchain family is [%s]" \\r
1730 % (str(F), F.ToolChainFamily, self.ToolChainFamily))\r
1731 continue\r
1732\r
1733 # add the file path into search path list for file including\r
1734 if F.Dir not in self.IncludePathList and self.AutoGenVersion >= 0x00010005:\r
1735 self.IncludePathList.insert(0, F.Dir)\r
1736 self._SourceFileList.append(F)\r
1737 self._ApplyBuildRule(F, TAB_UNKNOWN_FILE)\r
1738 return self._SourceFileList\r
1739\r
1740 ## Return the list of unicode files\r
1741 def _GetUnicodeFileList(self):\r
1742 if self._UnicodeFileList == None:\r
1743 if TAB_UNICODE_FILE in self.FileTypes:\r
1744 self._UnicodeFileList = self.FileTypes[TAB_UNICODE_FILE]\r
1745 else:\r
1746 self._UnicodeFileList = []\r
1747 return self._UnicodeFileList\r
1748\r
1749 ## Return a list of files which can be built from binary\r
1750 #\r
1751 # "Build" binary files are just to copy them to build directory.\r
1752 #\r
1753 # @retval list The list of files which can be built later\r
1754 #\r
1755 def _GetBinaryFiles(self):\r
1756 if self._BinaryFileList == None:\r
1757 self._BinaryFileList = []\r
1758 for F in self.Module.Binaries:\r
1759 if F.Target not in ['COMMON', '*'] and F.Target != self.BuildTarget:\r
1760 continue\r
1761 self._BinaryFileList.append(F)\r
1762 self._ApplyBuildRule(F, F.Type)\r
1763 return self._BinaryFileList\r
1764\r
1765 def _GetBuildRules(self):\r
1766 if self._BuildRules == None:\r
1767 BuildRules = {}\r
1768 BuildRuleDatabase = self.PlatformInfo.BuildRule\r
1769 for Type in BuildRuleDatabase.FileTypeList:\r
1770 #first try getting build rule by BuildRuleFamily\r
1771 RuleObject = BuildRuleDatabase[Type, self.BuildType, self.Arch, self.BuildRuleFamily]\r
1772 if not RuleObject:\r
1773 # build type is always module type, but ...\r
1774 if self.ModuleType != self.BuildType:\r
1775 RuleObject = BuildRuleDatabase[Type, self.ModuleType, self.Arch, self.BuildRuleFamily]\r
1776 #second try getting build rule by ToolChainFamily\r
1777 if not RuleObject:\r
1778 RuleObject = BuildRuleDatabase[Type, self.BuildType, self.Arch, self.ToolChainFamily]\r
1779 if not RuleObject:\r
1780 # build type is always module type, but ...\r
1781 if self.ModuleType != self.BuildType:\r
1782 RuleObject = BuildRuleDatabase[Type, self.ModuleType, self.Arch, self.ToolChainFamily]\r
1783 if not RuleObject:\r
1784 continue\r
1785 RuleObject = RuleObject.Instantiate(self.Macros)\r
1786 BuildRules[Type] = RuleObject\r
1787 for Ext in RuleObject.SourceFileExtList:\r
1788 BuildRules[Ext] = RuleObject\r
1789 self._BuildRules = BuildRules\r
1790 return self._BuildRules\r
1791\r
1792 def _ApplyBuildRule(self, File, FileType):\r
1793 if self._BuildTargets == None:\r
1794 self._IntroBuildTargetList = set()\r
1795 self._FinalBuildTargetList = set()\r
1796 self._BuildTargets = {}\r
1797 self._FileTypes = {}\r
1798\r
1799 LastTarget = None\r
1800 RuleChain = []\r
1801 SourceList = [File]\r
1802 Index = 0\r
1803 while Index < len(SourceList):\r
1804 Source = SourceList[Index]\r
1805 Index = Index + 1\r
1806\r
1807 if Source != File:\r
1808 CreateDirectory(Source.Dir)\r
1809\r
1810 if File.IsBinary and File == Source and self._BinaryFileList != None and File in self._BinaryFileList:\r
1811 RuleObject = self.BuildRules[TAB_DEFAULT_BINARY_FILE]\r
1812 elif FileType in self.BuildRules:\r
1813 RuleObject = self.BuildRules[FileType]\r
1814 elif Source.Ext in self.BuildRules:\r
1815 RuleObject = self.BuildRules[Source.Ext]\r
1816 else:\r
1817 # stop at no more rules\r
1818 if LastTarget:\r
1819 self._FinalBuildTargetList.add(LastTarget)\r
1820 break\r
1821\r
1822 FileType = RuleObject.SourceFileType\r
1823 if FileType not in self._FileTypes:\r
1824 self._FileTypes[FileType] = set()\r
1825 self._FileTypes[FileType].add(Source)\r
1826\r
1827 # stop at STATIC_LIBRARY for library\r
1828 if self.IsLibrary and FileType == TAB_STATIC_LIBRARY:\r
1829 if LastTarget:\r
1830 self._FinalBuildTargetList.add(LastTarget)\r
1831 break\r
1832\r
1833 Target = RuleObject.Apply(Source)\r
1834 if not Target:\r
1835 if LastTarget:\r
1836 self._FinalBuildTargetList.add(LastTarget)\r
1837 break\r
1838 elif not Target.Outputs:\r
1839 # Only do build for target with outputs\r
1840 self._FinalBuildTargetList.add(Target)\r
1841\r
1842 if FileType not in self._BuildTargets:\r
1843 self._BuildTargets[FileType] = set()\r
1844 self._BuildTargets[FileType].add(Target)\r
1845\r
1846 if not Source.IsBinary and Source == File:\r
1847 self._IntroBuildTargetList.add(Target)\r
1848\r
1849 # to avoid cyclic rule\r
1850 if FileType in RuleChain:\r
1851 break\r
1852\r
1853 RuleChain.append(FileType)\r
1854 SourceList.extend(Target.Outputs)\r
1855 LastTarget = Target\r
1856 FileType = TAB_UNKNOWN_FILE\r
1857\r
1858 def _GetTargets(self):\r
1859 if self._BuildTargets == None:\r
1860 self._IntroBuildTargetList = set()\r
1861 self._FinalBuildTargetList = set()\r
1862 self._BuildTargets = {}\r
1863 self._FileTypes = {}\r
1864\r
1865 #TRICK: call _GetSourceFileList to apply build rule for binary files\r
1866 if self.SourceFileList:\r
1867 pass\r
1868\r
1869 #TRICK: call _GetBinaryFileList to apply build rule for binary files\r
1870 if self.BinaryFileList:\r
1871 pass\r
1872\r
1873 return self._BuildTargets\r
1874\r
1875 def _GetIntroTargetList(self):\r
1876 self._GetTargets()\r
1877 return self._IntroBuildTargetList\r
1878\r
1879 def _GetFinalTargetList(self):\r
1880 self._GetTargets()\r
1881 return self._FinalBuildTargetList\r
1882\r
1883 def _GetFileTypes(self):\r
1884 self._GetTargets()\r
1885 return self._FileTypes\r
1886\r
1887 ## Get the list of package object the module depends on\r
1888 #\r
1889 # @retval list The package object list\r
1890 #\r
1891 def _GetDependentPackageList(self):\r
1892 return self.Module.Packages\r
1893\r
1894 ## Return the list of auto-generated code file\r
1895 #\r
1896 # @retval list The list of auto-generated file\r
1897 #\r
1898 def _GetAutoGenFileList(self):\r
1899 UniStringAutoGenC = True\r
1900 UniStringBinBuffer = None\r
1901 if self.BuildType == 'UEFI_HII':\r
1902 UniStringBinBuffer = StringIO()\r
1903 UniStringAutoGenC = False\r
1904 if self._AutoGenFileList == None:\r
1905 self._AutoGenFileList = {}\r
1906 AutoGenC = TemplateString()\r
1907 AutoGenH = TemplateString()\r
1908 StringH = TemplateString()\r
1909 GenC.CreateCode(self, AutoGenC, AutoGenH, StringH, UniStringAutoGenC, UniStringBinBuffer)\r
1910 if str(AutoGenC) != "" and TAB_C_CODE_FILE in self.FileTypes:\r
1911 AutoFile = PathClass(gAutoGenCodeFileName, self.DebugDir)\r
1912 self._AutoGenFileList[AutoFile] = str(AutoGenC)\r
1913 self._ApplyBuildRule(AutoFile, TAB_UNKNOWN_FILE)\r
1914 if str(AutoGenH) != "":\r
1915 AutoFile = PathClass(gAutoGenHeaderFileName, self.DebugDir)\r
1916 self._AutoGenFileList[AutoFile] = str(AutoGenH)\r
1917 self._ApplyBuildRule(AutoFile, TAB_UNKNOWN_FILE)\r
1918 if str(StringH) != "":\r
1919 AutoFile = PathClass(gAutoGenStringFileName % {"module_name":self.Name}, self.DebugDir)\r
1920 self._AutoGenFileList[AutoFile] = str(StringH)\r
1921 self._ApplyBuildRule(AutoFile, TAB_UNKNOWN_FILE)\r
1922 if UniStringBinBuffer != None and UniStringBinBuffer.getvalue() != "":\r
1923 AutoFile = PathClass(gAutoGenStringFormFileName % {"module_name":self.Name}, self.OutputDir)\r
1924 self._AutoGenFileList[AutoFile] = UniStringBinBuffer.getvalue()\r
1925 AutoFile.IsBinary = True\r
1926 self._ApplyBuildRule(AutoFile, TAB_UNKNOWN_FILE)\r
1927 if UniStringBinBuffer != None:\r
1928 UniStringBinBuffer.close()\r
1929 return self._AutoGenFileList\r
1930\r
1931 ## Return the list of library modules explicitly or implicityly used by this module\r
1932 def _GetLibraryList(self):\r
1933 if self._DependentLibraryList == None:\r
1934 # only merge library classes and PCD for non-library module\r
1935 if self.IsLibrary:\r
1936 self._DependentLibraryList = []\r
1937 else:\r
1938 if self.AutoGenVersion < 0x00010005:\r
1939 self._DependentLibraryList = self.PlatformInfo.ResolveLibraryReference(self.Module)\r
1940 else:\r
1941 self._DependentLibraryList = self.PlatformInfo.ApplyLibraryInstance(self.Module)\r
1942 return self._DependentLibraryList\r
1943\r
1944 ## Get the list of PCDs from current module\r
1945 #\r
1946 # @retval list The list of PCD\r
1947 #\r
1948 def _GetModulePcdList(self):\r
1949 if self._ModulePcdList == None:\r
1950 # apply PCD settings from platform\r
1951 self._ModulePcdList = self.PlatformInfo.ApplyPcdSetting(self.Module, self.Module.Pcds)\r
1952 return self._ModulePcdList\r
1953\r
1954 ## Get the list of PCDs from dependent libraries\r
1955 #\r
1956 # @retval list The list of PCD\r
1957 #\r
1958 def _GetLibraryPcdList(self):\r
1959 if self._LibraryPcdList == None:\r
1960 Pcds = {}\r
1961 if not self.IsLibrary:\r
1962 # get PCDs from dependent libraries\r
1963 for Library in self.DependentLibraryList:\r
1964 for Key in Library.Pcds:\r
1965 # skip duplicated PCDs\r
1966 if Key in self.Module.Pcds or Key in Pcds:\r
1967 continue\r
1968 Pcds[Key] = copy.copy(Library.Pcds[Key])\r
1969 # apply PCD settings from platform\r
1970 self._LibraryPcdList = self.PlatformInfo.ApplyPcdSetting(self.Module, Pcds)\r
1971 else:\r
1972 self._LibraryPcdList = []\r
1973 return self._LibraryPcdList\r
1974\r
1975 ## Get the GUID value mapping\r
1976 #\r
1977 # @retval dict The mapping between GUID cname and its value\r
1978 #\r
1979 def _GetGuidList(self):\r
1980 if self._GuidList == None:\r
1981 self._GuidList = self.Module.Guids\r
1982 for Library in self.DependentLibraryList:\r
1983 self._GuidList.update(Library.Guids)\r
1984 return self._GuidList\r
1985\r
1986 ## Get the protocol value mapping\r
1987 #\r
1988 # @retval dict The mapping between protocol cname and its value\r
1989 #\r
1990 def _GetProtocolList(self):\r
1991 if self._ProtocolList == None:\r
1992 self._ProtocolList = self.Module.Protocols\r
1993 for Library in self.DependentLibraryList:\r
1994 self._ProtocolList.update(Library.Protocols)\r
1995 return self._ProtocolList\r
1996\r
1997 ## Get the PPI value mapping\r
1998 #\r
1999 # @retval dict The mapping between PPI cname and its value\r
2000 #\r
2001 def _GetPpiList(self):\r
2002 if self._PpiList == None:\r
2003 self._PpiList = self.Module.Ppis\r
2004 for Library in self.DependentLibraryList:\r
2005 self._PpiList.update(Library.Ppis)\r
2006 return self._PpiList\r
2007\r
2008 ## Get the list of include search path\r
2009 #\r
2010 # @retval list The list path\r
2011 #\r
2012 def _GetIncludePathList(self):\r
2013 if self._IncludePathList == None:\r
2014 self._IncludePathList = []\r
2015 if self.AutoGenVersion < 0x00010005:\r
2016 for Inc in self.Module.Includes:\r
2017 if Inc not in self._IncludePathList:\r
2018 self._IncludePathList.append(Inc)\r
2019 # for r8 modules\r
2020 Inc = path.join(Inc, self.Arch.capitalize())\r
2021 if os.path.exists(Inc) and Inc not in self._IncludePathList:\r
2022 self._IncludePathList.append(Inc)\r
2023 # r8 module needs to put DEBUG_DIR at the end of search path and not to use SOURCE_DIR all the time\r
2024 self._IncludePathList.append(self.DebugDir)\r
2025 else:\r
2026 self._IncludePathList.append(self.MetaFile.Dir)\r
2027 self._IncludePathList.append(self.DebugDir)\r
2028\r
2029 for Package in self.Module.Packages:\r
2030 PackageDir = path.join(self.WorkspaceDir, Package.MetaFile.Dir)\r
2031 if PackageDir not in self._IncludePathList:\r
2032 self._IncludePathList.append(PackageDir)\r
2033 for Inc in Package.Includes:\r
2034 if Inc not in self._IncludePathList:\r
2035 self._IncludePathList.append(str(Inc))\r
2036 return self._IncludePathList\r
2037\r
2038 ## Create makefile for the module and its dependent libraries\r
2039 #\r
2040 # @param CreateLibraryMakeFile Flag indicating if or not the makefiles of\r
2041 # dependent libraries will be created\r
2042 #\r
2043 def CreateMakeFile(self, CreateLibraryMakeFile=True):\r
2044 if self.IsMakeFileCreated:\r
2045 return\r
2046\r
2047 if not self.IsLibrary and CreateLibraryMakeFile:\r
2048 for LibraryAutoGen in self.LibraryAutoGenList:\r
2049 LibraryAutoGen.CreateMakeFile()\r
2050\r
2051 if len(self.CustomMakefile) == 0:\r
2052 Makefile = GenMake.ModuleMakefile(self)\r
2053 else:\r
2054 Makefile = GenMake.CustomMakefile(self)\r
2055 if Makefile.Generate():\r
2056 EdkLogger.debug(EdkLogger.DEBUG_9, "Generated makefile for module %s [%s]" %\r
2057 (self.Name, self.Arch))\r
2058 else:\r
2059 EdkLogger.debug(EdkLogger.DEBUG_9, "Skipped the generation of makefile for module %s [%s]" %\r
2060 (self.Name, self.Arch))\r
2061\r
2062 self.IsMakeFileCreated = True\r
2063\r
2064 ## Create autogen code for the module and its dependent libraries\r
2065 #\r
2066 # @param CreateLibraryCodeFile Flag indicating if or not the code of\r
2067 # dependent libraries will be created\r
2068 #\r
2069 def CreateCodeFile(self, CreateLibraryCodeFile=True):\r
2070 if self.IsCodeFileCreated:\r
2071 return\r
2072\r
2073 if not self.IsLibrary and CreateLibraryCodeFile:\r
2074 for LibraryAutoGen in self.LibraryAutoGenList:\r
2075 LibraryAutoGen.CreateCodeFile()\r
2076\r
2077 AutoGenList = []\r
2078 IgoredAutoGenList = []\r
2079\r
2080 for File in self.AutoGenFileList:\r
2081 if GenC.Generate(File.Path, self.AutoGenFileList[File], File.IsBinary):\r
2082 #Ignore R8 AutoGen.c\r
2083 if self.AutoGenVersion < 0x00010005 and File.Name == 'AutoGen.c':\r
2084 continue\r
2085\r
2086 AutoGenList.append(str(File))\r
2087 else:\r
2088 IgoredAutoGenList.append(str(File))\r
2089\r
2090 # Skip the following code for EDK I inf\r
2091 if self.AutoGenVersion < 0x00010005:\r
2092 return\r
2093\r
2094 for ModuleType in self.DepexList:\r
40d841f6
LG
2095 # Ignore empty [depex] section or [depex] section for "USER_DEFINED" module\r
2096 if len(self.DepexList[ModuleType]) == 0 or ModuleType == "USER_DEFINED":\r
52302d4d 2097 continue\r
40d841f6 2098\r
52302d4d
LG
2099 Dpx = GenDepex.DependencyExpression(self.DepexList[ModuleType], ModuleType, True)\r
2100 DpxFile = gAutoGenDepexFileName % {"module_name" : self.Name}\r
2101\r
2102 if Dpx.Generate(path.join(self.OutputDir, DpxFile)):\r
2103 AutoGenList.append(str(DpxFile))\r
2104 else:\r
2105 IgoredAutoGenList.append(str(DpxFile))\r
2106\r
2107 if IgoredAutoGenList == []:\r
2108 EdkLogger.debug(EdkLogger.DEBUG_9, "Generated [%s] files for module %s [%s]" %\r
2109 (" ".join(AutoGenList), self.Name, self.Arch))\r
2110 elif AutoGenList == []:\r
2111 EdkLogger.debug(EdkLogger.DEBUG_9, "Skipped the generation of [%s] files for module %s [%s]" %\r
2112 (" ".join(IgoredAutoGenList), self.Name, self.Arch))\r
2113 else:\r
2114 EdkLogger.debug(EdkLogger.DEBUG_9, "Generated [%s] (skipped %s) files for module %s [%s]" %\r
2115 (" ".join(AutoGenList), " ".join(IgoredAutoGenList), self.Name, self.Arch))\r
2116\r
2117 self.IsCodeFileCreated = True\r
2118 return AutoGenList\r
2119\r
2120 ## Summarize the ModuleAutoGen objects of all libraries used by this module\r
2121 def _GetLibraryAutoGenList(self):\r
2122 if self._LibraryAutoGenList == None:\r
2123 self._LibraryAutoGenList = []\r
2124 for Library in self.DependentLibraryList:\r
2125 La = ModuleAutoGen(\r
2126 self.Workspace,\r
2127 Library.MetaFile,\r
2128 self.BuildTarget,\r
2129 self.ToolChain,\r
2130 self.Arch,\r
2131 self.PlatformInfo.MetaFile\r
2132 )\r
2133 if La not in self._LibraryAutoGenList:\r
2134 self._LibraryAutoGenList.append(La)\r
2135 for Lib in La.CodaTargetList:\r
2136 self._ApplyBuildRule(Lib.Target, TAB_UNKNOWN_FILE)\r
2137 return self._LibraryAutoGenList\r
2138\r
52302d4d
LG
2139 Module = property(_GetModule)\r
2140 Name = property(_GetBaseName)\r
2141 Guid = property(_GetGuid)\r
2142 Version = property(_GetVersion)\r
2143 ModuleType = property(_GetModuleType)\r
2144 ComponentType = property(_GetComponentType)\r
2145 BuildType = property(_GetBuildType)\r
2146 PcdIsDriver = property(_GetPcdIsDriver)\r
2147 AutoGenVersion = property(_GetAutoGenVersion)\r
2148 Macros = property(_GetMacros)\r
2149 Specification = property(_GetSpecification)\r
2150\r
2151 IsLibrary = property(_IsLibrary)\r
2152\r
2153 BuildDir = property(_GetBuildDir)\r
2154 OutputDir = property(_GetOutputDir)\r
2155 DebugDir = property(_GetDebugDir)\r
2156 MakeFileDir = property(_GetMakeFileDir)\r
2157 CustomMakefile = property(_GetCustomMakefile)\r
2158\r
2159 IncludePathList = property(_GetIncludePathList)\r
2160 AutoGenFileList = property(_GetAutoGenFileList)\r
2161 UnicodeFileList = property(_GetUnicodeFileList)\r
2162 SourceFileList = property(_GetSourceFileList)\r
2163 BinaryFileList = property(_GetBinaryFiles) # FileType : [File List]\r
2164 Targets = property(_GetTargets)\r
2165 IntroTargetList = property(_GetIntroTargetList)\r
2166 CodaTargetList = property(_GetFinalTargetList)\r
2167 FileTypes = property(_GetFileTypes)\r
2168 BuildRules = property(_GetBuildRules)\r
2169\r
2170 DependentPackageList = property(_GetDependentPackageList)\r
2171 DependentLibraryList = property(_GetLibraryList)\r
2172 LibraryAutoGenList = property(_GetLibraryAutoGenList)\r
2173 DerivedPackageList = property(_GetDerivedPackageList)\r
2174\r
2175 ModulePcdList = property(_GetModulePcdList)\r
2176 LibraryPcdList = property(_GetLibraryPcdList)\r
2177 GuidList = property(_GetGuidList)\r
2178 ProtocolList = property(_GetProtocolList)\r
2179 PpiList = property(_GetPpiList)\r
2180 DepexList = property(_GetDepexTokenList)\r
2181 DepexExpressionList = property(_GetDepexExpressionTokenList)\r
2182 BuildOption = property(_GetModuleBuildOption)\r
2183 BuildCommand = property(_GetBuildCommand)\r
2184\r
2185# This acts like the main() function for the script, unless it is 'import'ed into another script.\r
2186if __name__ == '__main__':\r
2187 pass\r
2188\r