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