]> git.proxmox.com Git - mirror_edk2.git/blame - BaseTools/Source/Python/AutoGen/PlatformAutoGen.py
BaseTools: Fixed issue of incorrect Module Unique Name
[mirror_edk2.git] / BaseTools / Source / Python / AutoGen / PlatformAutoGen.py
CommitLineData
e8449e1d
FB
1## @file\r
2# Create makefile for MS nmake and GNU make\r
3#\r
4# Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>\r
5# SPDX-License-Identifier: BSD-2-Clause-Patent\r
6#\r
7\r
8## Import Modules\r
9#\r
10from __future__ import print_function\r
11from __future__ import absolute_import\r
12import os.path as path\r
13import copy\r
14from collections import defaultdict\r
15\r
16from .BuildEngine import BuildRule,gDefaultBuildRuleFile,AutoGenReqBuildRuleVerNum\r
17from .GenVar import VariableMgr, var_info\r
18from . import GenMake\r
19from AutoGen.DataPipe import MemoryDataPipe\r
20from AutoGen.ModuleAutoGen import ModuleAutoGen\r
21from AutoGen.AutoGen import AutoGen\r
22from AutoGen.AutoGen import CalculatePriorityValue\r
23from Workspace.WorkspaceCommon import GetModuleLibInstances\r
24from CommonDataClass.CommonClass import SkuInfoClass\r
25from Common.caching import cached_class_function\r
26from Common.Expression import ValueExpressionEx\r
27from Common.StringUtils import StringToArray,NormPath\r
28from Common.BuildToolError import *\r
29from Common.DataType import *\r
30from Common.Misc import *\r
31import Common.VpdInfoFile as VpdInfoFile\r
32\r
33## Split command line option string to list\r
34#\r
35# subprocess.Popen needs the args to be a sequence. Otherwise there's problem\r
36# in non-windows platform to launch command\r
37#\r
38def _SplitOption(OptionString):\r
39 OptionList = []\r
40 LastChar = " "\r
41 OptionStart = 0\r
42 QuotationMark = ""\r
43 for Index in range(0, len(OptionString)):\r
44 CurrentChar = OptionString[Index]\r
45 if CurrentChar in ['"', "'"]:\r
46 if QuotationMark == CurrentChar:\r
47 QuotationMark = ""\r
48 elif QuotationMark == "":\r
49 QuotationMark = CurrentChar\r
50 continue\r
51 elif QuotationMark:\r
52 continue\r
53\r
54 if CurrentChar in ["/", "-"] and LastChar in [" ", "\t", "\r", "\n"]:\r
55 if Index > OptionStart:\r
56 OptionList.append(OptionString[OptionStart:Index - 1])\r
57 OptionStart = Index\r
58 LastChar = CurrentChar\r
59 OptionList.append(OptionString[OptionStart:])\r
60 return OptionList\r
61\r
62## AutoGen class for platform\r
63#\r
64# PlatformAutoGen class will process the original information in platform\r
65# file in order to generate makefile for platform.\r
66#\r
67class PlatformAutoGen(AutoGen):\r
68 # call super().__init__ then call the worker function with different parameter count\r
69 def __init__(self, Workspace, MetaFile, Target, Toolchain, Arch, *args, **kwargs):\r
70 if not hasattr(self, "_Init"):\r
71 self._InitWorker(Workspace, MetaFile, Target, Toolchain, Arch)\r
72 self._Init = True\r
73 #\r
74 # Used to store all PCDs for both PEI and DXE phase, in order to generate\r
75 # correct PCD database\r
76 #\r
77 _DynaPcdList_ = []\r
78 _NonDynaPcdList_ = []\r
79 _PlatformPcds = {}\r
80\r
81\r
82\r
83 ## Initialize PlatformAutoGen\r
84 #\r
85 #\r
86 # @param Workspace WorkspaceAutoGen object\r
87 # @param PlatformFile Platform file (DSC file)\r
88 # @param Target Build target (DEBUG, RELEASE)\r
89 # @param Toolchain Name of tool chain\r
90 # @param Arch arch of the platform supports\r
91 #\r
92 def _InitWorker(self, Workspace, PlatformFile, Target, Toolchain, Arch):\r
93 EdkLogger.debug(EdkLogger.DEBUG_9, "AutoGen platform [%s] [%s]" % (PlatformFile, Arch))\r
94 GlobalData.gProcessingFile = "%s [%s, %s, %s]" % (PlatformFile, Arch, Toolchain, Target)\r
95\r
96 self.MetaFile = PlatformFile\r
97 self.Workspace = Workspace\r
98 self.WorkspaceDir = Workspace.WorkspaceDir\r
99 self.ToolChain = Toolchain\r
100 self.BuildTarget = Target\r
101 self.Arch = Arch\r
102 self.SourceDir = PlatformFile.SubDir\r
103 self.FdTargetList = self.Workspace.FdTargetList\r
104 self.FvTargetList = self.Workspace.FvTargetList\r
105 # get the original module/package/platform objects\r
106 self.BuildDatabase = Workspace.BuildDatabase\r
107 self.DscBuildDataObj = Workspace.Platform\r
108\r
109 # flag indicating if the makefile/C-code file has been created or not\r
110 self.IsMakeFileCreated = False\r
111\r
112 self._DynamicPcdList = None # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]\r
113 self._NonDynamicPcdList = None # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]\r
114\r
115 self._AsBuildInfList = []\r
116 self._AsBuildModuleList = []\r
117\r
118 self.VariableInfo = None\r
119\r
120 if GlobalData.gFdfParser is not None:\r
121 self._AsBuildInfList = GlobalData.gFdfParser.Profile.InfList\r
122 for Inf in self._AsBuildInfList:\r
123 InfClass = PathClass(NormPath(Inf), GlobalData.gWorkspace, self.Arch)\r
124 M = self.BuildDatabase[InfClass, self.Arch, self.BuildTarget, self.ToolChain]\r
125 if not M.IsBinaryModule:\r
126 continue\r
127 self._AsBuildModuleList.append(InfClass)\r
128 # get library/modules for build\r
129 self.LibraryBuildDirectoryList = []\r
130 self.ModuleBuildDirectoryList = []\r
131\r
132 self.DataPipe = MemoryDataPipe(self.BuildDir)\r
133 self.DataPipe.FillData(self)\r
134\r
135 return True\r
673d09a2
FB
136 def FillData_LibConstPcd(self):\r
137 libConstPcd = {}\r
138 for LibAuto in self.LibraryAutoGenList:\r
139 if LibAuto.ConstPcd:\r
140 libConstPcd[(LibAuto.MetaFile.File,LibAuto.MetaFile.Root,LibAuto.Arch,LibAuto.MetaFile.Path)] = LibAuto.ConstPcd\r
141 self.DataPipe.DataContainer = {"LibConstPcd":libConstPcd}\r
e8449e1d
FB
142 ## hash() operator of PlatformAutoGen\r
143 #\r
144 # The platform file path and arch string will be used to represent\r
145 # hash value of this object\r
146 #\r
147 # @retval int Hash value of the platform file path and arch\r
148 #\r
149 @cached_class_function\r
150 def __hash__(self):\r
151 return hash((self.MetaFile, self.Arch))\r
152 @cached_class_function\r
153 def __repr__(self):\r
154 return "%s [%s]" % (self.MetaFile, self.Arch)\r
155\r
156 ## Create autogen code for platform and modules\r
157 #\r
158 # Since there's no autogen code for platform, this method will do nothing\r
159 # if CreateModuleCodeFile is set to False.\r
160 #\r
161 # @param CreateModuleCodeFile Flag indicating if creating module's\r
162 # autogen code file or not\r
163 #\r
164 @cached_class_function\r
165 def CreateCodeFile(self, CreateModuleCodeFile=False):\r
166 # only module has code to be created, so do nothing if CreateModuleCodeFile is False\r
167 if not CreateModuleCodeFile:\r
168 return\r
169\r
170 for Ma in self.ModuleAutoGenList:\r
673d09a2 171 Ma.CreateCodeFile(CreateModuleCodeFile)\r
e8449e1d
FB
172\r
173 ## Generate Fds Command\r
174 @cached_property\r
175 def GenFdsCommand(self):\r
176 return self.Workspace.GenFdsCommand\r
177\r
178 ## Create makefile for the platform and modules in it\r
179 #\r
180 # @param CreateModuleMakeFile Flag indicating if the makefile for\r
181 # modules will be created as well\r
182 #\r
183 def CreateMakeFile(self, CreateModuleMakeFile=False, FfsCommand = {}):\r
184 if CreateModuleMakeFile:\r
185 for Ma in self._MaList:\r
186 key = (Ma.MetaFile.File, self.Arch)\r
187 if key in FfsCommand:\r
673d09a2 188 Ma.CreateMakeFile(CreateModuleMakeFile, FfsCommand[key])\r
e8449e1d 189 else:\r
673d09a2 190 Ma.CreateMakeFile(CreateModuleMakeFile)\r
e8449e1d
FB
191\r
192 # no need to create makefile for the platform more than once\r
193 if self.IsMakeFileCreated:\r
194 return\r
195\r
196 # create library/module build dirs for platform\r
197 Makefile = GenMake.PlatformMakefile(self)\r
198 self.LibraryBuildDirectoryList = Makefile.GetLibraryBuildDirectoryList()\r
199 self.ModuleBuildDirectoryList = Makefile.GetModuleBuildDirectoryList()\r
200\r
201 self.IsMakeFileCreated = True\r
202\r
203 @property\r
204 def AllPcdList(self):\r
205 return self.DynamicPcdList + self.NonDynamicPcdList\r
206 ## Deal with Shared FixedAtBuild Pcds\r
207 #\r
208 def CollectFixedAtBuildPcds(self):\r
209 for LibAuto in self.LibraryAutoGenList:\r
210 FixedAtBuildPcds = {}\r
211 ShareFixedAtBuildPcdsSameValue = {}\r
212 for Module in LibAuto.ReferenceModules:\r
213 for Pcd in set(Module.FixedAtBuildPcds + LibAuto.FixedAtBuildPcds):\r
214 DefaultValue = Pcd.DefaultValue\r
215 # Cover the case: DSC component override the Pcd value and the Pcd only used in one Lib\r
216 if Pcd in Module.LibraryPcdList:\r
217 Index = Module.LibraryPcdList.index(Pcd)\r
218 DefaultValue = Module.LibraryPcdList[Index].DefaultValue\r
219 key = ".".join((Pcd.TokenSpaceGuidCName, Pcd.TokenCName))\r
220 if key not in FixedAtBuildPcds:\r
221 ShareFixedAtBuildPcdsSameValue[key] = True\r
222 FixedAtBuildPcds[key] = DefaultValue\r
223 else:\r
224 if FixedAtBuildPcds[key] != DefaultValue:\r
225 ShareFixedAtBuildPcdsSameValue[key] = False\r
226 for Pcd in LibAuto.FixedAtBuildPcds:\r
227 key = ".".join((Pcd.TokenSpaceGuidCName, Pcd.TokenCName))\r
228 if (Pcd.TokenCName, Pcd.TokenSpaceGuidCName) not in self.NonDynamicPcdDict:\r
229 continue\r
230 else:\r
231 DscPcd = self.NonDynamicPcdDict[(Pcd.TokenCName, Pcd.TokenSpaceGuidCName)]\r
232 if DscPcd.Type != TAB_PCDS_FIXED_AT_BUILD:\r
233 continue\r
234 if key in ShareFixedAtBuildPcdsSameValue and ShareFixedAtBuildPcdsSameValue[key]:\r
235 LibAuto.ConstPcd[key] = FixedAtBuildPcds[key]\r
236\r
237 def CollectVariables(self, DynamicPcdSet):\r
238 VpdRegionSize = 0\r
239 VpdRegionBase = 0\r
240 if self.Workspace.FdfFile:\r
241 FdDict = self.Workspace.FdfProfile.FdDict[GlobalData.gFdfParser.CurrentFdName]\r
242 for FdRegion in FdDict.RegionList:\r
243 for item in FdRegion.RegionDataList:\r
244 if self.Platform.VpdToolGuid.strip() and self.Platform.VpdToolGuid in item:\r
245 VpdRegionSize = FdRegion.Size\r
246 VpdRegionBase = FdRegion.Offset\r
247 break\r
248\r
249 VariableInfo = VariableMgr(self.DscBuildDataObj._GetDefaultStores(), self.DscBuildDataObj.SkuIds)\r
250 VariableInfo.SetVpdRegionMaxSize(VpdRegionSize)\r
251 VariableInfo.SetVpdRegionOffset(VpdRegionBase)\r
252 Index = 0\r
253 for Pcd in DynamicPcdSet:\r
254 pcdname = ".".join((Pcd.TokenSpaceGuidCName, Pcd.TokenCName))\r
255 for SkuName in Pcd.SkuInfoList:\r
256 Sku = Pcd.SkuInfoList[SkuName]\r
257 SkuId = Sku.SkuId\r
258 if SkuId is None or SkuId == '':\r
259 continue\r
260 if len(Sku.VariableName) > 0:\r
261 if Sku.VariableAttribute and 'NV' not in Sku.VariableAttribute:\r
262 continue\r
263 VariableGuidStructure = Sku.VariableGuidValue\r
264 VariableGuid = GuidStructureStringToGuidString(VariableGuidStructure)\r
265 for StorageName in Sku.DefaultStoreDict:\r
266 VariableInfo.append_variable(var_info(Index, pcdname, StorageName, SkuName, StringToArray(Sku.VariableName), VariableGuid, Sku.VariableOffset, Sku.VariableAttribute, Sku.HiiDefaultValue, Sku.DefaultStoreDict[StorageName] if Pcd.DatumType in TAB_PCD_NUMERIC_TYPES else StringToArray(Sku.DefaultStoreDict[StorageName]), Pcd.DatumType, Pcd.CustomAttribute['DscPosition'], Pcd.CustomAttribute.get('IsStru',False)))\r
267 Index += 1\r
268 return VariableInfo\r
269\r
270 def UpdateNVStoreMaxSize(self, OrgVpdFile):\r
271 if self.VariableInfo:\r
272 VpdMapFilePath = os.path.join(self.BuildDir, TAB_FV_DIRECTORY, "%s.map" % self.Platform.VpdToolGuid)\r
273 PcdNvStoreDfBuffer = [item for item in self._DynamicPcdList if item.TokenCName == "PcdNvStoreDefaultValueBuffer" and item.TokenSpaceGuidCName == "gEfiMdeModulePkgTokenSpaceGuid"]\r
274\r
275 if PcdNvStoreDfBuffer:\r
276 if os.path.exists(VpdMapFilePath):\r
277 OrgVpdFile.Read(VpdMapFilePath)\r
278 PcdItems = OrgVpdFile.GetOffset(PcdNvStoreDfBuffer[0])\r
279 NvStoreOffset = list(PcdItems.values())[0].strip() if PcdItems else '0'\r
280 else:\r
281 EdkLogger.error("build", FILE_READ_FAILURE, "Can not find VPD map file %s to fix up VPD offset." % VpdMapFilePath)\r
282\r
283 NvStoreOffset = int(NvStoreOffset, 16) if NvStoreOffset.upper().startswith("0X") else int(NvStoreOffset)\r
284 default_skuobj = PcdNvStoreDfBuffer[0].SkuInfoList.get(TAB_DEFAULT)\r
285 maxsize = self.VariableInfo.VpdRegionSize - NvStoreOffset if self.VariableInfo.VpdRegionSize else len(default_skuobj.DefaultValue.split(","))\r
286 var_data = self.VariableInfo.PatchNVStoreDefaultMaxSize(maxsize)\r
287\r
288 if var_data and default_skuobj:\r
289 default_skuobj.DefaultValue = var_data\r
290 PcdNvStoreDfBuffer[0].DefaultValue = var_data\r
291 PcdNvStoreDfBuffer[0].SkuInfoList.clear()\r
292 PcdNvStoreDfBuffer[0].SkuInfoList[TAB_DEFAULT] = default_skuobj\r
293 PcdNvStoreDfBuffer[0].MaxDatumSize = str(len(default_skuobj.DefaultValue.split(",")))\r
294\r
295 return OrgVpdFile\r
296\r
297 ## Collect dynamic PCDs\r
298 #\r
299 # Gather dynamic PCDs list from each module and their settings from platform\r
300 # This interface should be invoked explicitly when platform action is created.\r
301 #\r
302 def CollectPlatformDynamicPcds(self):\r
303 self.CategoryPcds()\r
304 self.SortDynamicPcd()\r
305\r
306 def CategoryPcds(self):\r
307 # Category Pcds into DynamicPcds and NonDynamicPcds\r
308 # for gathering error information\r
309 NoDatumTypePcdList = set()\r
310 FdfModuleList = []\r
311 for InfName in self._AsBuildInfList:\r
312 InfName = mws.join(self.WorkspaceDir, InfName)\r
313 FdfModuleList.append(os.path.normpath(InfName))\r
314 for M in self._MbList:\r
315# F is the Module for which M is the module autogen\r
316 ModPcdList = self.ApplyPcdSetting(M, M.ModulePcdList)\r
317 LibPcdList = []\r
318 for lib in M.LibraryPcdList:\r
319 LibPcdList.extend(self.ApplyPcdSetting(M, M.LibraryPcdList[lib], lib))\r
320 for PcdFromModule in ModPcdList + LibPcdList:\r
321\r
322 # make sure that the "VOID*" kind of datum has MaxDatumSize set\r
323 if PcdFromModule.DatumType == TAB_VOID and not PcdFromModule.MaxDatumSize:\r
324 NoDatumTypePcdList.add("%s.%s [%s]" % (PcdFromModule.TokenSpaceGuidCName, PcdFromModule.TokenCName, M.MetaFile))\r
325\r
326 # Check the PCD from Binary INF or Source INF\r
327 if M.IsBinaryModule == True:\r
328 PcdFromModule.IsFromBinaryInf = True\r
329\r
330 # Check the PCD from DSC or not\r
331 PcdFromModule.IsFromDsc = (PcdFromModule.TokenCName, PcdFromModule.TokenSpaceGuidCName) in self.Platform.Pcds\r
332\r
333 if PcdFromModule.Type in PCD_DYNAMIC_TYPE_SET or PcdFromModule.Type in PCD_DYNAMIC_EX_TYPE_SET:\r
334 if M.MetaFile.Path not in FdfModuleList:\r
335 # If one of the Source built modules listed in the DSC is not listed\r
336 # in FDF modules, and the INF lists a PCD can only use the PcdsDynamic\r
337 # access method (it is only listed in the DEC file that declares the\r
338 # PCD as PcdsDynamic), then build tool will report warning message\r
339 # notify the PI that they are attempting to build a module that must\r
340 # be included in a flash image in order to be functional. These Dynamic\r
341 # PCD will not be added into the Database unless it is used by other\r
342 # modules that are included in the FDF file.\r
343 if PcdFromModule.Type in PCD_DYNAMIC_TYPE_SET and \\r
344 PcdFromModule.IsFromBinaryInf == False:\r
345 # Print warning message to let the developer make a determine.\r
346 continue\r
347 # If one of the Source built modules listed in the DSC is not listed in\r
348 # FDF modules, and the INF lists a PCD can only use the PcdsDynamicEx\r
349 # access method (it is only listed in the DEC file that declares the\r
350 # PCD as PcdsDynamicEx), then DO NOT break the build; DO NOT add the\r
351 # PCD to the Platform's PCD Database.\r
352 if PcdFromModule.Type in PCD_DYNAMIC_EX_TYPE_SET:\r
353 continue\r
354 #\r
355 # If a dynamic PCD used by a PEM module/PEI module & DXE module,\r
356 # it should be stored in Pcd PEI database, If a dynamic only\r
357 # used by DXE module, it should be stored in DXE PCD database.\r
358 # The default Phase is DXE\r
359 #\r
360 if M.ModuleType in SUP_MODULE_SET_PEI:\r
361 PcdFromModule.Phase = "PEI"\r
362 if PcdFromModule not in self._DynaPcdList_:\r
363 self._DynaPcdList_.append(PcdFromModule)\r
364 elif PcdFromModule.Phase == 'PEI':\r
365 # overwrite any the same PCD existing, if Phase is PEI\r
366 Index = self._DynaPcdList_.index(PcdFromModule)\r
367 self._DynaPcdList_[Index] = PcdFromModule\r
368 elif PcdFromModule not in self._NonDynaPcdList_:\r
369 self._NonDynaPcdList_.append(PcdFromModule)\r
370 elif PcdFromModule in self._NonDynaPcdList_ and PcdFromModule.IsFromBinaryInf == True:\r
371 Index = self._NonDynaPcdList_.index(PcdFromModule)\r
372 if self._NonDynaPcdList_[Index].IsFromBinaryInf == False:\r
373 #The PCD from Binary INF will override the same one from source INF\r
374 self._NonDynaPcdList_.remove (self._NonDynaPcdList_[Index])\r
375 PcdFromModule.Pending = False\r
376 self._NonDynaPcdList_.append (PcdFromModule)\r
377 DscModuleSet = {os.path.normpath(ModuleInf.Path) for ModuleInf in self.Platform.Modules}\r
378 # add the PCD from modules that listed in FDF but not in DSC to Database\r
379 for InfName in FdfModuleList:\r
380 if InfName not in DscModuleSet:\r
381 InfClass = PathClass(InfName)\r
382 M = self.BuildDatabase[InfClass, self.Arch, self.BuildTarget, self.ToolChain]\r
383 # If a module INF in FDF but not in current arch's DSC module list, it must be module (either binary or source)\r
384 # for different Arch. PCDs in source module for different Arch is already added before, so skip the source module here.\r
385 # For binary module, if in current arch, we need to list the PCDs into database.\r
386 if not M.IsBinaryModule:\r
387 continue\r
388 # Override the module PCD setting by platform setting\r
389 ModulePcdList = self.ApplyPcdSetting(M, M.Pcds)\r
390 for PcdFromModule in ModulePcdList:\r
391 PcdFromModule.IsFromBinaryInf = True\r
392 PcdFromModule.IsFromDsc = False\r
393 # Only allow the DynamicEx and Patchable PCD in AsBuild INF\r
394 if PcdFromModule.Type not in PCD_DYNAMIC_EX_TYPE_SET and PcdFromModule.Type not in TAB_PCDS_PATCHABLE_IN_MODULE:\r
395 EdkLogger.error("build", AUTOGEN_ERROR, "PCD setting error",\r
396 File=self.MetaFile,\r
397 ExtraData="\n\tExisted %s PCD %s in:\n\t\t%s\n"\r
398 % (PcdFromModule.Type, PcdFromModule.TokenCName, InfName))\r
399 # make sure that the "VOID*" kind of datum has MaxDatumSize set\r
400 if PcdFromModule.DatumType == TAB_VOID and not PcdFromModule.MaxDatumSize:\r
401 NoDatumTypePcdList.add("%s.%s [%s]" % (PcdFromModule.TokenSpaceGuidCName, PcdFromModule.TokenCName, InfName))\r
402 if M.ModuleType in SUP_MODULE_SET_PEI:\r
403 PcdFromModule.Phase = "PEI"\r
404 if PcdFromModule not in self._DynaPcdList_ and PcdFromModule.Type in PCD_DYNAMIC_EX_TYPE_SET:\r
405 self._DynaPcdList_.append(PcdFromModule)\r
406 elif PcdFromModule not in self._NonDynaPcdList_ and PcdFromModule.Type in TAB_PCDS_PATCHABLE_IN_MODULE:\r
407 self._NonDynaPcdList_.append(PcdFromModule)\r
408 if PcdFromModule in self._DynaPcdList_ and PcdFromModule.Phase == 'PEI' and PcdFromModule.Type in PCD_DYNAMIC_EX_TYPE_SET:\r
409 # Overwrite the phase of any the same PCD existing, if Phase is PEI.\r
410 # It is to solve the case that a dynamic PCD used by a PEM module/PEI\r
411 # module & DXE module at a same time.\r
412 # Overwrite the type of the PCDs in source INF by the type of AsBuild\r
413 # INF file as DynamicEx.\r
414 Index = self._DynaPcdList_.index(PcdFromModule)\r
415 self._DynaPcdList_[Index].Phase = PcdFromModule.Phase\r
416 self._DynaPcdList_[Index].Type = PcdFromModule.Type\r
417 for PcdFromModule in self._NonDynaPcdList_:\r
418 # If a PCD is not listed in the DSC file, but binary INF files used by\r
419 # this platform all (that use this PCD) list the PCD in a [PatchPcds]\r
420 # section, AND all source INF files used by this platform the build\r
421 # that use the PCD list the PCD in either a [Pcds] or [PatchPcds]\r
422 # section, then the tools must NOT add the PCD to the Platform's PCD\r
423 # Database; the build must assign the access method for this PCD as\r
424 # PcdsPatchableInModule.\r
425 if PcdFromModule not in self._DynaPcdList_:\r
426 continue\r
427 Index = self._DynaPcdList_.index(PcdFromModule)\r
428 if PcdFromModule.IsFromDsc == False and \\r
429 PcdFromModule.Type in TAB_PCDS_PATCHABLE_IN_MODULE and \\r
430 PcdFromModule.IsFromBinaryInf == True and \\r
431 self._DynaPcdList_[Index].IsFromBinaryInf == False:\r
432 Index = self._DynaPcdList_.index(PcdFromModule)\r
433 self._DynaPcdList_.remove (self._DynaPcdList_[Index])\r
434\r
435 # print out error information and break the build, if error found\r
436 if len(NoDatumTypePcdList) > 0:\r
437 NoDatumTypePcdListString = "\n\t\t".join(NoDatumTypePcdList)\r
438 EdkLogger.error("build", AUTOGEN_ERROR, "PCD setting error",\r
439 File=self.MetaFile,\r
440 ExtraData="\n\tPCD(s) without MaxDatumSize:\n\t\t%s\n"\r
441 % NoDatumTypePcdListString)\r
442 self._NonDynamicPcdList = self._NonDynaPcdList_\r
443 self._DynamicPcdList = self._DynaPcdList_\r
444\r
445 def SortDynamicPcd(self):\r
446 #\r
447 # Sort dynamic PCD list to:\r
448 # 1) If PCD's datum type is VOID* and value is unicode string which starts with L, the PCD item should\r
449 # try to be put header of dynamicd List\r
450 # 2) If PCD is HII type, the PCD item should be put after unicode type PCD\r
451 #\r
452 # The reason of sorting is make sure the unicode string is in double-byte alignment in string table.\r
453 #\r
454 UnicodePcdArray = set()\r
455 HiiPcdArray = set()\r
456 OtherPcdArray = set()\r
457 VpdPcdDict = {}\r
458 VpdFile = VpdInfoFile.VpdInfoFile()\r
459 NeedProcessVpdMapFile = False\r
460\r
461 for pcd in self.Platform.Pcds:\r
462 if pcd not in self._PlatformPcds:\r
463 self._PlatformPcds[pcd] = self.Platform.Pcds[pcd]\r
464\r
465 for item in self._PlatformPcds:\r
466 if self._PlatformPcds[item].DatumType and self._PlatformPcds[item].DatumType not in [TAB_UINT8, TAB_UINT16, TAB_UINT32, TAB_UINT64, TAB_VOID, "BOOLEAN"]:\r
467 self._PlatformPcds[item].DatumType = TAB_VOID\r
468\r
469 if (self.Workspace.ArchList[-1] == self.Arch):\r
470 for Pcd in self._DynamicPcdList:\r
471 # just pick the a value to determine whether is unicode string type\r
472 Sku = Pcd.SkuInfoList.get(TAB_DEFAULT)\r
473 Sku.VpdOffset = Sku.VpdOffset.strip()\r
474\r
475 if Pcd.DatumType not in [TAB_UINT8, TAB_UINT16, TAB_UINT32, TAB_UINT64, TAB_VOID, "BOOLEAN"]:\r
476 Pcd.DatumType = TAB_VOID\r
477\r
478 # if found PCD which datum value is unicode string the insert to left size of UnicodeIndex\r
479 # if found HII type PCD then insert to right of UnicodeIndex\r
480 if Pcd.Type in [TAB_PCDS_DYNAMIC_VPD, TAB_PCDS_DYNAMIC_EX_VPD]:\r
481 VpdPcdDict[(Pcd.TokenCName, Pcd.TokenSpaceGuidCName)] = Pcd\r
482\r
483 #Collect DynamicHii PCD values and assign it to DynamicExVpd PCD gEfiMdeModulePkgTokenSpaceGuid.PcdNvStoreDefaultValueBuffer\r
484 PcdNvStoreDfBuffer = VpdPcdDict.get(("PcdNvStoreDefaultValueBuffer", "gEfiMdeModulePkgTokenSpaceGuid"))\r
485 if PcdNvStoreDfBuffer:\r
486 self.VariableInfo = self.CollectVariables(self._DynamicPcdList)\r
487 vardump = self.VariableInfo.dump()\r
488 if vardump:\r
489 #\r
490 #According to PCD_DATABASE_INIT in edk2\MdeModulePkg\Include\Guid\PcdDataBaseSignatureGuid.h,\r
491 #the max size for string PCD should not exceed USHRT_MAX 65535(0xffff).\r
492 #typedef UINT16 SIZE_INFO;\r
493 #//SIZE_INFO SizeTable[];\r
494 if len(vardump.split(",")) > 0xffff:\r
495 EdkLogger.error("build", RESOURCE_OVERFLOW, 'The current length of PCD %s value is %d, it exceeds to the max size of String PCD.' %(".".join([PcdNvStoreDfBuffer.TokenSpaceGuidCName,PcdNvStoreDfBuffer.TokenCName]) ,len(vardump.split(","))))\r
496 PcdNvStoreDfBuffer.DefaultValue = vardump\r
497 for skuname in PcdNvStoreDfBuffer.SkuInfoList:\r
498 PcdNvStoreDfBuffer.SkuInfoList[skuname].DefaultValue = vardump\r
499 PcdNvStoreDfBuffer.MaxDatumSize = str(len(vardump.split(",")))\r
500 else:\r
501 #If the end user define [DefaultStores] and [XXX.Menufacturing] in DSC, but forget to configure PcdNvStoreDefaultValueBuffer to PcdsDynamicVpd\r
502 if [Pcd for Pcd in self._DynamicPcdList if Pcd.UserDefinedDefaultStoresFlag]:\r
503 EdkLogger.warn("build", "PcdNvStoreDefaultValueBuffer should be defined as PcdsDynamicExVpd in dsc file since the DefaultStores is enabled for this platform.\n%s" %self.Platform.MetaFile.Path)\r
504 PlatformPcds = sorted(self._PlatformPcds.keys())\r
505 #\r
506 # Add VPD type PCD into VpdFile and determine whether the VPD PCD need to be fixed up.\r
507 #\r
508 VpdSkuMap = {}\r
509 for PcdKey in PlatformPcds:\r
510 Pcd = self._PlatformPcds[PcdKey]\r
511 if Pcd.Type in [TAB_PCDS_DYNAMIC_VPD, TAB_PCDS_DYNAMIC_EX_VPD] and \\r
512 PcdKey in VpdPcdDict:\r
513 Pcd = VpdPcdDict[PcdKey]\r
514 SkuValueMap = {}\r
515 DefaultSku = Pcd.SkuInfoList.get(TAB_DEFAULT)\r
516 if DefaultSku:\r
517 PcdValue = DefaultSku.DefaultValue\r
518 if PcdValue not in SkuValueMap:\r
519 SkuValueMap[PcdValue] = []\r
520 VpdFile.Add(Pcd, TAB_DEFAULT, DefaultSku.VpdOffset)\r
521 SkuValueMap[PcdValue].append(DefaultSku)\r
522\r
523 for (SkuName, Sku) in Pcd.SkuInfoList.items():\r
524 Sku.VpdOffset = Sku.VpdOffset.strip()\r
525 PcdValue = Sku.DefaultValue\r
526 if PcdValue == "":\r
527 PcdValue = Pcd.DefaultValue\r
528 if Sku.VpdOffset != TAB_STAR:\r
529 if PcdValue.startswith("{"):\r
530 Alignment = 8\r
531 elif PcdValue.startswith("L"):\r
532 Alignment = 2\r
533 else:\r
534 Alignment = 1\r
535 try:\r
536 VpdOffset = int(Sku.VpdOffset)\r
537 except:\r
538 try:\r
539 VpdOffset = int(Sku.VpdOffset, 16)\r
540 except:\r
541 EdkLogger.error("build", FORMAT_INVALID, "Invalid offset value %s for PCD %s.%s." % (Sku.VpdOffset, Pcd.TokenSpaceGuidCName, Pcd.TokenCName))\r
542 if VpdOffset % Alignment != 0:\r
543 if PcdValue.startswith("{"):\r
544 EdkLogger.warn("build", "The offset value of PCD %s.%s is not 8-byte aligned!" %(Pcd.TokenSpaceGuidCName, Pcd.TokenCName), File=self.MetaFile)\r
545 else:\r
546 EdkLogger.error("build", FORMAT_INVALID, 'The offset value of PCD %s.%s should be %s-byte aligned.' % (Pcd.TokenSpaceGuidCName, Pcd.TokenCName, Alignment))\r
547 if PcdValue not in SkuValueMap:\r
548 SkuValueMap[PcdValue] = []\r
549 VpdFile.Add(Pcd, SkuName, Sku.VpdOffset)\r
550 SkuValueMap[PcdValue].append(Sku)\r
551 # if the offset of a VPD is *, then it need to be fixed up by third party tool.\r
552 if not NeedProcessVpdMapFile and Sku.VpdOffset == TAB_STAR:\r
553 NeedProcessVpdMapFile = True\r
554 if self.Platform.VpdToolGuid is None or self.Platform.VpdToolGuid == '':\r
555 EdkLogger.error("Build", FILE_NOT_FOUND, \\r
556 "Fail to find third-party BPDG tool to process VPD PCDs. BPDG Guid tool need to be defined in tools_def.txt and VPD_TOOL_GUID need to be provided in DSC file.")\r
557\r
558 VpdSkuMap[PcdKey] = SkuValueMap\r
559 #\r
560 # Fix the PCDs define in VPD PCD section that never referenced by module.\r
561 # An example is PCD for signature usage.\r
562 #\r
563 for DscPcd in PlatformPcds:\r
564 DscPcdEntry = self._PlatformPcds[DscPcd]\r
565 if DscPcdEntry.Type in [TAB_PCDS_DYNAMIC_VPD, TAB_PCDS_DYNAMIC_EX_VPD]:\r
566 if not (self.Platform.VpdToolGuid is None or self.Platform.VpdToolGuid == ''):\r
567 FoundFlag = False\r
568 for VpdPcd in VpdFile._VpdArray:\r
569 # This PCD has been referenced by module\r
570 if (VpdPcd.TokenSpaceGuidCName == DscPcdEntry.TokenSpaceGuidCName) and \\r
571 (VpdPcd.TokenCName == DscPcdEntry.TokenCName):\r
572 FoundFlag = True\r
573\r
574 # Not found, it should be signature\r
575 if not FoundFlag :\r
576 # just pick the a value to determine whether is unicode string type\r
577 SkuValueMap = {}\r
578 SkuObjList = list(DscPcdEntry.SkuInfoList.items())\r
579 DefaultSku = DscPcdEntry.SkuInfoList.get(TAB_DEFAULT)\r
580 if DefaultSku:\r
581 defaultindex = SkuObjList.index((TAB_DEFAULT, DefaultSku))\r
582 SkuObjList[0], SkuObjList[defaultindex] = SkuObjList[defaultindex], SkuObjList[0]\r
583 for (SkuName, Sku) in SkuObjList:\r
584 Sku.VpdOffset = Sku.VpdOffset.strip()\r
585\r
586 # Need to iterate DEC pcd information to get the value & datumtype\r
587 for eachDec in self.PackageList:\r
588 for DecPcd in eachDec.Pcds:\r
589 DecPcdEntry = eachDec.Pcds[DecPcd]\r
590 if (DecPcdEntry.TokenSpaceGuidCName == DscPcdEntry.TokenSpaceGuidCName) and \\r
591 (DecPcdEntry.TokenCName == DscPcdEntry.TokenCName):\r
592 # Print warning message to let the developer make a determine.\r
593 EdkLogger.warn("build", "Unreferenced vpd pcd used!",\r
594 File=self.MetaFile, \\r
595 ExtraData = "PCD: %s.%s used in the DSC file %s is unreferenced." \\r
596 %(DscPcdEntry.TokenSpaceGuidCName, DscPcdEntry.TokenCName, self.Platform.MetaFile.Path))\r
597\r
598 DscPcdEntry.DatumType = DecPcdEntry.DatumType\r
599 DscPcdEntry.DefaultValue = DecPcdEntry.DefaultValue\r
600 DscPcdEntry.TokenValue = DecPcdEntry.TokenValue\r
601 DscPcdEntry.TokenSpaceGuidValue = eachDec.Guids[DecPcdEntry.TokenSpaceGuidCName]\r
602 # Only fix the value while no value provided in DSC file.\r
603 if not Sku.DefaultValue:\r
604 DscPcdEntry.SkuInfoList[list(DscPcdEntry.SkuInfoList.keys())[0]].DefaultValue = DecPcdEntry.DefaultValue\r
605\r
606 if DscPcdEntry not in self._DynamicPcdList:\r
607 self._DynamicPcdList.append(DscPcdEntry)\r
608 Sku.VpdOffset = Sku.VpdOffset.strip()\r
609 PcdValue = Sku.DefaultValue\r
610 if PcdValue == "":\r
611 PcdValue = DscPcdEntry.DefaultValue\r
612 if Sku.VpdOffset != TAB_STAR:\r
613 if PcdValue.startswith("{"):\r
614 Alignment = 8\r
615 elif PcdValue.startswith("L"):\r
616 Alignment = 2\r
617 else:\r
618 Alignment = 1\r
619 try:\r
620 VpdOffset = int(Sku.VpdOffset)\r
621 except:\r
622 try:\r
623 VpdOffset = int(Sku.VpdOffset, 16)\r
624 except:\r
625 EdkLogger.error("build", FORMAT_INVALID, "Invalid offset value %s for PCD %s.%s." % (Sku.VpdOffset, DscPcdEntry.TokenSpaceGuidCName, DscPcdEntry.TokenCName))\r
626 if VpdOffset % Alignment != 0:\r
627 if PcdValue.startswith("{"):\r
628 EdkLogger.warn("build", "The offset value of PCD %s.%s is not 8-byte aligned!" %(DscPcdEntry.TokenSpaceGuidCName, DscPcdEntry.TokenCName), File=self.MetaFile)\r
629 else:\r
630 EdkLogger.error("build", FORMAT_INVALID, 'The offset value of PCD %s.%s should be %s-byte aligned.' % (DscPcdEntry.TokenSpaceGuidCName, DscPcdEntry.TokenCName, Alignment))\r
631 if PcdValue not in SkuValueMap:\r
632 SkuValueMap[PcdValue] = []\r
633 VpdFile.Add(DscPcdEntry, SkuName, Sku.VpdOffset)\r
634 SkuValueMap[PcdValue].append(Sku)\r
635 if not NeedProcessVpdMapFile and Sku.VpdOffset == TAB_STAR:\r
636 NeedProcessVpdMapFile = True\r
637 if DscPcdEntry.DatumType == TAB_VOID and PcdValue.startswith("L"):\r
638 UnicodePcdArray.add(DscPcdEntry)\r
639 elif len(Sku.VariableName) > 0:\r
640 HiiPcdArray.add(DscPcdEntry)\r
641 else:\r
642 OtherPcdArray.add(DscPcdEntry)\r
643\r
644 # if the offset of a VPD is *, then it need to be fixed up by third party tool.\r
645 VpdSkuMap[DscPcd] = SkuValueMap\r
646 if (self.Platform.FlashDefinition is None or self.Platform.FlashDefinition == '') and \\r
647 VpdFile.GetCount() != 0:\r
648 EdkLogger.error("build", ATTRIBUTE_NOT_AVAILABLE,\r
649 "Fail to get FLASH_DEFINITION definition in DSC file %s which is required when DSC contains VPD PCD." % str(self.Platform.MetaFile))\r
650\r
651 if VpdFile.GetCount() != 0:\r
652\r
653 self.FixVpdOffset(VpdFile)\r
654\r
655 self.FixVpdOffset(self.UpdateNVStoreMaxSize(VpdFile))\r
656 PcdNvStoreDfBuffer = [item for item in self._DynamicPcdList if item.TokenCName == "PcdNvStoreDefaultValueBuffer" and item.TokenSpaceGuidCName == "gEfiMdeModulePkgTokenSpaceGuid"]\r
657 if PcdNvStoreDfBuffer:\r
658 PcdName,PcdGuid = PcdNvStoreDfBuffer[0].TokenCName, PcdNvStoreDfBuffer[0].TokenSpaceGuidCName\r
659 if (PcdName,PcdGuid) in VpdSkuMap:\r
660 DefaultSku = PcdNvStoreDfBuffer[0].SkuInfoList.get(TAB_DEFAULT)\r
661 VpdSkuMap[(PcdName,PcdGuid)] = {DefaultSku.DefaultValue:[SkuObj for SkuObj in PcdNvStoreDfBuffer[0].SkuInfoList.values() ]}\r
662\r
663 # Process VPD map file generated by third party BPDG tool\r
664 if NeedProcessVpdMapFile:\r
665 VpdMapFilePath = os.path.join(self.BuildDir, TAB_FV_DIRECTORY, "%s.map" % self.Platform.VpdToolGuid)\r
666 if os.path.exists(VpdMapFilePath):\r
667 VpdFile.Read(VpdMapFilePath)\r
668\r
669 # Fixup TAB_STAR offset\r
670 for pcd in VpdSkuMap:\r
671 vpdinfo = VpdFile.GetVpdInfo(pcd)\r
672 if vpdinfo is None:\r
673 # just pick the a value to determine whether is unicode string type\r
674 continue\r
675 for pcdvalue in VpdSkuMap[pcd]:\r
676 for sku in VpdSkuMap[pcd][pcdvalue]:\r
677 for item in vpdinfo:\r
678 if item[2] == pcdvalue:\r
679 sku.VpdOffset = item[1]\r
680 else:\r
681 EdkLogger.error("build", FILE_READ_FAILURE, "Can not find VPD map file %s to fix up VPD offset." % VpdMapFilePath)\r
682\r
683 # Delete the DynamicPcdList At the last time enter into this function\r
684 for Pcd in self._DynamicPcdList:\r
685 # just pick the a value to determine whether is unicode string type\r
686 Sku = Pcd.SkuInfoList.get(TAB_DEFAULT)\r
687 Sku.VpdOffset = Sku.VpdOffset.strip()\r
688\r
689 if Pcd.DatumType not in [TAB_UINT8, TAB_UINT16, TAB_UINT32, TAB_UINT64, TAB_VOID, "BOOLEAN"]:\r
690 Pcd.DatumType = TAB_VOID\r
691\r
692 PcdValue = Sku.DefaultValue\r
693 if Pcd.DatumType == TAB_VOID and PcdValue.startswith("L"):\r
694 # if found PCD which datum value is unicode string the insert to left size of UnicodeIndex\r
695 UnicodePcdArray.add(Pcd)\r
696 elif len(Sku.VariableName) > 0:\r
697 # if found HII type PCD then insert to right of UnicodeIndex\r
698 HiiPcdArray.add(Pcd)\r
699 else:\r
700 OtherPcdArray.add(Pcd)\r
701 del self._DynamicPcdList[:]\r
702 self._DynamicPcdList.extend(list(UnicodePcdArray))\r
703 self._DynamicPcdList.extend(list(HiiPcdArray))\r
704 self._DynamicPcdList.extend(list(OtherPcdArray))\r
705 allskuset = [(SkuName, Sku.SkuId) for pcd in self._DynamicPcdList for (SkuName, Sku) in pcd.SkuInfoList.items()]\r
706 for pcd in self._DynamicPcdList:\r
707 if len(pcd.SkuInfoList) == 1:\r
708 for (SkuName, SkuId) in allskuset:\r
709 if isinstance(SkuId, str) and eval(SkuId) == 0 or SkuId == 0:\r
710 continue\r
711 pcd.SkuInfoList[SkuName] = copy.deepcopy(pcd.SkuInfoList[TAB_DEFAULT])\r
712 pcd.SkuInfoList[SkuName].SkuId = SkuId\r
713 pcd.SkuInfoList[SkuName].SkuIdName = SkuName\r
714\r
715 def FixVpdOffset(self, VpdFile ):\r
716 FvPath = os.path.join(self.BuildDir, TAB_FV_DIRECTORY)\r
717 if not os.path.exists(FvPath):\r
718 try:\r
719 os.makedirs(FvPath)\r
720 except:\r
721 EdkLogger.error("build", FILE_WRITE_FAILURE, "Fail to create FV folder under %s" % self.BuildDir)\r
722\r
723 VpdFilePath = os.path.join(FvPath, "%s.txt" % self.Platform.VpdToolGuid)\r
724\r
725 if VpdFile.Write(VpdFilePath):\r
726 # retrieve BPDG tool's path from tool_def.txt according to VPD_TOOL_GUID defined in DSC file.\r
727 BPDGToolName = None\r
728 for ToolDef in self.ToolDefinition.values():\r
729 if TAB_GUID in ToolDef and ToolDef[TAB_GUID] == self.Platform.VpdToolGuid:\r
730 if "PATH" not in ToolDef:\r
731 EdkLogger.error("build", ATTRIBUTE_NOT_AVAILABLE, "PATH attribute was not provided for BPDG guid tool %s in tools_def.txt" % self.Platform.VpdToolGuid)\r
732 BPDGToolName = ToolDef["PATH"]\r
733 break\r
734 # Call third party GUID BPDG tool.\r
735 if BPDGToolName is not None:\r
736 VpdInfoFile.CallExtenalBPDGTool(BPDGToolName, VpdFilePath)\r
737 else:\r
738 EdkLogger.error("Build", FILE_NOT_FOUND, "Fail to find third-party BPDG tool to process VPD PCDs. BPDG Guid tool need to be defined in tools_def.txt and VPD_TOOL_GUID need to be provided in DSC file.")\r
739\r
740 ## Return the platform build data object\r
741 @cached_property\r
742 def Platform(self):\r
743 return self.BuildDatabase[self.MetaFile, self.Arch, self.BuildTarget, self.ToolChain]\r
744\r
745 ## Return platform name\r
746 @cached_property\r
747 def Name(self):\r
748 return self.Platform.PlatformName\r
749\r
750 ## Return the meta file GUID\r
751 @cached_property\r
752 def Guid(self):\r
753 return self.Platform.Guid\r
754\r
755 ## Return the platform version\r
756 @cached_property\r
757 def Version(self):\r
758 return self.Platform.Version\r
759\r
760 ## Return the FDF file name\r
761 @cached_property\r
762 def FdfFile(self):\r
763 if self.Workspace.FdfFile:\r
764 RetVal= mws.join(self.WorkspaceDir, self.Workspace.FdfFile)\r
765 else:\r
766 RetVal = ''\r
767 return RetVal\r
768\r
769 ## Return the build output directory platform specifies\r
770 @cached_property\r
771 def OutputDir(self):\r
772 return self.Platform.OutputDirectory\r
773\r
774 ## Return the directory to store all intermediate and final files built\r
775 @cached_property\r
776 def BuildDir(self):\r
777 if os.path.isabs(self.OutputDir):\r
778 GlobalData.gBuildDirectory = RetVal = path.join(\r
779 path.abspath(self.OutputDir),\r
780 self.BuildTarget + "_" + self.ToolChain,\r
781 )\r
782 else:\r
783 GlobalData.gBuildDirectory = RetVal = path.join(\r
784 self.WorkspaceDir,\r
785 self.OutputDir,\r
786 self.BuildTarget + "_" + self.ToolChain,\r
787 )\r
788 return RetVal\r
789\r
790 ## Return directory of platform makefile\r
791 #\r
792 # @retval string Makefile directory\r
793 #\r
794 @cached_property\r
795 def MakeFileDir(self):\r
796 return path.join(self.BuildDir, self.Arch)\r
797\r
798 ## Return build command string\r
799 #\r
800 # @retval string Build command string\r
801 #\r
802 @cached_property\r
803 def BuildCommand(self):\r
804 RetVal = []\r
805 if "MAKE" in self.ToolDefinition and "PATH" in self.ToolDefinition["MAKE"]:\r
806 RetVal += _SplitOption(self.ToolDefinition["MAKE"]["PATH"])\r
807 if "FLAGS" in self.ToolDefinition["MAKE"]:\r
808 NewOption = self.ToolDefinition["MAKE"]["FLAGS"].strip()\r
809 if NewOption != '':\r
810 RetVal += _SplitOption(NewOption)\r
811 if "MAKE" in self.EdkIIBuildOption:\r
812 if "FLAGS" in self.EdkIIBuildOption["MAKE"]:\r
813 Flags = self.EdkIIBuildOption["MAKE"]["FLAGS"]\r
814 if Flags.startswith('='):\r
815 RetVal = [RetVal[0]] + [Flags[1:]]\r
816 else:\r
817 RetVal.append(Flags)\r
818 return RetVal\r
819\r
820 ## Get tool chain definition\r
821 #\r
822 # Get each tool definition for given tool chain from tools_def.txt and platform\r
823 #\r
824 @cached_property\r
825 def ToolDefinition(self):\r
826 ToolDefinition = self.Workspace.ToolDef.ToolsDefTxtDictionary\r
827 if TAB_TOD_DEFINES_COMMAND_TYPE not in self.Workspace.ToolDef.ToolsDefTxtDatabase:\r
828 EdkLogger.error('build', RESOURCE_NOT_AVAILABLE, "No tools found in configuration",\r
829 ExtraData="[%s]" % self.MetaFile)\r
830 RetVal = OrderedDict()\r
831 DllPathList = set()\r
832 for Def in ToolDefinition:\r
833 Target, Tag, Arch, Tool, Attr = Def.split("_")\r
834 if Target != self.BuildTarget or Tag != self.ToolChain or Arch != self.Arch:\r
835 continue\r
836\r
837 Value = ToolDefinition[Def]\r
838 # don't record the DLL\r
839 if Attr == "DLL":\r
840 DllPathList.add(Value)\r
841 continue\r
842\r
843 if Tool not in RetVal:\r
844 RetVal[Tool] = OrderedDict()\r
845 RetVal[Tool][Attr] = Value\r
846\r
847 ToolsDef = ''\r
848 if GlobalData.gOptions.SilentMode and "MAKE" in RetVal:\r
849 if "FLAGS" not in RetVal["MAKE"]:\r
850 RetVal["MAKE"]["FLAGS"] = ""\r
851 RetVal["MAKE"]["FLAGS"] += " -s"\r
852 MakeFlags = ''\r
853 for Tool in RetVal:\r
854 for Attr in RetVal[Tool]:\r
855 Value = RetVal[Tool][Attr]\r
856 if Tool in self._BuildOptionWithToolDef(RetVal) and Attr in self._BuildOptionWithToolDef(RetVal)[Tool]:\r
857 # check if override is indicated\r
858 if self._BuildOptionWithToolDef(RetVal)[Tool][Attr].startswith('='):\r
859 Value = self._BuildOptionWithToolDef(RetVal)[Tool][Attr][1:]\r
860 else:\r
861 if Attr != 'PATH':\r
862 Value += " " + self._BuildOptionWithToolDef(RetVal)[Tool][Attr]\r
863 else:\r
864 Value = self._BuildOptionWithToolDef(RetVal)[Tool][Attr]\r
865\r
866 if Attr == "PATH":\r
867 # Don't put MAKE definition in the file\r
868 if Tool != "MAKE":\r
869 ToolsDef += "%s = %s\n" % (Tool, Value)\r
870 elif Attr != "DLL":\r
871 # Don't put MAKE definition in the file\r
872 if Tool == "MAKE":\r
873 if Attr == "FLAGS":\r
874 MakeFlags = Value\r
875 else:\r
876 ToolsDef += "%s_%s = %s\n" % (Tool, Attr, Value)\r
877 ToolsDef += "\n"\r
878\r
879 tool_def_file = os.path.join(self.MakeFileDir, "TOOLS_DEF." + self.Arch)\r
880 SaveFileOnChange(tool_def_file, ToolsDef, False)\r
881 for DllPath in DllPathList:\r
882 os.environ["PATH"] = DllPath + os.pathsep + os.environ["PATH"]\r
883 os.environ["MAKE_FLAGS"] = MakeFlags\r
884\r
885 return RetVal\r
886\r
887 ## Return the paths of tools\r
888 @cached_property\r
889 def ToolDefinitionFile(self):\r
890 tool_def_file = os.path.join(self.MakeFileDir, "TOOLS_DEF." + self.Arch)\r
891 if not os.path.exists(tool_def_file):\r
892 self.ToolDefinition\r
893 return tool_def_file\r
894\r
895 ## Retrieve the toolchain family of given toolchain tag. Default to 'MSFT'.\r
896 @cached_property\r
897 def ToolChainFamily(self):\r
898 ToolDefinition = self.Workspace.ToolDef.ToolsDefTxtDatabase\r
899 if TAB_TOD_DEFINES_FAMILY not in ToolDefinition \\r
900 or self.ToolChain not in ToolDefinition[TAB_TOD_DEFINES_FAMILY] \\r
901 or not ToolDefinition[TAB_TOD_DEFINES_FAMILY][self.ToolChain]:\r
902 EdkLogger.verbose("No tool chain family found in configuration for %s. Default to MSFT." \\r
903 % self.ToolChain)\r
904 RetVal = TAB_COMPILER_MSFT\r
905 else:\r
906 RetVal = ToolDefinition[TAB_TOD_DEFINES_FAMILY][self.ToolChain]\r
907 return RetVal\r
908\r
909 @cached_property\r
910 def BuildRuleFamily(self):\r
911 ToolDefinition = self.Workspace.ToolDef.ToolsDefTxtDatabase\r
912 if TAB_TOD_DEFINES_BUILDRULEFAMILY not in ToolDefinition \\r
913 or self.ToolChain not in ToolDefinition[TAB_TOD_DEFINES_BUILDRULEFAMILY] \\r
914 or not ToolDefinition[TAB_TOD_DEFINES_BUILDRULEFAMILY][self.ToolChain]:\r
915 EdkLogger.verbose("No tool chain family found in configuration for %s. Default to MSFT." \\r
916 % self.ToolChain)\r
917 return TAB_COMPILER_MSFT\r
918\r
919 return ToolDefinition[TAB_TOD_DEFINES_BUILDRULEFAMILY][self.ToolChain]\r
920\r
921 ## Return the build options specific for all modules in this platform\r
922 @cached_property\r
923 def BuildOption(self):\r
924 return self._ExpandBuildOption(self.Platform.BuildOptions)\r
925\r
926 def _BuildOptionWithToolDef(self, ToolDef):\r
927 return self._ExpandBuildOption(self.Platform.BuildOptions, ToolDef=ToolDef)\r
928\r
929 ## Return the build options specific for EDK modules in this platform\r
930 @cached_property\r
931 def EdkBuildOption(self):\r
932 return self._ExpandBuildOption(self.Platform.BuildOptions, EDK_NAME)\r
933\r
934 ## Return the build options specific for EDKII modules in this platform\r
935 @cached_property\r
936 def EdkIIBuildOption(self):\r
937 return self._ExpandBuildOption(self.Platform.BuildOptions, EDKII_NAME)\r
938\r
939 ## Parse build_rule.txt in Conf Directory.\r
940 #\r
941 # @retval BuildRule object\r
942 #\r
943 @cached_property\r
944 def BuildRule(self):\r
945 BuildRuleFile = None\r
946 if TAB_TAT_DEFINES_BUILD_RULE_CONF in self.Workspace.TargetTxt.TargetTxtDictionary:\r
947 BuildRuleFile = self.Workspace.TargetTxt.TargetTxtDictionary[TAB_TAT_DEFINES_BUILD_RULE_CONF]\r
948 if not BuildRuleFile:\r
949 BuildRuleFile = gDefaultBuildRuleFile\r
950 RetVal = BuildRule(BuildRuleFile)\r
951 if RetVal._FileVersion == "":\r
952 RetVal._FileVersion = AutoGenReqBuildRuleVerNum\r
953 else:\r
954 if RetVal._FileVersion < AutoGenReqBuildRuleVerNum :\r
955 # If Build Rule's version is less than the version number required by the tools, halting the build.\r
956 EdkLogger.error("build", AUTOGEN_ERROR,\r
957 ExtraData="The version number [%s] of build_rule.txt is less than the version number required by the AutoGen.(the minimum required version number is [%s])"\\r
958 % (RetVal._FileVersion, AutoGenReqBuildRuleVerNum))\r
959 return RetVal\r
960\r
961 ## Summarize the packages used by modules in this platform\r
962 @cached_property\r
963 def PackageList(self):\r
964 RetVal = set()\r
965 for Mb in self._MbList:\r
966 RetVal.update(Mb.Packages)\r
967 for lb in Mb.LibInstances:\r
968 RetVal.update(lb.Packages)\r
969 #Collect package set information from INF of FDF\r
970 for ModuleFile in self._AsBuildModuleList:\r
971 if ModuleFile in self.Platform.Modules:\r
972 continue\r
973 ModuleData = self.BuildDatabase[ModuleFile, self.Arch, self.BuildTarget, self.ToolChain]\r
974 RetVal.update(ModuleData.Packages)\r
975 return list(RetVal)\r
976\r
977 @cached_property\r
978 def NonDynamicPcdDict(self):\r
979 return {(Pcd.TokenCName, Pcd.TokenSpaceGuidCName):Pcd for Pcd in self.NonDynamicPcdList}\r
980\r
981 ## Get list of non-dynamic PCDs\r
982 @property\r
983 def NonDynamicPcdList(self):\r
984 if not self._NonDynamicPcdList:\r
985 self.CollectPlatformDynamicPcds()\r
986 return self._NonDynamicPcdList\r
987\r
988 ## Get list of dynamic PCDs\r
989 @property\r
990 def DynamicPcdList(self):\r
991 if not self._DynamicPcdList:\r
992 self.CollectPlatformDynamicPcds()\r
993 return self._DynamicPcdList\r
994\r
995 ## Generate Token Number for all PCD\r
996 @cached_property\r
997 def PcdTokenNumber(self):\r
998 RetVal = OrderedDict()\r
999 TokenNumber = 1\r
1000 #\r
1001 # Make the Dynamic and DynamicEx PCD use within different TokenNumber area.\r
1002 # Such as:\r
1003 #\r
1004 # Dynamic PCD:\r
1005 # TokenNumber 0 ~ 10\r
1006 # DynamicEx PCD:\r
1007 # TokeNumber 11 ~ 20\r
1008 #\r
1009 for Pcd in self.DynamicPcdList:\r
1010 if Pcd.Phase == "PEI" and Pcd.Type in PCD_DYNAMIC_TYPE_SET:\r
1011 EdkLogger.debug(EdkLogger.DEBUG_5, "%s %s (%s) -> %d" % (Pcd.TokenCName, Pcd.TokenSpaceGuidCName, Pcd.Phase, TokenNumber))\r
1012 RetVal[Pcd.TokenCName, Pcd.TokenSpaceGuidCName] = TokenNumber\r
1013 TokenNumber += 1\r
1014\r
1015 for Pcd in self.DynamicPcdList:\r
1016 if Pcd.Phase == "PEI" and Pcd.Type in PCD_DYNAMIC_EX_TYPE_SET:\r
1017 EdkLogger.debug(EdkLogger.DEBUG_5, "%s %s (%s) -> %d" % (Pcd.TokenCName, Pcd.TokenSpaceGuidCName, Pcd.Phase, TokenNumber))\r
1018 RetVal[Pcd.TokenCName, Pcd.TokenSpaceGuidCName] = TokenNumber\r
1019 TokenNumber += 1\r
1020\r
1021 for Pcd in self.DynamicPcdList:\r
1022 if Pcd.Phase == "DXE" and Pcd.Type in PCD_DYNAMIC_TYPE_SET:\r
1023 EdkLogger.debug(EdkLogger.DEBUG_5, "%s %s (%s) -> %d" % (Pcd.TokenCName, Pcd.TokenSpaceGuidCName, Pcd.Phase, TokenNumber))\r
1024 RetVal[Pcd.TokenCName, Pcd.TokenSpaceGuidCName] = TokenNumber\r
1025 TokenNumber += 1\r
1026\r
1027 for Pcd in self.DynamicPcdList:\r
1028 if Pcd.Phase == "DXE" and Pcd.Type in PCD_DYNAMIC_EX_TYPE_SET:\r
1029 EdkLogger.debug(EdkLogger.DEBUG_5, "%s %s (%s) -> %d" % (Pcd.TokenCName, Pcd.TokenSpaceGuidCName, Pcd.Phase, TokenNumber))\r
1030 RetVal[Pcd.TokenCName, Pcd.TokenSpaceGuidCName] = TokenNumber\r
1031 TokenNumber += 1\r
1032\r
1033 for Pcd in self.NonDynamicPcdList:\r
1034 RetVal[Pcd.TokenCName, Pcd.TokenSpaceGuidCName] = TokenNumber\r
1035 TokenNumber += 1\r
1036 return RetVal\r
1037\r
1038 @cached_property\r
1039 def _MbList(self):\r
1040 return [self.BuildDatabase[m, self.Arch, self.BuildTarget, self.ToolChain] for m in self.Platform.Modules]\r
1041\r
1042 @cached_property\r
1043 def _MaList(self):\r
1044 for ModuleFile in self.Platform.Modules:\r
1045 Ma = ModuleAutoGen(\r
1046 self.Workspace,\r
1047 ModuleFile,\r
1048 self.BuildTarget,\r
1049 self.ToolChain,\r
1050 self.Arch,\r
1051 self.MetaFile,\r
1052 self.DataPipe\r
1053 )\r
1054 self.Platform.Modules[ModuleFile].M = Ma\r
1055 return [x.M for x in self.Platform.Modules.values()]\r
1056\r
1057 ## Summarize ModuleAutoGen objects of all modules to be built for this platform\r
1058 @cached_property\r
1059 def ModuleAutoGenList(self):\r
1060 RetVal = []\r
1061 for Ma in self._MaList:\r
1062 if Ma not in RetVal:\r
1063 RetVal.append(Ma)\r
1064 return RetVal\r
1065\r
1066 ## Summarize ModuleAutoGen objects of all libraries to be built for this platform\r
1067 @cached_property\r
1068 def LibraryAutoGenList(self):\r
1069 RetVal = []\r
1070 for Ma in self._MaList:\r
1071 for La in Ma.LibraryAutoGenList:\r
1072 if La not in RetVal:\r
1073 RetVal.append(La)\r
1074 if Ma not in La.ReferenceModules:\r
1075 La.ReferenceModules.append(Ma)\r
1076 return RetVal\r
1077\r
1078 ## Test if a module is supported by the platform\r
1079 #\r
1080 # An error will be raised directly if the module or its arch is not supported\r
1081 # by the platform or current configuration\r
1082 #\r
1083 def ValidModule(self, Module):\r
1084 return Module in self.Platform.Modules or Module in self.Platform.LibraryInstances \\r
1085 or Module in self._AsBuildModuleList\r
1086 @cached_property\r
1087 def GetAllModuleInfo(self,WithoutPcd=True):\r
1088 ModuleLibs = set()\r
1089 for m in self.Platform.Modules:\r
1090 module_obj = self.BuildDatabase[m,self.Arch,self.BuildTarget,self.ToolChain]\r
1091 if not bool(module_obj.LibraryClass):\r
1092 Libs = GetModuleLibInstances(module_obj, self.Platform, self.BuildDatabase, self.Arch,self.BuildTarget,self.ToolChain)\r
1093 else:\r
1094 Libs = []\r
673d09a2 1095 ModuleLibs.update( set([(l.MetaFile.File,l.MetaFile.Root,l.MetaFile.Path,l.MetaFile.BaseName,l.MetaFile.OriginalPath,l.Arch,True) for l in Libs]))\r
e8449e1d
FB
1096 if WithoutPcd and module_obj.PcdIsDriver:\r
1097 continue\r
673d09a2 1098 ModuleLibs.add((m.File,m.Root,m.Path,m.BaseName,m.OriginalPath,module_obj.Arch,bool(module_obj.LibraryClass)))\r
e8449e1d
FB
1099\r
1100 return ModuleLibs\r
1101\r
1102 ## Resolve the library classes in a module to library instances\r
1103 #\r
1104 # This method will not only resolve library classes but also sort the library\r
1105 # instances according to the dependency-ship.\r
1106 #\r
1107 # @param Module The module from which the library classes will be resolved\r
1108 #\r
1109 # @retval library_list List of library instances sorted\r
1110 #\r
1111 def ApplyLibraryInstance(self, Module):\r
1112 # Cover the case that the binary INF file is list in the FDF file but not DSC file, return empty list directly\r
1113 if str(Module) not in self.Platform.Modules:\r
1114 return []\r
1115\r
1116 return GetModuleLibInstances(Module,\r
1117 self.Platform,\r
1118 self.BuildDatabase,\r
1119 self.Arch,\r
1120 self.BuildTarget,\r
1121 self.ToolChain,\r
1122 self.MetaFile,\r
1123 EdkLogger)\r
1124\r
1125 ## Override PCD setting (type, value, ...)\r
1126 #\r
1127 # @param ToPcd The PCD to be overridden\r
1128 # @param FromPcd The PCD overriding from\r
1129 #\r
1130 def _OverridePcd(self, ToPcd, FromPcd, Module="", Msg="", Library=""):\r
1131 #\r
1132 # in case there's PCDs coming from FDF file, which have no type given.\r
1133 # at this point, ToPcd.Type has the type found from dependent\r
1134 # package\r
1135 #\r
1136 TokenCName = ToPcd.TokenCName\r
1137 for PcdItem in GlobalData.MixedPcd:\r
1138 if (ToPcd.TokenCName, ToPcd.TokenSpaceGuidCName) in GlobalData.MixedPcd[PcdItem]:\r
1139 TokenCName = PcdItem[0]\r
1140 break\r
1141 if FromPcd is not None:\r
1142 if ToPcd.Pending and FromPcd.Type:\r
1143 ToPcd.Type = FromPcd.Type\r
1144 elif ToPcd.Type and FromPcd.Type\\r
1145 and ToPcd.Type != FromPcd.Type and ToPcd.Type in FromPcd.Type:\r
1146 if ToPcd.Type.strip() == TAB_PCDS_DYNAMIC_EX:\r
1147 ToPcd.Type = FromPcd.Type\r
1148 elif ToPcd.Type and FromPcd.Type \\r
1149 and ToPcd.Type != FromPcd.Type:\r
1150 if Library:\r
1151 Module = str(Module) + " 's library file (" + str(Library) + ")"\r
1152 EdkLogger.error("build", OPTION_CONFLICT, "Mismatched PCD type",\r
1153 ExtraData="%s.%s is used as [%s] in module %s, but as [%s] in %s."\\r
1154 % (ToPcd.TokenSpaceGuidCName, TokenCName,\r
1155 ToPcd.Type, Module, FromPcd.Type, Msg),\r
1156 File=self.MetaFile)\r
1157\r
1158 if FromPcd.MaxDatumSize:\r
1159 ToPcd.MaxDatumSize = FromPcd.MaxDatumSize\r
1160 ToPcd.MaxSizeUserSet = FromPcd.MaxDatumSize\r
1161 if FromPcd.DefaultValue:\r
1162 ToPcd.DefaultValue = FromPcd.DefaultValue\r
1163 if FromPcd.TokenValue:\r
1164 ToPcd.TokenValue = FromPcd.TokenValue\r
1165 if FromPcd.DatumType:\r
1166 ToPcd.DatumType = FromPcd.DatumType\r
1167 if FromPcd.SkuInfoList:\r
1168 ToPcd.SkuInfoList = FromPcd.SkuInfoList\r
1169 if FromPcd.UserDefinedDefaultStoresFlag:\r
1170 ToPcd.UserDefinedDefaultStoresFlag = FromPcd.UserDefinedDefaultStoresFlag\r
1171 # Add Flexible PCD format parse\r
1172 if ToPcd.DefaultValue:\r
1173 try:\r
1174 ToPcd.DefaultValue = ValueExpressionEx(ToPcd.DefaultValue, ToPcd.DatumType, self.Platform._GuidDict)(True)\r
1175 except BadExpression as Value:\r
1176 EdkLogger.error('Parser', FORMAT_INVALID, 'PCD [%s.%s] Value "%s", %s' %(ToPcd.TokenSpaceGuidCName, ToPcd.TokenCName, ToPcd.DefaultValue, Value),\r
1177 File=self.MetaFile)\r
1178\r
1179 # check the validation of datum\r
1180 IsValid, Cause = CheckPcdDatum(ToPcd.DatumType, ToPcd.DefaultValue)\r
1181 if not IsValid:\r
1182 EdkLogger.error('build', FORMAT_INVALID, Cause, File=self.MetaFile,\r
1183 ExtraData="%s.%s" % (ToPcd.TokenSpaceGuidCName, TokenCName))\r
1184 ToPcd.validateranges = FromPcd.validateranges\r
1185 ToPcd.validlists = FromPcd.validlists\r
1186 ToPcd.expressions = FromPcd.expressions\r
1187 ToPcd.CustomAttribute = FromPcd.CustomAttribute\r
1188\r
1189 if FromPcd is not None and ToPcd.DatumType == TAB_VOID and not ToPcd.MaxDatumSize:\r
1190 EdkLogger.debug(EdkLogger.DEBUG_9, "No MaxDatumSize specified for PCD %s.%s" \\r
1191 % (ToPcd.TokenSpaceGuidCName, TokenCName))\r
1192 Value = ToPcd.DefaultValue\r
1193 if not Value:\r
1194 ToPcd.MaxDatumSize = '1'\r
1195 elif Value[0] == 'L':\r
1196 ToPcd.MaxDatumSize = str((len(Value) - 2) * 2)\r
1197 elif Value[0] == '{':\r
1198 ToPcd.MaxDatumSize = str(len(Value.split(',')))\r
1199 else:\r
1200 ToPcd.MaxDatumSize = str(len(Value) - 1)\r
1201\r
1202 # apply default SKU for dynamic PCDS if specified one is not available\r
1203 if (ToPcd.Type in PCD_DYNAMIC_TYPE_SET or ToPcd.Type in PCD_DYNAMIC_EX_TYPE_SET) \\r
1204 and not ToPcd.SkuInfoList:\r
1205 if self.Platform.SkuName in self.Platform.SkuIds:\r
1206 SkuName = self.Platform.SkuName\r
1207 else:\r
1208 SkuName = TAB_DEFAULT\r
1209 ToPcd.SkuInfoList = {\r
1210 SkuName : SkuInfoClass(SkuName, self.Platform.SkuIds[SkuName][0], '', '', '', '', '', ToPcd.DefaultValue)\r
1211 }\r
1212\r
1213 ## Apply PCD setting defined platform to a module\r
1214 #\r
1215 # @param Module The module from which the PCD setting will be overridden\r
1216 #\r
1217 # @retval PCD_list The list PCDs with settings from platform\r
1218 #\r
1219 def ApplyPcdSetting(self, Module, Pcds, Library=""):\r
1220 # for each PCD in module\r
1221 for Name, Guid in Pcds:\r
1222 PcdInModule = Pcds[Name, Guid]\r
1223 # find out the PCD setting in platform\r
1224 if (Name, Guid) in self.Platform.Pcds:\r
1225 PcdInPlatform = self.Platform.Pcds[Name, Guid]\r
1226 else:\r
1227 PcdInPlatform = None\r
1228 # then override the settings if any\r
1229 self._OverridePcd(PcdInModule, PcdInPlatform, Module, Msg="DSC PCD sections", Library=Library)\r
1230 # resolve the VariableGuid value\r
1231 for SkuId in PcdInModule.SkuInfoList:\r
1232 Sku = PcdInModule.SkuInfoList[SkuId]\r
1233 if Sku.VariableGuid == '': continue\r
1234 Sku.VariableGuidValue = GuidValue(Sku.VariableGuid, self.PackageList, self.MetaFile.Path)\r
1235 if Sku.VariableGuidValue is None:\r
1236 PackageList = "\n\t".join(str(P) for P in self.PackageList)\r
1237 EdkLogger.error(\r
1238 'build',\r
1239 RESOURCE_NOT_AVAILABLE,\r
1240 "Value of GUID [%s] is not found in" % Sku.VariableGuid,\r
1241 ExtraData=PackageList + "\n\t(used with %s.%s from module %s)" \\r
1242 % (Guid, Name, str(Module)),\r
1243 File=self.MetaFile\r
1244 )\r
1245\r
1246 # override PCD settings with module specific setting\r
1247 if Module in self.Platform.Modules:\r
1248 PlatformModule = self.Platform.Modules[str(Module)]\r
1249 for Key in PlatformModule.Pcds:\r
1250 if GlobalData.BuildOptionPcd:\r
1251 for pcd in GlobalData.BuildOptionPcd:\r
1252 (TokenSpaceGuidCName, TokenCName, FieldName, pcdvalue, _) = pcd\r
1253 if (TokenCName, TokenSpaceGuidCName) == Key and FieldName =="":\r
1254 PlatformModule.Pcds[Key].DefaultValue = pcdvalue\r
1255 PlatformModule.Pcds[Key].PcdValueFromComm = pcdvalue\r
1256 break\r
1257 Flag = False\r
1258 if Key in Pcds:\r
1259 ToPcd = Pcds[Key]\r
1260 Flag = True\r
1261 elif Key in GlobalData.MixedPcd:\r
1262 for PcdItem in GlobalData.MixedPcd[Key]:\r
1263 if PcdItem in Pcds:\r
1264 ToPcd = Pcds[PcdItem]\r
1265 Flag = True\r
1266 break\r
1267 if Flag:\r
1268 self._OverridePcd(ToPcd, PlatformModule.Pcds[Key], Module, Msg="DSC Components Module scoped PCD section", Library=Library)\r
1269 # use PCD value to calculate the MaxDatumSize when it is not specified\r
1270 for Name, Guid in Pcds:\r
1271 Pcd = Pcds[Name, Guid]\r
1272 if Pcd.DatumType == TAB_VOID and not Pcd.MaxDatumSize:\r
1273 Pcd.MaxSizeUserSet = None\r
1274 Value = Pcd.DefaultValue\r
1275 if not Value:\r
1276 Pcd.MaxDatumSize = '1'\r
1277 elif Value[0] == 'L':\r
1278 Pcd.MaxDatumSize = str((len(Value) - 2) * 2)\r
1279 elif Value[0] == '{':\r
1280 Pcd.MaxDatumSize = str(len(Value.split(',')))\r
1281 else:\r
1282 Pcd.MaxDatumSize = str(len(Value) - 1)\r
1283 return list(Pcds.values())\r
1284\r
1285 ## Append build options in platform to a module\r
1286 #\r
1287 # @param Module The module to which the build options will be appended\r
1288 #\r
1289 # @retval options The options appended with build options in platform\r
1290 #\r
1291 def ApplyBuildOption(self, Module):\r
1292 # Get the different options for the different style module\r
1293 PlatformOptions = self.EdkIIBuildOption\r
1294 ModuleTypeOptions = self.Platform.GetBuildOptionsByModuleType(EDKII_NAME, Module.ModuleType)\r
1295 ModuleTypeOptions = self._ExpandBuildOption(ModuleTypeOptions)\r
1296 ModuleOptions = self._ExpandBuildOption(Module.BuildOptions)\r
1297 if Module in self.Platform.Modules:\r
1298 PlatformModule = self.Platform.Modules[str(Module)]\r
1299 PlatformModuleOptions = self._ExpandBuildOption(PlatformModule.BuildOptions)\r
1300 else:\r
1301 PlatformModuleOptions = {}\r
1302\r
1303 BuildRuleOrder = None\r
1304 for Options in [self.ToolDefinition, ModuleOptions, PlatformOptions, ModuleTypeOptions, PlatformModuleOptions]:\r
1305 for Tool in Options:\r
1306 for Attr in Options[Tool]:\r
1307 if Attr == TAB_TOD_DEFINES_BUILDRULEORDER:\r
1308 BuildRuleOrder = Options[Tool][Attr]\r
1309\r
1310 AllTools = set(list(ModuleOptions.keys()) + list(PlatformOptions.keys()) +\r
1311 list(PlatformModuleOptions.keys()) + list(ModuleTypeOptions.keys()) +\r
1312 list(self.ToolDefinition.keys()))\r
1313 BuildOptions = defaultdict(lambda: defaultdict(str))\r
1314 for Tool in AllTools:\r
1315 for Options in [self.ToolDefinition, ModuleOptions, PlatformOptions, ModuleTypeOptions, PlatformModuleOptions]:\r
1316 if Tool not in Options:\r
1317 continue\r
1318 for Attr in Options[Tool]:\r
1319 #\r
1320 # Do not generate it in Makefile\r
1321 #\r
1322 if Attr == TAB_TOD_DEFINES_BUILDRULEORDER:\r
1323 continue\r
1324 Value = Options[Tool][Attr]\r
1325 # check if override is indicated\r
1326 if Value.startswith('='):\r
1327 BuildOptions[Tool][Attr] = mws.handleWsMacro(Value[1:])\r
1328 else:\r
1329 if Attr != 'PATH':\r
1330 BuildOptions[Tool][Attr] += " " + mws.handleWsMacro(Value)\r
1331 else:\r
1332 BuildOptions[Tool][Attr] = mws.handleWsMacro(Value)\r
1333\r
1334 return BuildOptions, BuildRuleOrder\r
1335\r
1336\r
1337 def GetGlobalBuildOptions(self,Module):\r
1338 ModuleTypeOptions = self.Platform.GetBuildOptionsByModuleType(EDKII_NAME, Module.ModuleType)\r
1339 ModuleTypeOptions = self._ExpandBuildOption(ModuleTypeOptions)\r
1340\r
1341 if Module in self.Platform.Modules:\r
1342 PlatformModule = self.Platform.Modules[str(Module)]\r
1343 PlatformModuleOptions = self._ExpandBuildOption(PlatformModule.BuildOptions)\r
1344 else:\r
1345 PlatformModuleOptions = {}\r
1346\r
1347 return ModuleTypeOptions,PlatformModuleOptions\r
1348 def ModuleGuid(self,Module):\r
1349 if os.path.basename(Module.MetaFile.File) != os.path.basename(Module.MetaFile.Path):\r
1350 #\r
1351 # Length of GUID is 36\r
1352 #\r
1353 return os.path.basename(Module.MetaFile.Path)[:36]\r
1354 return Module.Guid\r
1355 @cached_property\r
1356 def UniqueBaseName(self):\r
1357 retVal ={}\r
1358 ModuleNameDict = {}\r
1359 UniqueName = {}\r
1360 for Module in self._MbList:\r
1361 unique_base_name = '%s_%s' % (Module.BaseName,self.ModuleGuid(Module))\r
1362 if unique_base_name not in ModuleNameDict:\r
1363 ModuleNameDict[unique_base_name] = []\r
1364 ModuleNameDict[unique_base_name].append(Module.MetaFile)\r
1365 if Module.BaseName not in UniqueName:\r
1366 UniqueName[Module.BaseName] = set()\r
1367 UniqueName[Module.BaseName].add((self.ModuleGuid(Module),Module.MetaFile))\r
1368 for module_paths in ModuleNameDict.values():\r
76e12fa3 1369 if len(set(module_paths))>1:\r
e8449e1d
FB
1370 samemodules = list(set(module_paths))\r
1371 EdkLogger.error("build", FILE_DUPLICATED, 'Modules have same BaseName and FILE_GUID:\n'\r
1372 ' %s\n %s' % (samemodules[0], samemodules[1]))\r
1373 for name in UniqueName:\r
1374 Guid_Path = UniqueName[name]\r
1375 if len(Guid_Path) > 1:\r
76e12fa3
FB
1376 for guid,mpath in Guid_Path:\r
1377 retVal[(name,mpath)] = '%s_%s' % (name,guid)\r
e8449e1d
FB
1378 return retVal\r
1379 ## Expand * in build option key\r
1380 #\r
1381 # @param Options Options to be expanded\r
1382 # @param ToolDef Use specified ToolDef instead of full version.\r
1383 # This is needed during initialization to prevent\r
1384 # infinite recursion betweeh BuildOptions,\r
1385 # ToolDefinition, and this function.\r
1386 #\r
1387 # @retval options Options expanded\r
1388 #\r
1389 def _ExpandBuildOption(self, Options, ModuleStyle=None, ToolDef=None):\r
1390 if not ToolDef:\r
1391 ToolDef = self.ToolDefinition\r
1392 BuildOptions = {}\r
1393 FamilyMatch = False\r
1394 FamilyIsNull = True\r
1395\r
1396 OverrideList = {}\r
1397 #\r
1398 # Construct a list contain the build options which need override.\r
1399 #\r
1400 for Key in Options:\r
1401 #\r
1402 # Key[0] -- tool family\r
1403 # Key[1] -- TARGET_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE\r
1404 #\r
1405 if (Key[0] == self.BuildRuleFamily and\r
1406 (ModuleStyle is None or len(Key) < 3 or (len(Key) > 2 and Key[2] == ModuleStyle))):\r
1407 Target, ToolChain, Arch, CommandType, Attr = Key[1].split('_')\r
1408 if (Target == self.BuildTarget or Target == TAB_STAR) and\\r
1409 (ToolChain == self.ToolChain or ToolChain == TAB_STAR) and\\r
1410 (Arch == self.Arch or Arch == TAB_STAR) and\\r
1411 Options[Key].startswith("="):\r
1412\r
1413 if OverrideList.get(Key[1]) is not None:\r
1414 OverrideList.pop(Key[1])\r
1415 OverrideList[Key[1]] = Options[Key]\r
1416\r
1417 #\r
1418 # Use the highest priority value.\r
1419 #\r
1420 if (len(OverrideList) >= 2):\r
1421 KeyList = list(OverrideList.keys())\r
1422 for Index in range(len(KeyList)):\r
1423 NowKey = KeyList[Index]\r
1424 Target1, ToolChain1, Arch1, CommandType1, Attr1 = NowKey.split("_")\r
1425 for Index1 in range(len(KeyList) - Index - 1):\r
1426 NextKey = KeyList[Index1 + Index + 1]\r
1427 #\r
1428 # Compare two Key, if one is included by another, choose the higher priority one\r
1429 #\r
1430 Target2, ToolChain2, Arch2, CommandType2, Attr2 = NextKey.split("_")\r
1431 if (Target1 == Target2 or Target1 == TAB_STAR or Target2 == TAB_STAR) and\\r
1432 (ToolChain1 == ToolChain2 or ToolChain1 == TAB_STAR or ToolChain2 == TAB_STAR) and\\r
1433 (Arch1 == Arch2 or Arch1 == TAB_STAR or Arch2 == TAB_STAR) and\\r
1434 (CommandType1 == CommandType2 or CommandType1 == TAB_STAR or CommandType2 == TAB_STAR) and\\r
1435 (Attr1 == Attr2 or Attr1 == TAB_STAR or Attr2 == TAB_STAR):\r
1436\r
1437 if CalculatePriorityValue(NowKey) > CalculatePriorityValue(NextKey):\r
1438 if Options.get((self.BuildRuleFamily, NextKey)) is not None:\r
1439 Options.pop((self.BuildRuleFamily, NextKey))\r
1440 else:\r
1441 if Options.get((self.BuildRuleFamily, NowKey)) is not None:\r
1442 Options.pop((self.BuildRuleFamily, NowKey))\r
1443\r
1444 for Key in Options:\r
1445 if ModuleStyle is not None and len (Key) > 2:\r
1446 # Check Module style is EDK or EDKII.\r
1447 # Only append build option for the matched style module.\r
1448 if ModuleStyle == EDK_NAME and Key[2] != EDK_NAME:\r
1449 continue\r
1450 elif ModuleStyle == EDKII_NAME and Key[2] != EDKII_NAME:\r
1451 continue\r
1452 Family = Key[0]\r
1453 Target, Tag, Arch, Tool, Attr = Key[1].split("_")\r
1454 # if tool chain family doesn't match, skip it\r
1455 if Tool in ToolDef and Family != "":\r
1456 FamilyIsNull = False\r
1457 if ToolDef[Tool].get(TAB_TOD_DEFINES_BUILDRULEFAMILY, "") != "":\r
1458 if Family != ToolDef[Tool][TAB_TOD_DEFINES_BUILDRULEFAMILY]:\r
1459 continue\r
1460 elif Family != ToolDef[Tool][TAB_TOD_DEFINES_FAMILY]:\r
1461 continue\r
1462 FamilyMatch = True\r
1463 # expand any wildcard\r
1464 if Target == TAB_STAR or Target == self.BuildTarget:\r
1465 if Tag == TAB_STAR or Tag == self.ToolChain:\r
1466 if Arch == TAB_STAR or Arch == self.Arch:\r
1467 if Tool not in BuildOptions:\r
1468 BuildOptions[Tool] = {}\r
1469 if Attr != "FLAGS" or Attr not in BuildOptions[Tool] or Options[Key].startswith('='):\r
1470 BuildOptions[Tool][Attr] = Options[Key]\r
1471 else:\r
1472 # append options for the same tool except PATH\r
1473 if Attr != 'PATH':\r
1474 BuildOptions[Tool][Attr] += " " + Options[Key]\r
1475 else:\r
1476 BuildOptions[Tool][Attr] = Options[Key]\r
1477 # Build Option Family has been checked, which need't to be checked again for family.\r
1478 if FamilyMatch or FamilyIsNull:\r
1479 return BuildOptions\r
1480\r
1481 for Key in Options:\r
1482 if ModuleStyle is not None and len (Key) > 2:\r
1483 # Check Module style is EDK or EDKII.\r
1484 # Only append build option for the matched style module.\r
1485 if ModuleStyle == EDK_NAME and Key[2] != EDK_NAME:\r
1486 continue\r
1487 elif ModuleStyle == EDKII_NAME and Key[2] != EDKII_NAME:\r
1488 continue\r
1489 Family = Key[0]\r
1490 Target, Tag, Arch, Tool, Attr = Key[1].split("_")\r
1491 # if tool chain family doesn't match, skip it\r
1492 if Tool not in ToolDef or Family == "":\r
1493 continue\r
1494 # option has been added before\r
1495 if Family != ToolDef[Tool][TAB_TOD_DEFINES_FAMILY]:\r
1496 continue\r
1497\r
1498 # expand any wildcard\r
1499 if Target == TAB_STAR or Target == self.BuildTarget:\r
1500 if Tag == TAB_STAR or Tag == self.ToolChain:\r
1501 if Arch == TAB_STAR or Arch == self.Arch:\r
1502 if Tool not in BuildOptions:\r
1503 BuildOptions[Tool] = {}\r
1504 if Attr != "FLAGS" or Attr not in BuildOptions[Tool] or Options[Key].startswith('='):\r
1505 BuildOptions[Tool][Attr] = Options[Key]\r
1506 else:\r
1507 # append options for the same tool except PATH\r
1508 if Attr != 'PATH':\r
1509 BuildOptions[Tool][Attr] += " " + Options[Key]\r
1510 else:\r
1511 BuildOptions[Tool][Attr] = Options[Key]\r
1512 return BuildOptions\r