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
10 from __future__
import print_function
11 from __future__
import absolute_import
12 import os
.path
as path
14 from collections
import defaultdict
15 from GenFds
.FdfParser
import FdfParser
16 from Workspace
.WorkspaceCommon
import GetModuleLibInstances
17 from AutoGen
import GenMake
18 from AutoGen
.AutoGen
import AutoGen
19 from AutoGen
.PlatformAutoGen
import PlatformAutoGen
20 from AutoGen
.BuildEngine
import gDefaultBuildRuleFile
21 from Common
.ToolDefClassObject
import gDefaultToolsDefFile
22 from Common
.StringUtils
import NormPath
23 from Common
.BuildToolError
import *
24 from Common
.DataType
import *
25 from Common
.Misc
import *
27 ## Regular expression for splitting Dependency Expression string into tokens
28 gDepexTokenPattern
= re
.compile("(\(|\)|\w+| \S+\.inf)")
30 ## Regular expression for match: PCD(xxxx.yyy)
31 gPCDAsGuidPattern
= re
.compile(r
"^PCD\(.+\..+\)$")
33 ## Workspace AutoGen class
35 # This class is used mainly to control the whole platform build for different
36 # architecture. This class will generate top level makefile.
38 class WorkspaceAutoGen(AutoGen
):
39 # call super().__init__ then call the worker function with different parameter count
40 def __init__(self
, Workspace
, MetaFile
, Target
, Toolchain
, Arch
, *args
, **kwargs
):
41 if not hasattr(self
, "_Init"):
42 self
._InitWorker
(Workspace
, MetaFile
, Target
, Toolchain
, Arch
, *args
, **kwargs
)
45 ## Initialize WorkspaceAutoGen
47 # @param WorkspaceDir Root directory of workspace
48 # @param ActivePlatform Meta-file of active platform
49 # @param Target Build target
50 # @param Toolchain Tool chain name
51 # @param ArchList List of architecture of current build
52 # @param MetaFileDb Database containing meta-files
53 # @param BuildConfig Configuration of build
54 # @param ToolDefinition Tool chain definitions
55 # @param FlashDefinitionFile File of flash definition
56 # @param Fds FD list to be generated
57 # @param Fvs FV list to be generated
58 # @param Caps Capsule list to be generated
59 # @param SkuId SKU id from command line
61 def _InitWorker(self
, WorkspaceDir
, ActivePlatform
, Target
, Toolchain
, ArchList
, MetaFileDb
,
62 BuildConfig
, ToolDefinition
, FlashDefinitionFile
='', Fds
=None, Fvs
=None, Caps
=None, SkuId
='', UniFlag
=None,
63 Progress
=None, BuildModule
=None):
64 self
.BuildDatabase
= MetaFileDb
65 self
.MetaFile
= ActivePlatform
66 self
.WorkspaceDir
= WorkspaceDir
67 self
.Platform
= self
.BuildDatabase
[self
.MetaFile
, TAB_ARCH_COMMON
, Target
, Toolchain
]
68 GlobalData
.gActivePlatform
= self
.Platform
69 self
.BuildTarget
= Target
70 self
.ToolChain
= Toolchain
71 self
.ArchList
= ArchList
73 self
.UniFlag
= UniFlag
75 self
.TargetTxt
= BuildConfig
76 self
.ToolDef
= ToolDefinition
77 self
.FdfFile
= FlashDefinitionFile
78 self
.FdTargetList
= Fds
if Fds
else []
79 self
.FvTargetList
= Fvs
if Fvs
else []
80 self
.CapTargetList
= Caps
if Caps
else []
81 self
.AutoGenObjectList
= []
84 # there's many relative directory operations, so ...
85 os
.chdir(self
.WorkspaceDir
)
88 self
.ValidateBuildTarget()
92 EdkLogger
.info('%-16s = %s' % ("Architecture(s)", ' '.join(self
.ArchList
)))
93 EdkLogger
.info('%-16s = %s' % ("Build target", self
.BuildTarget
))
94 EdkLogger
.info('%-16s = %s' % ("Toolchain", self
.ToolChain
))
96 EdkLogger
.info('\n%-24s = %s' % ("Active Platform", self
.Platform
))
98 EdkLogger
.info('%-24s = %s' % ("Active Module", BuildModule
))
101 EdkLogger
.info('%-24s = %s' % ("Flash Image Definition", self
.FdfFile
))
103 EdkLogger
.verbose("\nFLASH_DEFINITION = %s" % self
.FdfFile
)
106 Progress
.Start("\nProcessing meta-data")
108 # Mark now build in AutoGen Phase
110 GlobalData
.gAutoGenPhase
= True
111 self
.ProcessModuleFromPdf()
112 self
.ProcessPcdType()
113 self
.ProcessMixedPcd()
114 self
.VerifyPcdsFromFDF()
115 self
.CollectAllPcds()
116 for Pa
in self
.AutoGenObjectList
:
117 Pa
.FillData_LibConstPcd()
118 self
.GeneratePkgLevelHash()
120 # Check PCDs token value conflict in each DEC file.
122 self
._CheckAllPcdsTokenValueConflict
()
124 # Check PCD type and definition between DSC and DEC
126 self
._CheckPcdDefineAndType
()
128 self
.CreateBuildOptionsFile()
129 self
.CreatePcdTokenNumberFile()
130 self
.CreateModuleHashInfo()
136 if not self
.ArchList
:
137 ArchList
= set(self
.Platform
.SupArchList
)
139 ArchList
= set(self
.ArchList
) & set(self
.Platform
.SupArchList
)
141 EdkLogger
.error("build", PARAMETER_INVALID
,
142 ExtraData
= "Invalid ARCH specified. [Valid ARCH: %s]" % (" ".join(self
.Platform
.SupArchList
)))
143 elif self
.ArchList
and len(ArchList
) != len(self
.ArchList
):
144 SkippedArchList
= set(self
.ArchList
).symmetric_difference(set(self
.Platform
.SupArchList
))
145 EdkLogger
.verbose("\nArch [%s] is ignored because the platform supports [%s] only!"
146 % (" ".join(SkippedArchList
), " ".join(self
.Platform
.SupArchList
)))
147 self
.ArchList
= tuple(ArchList
)
149 # Validate build target
150 def ValidateBuildTarget(self
):
151 if self
.BuildTarget
not in self
.Platform
.BuildTargets
:
152 EdkLogger
.error("build", PARAMETER_INVALID
,
153 ExtraData
="Build target [%s] is not supported by the platform. [Valid target: %s]"
154 % (self
.BuildTarget
, " ".join(self
.Platform
.BuildTargets
)))
156 def FdfProfile(self
):
158 self
.FdfFile
= self
.Platform
.FlashDefinition
162 Fdf
= FdfParser(self
.FdfFile
.Path
)
164 GlobalData
.gFdfParser
= Fdf
165 if Fdf
.CurrentFdName
and Fdf
.CurrentFdName
in Fdf
.Profile
.FdDict
:
166 FdDict
= Fdf
.Profile
.FdDict
[Fdf
.CurrentFdName
]
167 for FdRegion
in FdDict
.RegionList
:
168 if str(FdRegion
.RegionType
) is 'FILE' and self
.Platform
.VpdToolGuid
in str(FdRegion
.RegionDataList
):
169 if int(FdRegion
.Offset
) % 8 != 0:
170 EdkLogger
.error("build", FORMAT_INVALID
, 'The VPD Base Address %s must be 8-byte aligned.' % (FdRegion
.Offset
))
171 FdfProfile
= Fdf
.Profile
173 if self
.FdTargetList
:
174 EdkLogger
.info("No flash definition file found. FD [%s] will be ignored." % " ".join(self
.FdTargetList
))
175 self
.FdTargetList
= []
176 if self
.FvTargetList
:
177 EdkLogger
.info("No flash definition file found. FV [%s] will be ignored." % " ".join(self
.FvTargetList
))
178 self
.FvTargetList
= []
179 if self
.CapTargetList
:
180 EdkLogger
.info("No flash definition file found. Capsule [%s] will be ignored." % " ".join(self
.CapTargetList
))
181 self
.CapTargetList
= []
185 def ProcessModuleFromPdf(self
):
188 for fvname
in self
.FvTargetList
:
189 if fvname
.upper() not in self
.FdfProfile
.FvDict
:
190 EdkLogger
.error("build", OPTION_VALUE_INVALID
,
191 "No such an FV in FDF file: %s" % fvname
)
193 # In DSC file may use FILE_GUID to override the module, then in the Platform.Modules use FILE_GUIDmodule.inf as key,
194 # but the path (self.MetaFile.Path) is the real path
195 for key
in self
.FdfProfile
.InfDict
:
197 MetaFile_cache
= defaultdict(set)
198 for Arch
in self
.ArchList
:
199 Current_Platform_cache
= self
.BuildDatabase
[self
.MetaFile
, Arch
, self
.BuildTarget
, self
.ToolChain
]
200 for Pkey
in Current_Platform_cache
.Modules
:
201 MetaFile_cache
[Arch
].add(Current_Platform_cache
.Modules
[Pkey
].MetaFile
)
202 for Inf
in self
.FdfProfile
.InfDict
[key
]:
203 ModuleFile
= PathClass(NormPath(Inf
), GlobalData
.gWorkspace
, Arch
)
204 for Arch
in self
.ArchList
:
205 if ModuleFile
in MetaFile_cache
[Arch
]:
208 ModuleData
= self
.BuildDatabase
[ModuleFile
, Arch
, self
.BuildTarget
, self
.ToolChain
]
209 if not ModuleData
.IsBinaryModule
:
210 EdkLogger
.error('build', PARSER_ERROR
, "Module %s NOT found in DSC file; Is it really a binary module?" % ModuleFile
)
213 for Arch
in self
.ArchList
:
215 Platform
= self
.BuildDatabase
[self
.MetaFile
, Arch
, self
.BuildTarget
, self
.ToolChain
]
217 for Pkey
in Platform
.Modules
:
218 MetaFileList
.add(Platform
.Modules
[Pkey
].MetaFile
)
219 for Inf
in self
.FdfProfile
.InfDict
[key
]:
220 ModuleFile
= PathClass(NormPath(Inf
), GlobalData
.gWorkspace
, Arch
)
221 if ModuleFile
in MetaFileList
:
223 ModuleData
= self
.BuildDatabase
[ModuleFile
, Arch
, self
.BuildTarget
, self
.ToolChain
]
224 if not ModuleData
.IsBinaryModule
:
225 EdkLogger
.error('build', PARSER_ERROR
, "Module %s NOT found in DSC file; Is it really a binary module?" % ModuleFile
)
229 # parse FDF file to get PCDs in it, if any
230 def VerifyPcdsFromFDF(self
):
233 PcdSet
= self
.FdfProfile
.PcdDict
234 self
.VerifyPcdDeclearation(PcdSet
)
236 def ProcessPcdType(self
):
237 for Arch
in self
.ArchList
:
238 Platform
= self
.BuildDatabase
[self
.MetaFile
, Arch
, self
.BuildTarget
, self
.ToolChain
]
240 # generate the SourcePcdDict and BinaryPcdDict
242 for BuildData
in list(self
.BuildDatabase
._CACHE
_.values()):
243 if BuildData
.Arch
!= Arch
:
245 if BuildData
.MetaFile
.Ext
== '.inf' and str(BuildData
) in Platform
.Modules
:
246 Libs
.extend(GetModuleLibInstances(BuildData
, Platform
,
251 self
.Platform
.MetaFile
,
254 for BuildData
in list(self
.BuildDatabase
._CACHE
_.values()):
255 if BuildData
.Arch
!= Arch
:
257 if BuildData
.MetaFile
.Ext
== '.inf':
258 for key
in BuildData
.Pcds
:
259 if BuildData
.Pcds
[key
].Pending
:
260 if key
in Platform
.Pcds
:
261 PcdInPlatform
= Platform
.Pcds
[key
]
262 if PcdInPlatform
.Type
:
263 BuildData
.Pcds
[key
].Type
= PcdInPlatform
.Type
264 BuildData
.Pcds
[key
].Pending
= False
266 if BuildData
.MetaFile
in Platform
.Modules
:
267 PlatformModule
= Platform
.Modules
[str(BuildData
.MetaFile
)]
268 if key
in PlatformModule
.Pcds
:
269 PcdInPlatform
= PlatformModule
.Pcds
[key
]
270 if PcdInPlatform
.Type
:
271 BuildData
.Pcds
[key
].Type
= PcdInPlatform
.Type
272 BuildData
.Pcds
[key
].Pending
= False
274 #Pcd used in Library, Pcd Type from reference module if Pcd Type is Pending
275 if BuildData
.Pcds
[key
].Pending
:
276 if bool(BuildData
.LibraryClass
):
277 if BuildData
in set(Libs
):
278 ReferenceModules
= BuildData
.ReferenceModules
279 for ReferenceModule
in ReferenceModules
:
280 if ReferenceModule
.MetaFile
in Platform
.Modules
:
281 RefPlatformModule
= Platform
.Modules
[str(ReferenceModule
.MetaFile
)]
282 if key
in RefPlatformModule
.Pcds
:
283 PcdInReferenceModule
= RefPlatformModule
.Pcds
[key
]
284 if PcdInReferenceModule
.Type
:
285 BuildData
.Pcds
[key
].Type
= PcdInReferenceModule
.Type
286 BuildData
.Pcds
[key
].Pending
= False
289 def ProcessMixedPcd(self
):
290 for Arch
in self
.ArchList
:
291 SourcePcdDict
= {TAB_PCDS_DYNAMIC_EX
:set(), TAB_PCDS_PATCHABLE_IN_MODULE
:set(),TAB_PCDS_DYNAMIC
:set(),TAB_PCDS_FIXED_AT_BUILD
:set()}
292 BinaryPcdDict
= {TAB_PCDS_DYNAMIC_EX
:set(), TAB_PCDS_PATCHABLE_IN_MODULE
:set()}
293 SourcePcdDict_Keys
= SourcePcdDict
.keys()
294 BinaryPcdDict_Keys
= BinaryPcdDict
.keys()
296 # generate the SourcePcdDict and BinaryPcdDict
298 for BuildData
in list(self
.BuildDatabase
._CACHE
_.values()):
299 if BuildData
.Arch
!= Arch
:
301 if BuildData
.MetaFile
.Ext
== '.inf':
302 for key
in BuildData
.Pcds
:
303 if TAB_PCDS_DYNAMIC_EX
in BuildData
.Pcds
[key
].Type
:
304 if BuildData
.IsBinaryModule
:
305 BinaryPcdDict
[TAB_PCDS_DYNAMIC_EX
].add((BuildData
.Pcds
[key
].TokenCName
, BuildData
.Pcds
[key
].TokenSpaceGuidCName
))
307 SourcePcdDict
[TAB_PCDS_DYNAMIC_EX
].add((BuildData
.Pcds
[key
].TokenCName
, BuildData
.Pcds
[key
].TokenSpaceGuidCName
))
309 elif TAB_PCDS_PATCHABLE_IN_MODULE
in BuildData
.Pcds
[key
].Type
:
310 if BuildData
.MetaFile
.Ext
== '.inf':
311 if BuildData
.IsBinaryModule
:
312 BinaryPcdDict
[TAB_PCDS_PATCHABLE_IN_MODULE
].add((BuildData
.Pcds
[key
].TokenCName
, BuildData
.Pcds
[key
].TokenSpaceGuidCName
))
314 SourcePcdDict
[TAB_PCDS_PATCHABLE_IN_MODULE
].add((BuildData
.Pcds
[key
].TokenCName
, BuildData
.Pcds
[key
].TokenSpaceGuidCName
))
316 elif TAB_PCDS_DYNAMIC
in BuildData
.Pcds
[key
].Type
:
317 SourcePcdDict
[TAB_PCDS_DYNAMIC
].add((BuildData
.Pcds
[key
].TokenCName
, BuildData
.Pcds
[key
].TokenSpaceGuidCName
))
318 elif TAB_PCDS_FIXED_AT_BUILD
in BuildData
.Pcds
[key
].Type
:
319 SourcePcdDict
[TAB_PCDS_FIXED_AT_BUILD
].add((BuildData
.Pcds
[key
].TokenCName
, BuildData
.Pcds
[key
].TokenSpaceGuidCName
))
322 # A PCD can only use one type for all source modules
324 for i
in SourcePcdDict_Keys
:
325 for j
in SourcePcdDict_Keys
:
327 Intersections
= SourcePcdDict
[i
].intersection(SourcePcdDict
[j
])
328 if len(Intersections
) > 0:
332 "Building modules from source INFs, following PCD use %s and %s access method. It must be corrected to use only one access method." % (i
, j
),
333 ExtraData
='\n\t'.join(str(P
[1]+'.'+P
[0]) for P
in Intersections
)
337 # intersection the BinaryPCD for Mixed PCD
339 for i
in BinaryPcdDict_Keys
:
340 for j
in BinaryPcdDict_Keys
:
342 Intersections
= BinaryPcdDict
[i
].intersection(BinaryPcdDict
[j
])
343 for item
in Intersections
:
344 NewPcd1
= (item
[0] + '_' + i
, item
[1])
345 NewPcd2
= (item
[0] + '_' + j
, item
[1])
346 if item
not in GlobalData
.MixedPcd
:
347 GlobalData
.MixedPcd
[item
] = [NewPcd1
, NewPcd2
]
349 if NewPcd1
not in GlobalData
.MixedPcd
[item
]:
350 GlobalData
.MixedPcd
[item
].append(NewPcd1
)
351 if NewPcd2
not in GlobalData
.MixedPcd
[item
]:
352 GlobalData
.MixedPcd
[item
].append(NewPcd2
)
355 # intersection the SourcePCD and BinaryPCD for Mixed PCD
357 for i
in SourcePcdDict_Keys
:
358 for j
in BinaryPcdDict_Keys
:
360 Intersections
= SourcePcdDict
[i
].intersection(BinaryPcdDict
[j
])
361 for item
in Intersections
:
362 NewPcd1
= (item
[0] + '_' + i
, item
[1])
363 NewPcd2
= (item
[0] + '_' + j
, item
[1])
364 if item
not in GlobalData
.MixedPcd
:
365 GlobalData
.MixedPcd
[item
] = [NewPcd1
, NewPcd2
]
367 if NewPcd1
not in GlobalData
.MixedPcd
[item
]:
368 GlobalData
.MixedPcd
[item
].append(NewPcd1
)
369 if NewPcd2
not in GlobalData
.MixedPcd
[item
]:
370 GlobalData
.MixedPcd
[item
].append(NewPcd2
)
372 BuildData
= self
.BuildDatabase
[self
.MetaFile
, Arch
, self
.BuildTarget
, self
.ToolChain
]
373 for key
in BuildData
.Pcds
:
374 for SinglePcd
in GlobalData
.MixedPcd
:
375 if (BuildData
.Pcds
[key
].TokenCName
, BuildData
.Pcds
[key
].TokenSpaceGuidCName
) == SinglePcd
:
376 for item
in GlobalData
.MixedPcd
[SinglePcd
]:
377 Pcd_Type
= item
[0].split('_')[-1]
378 if (Pcd_Type
== BuildData
.Pcds
[key
].Type
) or (Pcd_Type
== TAB_PCDS_DYNAMIC_EX
and BuildData
.Pcds
[key
].Type
in PCD_DYNAMIC_EX_TYPE_SET
) or \
379 (Pcd_Type
== TAB_PCDS_DYNAMIC
and BuildData
.Pcds
[key
].Type
in PCD_DYNAMIC_TYPE_SET
):
380 Value
= BuildData
.Pcds
[key
]
381 Value
.TokenCName
= BuildData
.Pcds
[key
].TokenCName
+ '_' + Pcd_Type
383 newkey
= (Value
.TokenCName
, key
[1])
385 newkey
= (Value
.TokenCName
, key
[1], key
[2])
386 del BuildData
.Pcds
[key
]
387 BuildData
.Pcds
[newkey
] = Value
392 PcdSet
= self
.FdfProfile
.PcdDict
393 # handle the mixed pcd in FDF file
395 if key
in GlobalData
.MixedPcd
:
398 for item
in GlobalData
.MixedPcd
[key
]:
401 #Collect package set information from INF of FDF
405 self
.FdfFile
= self
.Platform
.FlashDefinition
408 ModuleList
= self
.FdfProfile
.InfList
412 for Arch
in self
.ArchList
:
413 Platform
= self
.BuildDatabase
[self
.MetaFile
, Arch
, self
.BuildTarget
, self
.ToolChain
]
415 for mb
in [self
.BuildDatabase
[m
, Arch
, self
.BuildTarget
, self
.ToolChain
] for m
in Platform
.Modules
]:
416 PkgSet
.update(mb
.Packages
)
417 for Inf
in ModuleList
:
418 ModuleFile
= PathClass(NormPath(Inf
), GlobalData
.gWorkspace
, Arch
)
419 if ModuleFile
in Platform
.Modules
:
421 ModuleData
= self
.BuildDatabase
[ModuleFile
, Arch
, self
.BuildTarget
, self
.ToolChain
]
422 PkgSet
.update(ModuleData
.Packages
)
423 Pkgs
[Arch
] = list(PkgSet
)
426 def VerifyPcdDeclearation(self
,PcdSet
):
427 for Arch
in self
.ArchList
:
428 Platform
= self
.BuildDatabase
[self
.MetaFile
, Arch
, self
.BuildTarget
, self
.ToolChain
]
429 Pkgs
= self
.PkgSet
[Arch
]
434 DecPcds
.add((Pcd
[0], Pcd
[1]))
435 DecPcdsKey
.add((Pcd
[0], Pcd
[1], Pcd
[2]))
437 Platform
.SkuName
= self
.SkuId
438 for Name
, Guid
,Fileds
in PcdSet
:
439 if (Name
, Guid
) not in DecPcds
:
443 "PCD (%s.%s) used in FDF is not declared in DEC files." % (Guid
, Name
),
444 File
= self
.FdfProfile
.PcdFileLineDict
[Name
, Guid
, Fileds
][0],
445 Line
= self
.FdfProfile
.PcdFileLineDict
[Name
, Guid
, Fileds
][1]
448 # Check whether Dynamic or DynamicEx PCD used in FDF file. If used, build break and give a error message.
449 if (Name
, Guid
, TAB_PCDS_FIXED_AT_BUILD
) in DecPcdsKey \
450 or (Name
, Guid
, TAB_PCDS_PATCHABLE_IN_MODULE
) in DecPcdsKey \
451 or (Name
, Guid
, TAB_PCDS_FEATURE_FLAG
) in DecPcdsKey
:
453 elif (Name
, Guid
, TAB_PCDS_DYNAMIC
) in DecPcdsKey
or (Name
, Guid
, TAB_PCDS_DYNAMIC_EX
) in DecPcdsKey
:
457 "Using Dynamic or DynamicEx type of PCD [%s.%s] in FDF file is not allowed." % (Guid
, Name
),
458 File
= self
.FdfProfile
.PcdFileLineDict
[Name
, Guid
, Fileds
][0],
459 Line
= self
.FdfProfile
.PcdFileLineDict
[Name
, Guid
, Fileds
][1]
461 def CollectAllPcds(self
):
463 for Arch
in self
.ArchList
:
464 Pa
= PlatformAutoGen(self
, self
.MetaFile
, self
.BuildTarget
, self
.ToolChain
, Arch
)
466 # Explicitly collect platform's dynamic PCDs
468 Pa
.CollectPlatformDynamicPcds()
469 Pa
.CollectFixedAtBuildPcds()
470 self
.AutoGenObjectList
.append(Pa
)
471 # We need to calculate the PcdTokenNumber after all Arch Pcds are collected.
472 for Arch
in self
.ArchList
:
474 Pa
= PlatformAutoGen(self
, self
.MetaFile
, self
.BuildTarget
, self
.ToolChain
, Arch
)
475 self
.UpdateModuleDataPipe(Arch
, {"PCD_TNUM":Pa
.PcdTokenNumber
})
477 def UpdateModuleDataPipe(self
,arch
, attr_dict
):
478 for (Target
, Toolchain
, Arch
, MetaFile
) in AutoGen
.Cache():
482 AutoGen
.Cache()[(Target
, Toolchain
, Arch
, MetaFile
)].DataPipe
.DataContainer
= attr_dict
486 # Generate Package level hash value
488 def GeneratePkgLevelHash(self
):
489 for Arch
in self
.ArchList
:
490 GlobalData
.gPackageHash
= {}
491 if GlobalData
.gUseHashCache
:
492 for Pkg
in self
.PkgSet
[Arch
]:
493 self
._GenPkgLevelHash
(Pkg
)
496 def CreateBuildOptionsFile(self
):
498 # Create BuildOptions Macro & PCD metafile, also add the Active Platform and FDF file.
500 content
= 'gCommandLineDefines: '
501 content
+= str(GlobalData
.gCommandLineDefines
)
502 content
+= TAB_LINE_BREAK
503 content
+= 'BuildOptionPcd: '
504 content
+= str(GlobalData
.BuildOptionPcd
)
505 content
+= TAB_LINE_BREAK
506 content
+= 'Active Platform: '
507 content
+= str(self
.Platform
)
508 content
+= TAB_LINE_BREAK
510 content
+= 'Flash Image Definition: '
511 content
+= str(self
.FdfFile
)
512 content
+= TAB_LINE_BREAK
513 SaveFileOnChange(os
.path
.join(self
.BuildDir
, 'BuildOptions'), content
, False)
515 def CreatePcdTokenNumberFile(self
):
517 # Create PcdToken Number file for Dynamic/DynamicEx Pcd.
519 PcdTokenNumber
= 'PcdTokenNumber: '
520 Pa
= self
.AutoGenObjectList
[0]
521 if Pa
.PcdTokenNumber
:
522 if Pa
.DynamicPcdList
:
523 for Pcd
in Pa
.DynamicPcdList
:
524 PcdTokenNumber
+= TAB_LINE_BREAK
525 PcdTokenNumber
+= str((Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
))
526 PcdTokenNumber
+= ' : '
527 PcdTokenNumber
+= str(Pa
.PcdTokenNumber
[Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
])
528 SaveFileOnChange(os
.path
.join(self
.BuildDir
, 'PcdTokenNumber'), PcdTokenNumber
, False)
530 def CreateModuleHashInfo(self
):
532 # Get set of workspace metafiles
534 AllWorkSpaceMetaFiles
= self
._GetMetaFiles
(self
.BuildTarget
, self
.ToolChain
)
537 # Retrieve latest modified time of all metafiles
540 for f
in AllWorkSpaceMetaFiles
:
541 if os
.stat(f
)[8] > SrcTimeStamp
:
542 SrcTimeStamp
= os
.stat(f
)[8]
543 self
._SrcTimeStamp
= SrcTimeStamp
545 if GlobalData
.gUseHashCache
:
547 for files
in AllWorkSpaceMetaFiles
:
548 if files
.endswith('.dec'):
550 f
= open(files
, 'rb')
554 SaveFileOnChange(os
.path
.join(self
.BuildDir
, 'AutoGen.hash'), m
.hexdigest(), False)
555 GlobalData
.gPlatformHash
= m
.hexdigest()
558 # Write metafile list to build directory
560 AutoGenFilePath
= os
.path
.join(self
.BuildDir
, 'AutoGen')
561 if os
.path
.exists (AutoGenFilePath
):
562 os
.remove(AutoGenFilePath
)
563 if not os
.path
.exists(self
.BuildDir
):
564 os
.makedirs(self
.BuildDir
)
565 with
open(os
.path
.join(self
.BuildDir
, 'AutoGen'), 'w+') as file:
566 for f
in AllWorkSpaceMetaFiles
:
570 def _GenPkgLevelHash(self
, Pkg
):
571 if Pkg
.PackageName
in GlobalData
.gPackageHash
:
574 PkgDir
= os
.path
.join(self
.BuildDir
, Pkg
.Arch
, Pkg
.PackageName
)
575 CreateDirectory(PkgDir
)
576 HashFile
= os
.path
.join(PkgDir
, Pkg
.PackageName
+ '.hash')
578 # Get .dec file's hash value
579 f
= open(Pkg
.MetaFile
.Path
, 'rb')
583 # Get include files hash value
585 for inc
in sorted(Pkg
.Includes
, key
=lambda x
: str(x
)):
586 for Root
, Dirs
, Files
in os
.walk(str(inc
)):
587 for File
in sorted(Files
):
588 File_Path
= os
.path
.join(Root
, File
)
589 f
= open(File_Path
, 'rb')
593 SaveFileOnChange(HashFile
, m
.hexdigest(), False)
594 GlobalData
.gPackageHash
[Pkg
.PackageName
] = m
.hexdigest()
596 def _GetMetaFiles(self
, Target
, Toolchain
):
597 AllWorkSpaceMetaFiles
= set()
602 AllWorkSpaceMetaFiles
.add (self
.FdfFile
.Path
)
603 for f
in GlobalData
.gFdfParser
.GetAllIncludedFile():
604 AllWorkSpaceMetaFiles
.add (f
.FileName
)
608 AllWorkSpaceMetaFiles
.add(self
.MetaFile
.Path
)
611 # add build_rule.txt & tools_def.txt
613 AllWorkSpaceMetaFiles
.add(os
.path
.join(GlobalData
.gConfDirectory
, gDefaultBuildRuleFile
))
614 AllWorkSpaceMetaFiles
.add(os
.path
.join(GlobalData
.gConfDirectory
, gDefaultToolsDefFile
))
616 # add BuildOption metafile
618 AllWorkSpaceMetaFiles
.add(os
.path
.join(self
.BuildDir
, 'BuildOptions'))
620 # add PcdToken Number file for Dynamic/DynamicEx Pcd
622 AllWorkSpaceMetaFiles
.add(os
.path
.join(self
.BuildDir
, 'PcdTokenNumber'))
624 for Pa
in self
.AutoGenObjectList
:
625 AllWorkSpaceMetaFiles
.add(Pa
.ToolDefinitionFile
)
627 for Arch
in self
.ArchList
:
631 for Package
in PlatformAutoGen(self
, self
.MetaFile
, Target
, Toolchain
, Arch
).PackageList
:
632 AllWorkSpaceMetaFiles
.add(Package
.MetaFile
.Path
)
637 for filePath
in self
.BuildDatabase
[self
.MetaFile
, Arch
, Target
, Toolchain
]._RawData
.IncludedFiles
:
638 AllWorkSpaceMetaFiles
.add(filePath
.Path
)
640 return AllWorkSpaceMetaFiles
642 def _CheckPcdDefineAndType(self
):
643 PcdTypeSet
= {TAB_PCDS_FIXED_AT_BUILD
,
644 TAB_PCDS_PATCHABLE_IN_MODULE
,
645 TAB_PCDS_FEATURE_FLAG
,
649 # This dict store PCDs which are not used by any modules with specified arches
650 UnusedPcd
= OrderedDict()
651 for Pa
in self
.AutoGenObjectList
:
652 # Key of DSC's Pcds dictionary is PcdCName, TokenSpaceGuid
653 for Pcd
in Pa
.Platform
.Pcds
:
654 PcdType
= Pa
.Platform
.Pcds
[Pcd
].Type
656 # If no PCD type, this PCD comes from FDF
660 # Try to remove Hii and Vpd suffix
661 if PcdType
.startswith(TAB_PCDS_DYNAMIC_EX
):
662 PcdType
= TAB_PCDS_DYNAMIC_EX
663 elif PcdType
.startswith(TAB_PCDS_DYNAMIC
):
664 PcdType
= TAB_PCDS_DYNAMIC
666 for Package
in Pa
.PackageList
:
667 # Key of DEC's Pcds dictionary is PcdCName, TokenSpaceGuid, PcdType
668 if (Pcd
[0], Pcd
[1], PcdType
) in Package
.Pcds
:
670 for Type
in PcdTypeSet
:
671 if (Pcd
[0], Pcd
[1], Type
) in Package
.Pcds
:
675 "Type [%s] of PCD [%s.%s] in DSC file doesn't match the type [%s] defined in DEC file." \
676 % (Pa
.Platform
.Pcds
[Pcd
].Type
, Pcd
[1], Pcd
[0], Type
),
681 UnusedPcd
.setdefault(Pcd
, []).append(Pa
.Arch
)
683 for Pcd
in UnusedPcd
:
686 "The PCD was not specified by any INF module in the platform for the given architecture.\n"
687 "\tPCD: [%s.%s]\n\tPlatform: [%s]\n\tArch: %s"
688 % (Pcd
[1], Pcd
[0], os
.path
.basename(str(self
.MetaFile
)), str(UnusedPcd
[Pcd
])),
693 return "%s [%s]" % (self
.MetaFile
, ", ".join(self
.ArchList
))
695 ## Return the directory to store FV files
698 return path
.join(self
.BuildDir
, TAB_FV_DIRECTORY
)
700 ## Return the directory to store all intermediate and final files built
703 return self
.AutoGenObjectList
[0].BuildDir
705 ## Return the build output directory platform specifies
708 return self
.Platform
.OutputDirectory
710 ## Return platform name
713 return self
.Platform
.PlatformName
715 ## Return meta-file GUID
718 return self
.Platform
.Guid
720 ## Return platform version
723 return self
.Platform
.Version
725 ## Return paths of tools
727 def ToolDefinition(self
):
728 return self
.AutoGenObjectList
[0].ToolDefinition
730 ## Return directory of platform makefile
732 # @retval string Makefile directory
735 def MakeFileDir(self
):
738 ## Return build command string
740 # @retval string Build command string
743 def BuildCommand(self
):
744 # BuildCommand should be all the same. So just get one from platform AutoGen
745 return self
.AutoGenObjectList
[0].BuildCommand
747 ## Check the PCDs token value conflict in each DEC file.
749 # Will cause build break and raise error message while two PCDs conflict.
753 def _CheckAllPcdsTokenValueConflict(self
):
754 for Pa
in self
.AutoGenObjectList
:
755 for Package
in Pa
.PackageList
:
756 PcdList
= list(Package
.Pcds
.values())
757 PcdList
.sort(key
=lambda x
: int(x
.TokenValue
, 0))
759 while (Count
< len(PcdList
) - 1) :
760 Item
= PcdList
[Count
]
761 ItemNext
= PcdList
[Count
+ 1]
763 # Make sure in the same token space the TokenValue should be unique
765 if (int(Item
.TokenValue
, 0) == int(ItemNext
.TokenValue
, 0)):
766 SameTokenValuePcdList
= []
767 SameTokenValuePcdList
.append(Item
)
768 SameTokenValuePcdList
.append(ItemNext
)
769 RemainPcdListLength
= len(PcdList
) - Count
- 2
770 for ValueSameCount
in range(RemainPcdListLength
):
771 if int(PcdList
[len(PcdList
) - RemainPcdListLength
+ ValueSameCount
].TokenValue
, 0) == int(Item
.TokenValue
, 0):
772 SameTokenValuePcdList
.append(PcdList
[len(PcdList
) - RemainPcdListLength
+ ValueSameCount
])
776 # Sort same token value PCD list with TokenGuid and TokenCName
778 SameTokenValuePcdList
.sort(key
=lambda x
: "%s.%s" % (x
.TokenSpaceGuidCName
, x
.TokenCName
))
779 SameTokenValuePcdListCount
= 0
780 while (SameTokenValuePcdListCount
< len(SameTokenValuePcdList
) - 1):
782 TemListItem
= SameTokenValuePcdList
[SameTokenValuePcdListCount
]
783 TemListItemNext
= SameTokenValuePcdList
[SameTokenValuePcdListCount
+ 1]
785 if (TemListItem
.TokenSpaceGuidCName
== TemListItemNext
.TokenSpaceGuidCName
) and (TemListItem
.TokenCName
!= TemListItemNext
.TokenCName
):
786 for PcdItem
in GlobalData
.MixedPcd
:
787 if (TemListItem
.TokenCName
, TemListItem
.TokenSpaceGuidCName
) in GlobalData
.MixedPcd
[PcdItem
] or \
788 (TemListItemNext
.TokenCName
, TemListItemNext
.TokenSpaceGuidCName
) in GlobalData
.MixedPcd
[PcdItem
]:
794 "The TokenValue [%s] of PCD [%s.%s] is conflict with: [%s.%s] in %s"\
795 % (TemListItem
.TokenValue
, TemListItem
.TokenSpaceGuidCName
, TemListItem
.TokenCName
, TemListItemNext
.TokenSpaceGuidCName
, TemListItemNext
.TokenCName
, Package
),
798 SameTokenValuePcdListCount
+= 1
799 Count
+= SameTokenValuePcdListCount
802 PcdList
= list(Package
.Pcds
.values())
803 PcdList
.sort(key
=lambda x
: "%s.%s" % (x
.TokenSpaceGuidCName
, x
.TokenCName
))
805 while (Count
< len(PcdList
) - 1) :
806 Item
= PcdList
[Count
]
807 ItemNext
= PcdList
[Count
+ 1]
809 # Check PCDs with same TokenSpaceGuidCName.TokenCName have same token value as well.
811 if (Item
.TokenSpaceGuidCName
== ItemNext
.TokenSpaceGuidCName
) and (Item
.TokenCName
== ItemNext
.TokenCName
) and (int(Item
.TokenValue
, 0) != int(ItemNext
.TokenValue
, 0)):
815 "The TokenValue [%s] of PCD [%s.%s] in %s defined in two places should be same as well."\
816 % (Item
.TokenValue
, Item
.TokenSpaceGuidCName
, Item
.TokenCName
, Package
),
820 ## Generate fds command
822 def GenFdsCommand(self
):
823 return (GenMake
.TopLevelMakefile(self
)._TEMPLATE
_.Replace(GenMake
.TopLevelMakefile(self
)._TemplateDict
)).strip()
826 def GenFdsCommandDict(self
):
828 LogLevel
= EdkLogger
.GetLevel()
829 if LogLevel
== EdkLogger
.VERBOSE
:
830 FdsCommandDict
["verbose"] = True
831 elif LogLevel
<= EdkLogger
.DEBUG_9
:
832 FdsCommandDict
["debug"] = LogLevel
- 1
833 elif LogLevel
== EdkLogger
.QUIET
:
834 FdsCommandDict
["quiet"] = True
836 FdsCommandDict
["GenfdsMultiThread"] = GlobalData
.gEnableGenfdsMultiThread
837 if GlobalData
.gIgnoreSource
:
838 FdsCommandDict
["IgnoreSources"] = True
840 FdsCommandDict
["OptionPcd"] = []
841 for pcd
in GlobalData
.BuildOptionPcd
:
843 pcdname
= '.'.join(pcd
[0:3])
845 pcdname
= '.'.join(pcd
[0:2])
846 if pcd
[3].startswith('{'):
847 FdsCommandDict
["OptionPcd"].append(pcdname
+ '=' + 'H' + '"' + pcd
[3] + '"')
849 FdsCommandDict
["OptionPcd"].append(pcdname
+ '=' + pcd
[3])
852 # macros passed to GenFds
854 MacroDict
.update(GlobalData
.gGlobalDefines
)
855 MacroDict
.update(GlobalData
.gCommandLineDefines
)
856 for MacroName
in MacroDict
:
857 if MacroDict
[MacroName
] != "":
858 MacroList
.append('"%s=%s"' % (MacroName
, MacroDict
[MacroName
].replace('\\', '\\\\')))
860 MacroList
.append('"%s"' % MacroName
)
861 FdsCommandDict
["macro"] = MacroList
863 FdsCommandDict
["fdf_file"] = [self
.FdfFile
]
864 FdsCommandDict
["build_target"] = self
.BuildTarget
865 FdsCommandDict
["toolchain_tag"] = self
.ToolChain
866 FdsCommandDict
["active_platform"] = str(self
)
868 FdsCommandDict
["conf_directory"] = GlobalData
.gConfDirectory
869 FdsCommandDict
["build_architecture_list"] = ','.join(self
.ArchList
)
870 FdsCommandDict
["platform_build_directory"] = self
.BuildDir
872 FdsCommandDict
["fd"] = self
.FdTargetList
873 FdsCommandDict
["fv"] = self
.FvTargetList
874 FdsCommandDict
["cap"] = self
.CapTargetList
875 return FdsCommandDict
877 ## Create makefile for the platform and modules in it
879 # @param CreateDepsMakeFile Flag indicating if the makefile for
880 # modules will be created as well
882 def CreateMakeFile(self
, CreateDepsMakeFile
=False):
883 if not CreateDepsMakeFile
:
885 for Pa
in self
.AutoGenObjectList
:
886 Pa
.CreateMakeFile(CreateDepsMakeFile
)
888 ## Create autogen code for platform and modules
890 # Since there's no autogen code for platform, this method will do nothing
891 # if CreateModuleCodeFile is set to False.
893 # @param CreateDepsCodeFile Flag indicating if creating module's
894 # autogen code file or not
896 def CreateCodeFile(self
, CreateDepsCodeFile
=False):
897 if not CreateDepsCodeFile
:
899 for Pa
in self
.AutoGenObjectList
:
900 Pa
.CreateCodeFile(CreateDepsCodeFile
)
902 ## Create AsBuilt INF file the platform
904 def CreateAsBuiltInf(self
):