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