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