2 # Create makefile for MS nmake and GNU make
4 # Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
5 # SPDX-License-Identifier: BSD-2-Clause-Patent
7 from __future__
import absolute_import
8 from AutoGen
.AutoGen
import AutoGen
9 from Common
.LongFilePathSupport
import CopyLongFilePath
10 from Common
.BuildToolError
import *
11 from Common
.DataType
import *
12 from Common
.Misc
import *
13 from Common
.StringUtils
import NormPath
,GetSplitList
14 from collections
import defaultdict
15 from Workspace
.WorkspaceCommon
import OrderedListDict
16 import os
.path
as path
19 from . import InfSectionParser
22 from . import GenDepex
23 from io
import BytesIO
24 from GenPatchPcdTable
.GenPatchPcdTable
import parsePcdInfoFromMapFile
25 from Workspace
.MetaFileCommentParser
import UsageList
26 from .GenPcdDb
import CreatePcdDatabaseCode
27 from Common
.caching
import cached_class_function
28 from AutoGen
.ModuleAutoGenHelper
import PlatformInfo
,WorkSpaceInfo
30 ## Mapping Makefile type
31 gMakeTypeMap
= {TAB_COMPILER_MSFT
:"nmake", "GCC":"gmake"}
33 # Regular expression for finding Include Directories, the difference between MSFT and INTEL/GCC/RVCT
34 # is the former use /I , the Latter used -I to specify include directories
36 gBuildOptIncludePatternMsft
= re
.compile(r
"(?:.*?)/I[ \t]*([^ ]*)", re
.MULTILINE | re
.DOTALL
)
37 gBuildOptIncludePatternOther
= re
.compile(r
"(?:.*?)-I[ \t]*([^ ]*)", re
.MULTILINE | re
.DOTALL
)
39 ## default file name for AutoGen
40 gAutoGenCodeFileName
= "AutoGen.c"
41 gAutoGenHeaderFileName
= "AutoGen.h"
42 gAutoGenStringFileName
= "%(module_name)sStrDefs.h"
43 gAutoGenStringFormFileName
= "%(module_name)sStrDefs.hpk"
44 gAutoGenDepexFileName
= "%(module_name)s.depex"
45 gAutoGenImageDefFileName
= "%(module_name)sImgDefs.h"
46 gAutoGenIdfFileName
= "%(module_name)sIdf.hpk"
47 gInfSpecVersion
= "0x00010017"
50 # Match name = variable
52 gEfiVarStoreNamePattern
= re
.compile("\s*name\s*=\s*(\w+)")
54 # The format of guid in efivarstore statement likes following and must be correct:
55 # guid = {0xA04A27f4, 0xDF00, 0x4D42, {0xB5, 0x52, 0x39, 0x51, 0x13, 0x02, 0x11, 0x3D}}
57 gEfiVarStoreGuidPattern
= re
.compile("\s*guid\s*=\s*({.*?{.*?}\s*})")
60 # Template string to generic AsBuilt INF
62 gAsBuiltInfHeaderString
= TemplateString("""${header_comments}
68 INF_VERSION = ${module_inf_version}
69 BASE_NAME = ${module_name}
70 FILE_GUID = ${module_guid}
71 MODULE_TYPE = ${module_module_type}${BEGIN}
72 VERSION_STRING = ${module_version_string}${END}${BEGIN}
73 PCD_IS_DRIVER = ${pcd_is_driver_string}${END}${BEGIN}
74 UEFI_SPECIFICATION_VERSION = ${module_uefi_specification_version}${END}${BEGIN}
75 PI_SPECIFICATION_VERSION = ${module_pi_specification_version}${END}${BEGIN}
76 ENTRY_POINT = ${module_entry_point}${END}${BEGIN}
77 UNLOAD_IMAGE = ${module_unload_image}${END}${BEGIN}
78 CONSTRUCTOR = ${module_constructor}${END}${BEGIN}
79 DESTRUCTOR = ${module_destructor}${END}${BEGIN}
80 SHADOW = ${module_shadow}${END}${BEGIN}
81 PCI_VENDOR_ID = ${module_pci_vendor_id}${END}${BEGIN}
82 PCI_DEVICE_ID = ${module_pci_device_id}${END}${BEGIN}
83 PCI_CLASS_CODE = ${module_pci_class_code}${END}${BEGIN}
84 PCI_REVISION = ${module_pci_revision}${END}${BEGIN}
85 BUILD_NUMBER = ${module_build_number}${END}${BEGIN}
86 SPEC = ${module_spec}${END}${BEGIN}
87 UEFI_HII_RESOURCE_SECTION = ${module_uefi_hii_resource_section}${END}${BEGIN}
88 MODULE_UNI_FILE = ${module_uni_file}${END}
90 [Packages.${module_arch}]${BEGIN}
93 [Binaries.${module_arch}]${BEGIN}
96 [PatchPcd.${module_arch}]${BEGIN}
100 [Protocols.${module_arch}]${BEGIN}
104 [Ppis.${module_arch}]${BEGIN}
108 [Guids.${module_arch}]${BEGIN}
112 [PcdEx.${module_arch}]${BEGIN}
116 [LibraryClasses.${module_arch}]
117 ## @LIB_INSTANCES${BEGIN}
118 # ${libraryclasses_item}${END}
122 ${userextension_tianocore_item}
126 [BuildOptions.${module_arch}]
128 ## ${flags_item}${END}
131 # extend lists contained in a dictionary with lists stored in another dictionary
132 # if CopyToDict is not derived from DefaultDict(list) then this may raise exception
134 def ExtendCopyDictionaryLists(CopyToDict
, CopyFromDict
):
135 for Key
in CopyFromDict
:
136 CopyToDict
[Key
].extend(CopyFromDict
[Key
])
138 # Create a directory specified by a set of path elements and return the full path
139 def _MakeDir(PathList
):
140 RetVal
= path
.join(*PathList
)
141 CreateDirectory(RetVal
)
145 # Convert string to C format array
147 def _ConvertStringToByteArray(Value
):
148 Value
= Value
.strip()
152 if not Value
.endswith('}'):
154 Value
= Value
.replace(' ', '').replace('{', '').replace('}', '')
155 ValFields
= Value
.split(',')
157 for Index
in range(len(ValFields
)):
158 ValFields
[Index
] = str(int(ValFields
[Index
], 0))
161 Value
= '{' + ','.join(ValFields
) + '}'
165 if Value
.startswith('L"'):
166 if not Value
.endswith('"'):
170 elif not Value
.startswith('"') or not Value
.endswith('"'):
173 Value
= eval(Value
) # translate escape character
175 for Index
in range(0, len(Value
)):
177 NewValue
= NewValue
+ str(ord(Value
[Index
]) % 0x10000) + ','
179 NewValue
= NewValue
+ str(ord(Value
[Index
]) % 0x100) + ','
180 Value
= NewValue
+ '0}'
183 ## ModuleAutoGen class
185 # This class encapsules the AutoGen behaviors for the build tools. In addition to
186 # the generation of AutoGen.h and AutoGen.c, it will generate *.depex file according
187 # to the [depex] section in module's inf file.
189 class ModuleAutoGen(AutoGen
):
190 # call super().__init__ then call the worker function with different parameter count
191 def __init__(self
, Workspace
, MetaFile
, Target
, Toolchain
, Arch
, *args
, **kwargs
):
192 if not hasattr(self
, "_Init"):
193 self
._InitWorker
(Workspace
, MetaFile
, Target
, Toolchain
, Arch
, *args
)
196 ## Cache the timestamps of metafiles of every module in a class attribute
200 def __new__(cls
, Workspace
, MetaFile
, Target
, Toolchain
, Arch
, *args
, **kwargs
):
201 # check if this module is employed by active platform
202 if not PlatformInfo(Workspace
, args
[0], Target
, Toolchain
, Arch
,args
[-1]).ValidModule(MetaFile
):
203 EdkLogger
.verbose("Module [%s] for [%s] is not employed by active platform\n" \
206 return super(ModuleAutoGen
, cls
).__new
__(cls
, Workspace
, MetaFile
, Target
, Toolchain
, Arch
, *args
, **kwargs
)
208 ## Initialize ModuleAutoGen
210 # @param Workspace EdkIIWorkspaceBuild object
211 # @param ModuleFile The path of module file
212 # @param Target Build target (DEBUG, RELEASE)
213 # @param Toolchain Name of tool chain
214 # @param Arch The arch the module supports
215 # @param PlatformFile Platform meta-file
217 def _InitWorker(self
, Workspace
, ModuleFile
, Target
, Toolchain
, Arch
, PlatformFile
,DataPipe
):
218 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "AutoGen module [%s] [%s]" % (ModuleFile
, Arch
))
219 GlobalData
.gProcessingFile
= "%s [%s, %s, %s]" % (ModuleFile
, Arch
, Toolchain
, Target
)
221 self
.Workspace
= Workspace
222 self
.WorkspaceDir
= ""
223 self
.PlatformInfo
= None
224 self
.DataPipe
= DataPipe
225 self
.__init
_platform
_info
__()
226 self
.MetaFile
= ModuleFile
227 self
.SourceDir
= self
.MetaFile
.SubDir
228 self
.SourceDir
= mws
.relpath(self
.SourceDir
, self
.WorkspaceDir
)
230 self
.ToolChain
= Toolchain
231 self
.BuildTarget
= Target
233 self
.ToolChainFamily
= self
.PlatformInfo
.ToolChainFamily
234 self
.BuildRuleFamily
= self
.PlatformInfo
.BuildRuleFamily
236 self
.IsCodeFileCreated
= False
237 self
.IsAsBuiltInfCreated
= False
238 self
.DepexGenerated
= False
240 self
.BuildDatabase
= self
.Workspace
.BuildDatabase
241 self
.BuildRuleOrder
= None
244 self
._GuidComments
= OrderedListDict()
245 self
._ProtocolComments
= OrderedListDict()
246 self
._PpiComments
= OrderedListDict()
247 self
._BuildTargets
= None
248 self
._IntroBuildTargetList
= None
249 self
._FinalBuildTargetList
= None
250 self
._FileTypes
= None
252 self
.AutoGenDepSet
= set()
253 self
.ReferenceModules
= []
256 def __init_platform_info__(self
):
257 pinfo
= self
.DataPipe
.Get("P_Info")
258 self
.WorkspaceDir
= pinfo
.get("WorkspaceDir")
259 self
.PlatformInfo
= PlatformInfo(self
.Workspace
,pinfo
.get("ActivePlatform"),pinfo
.get("Target"),pinfo
.get("ToolChain"),pinfo
.get("Arch"),self
.DataPipe
)
260 ## hash() operator of ModuleAutoGen
262 # The module file path and arch string will be used to represent
263 # hash value of this object
265 # @retval int Hash value of the module file path and arch
267 @cached_class_function
269 return hash((self
.MetaFile
, self
.Arch
))
271 return "%s [%s]" % (self
.MetaFile
, self
.Arch
)
273 # Get FixedAtBuild Pcds of this Module
275 def FixedAtBuildPcds(self
):
277 for Pcd
in self
.ModulePcdList
:
278 if Pcd
.Type
!= TAB_PCDS_FIXED_AT_BUILD
:
280 if Pcd
not in RetVal
:
285 def FixedVoidTypePcds(self
):
287 for Pcd
in self
.FixedAtBuildPcds
:
288 if Pcd
.DatumType
== TAB_VOID
:
289 if '.'.join((Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
)) not in RetVal
:
290 RetVal
['.'.join((Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
))] = Pcd
.DefaultValue
294 def UniqueBaseName(self
):
295 ModuleNames
= self
.DataPipe
.Get("M_Name")
298 return ModuleNames
.get(self
.Name
,self
.Name
)
300 # Macros could be used in build_rule.txt (also Makefile)
304 ("WORKSPACE" ,self
.WorkspaceDir
),
305 ("MODULE_NAME" ,self
.Name
),
306 ("MODULE_NAME_GUID" ,self
.UniqueBaseName
),
307 ("MODULE_GUID" ,self
.Guid
),
308 ("MODULE_VERSION" ,self
.Version
),
309 ("MODULE_TYPE" ,self
.ModuleType
),
310 ("MODULE_FILE" ,str(self
.MetaFile
)),
311 ("MODULE_FILE_BASE_NAME" ,self
.MetaFile
.BaseName
),
312 ("MODULE_RELATIVE_DIR" ,self
.SourceDir
),
313 ("MODULE_DIR" ,self
.SourceDir
),
314 ("BASE_NAME" ,self
.Name
),
316 ("TOOLCHAIN" ,self
.ToolChain
),
317 ("TOOLCHAIN_TAG" ,self
.ToolChain
),
318 ("TOOL_CHAIN_TAG" ,self
.ToolChain
),
319 ("TARGET" ,self
.BuildTarget
),
320 ("BUILD_DIR" ,self
.PlatformInfo
.BuildDir
),
321 ("BIN_DIR" ,os
.path
.join(self
.PlatformInfo
.BuildDir
, self
.Arch
)),
322 ("LIB_DIR" ,os
.path
.join(self
.PlatformInfo
.BuildDir
, self
.Arch
)),
323 ("MODULE_BUILD_DIR" ,self
.BuildDir
),
324 ("OUTPUT_DIR" ,self
.OutputDir
),
325 ("DEBUG_DIR" ,self
.DebugDir
),
326 ("DEST_DIR_OUTPUT" ,self
.OutputDir
),
327 ("DEST_DIR_DEBUG" ,self
.DebugDir
),
328 ("PLATFORM_NAME" ,self
.PlatformInfo
.Name
),
329 ("PLATFORM_GUID" ,self
.PlatformInfo
.Guid
),
330 ("PLATFORM_VERSION" ,self
.PlatformInfo
.Version
),
331 ("PLATFORM_RELATIVE_DIR" ,self
.PlatformInfo
.SourceDir
),
332 ("PLATFORM_DIR" ,mws
.join(self
.WorkspaceDir
, self
.PlatformInfo
.SourceDir
)),
333 ("PLATFORM_OUTPUT_DIR" ,self
.PlatformInfo
.OutputDir
),
334 ("FFS_OUTPUT_DIR" ,self
.FfsOutputDir
)
337 ## Return the module build data object
340 return self
.BuildDatabase
[self
.MetaFile
, self
.Arch
, self
.BuildTarget
, self
.ToolChain
]
342 ## Return the module name
345 return self
.Module
.BaseName
347 ## Return the module DxsFile if exist
350 return self
.Module
.DxsFile
352 ## Return the module meta-file GUID
356 # To build same module more than once, the module path with FILE_GUID overridden has
357 # the file name FILE_GUIDmodule.inf, but the relative path (self.MetaFile.File) is the real path
358 # in DSC. The overridden GUID can be retrieved from file name
360 if os
.path
.basename(self
.MetaFile
.File
) != os
.path
.basename(self
.MetaFile
.Path
):
362 # Length of GUID is 36
364 return os
.path
.basename(self
.MetaFile
.Path
)[:36]
365 return self
.Module
.Guid
367 ## Return the module version
370 return self
.Module
.Version
372 ## Return the module type
374 def ModuleType(self
):
375 return self
.Module
.ModuleType
377 ## Return the component type (for Edk.x style of module)
379 def ComponentType(self
):
380 return self
.Module
.ComponentType
382 ## Return the build type
385 return self
.Module
.BuildType
387 ## Return the PCD_IS_DRIVER setting
389 def PcdIsDriver(self
):
390 return self
.Module
.PcdIsDriver
392 ## Return the autogen version, i.e. module meta-file version
394 def AutoGenVersion(self
):
395 return self
.Module
.AutoGenVersion
397 ## Check if the module is library or not
400 return bool(self
.Module
.LibraryClass
)
402 ## Check if the module is binary module or not
404 def IsBinaryModule(self
):
405 return self
.Module
.IsBinaryModule
407 ## Return the directory to store intermediate files of the module
411 self
.PlatformInfo
.BuildDir
,
414 self
.MetaFile
.BaseName
417 ## Return the directory to store the intermediate object files of the module
420 return _MakeDir((self
.BuildDir
, "OUTPUT"))
422 ## Return the directory path to store ffs file
424 def FfsOutputDir(self
):
425 if GlobalData
.gFdfParser
:
426 return path
.join(self
.PlatformInfo
.BuildDir
, TAB_FV_DIRECTORY
, "Ffs", self
.Guid
+ self
.Name
)
429 ## Return the directory to store auto-gened source files of the module
432 return _MakeDir((self
.BuildDir
, "DEBUG"))
434 ## Return the path of custom file
436 def CustomMakefile(self
):
438 for Type
in self
.Module
.CustomMakefile
:
439 MakeType
= gMakeTypeMap
[Type
] if Type
in gMakeTypeMap
else 'nmake'
440 File
= os
.path
.join(self
.SourceDir
, self
.Module
.CustomMakefile
[Type
])
441 RetVal
[MakeType
] = File
444 ## Return the directory of the makefile
446 # @retval string The directory string of module's makefile
449 def MakeFileDir(self
):
452 ## Return build command string
454 # @retval string Build command string
457 def BuildCommand(self
):
458 return self
.PlatformInfo
.BuildCommand
460 ## Get object list of all packages the module and its dependent libraries belong to
462 # @retval list The list of package object
465 def DerivedPackageList(self
):
467 for M
in [self
.Module
] + self
.DependentLibraryList
:
468 for Package
in M
.Packages
:
469 if Package
in PackageList
:
471 PackageList
.append(Package
)
474 ## Get the depex string
476 # @return : a string contain all depex expression.
477 def _GetDepexExpresionString(self
):
480 ## DPX_SOURCE IN Define section.
481 if self
.Module
.DxsFile
:
483 for M
in [self
.Module
] + self
.DependentLibraryList
:
484 Filename
= M
.MetaFile
.Path
485 InfObj
= InfSectionParser
.InfSectionParser(Filename
)
486 DepexExpressionList
= InfObj
.GetDepexExpresionList()
487 for DepexExpression
in DepexExpressionList
:
488 for key
in DepexExpression
:
489 Arch
, ModuleType
= key
490 DepexExpr
= [x
for x
in DepexExpression
[key
] if not str(x
).startswith('#')]
491 # the type of build module is USER_DEFINED.
492 # All different DEPEX section tags would be copied into the As Built INF file
493 # and there would be separate DEPEX section tags
494 if self
.ModuleType
.upper() == SUP_MODULE_USER_DEFINED
or self
.ModuleType
.upper() == SUP_MODULE_HOST_APPLICATION
:
495 if (Arch
.upper() == self
.Arch
.upper()) and (ModuleType
.upper() != TAB_ARCH_COMMON
):
496 DepexList
.append({(Arch
, ModuleType
): DepexExpr
})
498 if Arch
.upper() == TAB_ARCH_COMMON
or \
499 (Arch
.upper() == self
.Arch
.upper() and \
500 ModuleType
.upper() in [TAB_ARCH_COMMON
, self
.ModuleType
.upper()]):
501 DepexList
.append({(Arch
, ModuleType
): DepexExpr
})
503 #the type of build module is USER_DEFINED.
504 if self
.ModuleType
.upper() == SUP_MODULE_USER_DEFINED
or self
.ModuleType
.upper() == SUP_MODULE_HOST_APPLICATION
:
505 for Depex
in DepexList
:
507 DepexStr
+= '[Depex.%s.%s]\n' % key
508 DepexStr
+= '\n'.join('# '+ val
for val
in Depex
[key
])
511 return '[Depex.%s]\n' % self
.Arch
514 #the type of build module not is USER_DEFINED.
516 for Depex
in DepexList
:
521 for D
in Depex
.values():
522 DepexStr
+= ' '.join(val
for val
in D
)
523 Index
= DepexStr
.find('END')
524 if Index
> -1 and Index
== len(DepexStr
) - 3:
525 DepexStr
= DepexStr
[:-3]
526 DepexStr
= DepexStr
.strip()
529 DepexStr
= DepexStr
.lstrip('(').rstrip(')').strip()
531 return '[Depex.%s]\n' % self
.Arch
532 return '[Depex.%s]\n# ' % self
.Arch
+ DepexStr
534 ## Merge dependency expression
536 # @retval list The token list of the dependency expression after parsed
540 if self
.DxsFile
or self
.IsLibrary
or TAB_DEPENDENCY_EXPRESSION_FILE
in self
.FileTypes
:
545 # Append depex from dependent libraries, if not "BEFORE", "AFTER" expression
547 FixedVoidTypePcds
= {}
548 for M
in [self
] + self
.LibraryAutoGenList
:
549 FixedVoidTypePcds
.update(M
.FixedVoidTypePcds
)
550 for M
in [self
] + self
.LibraryAutoGenList
:
552 for D
in M
.Module
.Depex
[self
.Arch
, self
.ModuleType
]:
554 DepexList
.append('AND')
555 DepexList
.append('(')
556 #replace D with value if D is FixedAtBuild PCD
563 Value
= FixedVoidTypePcds
[item
]
564 if len(Value
.split(',')) != 16:
565 EdkLogger
.error("build", FORMAT_INVALID
,
566 "{} used in [Depex] section should be used as FixedAtBuild type and VOID* datum type and 16 bytes in the module.".format(item
))
567 NewList
.append(Value
)
569 EdkLogger
.error("build", FORMAT_INVALID
, "{} used in [Depex] section should be used as FixedAtBuild type and VOID* datum type in the module.".format(item
))
571 DepexList
.extend(NewList
)
572 if DepexList
[-1] == 'END': # no need of a END at this time
574 DepexList
.append(')')
577 EdkLogger
.verbose("DEPEX[%s] (+%s) = %s" % (self
.Name
, M
.Module
.BaseName
, DepexList
))
578 if 'BEFORE' in DepexList
or 'AFTER' in DepexList
:
580 if len(DepexList
) > 0:
581 EdkLogger
.verbose('')
582 return {self
.ModuleType
:DepexList
}
584 ## Merge dependency expression
586 # @retval list The token list of the dependency expression after parsed
589 def DepexExpressionDict(self
):
590 if self
.DxsFile
or self
.IsLibrary
or TAB_DEPENDENCY_EXPRESSION_FILE
in self
.FileTypes
:
593 DepexExpressionString
= ''
595 # Append depex from dependent libraries, if not "BEFORE", "AFTER" expresion
597 for M
in [self
.Module
] + self
.DependentLibraryList
:
599 for D
in M
.DepexExpression
[self
.Arch
, self
.ModuleType
]:
600 if DepexExpressionString
!= '':
601 DepexExpressionString
+= ' AND '
602 DepexExpressionString
+= '('
603 DepexExpressionString
+= D
604 DepexExpressionString
= DepexExpressionString
.rstrip('END').strip()
605 DepexExpressionString
+= ')'
608 EdkLogger
.verbose("DEPEX[%s] (+%s) = %s" % (self
.Name
, M
.BaseName
, DepexExpressionString
))
609 if 'BEFORE' in DepexExpressionString
or 'AFTER' in DepexExpressionString
:
611 if len(DepexExpressionString
) > 0:
612 EdkLogger
.verbose('')
614 return {self
.ModuleType
:DepexExpressionString
}
616 # Get the tiano core user extension, it is contain dependent library.
617 # @retval: a list contain tiano core userextension.
619 def _GetTianoCoreUserExtensionList(self
):
620 TianoCoreUserExtentionList
= []
621 for M
in [self
.Module
] + self
.DependentLibraryList
:
622 Filename
= M
.MetaFile
.Path
623 InfObj
= InfSectionParser
.InfSectionParser(Filename
)
624 TianoCoreUserExtenList
= InfObj
.GetUserExtensionTianoCore()
625 for TianoCoreUserExtent
in TianoCoreUserExtenList
:
626 for Section
in TianoCoreUserExtent
:
627 ItemList
= Section
.split(TAB_SPLIT
)
629 if len(ItemList
) == 4:
631 if Arch
.upper() == TAB_ARCH_COMMON
or Arch
.upper() == self
.Arch
.upper():
633 TianoCoreList
.extend([TAB_SECTION_START
+ Section
+ TAB_SECTION_END
])
634 TianoCoreList
.extend(TianoCoreUserExtent
[Section
][:])
635 TianoCoreList
.append('\n')
636 TianoCoreUserExtentionList
.append(TianoCoreList
)
638 return TianoCoreUserExtentionList
640 ## Return the list of specification version required for the module
642 # @retval list The list of specification defined in module file
645 def Specification(self
):
646 return self
.Module
.Specification
648 ## Tool option for the module build
650 # @param PlatformInfo The object of PlatformBuildInfo
651 # @retval dict The dict containing valid options
654 def BuildOption(self
):
655 RetVal
, self
.BuildRuleOrder
= self
.PlatformInfo
.ApplyBuildOption(self
.Module
)
656 if self
.BuildRuleOrder
:
657 self
.BuildRuleOrder
= ['.%s' % Ext
for Ext
in self
.BuildRuleOrder
.split()]
660 ## Get include path list from tool option for the module build
662 # @retval list The include path list
665 def BuildOptionIncPathList(self
):
667 # Regular expression for finding Include Directories, the difference between MSFT and INTEL/GCC/RVCT
668 # is the former use /I , the Latter used -I to specify include directories
670 if self
.PlatformInfo
.ToolChainFamily
in (TAB_COMPILER_MSFT
):
671 BuildOptIncludeRegEx
= gBuildOptIncludePatternMsft
672 elif self
.PlatformInfo
.ToolChainFamily
in ('INTEL', 'GCC', 'RVCT'):
673 BuildOptIncludeRegEx
= gBuildOptIncludePatternOther
676 # New ToolChainFamily, don't known whether there is option to specify include directories
681 for Tool
in ('CC', 'PP', 'VFRPP', 'ASLPP', 'ASLCC', 'APP', 'ASM'):
683 FlagOption
= self
.BuildOption
[Tool
]['FLAGS']
687 if self
.ToolChainFamily
!= 'RVCT':
688 IncPathList
= [NormPath(Path
, self
.Macros
) for Path
in BuildOptIncludeRegEx
.findall(FlagOption
)]
691 # RVCT may specify a list of directory seperated by commas
694 for Path
in BuildOptIncludeRegEx
.findall(FlagOption
):
695 PathList
= GetSplitList(Path
, TAB_COMMA_SPLIT
)
696 IncPathList
.extend(NormPath(PathEntry
, self
.Macros
) for PathEntry
in PathList
)
699 # EDK II modules must not reference header files outside of the packages they depend on or
700 # within the module's directory tree. Report error if violation.
702 if GlobalData
.gDisableIncludePathCheck
== False:
703 for Path
in IncPathList
:
704 if (Path
not in self
.IncludePathList
) and (CommonPath([Path
, self
.MetaFile
.Dir
]) != self
.MetaFile
.Dir
):
705 ErrMsg
= "The include directory for the EDK II module in this line is invalid %s specified in %s FLAGS '%s'" % (Path
, Tool
, FlagOption
)
706 EdkLogger
.error("build",
709 File
=str(self
.MetaFile
))
710 RetVal
+= IncPathList
713 ## Return a list of files which can be built from source
715 # What kind of files can be built is determined by build rules in
716 # $(CONF_DIRECTORY)/build_rule.txt and toolchain family.
719 def SourceFileList(self
):
721 ToolChainTagSet
= {"", TAB_STAR
, self
.ToolChain
}
722 ToolChainFamilySet
= {"", TAB_STAR
, self
.ToolChainFamily
, self
.BuildRuleFamily
}
723 for F
in self
.Module
.Sources
:
725 if F
.TagName
not in ToolChainTagSet
:
726 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "The toolchain [%s] for processing file [%s] is found, "
727 "but [%s] is currently used" % (F
.TagName
, str(F
), self
.ToolChain
))
729 # match tool chain family or build rule family
730 if F
.ToolChainFamily
not in ToolChainFamilySet
:
733 "The file [%s] must be built by tools of [%s], " \
734 "but current toolchain family is [%s], buildrule family is [%s]" \
735 % (str(F
), F
.ToolChainFamily
, self
.ToolChainFamily
, self
.BuildRuleFamily
))
738 # add the file path into search path list for file including
739 if F
.Dir
not in self
.IncludePathList
:
740 self
.IncludePathList
.insert(0, F
.Dir
)
743 self
._MatchBuildRuleOrder
(RetVal
)
746 self
._ApplyBuildRule
(F
, TAB_UNKNOWN_FILE
)
749 def _MatchBuildRuleOrder(self
, FileList
):
752 for SingleFile
in FileList
:
753 if self
.BuildRuleOrder
and SingleFile
.Ext
in self
.BuildRuleOrder
and SingleFile
.Ext
in self
.BuildRules
:
754 key
= SingleFile
.Path
.rsplit(SingleFile
.Ext
,1)[0]
755 if key
in Order_Dict
:
756 Order_Dict
[key
].append(SingleFile
.Ext
)
758 Order_Dict
[key
] = [SingleFile
.Ext
]
762 if len(Order_Dict
[F
]) > 1:
763 Order_Dict
[F
].sort(key
=lambda i
: self
.BuildRuleOrder
.index(i
))
764 for Ext
in Order_Dict
[F
][1:]:
765 RemoveList
.append(F
+ Ext
)
767 for item
in RemoveList
:
768 FileList
.remove(item
)
772 ## Return the list of unicode files
774 def UnicodeFileList(self
):
775 return self
.FileTypes
.get(TAB_UNICODE_FILE
,[])
777 ## Return the list of vfr files
779 def VfrFileList(self
):
780 return self
.FileTypes
.get(TAB_VFR_FILE
, [])
782 ## Return the list of Image Definition files
784 def IdfFileList(self
):
785 return self
.FileTypes
.get(TAB_IMAGE_FILE
,[])
787 ## Return a list of files which can be built from binary
789 # "Build" binary files are just to copy them to build directory.
791 # @retval list The list of files which can be built later
794 def BinaryFileList(self
):
796 for F
in self
.Module
.Binaries
:
797 if F
.Target
not in [TAB_ARCH_COMMON
, TAB_STAR
] and F
.Target
!= self
.BuildTarget
:
800 self
._ApplyBuildRule
(F
, F
.Type
, BinaryFileList
=RetVal
)
804 def BuildRules(self
):
806 BuildRuleDatabase
= self
.PlatformInfo
.BuildRule
807 for Type
in BuildRuleDatabase
.FileTypeList
:
808 #first try getting build rule by BuildRuleFamily
809 RuleObject
= BuildRuleDatabase
[Type
, self
.BuildType
, self
.Arch
, self
.BuildRuleFamily
]
811 # build type is always module type, but ...
812 if self
.ModuleType
!= self
.BuildType
:
813 RuleObject
= BuildRuleDatabase
[Type
, self
.ModuleType
, self
.Arch
, self
.BuildRuleFamily
]
814 #second try getting build rule by ToolChainFamily
816 RuleObject
= BuildRuleDatabase
[Type
, self
.BuildType
, self
.Arch
, self
.ToolChainFamily
]
818 # build type is always module type, but ...
819 if self
.ModuleType
!= self
.BuildType
:
820 RuleObject
= BuildRuleDatabase
[Type
, self
.ModuleType
, self
.Arch
, self
.ToolChainFamily
]
823 RuleObject
= RuleObject
.Instantiate(self
.Macros
)
824 RetVal
[Type
] = RuleObject
825 for Ext
in RuleObject
.SourceFileExtList
:
826 RetVal
[Ext
] = RuleObject
829 def _ApplyBuildRule(self
, File
, FileType
, BinaryFileList
=None):
830 if self
._BuildTargets
is None:
831 self
._IntroBuildTargetList
= set()
832 self
._FinalBuildTargetList
= set()
833 self
._BuildTargets
= defaultdict(set)
834 self
._FileTypes
= defaultdict(set)
836 if not BinaryFileList
:
837 BinaryFileList
= self
.BinaryFileList
839 SubDirectory
= os
.path
.join(self
.OutputDir
, File
.SubDir
)
840 if not os
.path
.exists(SubDirectory
):
841 CreateDirectory(SubDirectory
)
847 # Make sure to get build rule order value
851 while Index
< len(SourceList
):
852 Source
= SourceList
[Index
]
856 CreateDirectory(Source
.Dir
)
858 if File
.IsBinary
and File
== Source
and File
in BinaryFileList
:
859 # Skip all files that are not binary libraries
860 if not self
.IsLibrary
:
862 RuleObject
= self
.BuildRules
[TAB_DEFAULT_BINARY_FILE
]
863 elif FileType
in self
.BuildRules
:
864 RuleObject
= self
.BuildRules
[FileType
]
865 elif Source
.Ext
in self
.BuildRules
:
866 RuleObject
= self
.BuildRules
[Source
.Ext
]
868 # stop at no more rules
870 self
._FinalBuildTargetList
.add(LastTarget
)
873 FileType
= RuleObject
.SourceFileType
874 self
._FileTypes
[FileType
].add(Source
)
876 # stop at STATIC_LIBRARY for library
877 if self
.IsLibrary
and FileType
== TAB_STATIC_LIBRARY
:
879 self
._FinalBuildTargetList
.add(LastTarget
)
882 Target
= RuleObject
.Apply(Source
, self
.BuildRuleOrder
)
885 self
._FinalBuildTargetList
.add(LastTarget
)
887 elif not Target
.Outputs
:
888 # Only do build for target with outputs
889 self
._FinalBuildTargetList
.add(Target
)
891 self
._BuildTargets
[FileType
].add(Target
)
893 if not Source
.IsBinary
and Source
== File
:
894 self
._IntroBuildTargetList
.add(Target
)
896 # to avoid cyclic rule
897 if FileType
in RuleChain
:
900 RuleChain
.add(FileType
)
901 SourceList
.extend(Target
.Outputs
)
903 FileType
= TAB_UNKNOWN_FILE
907 if self
._BuildTargets
is None:
908 self
._IntroBuildTargetList
= set()
909 self
._FinalBuildTargetList
= set()
910 self
._BuildTargets
= defaultdict(set)
911 self
._FileTypes
= defaultdict(set)
913 #TRICK: call SourceFileList property to apply build rule for source files
916 #TRICK: call _GetBinaryFileList to apply build rule for binary files
919 return self
._BuildTargets
922 def IntroTargetList(self
):
924 return self
._IntroBuildTargetList
927 def CodaTargetList(self
):
929 return self
._FinalBuildTargetList
934 return self
._FileTypes
936 ## Get the list of package object the module depends on
938 # @retval list The package object list
941 def DependentPackageList(self
):
942 return self
.Module
.Packages
944 ## Return the list of auto-generated code file
946 # @retval list The list of auto-generated file
949 def AutoGenFileList(self
):
950 AutoGenUniIdf
= self
.BuildType
!= 'UEFI_HII'
951 UniStringBinBuffer
= BytesIO()
952 IdfGenBinBuffer
= BytesIO()
954 AutoGenC
= TemplateString()
955 AutoGenH
= TemplateString()
956 StringH
= TemplateString()
957 StringIdf
= TemplateString()
958 GenC
.CreateCode(self
, AutoGenC
, AutoGenH
, StringH
, AutoGenUniIdf
, UniStringBinBuffer
, StringIdf
, AutoGenUniIdf
, IdfGenBinBuffer
)
960 # AutoGen.c is generated if there are library classes in inf, or there are object files
962 if str(AutoGenC
) != "" and (len(self
.Module
.LibraryClasses
) > 0
963 or TAB_OBJECT_FILE
in self
.FileTypes
):
964 AutoFile
= PathClass(gAutoGenCodeFileName
, self
.DebugDir
)
965 RetVal
[AutoFile
] = str(AutoGenC
)
966 self
._ApplyBuildRule
(AutoFile
, TAB_UNKNOWN_FILE
)
967 if str(AutoGenH
) != "":
968 AutoFile
= PathClass(gAutoGenHeaderFileName
, self
.DebugDir
)
969 RetVal
[AutoFile
] = str(AutoGenH
)
970 self
._ApplyBuildRule
(AutoFile
, TAB_UNKNOWN_FILE
)
971 if str(StringH
) != "":
972 AutoFile
= PathClass(gAutoGenStringFileName
% {"module_name":self
.Name
}, self
.DebugDir
)
973 RetVal
[AutoFile
] = str(StringH
)
974 self
._ApplyBuildRule
(AutoFile
, TAB_UNKNOWN_FILE
)
975 if UniStringBinBuffer
is not None and UniStringBinBuffer
.getvalue() != b
"":
976 AutoFile
= PathClass(gAutoGenStringFormFileName
% {"module_name":self
.Name
}, self
.OutputDir
)
977 RetVal
[AutoFile
] = UniStringBinBuffer
.getvalue()
978 AutoFile
.IsBinary
= True
979 self
._ApplyBuildRule
(AutoFile
, TAB_UNKNOWN_FILE
)
980 if UniStringBinBuffer
is not None:
981 UniStringBinBuffer
.close()
982 if str(StringIdf
) != "":
983 AutoFile
= PathClass(gAutoGenImageDefFileName
% {"module_name":self
.Name
}, self
.DebugDir
)
984 RetVal
[AutoFile
] = str(StringIdf
)
985 self
._ApplyBuildRule
(AutoFile
, TAB_UNKNOWN_FILE
)
986 if IdfGenBinBuffer
is not None and IdfGenBinBuffer
.getvalue() != b
"":
987 AutoFile
= PathClass(gAutoGenIdfFileName
% {"module_name":self
.Name
}, self
.OutputDir
)
988 RetVal
[AutoFile
] = IdfGenBinBuffer
.getvalue()
989 AutoFile
.IsBinary
= True
990 self
._ApplyBuildRule
(AutoFile
, TAB_UNKNOWN_FILE
)
991 if IdfGenBinBuffer
is not None:
992 IdfGenBinBuffer
.close()
995 ## Return the list of library modules explicitly or implicitly used by this module
997 def DependentLibraryList(self
):
998 # only merge library classes and PCD for non-library module
1001 return self
.PlatformInfo
.ApplyLibraryInstance(self
.Module
)
1003 ## Get the list of PCDs from current module
1005 # @retval list The list of PCD
1008 def ModulePcdList(self
):
1009 # apply PCD settings from platform
1010 RetVal
= self
.PlatformInfo
.ApplyPcdSetting(self
.Module
, self
.Module
.Pcds
)
1014 def _PcdComments(self
):
1015 ReVal
= OrderedListDict()
1016 ExtendCopyDictionaryLists(ReVal
, self
.Module
.PcdComments
)
1017 if not self
.IsLibrary
:
1018 for Library
in self
.DependentLibraryList
:
1019 ExtendCopyDictionaryLists(ReVal
, Library
.PcdComments
)
1022 ## Get the list of PCDs from dependent libraries
1024 # @retval list The list of PCD
1027 def LibraryPcdList(self
):
1032 # get PCDs from dependent libraries
1033 for Library
in self
.DependentLibraryList
:
1034 PcdsInLibrary
= OrderedDict()
1035 for Key
in Library
.Pcds
:
1036 # skip duplicated PCDs
1037 if Key
in self
.Module
.Pcds
or Key
in Pcds
:
1040 PcdsInLibrary
[Key
] = copy
.copy(Library
.Pcds
[Key
])
1041 RetVal
.extend(self
.PlatformInfo
.ApplyPcdSetting(self
.Module
, PcdsInLibrary
, Library
=Library
))
1044 ## Get the GUID value mapping
1046 # @retval dict The mapping between GUID cname and its value
1050 RetVal
= self
.Module
.Guids
1051 for Library
in self
.DependentLibraryList
:
1052 RetVal
.update(Library
.Guids
)
1053 ExtendCopyDictionaryLists(self
._GuidComments
, Library
.GuidComments
)
1054 ExtendCopyDictionaryLists(self
._GuidComments
, self
.Module
.GuidComments
)
1058 def GetGuidsUsedByPcd(self
):
1059 RetVal
= OrderedDict(self
.Module
.GetGuidsUsedByPcd())
1060 for Library
in self
.DependentLibraryList
:
1061 RetVal
.update(Library
.GetGuidsUsedByPcd())
1063 ## Get the protocol value mapping
1065 # @retval dict The mapping between protocol cname and its value
1068 def ProtocolList(self
):
1069 RetVal
= OrderedDict(self
.Module
.Protocols
)
1070 for Library
in self
.DependentLibraryList
:
1071 RetVal
.update(Library
.Protocols
)
1072 ExtendCopyDictionaryLists(self
._ProtocolComments
, Library
.ProtocolComments
)
1073 ExtendCopyDictionaryLists(self
._ProtocolComments
, self
.Module
.ProtocolComments
)
1076 ## Get the PPI value mapping
1078 # @retval dict The mapping between PPI cname and its value
1082 RetVal
= OrderedDict(self
.Module
.Ppis
)
1083 for Library
in self
.DependentLibraryList
:
1084 RetVal
.update(Library
.Ppis
)
1085 ExtendCopyDictionaryLists(self
._PpiComments
, Library
.PpiComments
)
1086 ExtendCopyDictionaryLists(self
._PpiComments
, self
.Module
.PpiComments
)
1089 ## Get the list of include search path
1091 # @retval list The list path
1094 def IncludePathList(self
):
1096 RetVal
.append(self
.MetaFile
.Dir
)
1097 RetVal
.append(self
.DebugDir
)
1099 for Package
in self
.Module
.Packages
:
1100 PackageDir
= mws
.join(self
.WorkspaceDir
, Package
.MetaFile
.Dir
)
1101 if PackageDir
not in RetVal
:
1102 RetVal
.append(PackageDir
)
1103 IncludesList
= Package
.Includes
1104 if Package
._PrivateIncludes
:
1105 if not self
.MetaFile
.OriginalPath
.Path
.startswith(PackageDir
):
1106 IncludesList
= list(set(Package
.Includes
).difference(set(Package
._PrivateIncludes
)))
1107 for Inc
in IncludesList
:
1108 if Inc
not in RetVal
:
1109 RetVal
.append(str(Inc
))
1113 def IncludePathLength(self
):
1114 return sum(len(inc
)+1 for inc
in self
.IncludePathList
)
1116 ## Get the list of include paths from the packages
1118 # @IncludesList list The list path
1121 def PackageIncludePathList(self
):
1123 for Package
in self
.Module
.Packages
:
1124 PackageDir
= mws
.join(self
.WorkspaceDir
, Package
.MetaFile
.Dir
)
1125 IncludesList
= Package
.Includes
1126 if Package
._PrivateIncludes
:
1127 if not self
.MetaFile
.Path
.startswith(PackageDir
):
1128 IncludesList
= list(set(Package
.Includes
).difference(set(Package
._PrivateIncludes
)))
1131 ## Get HII EX PCDs which maybe used by VFR
1133 # efivarstore used by VFR may relate with HII EX PCDs
1134 # Get the variable name and GUID from efivarstore and HII EX PCD
1135 # List the HII EX PCDs in As Built INF if both name and GUID match.
1137 # @retval list HII EX PCDs
1139 def _GetPcdsMaybeUsedByVfr(self
):
1140 if not self
.SourceFileList
:
1144 for SrcFile
in self
.SourceFileList
:
1145 if SrcFile
.Ext
.lower() != '.vfr':
1147 Vfri
= os
.path
.join(self
.OutputDir
, SrcFile
.BaseName
+ '.i')
1148 if not os
.path
.exists(Vfri
):
1150 VfriFile
= open(Vfri
, 'r')
1151 Content
= VfriFile
.read()
1153 Pos
= Content
.find('efivarstore')
1156 # Make sure 'efivarstore' is the start of efivarstore statement
1157 # In case of the value of 'name' (name = efivarstore) is equal to 'efivarstore'
1160 while Index
>= 0 and Content
[Index
] in ' \t\r\n':
1162 if Index
>= 0 and Content
[Index
] != ';':
1163 Pos
= Content
.find('efivarstore', Pos
+ len('efivarstore'))
1166 # 'efivarstore' must be followed by name and guid
1168 Name
= gEfiVarStoreNamePattern
.search(Content
, Pos
)
1171 Guid
= gEfiVarStoreGuidPattern
.search(Content
, Pos
)
1174 NameArray
= _ConvertStringToByteArray('L"' + Name
.group(1) + '"')
1175 NameGuids
.add((NameArray
, GuidStructureStringToGuidString(Guid
.group(1))))
1176 Pos
= Content
.find('efivarstore', Name
.end())
1180 for Pcd
in self
.PlatformInfo
.Pcds
.values():
1181 if Pcd
.Type
!= TAB_PCDS_DYNAMIC_EX_HII
:
1183 for SkuInfo
in Pcd
.SkuInfoList
.values():
1184 Value
= GuidValue(SkuInfo
.VariableGuid
, self
.PlatformInfo
.PackageList
, self
.MetaFile
.Path
)
1187 Name
= _ConvertStringToByteArray(SkuInfo
.VariableName
)
1188 Guid
= GuidStructureStringToGuidString(Value
)
1189 if (Name
, Guid
) in NameGuids
and Pcd
not in HiiExPcds
:
1190 HiiExPcds
.append(Pcd
)
1195 def _GenOffsetBin(self
):
1197 for SourceFile
in self
.Module
.Sources
:
1198 if SourceFile
.Type
.upper() == ".VFR" :
1200 # search the .map file to find the offset of vfr binary in the PE32+/TE file.
1202 VfrUniBaseName
[SourceFile
.BaseName
] = (SourceFile
.BaseName
+ "Bin")
1203 elif SourceFile
.Type
.upper() == ".UNI" :
1205 # search the .map file to find the offset of Uni strings binary in the PE32+/TE file.
1207 VfrUniBaseName
["UniOffsetName"] = (self
.Name
+ "Strings")
1209 if not VfrUniBaseName
:
1211 MapFileName
= os
.path
.join(self
.OutputDir
, self
.Name
+ ".map")
1212 EfiFileName
= os
.path
.join(self
.OutputDir
, self
.Name
+ ".efi")
1213 VfrUniOffsetList
= GetVariableOffset(MapFileName
, EfiFileName
, list(VfrUniBaseName
.values()))
1214 if not VfrUniOffsetList
:
1217 OutputName
= '%sOffset.bin' % self
.Name
1218 UniVfrOffsetFileName
= os
.path
.join( self
.OutputDir
, OutputName
)
1221 fInputfile
= open(UniVfrOffsetFileName
, "wb+", 0)
1223 EdkLogger
.error("build", FILE_OPEN_FAILURE
, "File open failed for %s" % UniVfrOffsetFileName
, None)
1225 # Use a instance of BytesIO to cache data
1226 fStringIO
= BytesIO()
1228 for Item
in VfrUniOffsetList
:
1229 if (Item
[0].find("Strings") != -1):
1231 # UNI offset in image.
1233 # { 0x8913c5e0, 0x33f6, 0x4d86, { 0x9b, 0xf1, 0x43, 0xef, 0x89, 0xfc, 0x6, 0x66 } }
1235 UniGuid
= b
'\xe0\xc5\x13\x89\xf63\x86M\x9b\xf1C\xef\x89\xfc\x06f'
1236 fStringIO
.write(UniGuid
)
1237 UniValue
= pack ('Q', int (Item
[1], 16))
1238 fStringIO
.write (UniValue
)
1241 # VFR binary offset in image.
1243 # { 0xd0bc7cb4, 0x6a47, 0x495f, { 0xaa, 0x11, 0x71, 0x7, 0x46, 0xda, 0x6, 0xa2 } };
1245 VfrGuid
= b
'\xb4|\xbc\xd0Gj_I\xaa\x11q\x07F\xda\x06\xa2'
1246 fStringIO
.write(VfrGuid
)
1247 VfrValue
= pack ('Q', int (Item
[1], 16))
1248 fStringIO
.write (VfrValue
)
1250 # write data into file.
1253 fInputfile
.write (fStringIO
.getvalue())
1255 EdkLogger
.error("build", FILE_WRITE_FAILURE
, "Write data to file %s failed, please check whether the "
1256 "file been locked or using by other applications." %UniVfrOffsetFileName
, None)
1262 def OutputFile(self
):
1264 OutputDir
= self
.OutputDir
.replace('\\', '/').strip('/')
1265 DebugDir
= self
.DebugDir
.replace('\\', '/').strip('/')
1266 for Item
in self
.CodaTargetList
:
1267 File
= Item
.Target
.Path
.replace('\\', '/').strip('/').replace(DebugDir
, '').replace(OutputDir
, '').strip('/')
1269 if self
.DepexGenerated
:
1270 retVal
.add(self
.Name
+ '.depex')
1272 Bin
= self
._GenOffsetBin
()
1276 for Root
, Dirs
, Files
in os
.walk(OutputDir
):
1278 if File
.lower().endswith('.pdb'):
1283 ## Create AsBuilt INF file the module
1285 def CreateAsBuiltInf(self
):
1287 if self
.IsAsBuiltInfCreated
:
1290 # Skip INF file generation for libraries
1294 # Skip the following code for modules with no source files
1295 if not self
.SourceFileList
:
1298 # Skip the following code for modules without any binary files
1299 if self
.BinaryFileList
:
1302 ### TODO: How to handles mixed source and binary modules
1304 # Find all DynamicEx and PatchableInModule PCDs used by this module and dependent libraries
1305 # Also find all packages that the DynamicEx PCDs depend on
1310 PcdTokenSpaceList
= []
1311 for Pcd
in self
.ModulePcdList
+ self
.LibraryPcdList
:
1312 if Pcd
.Type
== TAB_PCDS_PATCHABLE_IN_MODULE
:
1313 PatchablePcds
.append(Pcd
)
1314 PcdCheckList
.append((Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
, TAB_PCDS_PATCHABLE_IN_MODULE
))
1315 elif Pcd
.Type
in PCD_DYNAMIC_EX_TYPE_SET
:
1318 PcdCheckList
.append((Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
, TAB_PCDS_DYNAMIC_EX
))
1319 PcdCheckList
.append((Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
, TAB_PCDS_DYNAMIC
))
1320 PcdTokenSpaceList
.append(Pcd
.TokenSpaceGuidCName
)
1321 GuidList
= OrderedDict(self
.GuidList
)
1322 for TokenSpace
in self
.GetGuidsUsedByPcd
:
1323 # If token space is not referred by patch PCD or Ex PCD, remove the GUID from GUID list
1324 # The GUIDs in GUIDs section should really be the GUIDs in source INF or referred by Ex an patch PCDs
1325 if TokenSpace
not in PcdTokenSpaceList
and TokenSpace
in GuidList
:
1326 GuidList
.pop(TokenSpace
)
1327 CheckList
= (GuidList
, self
.PpiList
, self
.ProtocolList
, PcdCheckList
)
1328 for Package
in self
.DerivedPackageList
:
1329 if Package
in Packages
:
1331 BeChecked
= (Package
.Guids
, Package
.Ppis
, Package
.Protocols
, Package
.Pcds
)
1333 for Index
in range(len(BeChecked
)):
1334 for Item
in CheckList
[Index
]:
1335 if Item
in BeChecked
[Index
]:
1336 Packages
.append(Package
)
1342 VfrPcds
= self
._GetPcdsMaybeUsedByVfr
()
1343 for Pkg
in self
.PlatformInfo
.PackageList
:
1346 for VfrPcd
in VfrPcds
:
1347 if ((VfrPcd
.TokenCName
, VfrPcd
.TokenSpaceGuidCName
, TAB_PCDS_DYNAMIC_EX
) in Pkg
.Pcds
or
1348 (VfrPcd
.TokenCName
, VfrPcd
.TokenSpaceGuidCName
, TAB_PCDS_DYNAMIC
) in Pkg
.Pcds
):
1349 Packages
.append(Pkg
)
1352 ModuleType
= SUP_MODULE_DXE_DRIVER
if self
.ModuleType
== SUP_MODULE_UEFI_DRIVER
and self
.DepexGenerated
else self
.ModuleType
1353 DriverType
= self
.PcdIsDriver
if self
.PcdIsDriver
else ''
1355 MDefs
= self
.Module
.Defines
1358 'module_name' : self
.Name
,
1359 'module_guid' : Guid
,
1360 'module_module_type' : ModuleType
,
1361 'module_version_string' : [MDefs
['VERSION_STRING']] if 'VERSION_STRING' in MDefs
else [],
1362 'pcd_is_driver_string' : [],
1363 'module_uefi_specification_version' : [],
1364 'module_pi_specification_version' : [],
1365 'module_entry_point' : self
.Module
.ModuleEntryPointList
,
1366 'module_unload_image' : self
.Module
.ModuleUnloadImageList
,
1367 'module_constructor' : self
.Module
.ConstructorList
,
1368 'module_destructor' : self
.Module
.DestructorList
,
1369 'module_shadow' : [MDefs
['SHADOW']] if 'SHADOW' in MDefs
else [],
1370 'module_pci_vendor_id' : [MDefs
['PCI_VENDOR_ID']] if 'PCI_VENDOR_ID' in MDefs
else [],
1371 'module_pci_device_id' : [MDefs
['PCI_DEVICE_ID']] if 'PCI_DEVICE_ID' in MDefs
else [],
1372 'module_pci_class_code' : [MDefs
['PCI_CLASS_CODE']] if 'PCI_CLASS_CODE' in MDefs
else [],
1373 'module_pci_revision' : [MDefs
['PCI_REVISION']] if 'PCI_REVISION' in MDefs
else [],
1374 'module_build_number' : [MDefs
['BUILD_NUMBER']] if 'BUILD_NUMBER' in MDefs
else [],
1375 'module_spec' : [MDefs
['SPEC']] if 'SPEC' in MDefs
else [],
1376 'module_uefi_hii_resource_section' : [MDefs
['UEFI_HII_RESOURCE_SECTION']] if 'UEFI_HII_RESOURCE_SECTION' in MDefs
else [],
1377 'module_uni_file' : [MDefs
['MODULE_UNI_FILE']] if 'MODULE_UNI_FILE' in MDefs
else [],
1378 'module_arch' : self
.Arch
,
1379 'package_item' : [Package
.MetaFile
.File
.replace('\\', '/') for Package
in Packages
],
1381 'patchablepcd_item' : [],
1383 'protocol_item' : [],
1387 'libraryclasses_item' : []
1390 if 'MODULE_UNI_FILE' in MDefs
:
1391 UNIFile
= os
.path
.join(self
.MetaFile
.Dir
, MDefs
['MODULE_UNI_FILE'])
1392 if os
.path
.isfile(UNIFile
):
1393 shutil
.copy2(UNIFile
, self
.OutputDir
)
1395 if self
.AutoGenVersion
> int(gInfSpecVersion
, 0):
1396 AsBuiltInfDict
['module_inf_version'] = '0x%08x' % self
.AutoGenVersion
1398 AsBuiltInfDict
['module_inf_version'] = gInfSpecVersion
1401 AsBuiltInfDict
['pcd_is_driver_string'].append(DriverType
)
1403 if 'UEFI_SPECIFICATION_VERSION' in self
.Specification
:
1404 AsBuiltInfDict
['module_uefi_specification_version'].append(self
.Specification
['UEFI_SPECIFICATION_VERSION'])
1405 if 'PI_SPECIFICATION_VERSION' in self
.Specification
:
1406 AsBuiltInfDict
['module_pi_specification_version'].append(self
.Specification
['PI_SPECIFICATION_VERSION'])
1408 OutputDir
= self
.OutputDir
.replace('\\', '/').strip('/')
1409 DebugDir
= self
.DebugDir
.replace('\\', '/').strip('/')
1410 for Item
in self
.CodaTargetList
:
1411 File
= Item
.Target
.Path
.replace('\\', '/').strip('/').replace(DebugDir
, '').replace(OutputDir
, '').strip('/')
1412 if os
.path
.isabs(File
):
1413 File
= File
.replace('\\', '/').strip('/').replace(OutputDir
, '').strip('/')
1414 if Item
.Target
.Ext
.lower() == '.aml':
1415 AsBuiltInfDict
['binary_item'].append('ASL|' + File
)
1416 elif Item
.Target
.Ext
.lower() == '.acpi':
1417 AsBuiltInfDict
['binary_item'].append('ACPI|' + File
)
1418 elif Item
.Target
.Ext
.lower() == '.efi':
1419 AsBuiltInfDict
['binary_item'].append('PE32|' + self
.Name
+ '.efi')
1421 AsBuiltInfDict
['binary_item'].append('BIN|' + File
)
1422 if not self
.DepexGenerated
:
1423 DepexFile
= os
.path
.join(self
.OutputDir
, self
.Name
+ '.depex')
1424 if os
.path
.exists(DepexFile
):
1425 self
.DepexGenerated
= True
1426 if self
.DepexGenerated
:
1427 if self
.ModuleType
in [SUP_MODULE_PEIM
]:
1428 AsBuiltInfDict
['binary_item'].append('PEI_DEPEX|' + self
.Name
+ '.depex')
1429 elif self
.ModuleType
in [SUP_MODULE_DXE_DRIVER
, SUP_MODULE_DXE_RUNTIME_DRIVER
, SUP_MODULE_DXE_SAL_DRIVER
, SUP_MODULE_UEFI_DRIVER
]:
1430 AsBuiltInfDict
['binary_item'].append('DXE_DEPEX|' + self
.Name
+ '.depex')
1431 elif self
.ModuleType
in [SUP_MODULE_DXE_SMM_DRIVER
]:
1432 AsBuiltInfDict
['binary_item'].append('SMM_DEPEX|' + self
.Name
+ '.depex')
1434 Bin
= self
._GenOffsetBin
()
1436 AsBuiltInfDict
['binary_item'].append('BIN|%s' % Bin
)
1438 for Root
, Dirs
, Files
in os
.walk(OutputDir
):
1440 if File
.lower().endswith('.pdb'):
1441 AsBuiltInfDict
['binary_item'].append('DISPOSABLE|' + File
)
1442 HeaderComments
= self
.Module
.HeaderComments
1444 for Index
in range(len(HeaderComments
)):
1445 if HeaderComments
[Index
].find('@BinaryHeader') != -1:
1446 HeaderComments
[Index
] = HeaderComments
[Index
].replace('@BinaryHeader', '@file')
1449 AsBuiltInfDict
['header_comments'] = '\n'.join(HeaderComments
[StartPos
:]).replace(':#', '://')
1450 AsBuiltInfDict
['tail_comments'] = '\n'.join(self
.Module
.TailComments
)
1453 (self
.ProtocolList
, self
._ProtocolComments
, 'protocol_item'),
1454 (self
.PpiList
, self
._PpiComments
, 'ppi_item'),
1455 (GuidList
, self
._GuidComments
, 'guid_item')
1457 for Item
in GenList
:
1458 for CName
in Item
[0]:
1459 Comments
= '\n '.join(Item
[1][CName
]) if CName
in Item
[1] else ''
1460 Entry
= Comments
+ '\n ' + CName
if Comments
else CName
1461 AsBuiltInfDict
[Item
[2]].append(Entry
)
1462 PatchList
= parsePcdInfoFromMapFile(
1463 os
.path
.join(self
.OutputDir
, self
.Name
+ '.map'),
1464 os
.path
.join(self
.OutputDir
, self
.Name
+ '.efi')
1467 for Pcd
in PatchablePcds
:
1468 TokenCName
= Pcd
.TokenCName
1469 for PcdItem
in GlobalData
.MixedPcd
:
1470 if (Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
) in GlobalData
.MixedPcd
[PcdItem
]:
1471 TokenCName
= PcdItem
[0]
1473 for PatchPcd
in PatchList
:
1474 if TokenCName
== PatchPcd
[0]:
1479 if Pcd
.DatumType
== 'BOOLEAN':
1480 BoolValue
= Pcd
.DefaultValue
.upper()
1481 if BoolValue
== 'TRUE':
1482 Pcd
.DefaultValue
= '1'
1483 elif BoolValue
== 'FALSE':
1484 Pcd
.DefaultValue
= '0'
1486 if Pcd
.DatumType
in TAB_PCD_NUMERIC_TYPES
:
1487 HexFormat
= '0x%02x'
1488 if Pcd
.DatumType
== TAB_UINT16
:
1489 HexFormat
= '0x%04x'
1490 elif Pcd
.DatumType
== TAB_UINT32
:
1491 HexFormat
= '0x%08x'
1492 elif Pcd
.DatumType
== TAB_UINT64
:
1493 HexFormat
= '0x%016x'
1494 PcdValue
= HexFormat
% int(Pcd
.DefaultValue
, 0)
1496 if Pcd
.MaxDatumSize
is None or Pcd
.MaxDatumSize
== '':
1497 EdkLogger
.error("build", AUTOGEN_ERROR
,
1498 "Unknown [MaxDatumSize] of PCD [%s.%s]" % (Pcd
.TokenSpaceGuidCName
, TokenCName
)
1500 ArraySize
= int(Pcd
.MaxDatumSize
, 0)
1501 PcdValue
= Pcd
.DefaultValue
1502 if PcdValue
[0] != '{':
1504 if PcdValue
[0] == 'L':
1506 PcdValue
= PcdValue
.lstrip('L')
1507 PcdValue
= eval(PcdValue
)
1509 for Index
in range(0, len(PcdValue
)):
1511 CharVal
= ord(PcdValue
[Index
])
1512 NewValue
= NewValue
+ '0x%02x' % (CharVal
& 0x00FF) + ', ' \
1513 + '0x%02x' % (CharVal
>> 8) + ', '
1515 NewValue
= NewValue
+ '0x%02x' % (ord(PcdValue
[Index
]) % 0x100) + ', '
1518 Padding
= Padding
* 2
1519 ArraySize
= ArraySize
// 2
1520 if ArraySize
< (len(PcdValue
) + 1):
1521 if Pcd
.MaxSizeUserSet
:
1522 EdkLogger
.error("build", AUTOGEN_ERROR
,
1523 "The maximum size of VOID* type PCD '%s.%s' is less than its actual size occupied." % (Pcd
.TokenSpaceGuidCName
, TokenCName
)
1526 ArraySize
= len(PcdValue
) + 1
1527 if ArraySize
> len(PcdValue
) + 1:
1528 NewValue
= NewValue
+ Padding
* (ArraySize
- len(PcdValue
) - 1)
1529 PcdValue
= NewValue
+ Padding
.strip().rstrip(',') + '}'
1530 elif len(PcdValue
.split(',')) <= ArraySize
:
1531 PcdValue
= PcdValue
.rstrip('}') + ', 0x00' * (ArraySize
- len(PcdValue
.split(',')))
1534 if Pcd
.MaxSizeUserSet
:
1535 EdkLogger
.error("build", AUTOGEN_ERROR
,
1536 "The maximum size of VOID* type PCD '%s.%s' is less than its actual size occupied." % (Pcd
.TokenSpaceGuidCName
, TokenCName
)
1539 ArraySize
= len(PcdValue
) + 1
1540 PcdItem
= '%s.%s|%s|0x%X' % \
1541 (Pcd
.TokenSpaceGuidCName
, TokenCName
, PcdValue
, PatchPcd
[1])
1543 if (Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
) in self
._PcdComments
:
1544 PcdComments
= '\n '.join(self
._PcdComments
[Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
])
1546 PcdItem
= PcdComments
+ '\n ' + PcdItem
1547 AsBuiltInfDict
['patchablepcd_item'].append(PcdItem
)
1549 for Pcd
in Pcds
+ VfrPcds
:
1552 TokenCName
= Pcd
.TokenCName
1553 for PcdItem
in GlobalData
.MixedPcd
:
1554 if (Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
) in GlobalData
.MixedPcd
[PcdItem
]:
1555 TokenCName
= PcdItem
[0]
1557 if Pcd
.Type
== TAB_PCDS_DYNAMIC_EX_HII
:
1558 for SkuName
in Pcd
.SkuInfoList
:
1559 SkuInfo
= Pcd
.SkuInfoList
[SkuName
]
1560 HiiInfo
= '## %s|%s|%s' % (SkuInfo
.VariableName
, SkuInfo
.VariableGuid
, SkuInfo
.VariableOffset
)
1562 if (Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
) in self
._PcdComments
:
1563 PcdCommentList
= self
._PcdComments
[Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
][:]
1567 for Index
, Comment
in enumerate(PcdCommentList
):
1568 for Usage
in UsageList
:
1569 if Comment
.find(Usage
) != -1:
1573 if UsageIndex
!= -1:
1574 PcdCommentList
[UsageIndex
] = '## %s %s %s' % (UsageStr
, HiiInfo
, PcdCommentList
[UsageIndex
].replace(UsageStr
, ''))
1576 PcdCommentList
.append('## UNDEFINED ' + HiiInfo
)
1577 PcdComments
= '\n '.join(PcdCommentList
)
1578 PcdEntry
= Pcd
.TokenSpaceGuidCName
+ '.' + TokenCName
1580 PcdEntry
= PcdComments
+ '\n ' + PcdEntry
1581 AsBuiltInfDict
['pcd_item'].append(PcdEntry
)
1582 for Item
in self
.BuildOption
:
1583 if 'FLAGS' in self
.BuildOption
[Item
]:
1584 AsBuiltInfDict
['flags_item'].append('%s:%s_%s_%s_%s_FLAGS = %s' % (self
.ToolChainFamily
, self
.BuildTarget
, self
.ToolChain
, self
.Arch
, Item
, self
.BuildOption
[Item
]['FLAGS'].strip()))
1586 # Generated LibraryClasses section in comments.
1587 for Library
in self
.LibraryAutoGenList
:
1588 AsBuiltInfDict
['libraryclasses_item'].append(Library
.MetaFile
.File
.replace('\\', '/'))
1590 # Generated UserExtensions TianoCore section.
1591 # All tianocore user extensions are copied.
1593 for TianoCore
in self
._GetTianoCoreUserExtensionList
():
1594 UserExtStr
+= '\n'.join(TianoCore
)
1595 ExtensionFile
= os
.path
.join(self
.MetaFile
.Dir
, TianoCore
[1])
1596 if os
.path
.isfile(ExtensionFile
):
1597 shutil
.copy2(ExtensionFile
, self
.OutputDir
)
1598 AsBuiltInfDict
['userextension_tianocore_item'] = UserExtStr
1600 # Generated depex expression section in comments.
1601 DepexExpression
= self
._GetDepexExpresionString
()
1602 AsBuiltInfDict
['depexsection_item'] = DepexExpression
if DepexExpression
else ''
1604 AsBuiltInf
= TemplateString()
1605 AsBuiltInf
.Append(gAsBuiltInfHeaderString
.Replace(AsBuiltInfDict
))
1607 SaveFileOnChange(os
.path
.join(self
.OutputDir
, self
.Name
+ '.inf'), str(AsBuiltInf
), False)
1609 self
.IsAsBuiltInfCreated
= True
1611 def CopyModuleToCache(self
):
1612 FileDir
= path
.join(GlobalData
.gBinCacheDest
, self
.PlatformInfo
.Name
, self
.BuildTarget
+ "_" + self
.ToolChain
, self
.Arch
, self
.SourceDir
, self
.MetaFile
.BaseName
)
1613 CreateDirectory (FileDir
)
1614 HashFile
= path
.join(self
.BuildDir
, self
.Name
+ '.hash')
1615 if os
.path
.exists(HashFile
):
1616 CopyFileOnChange(HashFile
, FileDir
)
1617 ModuleFile
= path
.join(self
.OutputDir
, self
.Name
+ '.inf')
1618 if os
.path
.exists(ModuleFile
):
1619 CopyFileOnChange(ModuleFile
, FileDir
)
1620 if not self
.OutputFile
:
1621 Ma
= self
.BuildDatabase
[self
.MetaFile
, self
.Arch
, self
.BuildTarget
, self
.ToolChain
]
1622 self
.OutputFile
= Ma
.Binaries
1623 for File
in self
.OutputFile
:
1625 if not os
.path
.isabs(File
):
1626 File
= os
.path
.join(self
.OutputDir
, File
)
1627 if os
.path
.exists(File
):
1628 sub_dir
= os
.path
.relpath(File
, self
.OutputDir
)
1629 destination_file
= os
.path
.join(FileDir
, sub_dir
)
1630 destination_dir
= os
.path
.dirname(destination_file
)
1631 CreateDirectory(destination_dir
)
1632 CopyFileOnChange(File
, destination_dir
)
1634 def AttemptModuleCacheCopy(self
):
1635 # If library or Module is binary do not skip by hash
1636 if self
.IsBinaryModule
:
1638 # .inc is contains binary information so do not skip by hash as well
1639 for f_ext
in self
.SourceFileList
:
1640 if '.inc' in str(f_ext
):
1642 FileDir
= path
.join(GlobalData
.gBinCacheSource
, self
.PlatformInfo
.Name
, self
.BuildTarget
+ "_" + self
.ToolChain
, self
.Arch
, self
.SourceDir
, self
.MetaFile
.BaseName
)
1643 HashFile
= path
.join(FileDir
, self
.Name
+ '.hash')
1644 if os
.path
.exists(HashFile
):
1645 f
= open(HashFile
, 'r')
1646 CacheHash
= f
.read()
1648 self
.GenModuleHash()
1649 if GlobalData
.gModuleHash
[self
.Arch
][self
.Name
]:
1650 if CacheHash
== GlobalData
.gModuleHash
[self
.Arch
][self
.Name
]:
1651 for root
, dir, files
in os
.walk(FileDir
):
1653 if self
.Name
+ '.hash' in f
:
1654 CopyFileOnChange(HashFile
, self
.BuildDir
)
1656 File
= path
.join(root
, f
)
1657 sub_dir
= os
.path
.relpath(File
, FileDir
)
1658 destination_file
= os
.path
.join(self
.OutputDir
, sub_dir
)
1659 destination_dir
= os
.path
.dirname(destination_file
)
1660 CreateDirectory(destination_dir
)
1661 CopyFileOnChange(File
, destination_dir
)
1662 if self
.Name
== "PcdPeim" or self
.Name
== "PcdDxe":
1663 CreatePcdDatabaseCode(self
, TemplateString(), TemplateString())
1667 ## Create makefile for the module and its dependent libraries
1669 # @param CreateLibraryMakeFile Flag indicating if or not the makefiles of
1670 # dependent libraries will be created
1672 @cached_class_function
1673 def CreateMakeFile(self
, CreateLibraryMakeFile
=True, GenFfsList
= []):
1674 # nest this function inside it's only caller.
1675 def CreateTimeStamp():
1676 FileSet
= {self
.MetaFile
.Path
}
1678 for SourceFile
in self
.Module
.Sources
:
1679 FileSet
.add (SourceFile
.Path
)
1681 for Lib
in self
.DependentLibraryList
:
1682 FileSet
.add (Lib
.MetaFile
.Path
)
1684 for f
in self
.AutoGenDepSet
:
1685 FileSet
.add (f
.Path
)
1687 if os
.path
.exists (self
.TimeStampPath
):
1688 os
.remove (self
.TimeStampPath
)
1689 with
open(self
.TimeStampPath
, 'w+') as fd
:
1694 # Ignore generating makefile when it is a binary module
1695 if self
.IsBinaryModule
:
1698 self
.GenFfsList
= GenFfsList
1700 if not self
.IsLibrary
and CreateLibraryMakeFile
:
1701 for LibraryAutoGen
in self
.LibraryAutoGenList
:
1702 LibraryAutoGen
.CreateMakeFile()
1704 # Don't enable if hash feature enabled, CanSkip uses timestamps to determine build skipping
1705 if not GlobalData
.gUseHashCache
and self
.CanSkip():
1708 if len(self
.CustomMakefile
) == 0:
1709 Makefile
= GenMake
.ModuleMakefile(self
)
1711 Makefile
= GenMake
.CustomMakefile(self
)
1712 if Makefile
.Generate():
1713 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "Generated makefile for module %s [%s]" %
1714 (self
.Name
, self
.Arch
))
1716 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "Skipped the generation of makefile for module %s [%s]" %
1717 (self
.Name
, self
.Arch
))
1721 def CopyBinaryFiles(self
):
1722 for File
in self
.Module
.Binaries
:
1724 DstPath
= os
.path
.join(self
.OutputDir
, os
.path
.basename(SrcPath
))
1725 CopyLongFilePath(SrcPath
, DstPath
)
1726 ## Create autogen code for the module and its dependent libraries
1728 # @param CreateLibraryCodeFile Flag indicating if or not the code of
1729 # dependent libraries will be created
1731 def CreateCodeFile(self
, CreateLibraryCodeFile
=True):
1732 if self
.IsCodeFileCreated
:
1735 # Need to generate PcdDatabase even PcdDriver is binarymodule
1736 if self
.IsBinaryModule
and self
.PcdIsDriver
!= '':
1737 CreatePcdDatabaseCode(self
, TemplateString(), TemplateString())
1739 if self
.IsBinaryModule
:
1741 self
.CopyBinaryFiles()
1744 if not self
.IsLibrary
and CreateLibraryCodeFile
:
1745 for LibraryAutoGen
in self
.LibraryAutoGenList
:
1746 LibraryAutoGen
.CreateCodeFile()
1747 # Don't enable if hash feature enabled, CanSkip uses timestamps to determine build skipping
1748 if not GlobalData
.gUseHashCache
and self
.CanSkip():
1752 IgoredAutoGenList
= []
1754 for File
in self
.AutoGenFileList
:
1755 if GenC
.Generate(File
.Path
, self
.AutoGenFileList
[File
], File
.IsBinary
):
1756 AutoGenList
.append(str(File
))
1758 IgoredAutoGenList
.append(str(File
))
1761 for ModuleType
in self
.DepexList
:
1762 # Ignore empty [depex] section or [depex] section for SUP_MODULE_USER_DEFINED module
1763 if len(self
.DepexList
[ModuleType
]) == 0 or ModuleType
== SUP_MODULE_USER_DEFINED
or ModuleType
== SUP_MODULE_HOST_APPLICATION
:
1766 Dpx
= GenDepex
.DependencyExpression(self
.DepexList
[ModuleType
], ModuleType
, True)
1767 DpxFile
= gAutoGenDepexFileName
% {"module_name" : self
.Name
}
1769 if len(Dpx
.PostfixNotation
) != 0:
1770 self
.DepexGenerated
= True
1772 if Dpx
.Generate(path
.join(self
.OutputDir
, DpxFile
)):
1773 AutoGenList
.append(str(DpxFile
))
1775 IgoredAutoGenList
.append(str(DpxFile
))
1777 if IgoredAutoGenList
== []:
1778 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "Generated [%s] files for module %s [%s]" %
1779 (" ".join(AutoGenList
), self
.Name
, self
.Arch
))
1780 elif AutoGenList
== []:
1781 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "Skipped the generation of [%s] files for module %s [%s]" %
1782 (" ".join(IgoredAutoGenList
), self
.Name
, self
.Arch
))
1784 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "Generated [%s] (skipped %s) files for module %s [%s]" %
1785 (" ".join(AutoGenList
), " ".join(IgoredAutoGenList
), self
.Name
, self
.Arch
))
1787 self
.IsCodeFileCreated
= True
1790 ## Summarize the ModuleAutoGen objects of all libraries used by this module
1792 def LibraryAutoGenList(self
):
1794 for Library
in self
.DependentLibraryList
:
1801 self
.PlatformInfo
.MetaFile
,
1805 if La
not in RetVal
:
1807 for Lib
in La
.CodaTargetList
:
1808 self
._ApplyBuildRule
(Lib
.Target
, TAB_UNKNOWN_FILE
)
1811 def GenModuleHash(self
):
1812 # Initialize a dictionary for each arch type
1813 if self
.Arch
not in GlobalData
.gModuleHash
:
1814 GlobalData
.gModuleHash
[self
.Arch
] = {}
1816 # Early exit if module or library has been hashed and is in memory
1817 if self
.Name
in GlobalData
.gModuleHash
[self
.Arch
]:
1818 return GlobalData
.gModuleHash
[self
.Arch
][self
.Name
].encode('utf-8')
1820 # Initialze hash object
1823 # Add Platform level hash
1824 m
.update(GlobalData
.gPlatformHash
.encode('utf-8'))
1826 # Add Package level hash
1827 if self
.DependentPackageList
:
1828 for Pkg
in sorted(self
.DependentPackageList
, key
=lambda x
: x
.PackageName
):
1829 if Pkg
.PackageName
in GlobalData
.gPackageHash
:
1830 m
.update(GlobalData
.gPackageHash
[Pkg
.PackageName
].encode('utf-8'))
1833 if self
.LibraryAutoGenList
:
1834 for Lib
in sorted(self
.LibraryAutoGenList
, key
=lambda x
: x
.Name
):
1835 if Lib
.Name
not in GlobalData
.gModuleHash
[self
.Arch
]:
1837 m
.update(GlobalData
.gModuleHash
[self
.Arch
][Lib
.Name
].encode('utf-8'))
1840 f
= open(str(self
.MetaFile
), 'rb')
1845 # Add Module's source files
1846 if self
.SourceFileList
:
1847 for File
in sorted(self
.SourceFileList
, key
=lambda x
: str(x
)):
1848 f
= open(str(File
), 'rb')
1853 GlobalData
.gModuleHash
[self
.Arch
][self
.Name
] = m
.hexdigest()
1855 return GlobalData
.gModuleHash
[self
.Arch
][self
.Name
].encode('utf-8')
1857 ## Decide whether we can skip the ModuleAutoGen process
1858 def CanSkipbyHash(self
):
1859 # Hashing feature is off
1860 if not GlobalData
.gUseHashCache
:
1863 # Initialize a dictionary for each arch type
1864 if self
.Arch
not in GlobalData
.gBuildHashSkipTracking
:
1865 GlobalData
.gBuildHashSkipTracking
[self
.Arch
] = dict()
1867 # If library or Module is binary do not skip by hash
1868 if self
.IsBinaryModule
:
1871 # .inc is contains binary information so do not skip by hash as well
1872 for f_ext
in self
.SourceFileList
:
1873 if '.inc' in str(f_ext
):
1876 # Use Cache, if exists and if Module has a copy in cache
1877 if GlobalData
.gBinCacheSource
and self
.AttemptModuleCacheCopy():
1880 # Early exit for libraries that haven't yet finished building
1881 HashFile
= path
.join(self
.BuildDir
, self
.Name
+ ".hash")
1882 if self
.IsLibrary
and not os
.path
.exists(HashFile
):
1885 # Return a Boolean based on if can skip by hash, either from memory or from IO.
1886 if self
.Name
not in GlobalData
.gBuildHashSkipTracking
[self
.Arch
]:
1887 # If hashes are the same, SaveFileOnChange() will return False.
1888 GlobalData
.gBuildHashSkipTracking
[self
.Arch
][self
.Name
] = not SaveFileOnChange(HashFile
, self
.GenModuleHash(), True)
1889 return GlobalData
.gBuildHashSkipTracking
[self
.Arch
][self
.Name
]
1891 return GlobalData
.gBuildHashSkipTracking
[self
.Arch
][self
.Name
]
1893 ## Decide whether we can skip the ModuleAutoGen process
1894 # If any source file is newer than the module than we cannot skip
1897 if self
.MakeFileDir
in GlobalData
.gSikpAutoGenCache
:
1899 if not os
.path
.exists(self
.TimeStampPath
):
1901 #last creation time of the module
1902 DstTimeStamp
= os
.stat(self
.TimeStampPath
)[8]
1904 SrcTimeStamp
= self
.Workspace
._SrcTimeStamp
1905 if SrcTimeStamp
> DstTimeStamp
:
1908 with
open(self
.TimeStampPath
,'r') as f
:
1910 source
= source
.rstrip('\n')
1911 if not os
.path
.exists(source
):
1913 if source
not in ModuleAutoGen
.TimeDict
:
1914 ModuleAutoGen
.TimeDict
[source
] = os
.stat(source
)[8]
1915 if ModuleAutoGen
.TimeDict
[source
] > DstTimeStamp
:
1917 GlobalData
.gSikpAutoGenCache
.add(self
.MakeFileDir
)
1921 def TimeStampPath(self
):
1922 return os
.path
.join(self
.MakeFileDir
, 'AutoGenTimeStamp')