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