]> git.proxmox.com Git - mirror_edk2.git/blame - BaseTools/Source/Python/AutoGen/ModuleAutoGenHelper.py
BaseTools/Source/Python: New Target/ToolChain/Arch in DSC [BuildOptions]
[mirror_edk2.git] / BaseTools / Source / Python / AutoGen / ModuleAutoGenHelper.py
CommitLineData
e8449e1d
FB
1## @file\r
2# Create makefile for MS nmake and GNU make\r
3#\r
f2f4c6be 4# Copyright (c) 2019 - 2021, Intel Corporation. All rights reserved.<BR>\r
e8449e1d
FB
5# SPDX-License-Identifier: BSD-2-Clause-Patent\r
6#\r
7from __future__ import absolute_import\r
8from Workspace.WorkspaceDatabase import WorkspaceDatabase,BuildDB\r
9from Common.caching import cached_property\r
10from AutoGen.BuildEngine import BuildRule,AutoGenReqBuildRuleVerNum\r
11from AutoGen.AutoGen import CalculatePriorityValue\r
12from Common.Misc import CheckPcdDatum,GuidValue\r
13from Common.Expression import ValueExpressionEx\r
14from Common.DataType import *\r
15from CommonDataClass.Exceptions import *\r
16from CommonDataClass.CommonClass import SkuInfoClass\r
17import Common.EdkLogger as EdkLogger\r
18from Common.BuildToolError import OPTION_CONFLICT,FORMAT_INVALID,RESOURCE_NOT_AVAILABLE\r
19from Common.MultipleWorkspace import MultipleWorkspace as mws\r
20from collections import defaultdict\r
21from Common.Misc import PathClass\r
22import os\r
23\r
24\r
25#\r
26# The priority list while override build option\r
27#\r
28PrioList = {"0x11111" : 16, # TARGET_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE (Highest)\r
29 "0x01111" : 15, # ******_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE\r
30 "0x10111" : 14, # TARGET_*********_ARCH_COMMANDTYPE_ATTRIBUTE\r
31 "0x00111" : 13, # ******_*********_ARCH_COMMANDTYPE_ATTRIBUTE\r
32 "0x11011" : 12, # TARGET_TOOLCHAIN_****_COMMANDTYPE_ATTRIBUTE\r
33 "0x01011" : 11, # ******_TOOLCHAIN_****_COMMANDTYPE_ATTRIBUTE\r
34 "0x10011" : 10, # TARGET_*********_****_COMMANDTYPE_ATTRIBUTE\r
35 "0x00011" : 9, # ******_*********_****_COMMANDTYPE_ATTRIBUTE\r
36 "0x11101" : 8, # TARGET_TOOLCHAIN_ARCH_***********_ATTRIBUTE\r
37 "0x01101" : 7, # ******_TOOLCHAIN_ARCH_***********_ATTRIBUTE\r
38 "0x10101" : 6, # TARGET_*********_ARCH_***********_ATTRIBUTE\r
39 "0x00101" : 5, # ******_*********_ARCH_***********_ATTRIBUTE\r
40 "0x11001" : 4, # TARGET_TOOLCHAIN_****_***********_ATTRIBUTE\r
41 "0x01001" : 3, # ******_TOOLCHAIN_****_***********_ATTRIBUTE\r
42 "0x10001" : 2, # TARGET_*********_****_***********_ATTRIBUTE\r
43 "0x00001" : 1} # ******_*********_****_***********_ATTRIBUTE (Lowest)\r
44## Base class for AutoGen\r
45#\r
46# This class just implements the cache mechanism of AutoGen objects.\r
47#\r
48class AutoGenInfo(object):\r
49 # database to maintain the objects in each child class\r
50 __ObjectCache = {} # (BuildTarget, ToolChain, ARCH, platform file): AutoGen object\r
51\r
52 ## Factory method\r
53 #\r
54 # @param Class class object of real AutoGen class\r
55 # (WorkspaceAutoGen, ModuleAutoGen or PlatformAutoGen)\r
56 # @param Workspace Workspace directory or WorkspaceAutoGen object\r
57 # @param MetaFile The path of meta file\r
58 # @param Target Build target\r
59 # @param Toolchain Tool chain name\r
60 # @param Arch Target arch\r
61 # @param *args The specific class related parameters\r
62 # @param **kwargs The specific class related dict parameters\r
63 #\r
64 @classmethod\r
65 def GetCache(cls):\r
66 return cls.__ObjectCache\r
67 def __new__(cls, Workspace, MetaFile, Target, Toolchain, Arch, *args, **kwargs):\r
68 # check if the object has been created\r
69 Key = (Target, Toolchain, Arch, MetaFile)\r
70 if Key in cls.__ObjectCache:\r
71 # if it exists, just return it directly\r
72 return cls.__ObjectCache[Key]\r
73 # it didnt exist. create it, cache it, then return it\r
74 RetVal = cls.__ObjectCache[Key] = super(AutoGenInfo, cls).__new__(cls)\r
75 return RetVal\r
76\r
77\r
78 ## hash() operator\r
79 #\r
80 # The file path of platform file will be used to represent hash value of this object\r
81 #\r
82 # @retval int Hash value of the file path of platform file\r
83 #\r
84 def __hash__(self):\r
85 return hash(self.MetaFile)\r
86\r
87 ## str() operator\r
88 #\r
89 # The file path of platform file will be used to represent this object\r
90 #\r
91 # @retval string String of platform file path\r
92 #\r
93 def __str__(self):\r
94 return str(self.MetaFile)\r
95\r
96 ## "==" operator\r
97 def __eq__(self, Other):\r
98 return Other and self.MetaFile == Other\r
99\r
100 ## Expand * in build option key\r
101 #\r
102 # @param Options Options to be expanded\r
103 # @param ToolDef Use specified ToolDef instead of full version.\r
104 # This is needed during initialization to prevent\r
105 # infinite recursion betweeh BuildOptions,\r
106 # ToolDefinition, and this function.\r
107 #\r
108 # @retval options Options expanded\r
109 #\r
110 def _ExpandBuildOption(self, Options, ModuleStyle=None, ToolDef=None):\r
111 if not ToolDef:\r
112 ToolDef = self.ToolDefinition\r
113 BuildOptions = {}\r
114 FamilyMatch = False\r
115 FamilyIsNull = True\r
116\r
117 OverrideList = {}\r
118 #\r
119 # Construct a list contain the build options which need override.\r
120 #\r
121 for Key in Options:\r
122 #\r
123 # Key[0] -- tool family\r
124 # Key[1] -- TARGET_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE\r
125 #\r
126 if (Key[0] == self.BuildRuleFamily and\r
127 (ModuleStyle is None or len(Key) < 3 or (len(Key) > 2 and Key[2] == ModuleStyle))):\r
128 Target, ToolChain, Arch, CommandType, Attr = Key[1].split('_')\r
129 if (Target == self.BuildTarget or Target == TAB_STAR) and\\r
130 (ToolChain == self.ToolChain or ToolChain == TAB_STAR) and\\r
131 (Arch == self.Arch or Arch == TAB_STAR) and\\r
132 Options[Key].startswith("="):\r
133\r
134 if OverrideList.get(Key[1]) is not None:\r
135 OverrideList.pop(Key[1])\r
136 OverrideList[Key[1]] = Options[Key]\r
137\r
138 #\r
139 # Use the highest priority value.\r
140 #\r
141 if (len(OverrideList) >= 2):\r
142 KeyList = list(OverrideList.keys())\r
143 for Index in range(len(KeyList)):\r
144 NowKey = KeyList[Index]\r
145 Target1, ToolChain1, Arch1, CommandType1, Attr1 = NowKey.split("_")\r
146 for Index1 in range(len(KeyList) - Index - 1):\r
147 NextKey = KeyList[Index1 + Index + 1]\r
148 #\r
149 # Compare two Key, if one is included by another, choose the higher priority one\r
150 #\r
151 Target2, ToolChain2, Arch2, CommandType2, Attr2 = NextKey.split("_")\r
152 if (Target1 == Target2 or Target1 == TAB_STAR or Target2 == TAB_STAR) and\\r
153 (ToolChain1 == ToolChain2 or ToolChain1 == TAB_STAR or ToolChain2 == TAB_STAR) and\\r
154 (Arch1 == Arch2 or Arch1 == TAB_STAR or Arch2 == TAB_STAR) and\\r
155 (CommandType1 == CommandType2 or CommandType1 == TAB_STAR or CommandType2 == TAB_STAR) and\\r
156 (Attr1 == Attr2 or Attr1 == TAB_STAR or Attr2 == TAB_STAR):\r
157\r
158 if CalculatePriorityValue(NowKey) > CalculatePriorityValue(NextKey):\r
159 if Options.get((self.BuildRuleFamily, NextKey)) is not None:\r
160 Options.pop((self.BuildRuleFamily, NextKey))\r
161 else:\r
162 if Options.get((self.BuildRuleFamily, NowKey)) is not None:\r
163 Options.pop((self.BuildRuleFamily, NowKey))\r
164\r
165 for Key in Options:\r
166 if ModuleStyle is not None and len (Key) > 2:\r
167 # Check Module style is EDK or EDKII.\r
168 # Only append build option for the matched style module.\r
169 if ModuleStyle == EDK_NAME and Key[2] != EDK_NAME:\r
170 continue\r
171 elif ModuleStyle == EDKII_NAME and Key[2] != EDKII_NAME:\r
172 continue\r
173 Family = Key[0]\r
174 Target, Tag, Arch, Tool, Attr = Key[1].split("_")\r
175 # if tool chain family doesn't match, skip it\r
ab957f03
MK
176 if Family != "":\r
177 Found = False\r
178 if Tool in ToolDef:\r
179 FamilyIsNull = False\r
180 if TAB_TOD_DEFINES_BUILDRULEFAMILY in ToolDef[Tool]:\r
181 if Family == ToolDef[Tool][TAB_TOD_DEFINES_BUILDRULEFAMILY]:\r
182 FamilyMatch = True\r
183 Found = True\r
184 if TAB_TOD_DEFINES_FAMILY in ToolDef[Tool]:\r
185 if Family == ToolDef[Tool][TAB_TOD_DEFINES_FAMILY]:\r
186 FamilyMatch = True\r
187 Found = True\r
188 if TAB_STAR in ToolDef:\r
189 FamilyIsNull = False\r
190 if TAB_TOD_DEFINES_BUILDRULEFAMILY in ToolDef[TAB_STAR]:\r
191 if Family == ToolDef[TAB_STAR][TAB_TOD_DEFINES_BUILDRULEFAMILY]:\r
192 FamilyMatch = True\r
193 Found = True\r
194 if TAB_TOD_DEFINES_FAMILY in ToolDef[TAB_STAR]:\r
195 if Family == ToolDef[TAB_STAR][TAB_TOD_DEFINES_FAMILY]:\r
196 FamilyMatch = True\r
197 Found = True\r
198 if not Found:\r
199 continue\r
e8449e1d
FB
200 # expand any wildcard\r
201 if Target == TAB_STAR or Target == self.BuildTarget:\r
202 if Tag == TAB_STAR or Tag == self.ToolChain:\r
203 if Arch == TAB_STAR or Arch == self.Arch:\r
204 if Tool not in BuildOptions:\r
205 BuildOptions[Tool] = {}\r
206 if Attr != "FLAGS" or Attr not in BuildOptions[Tool] or Options[Key].startswith('='):\r
207 BuildOptions[Tool][Attr] = Options[Key]\r
208 else:\r
209 # append options for the same tool except PATH\r
210 if Attr != 'PATH':\r
211 BuildOptions[Tool][Attr] += " " + Options[Key]\r
212 else:\r
213 BuildOptions[Tool][Attr] = Options[Key]\r
214 # Build Option Family has been checked, which need't to be checked again for family.\r
215 if FamilyMatch or FamilyIsNull:\r
216 return BuildOptions\r
217\r
218 for Key in Options:\r
219 if ModuleStyle is not None and len (Key) > 2:\r
220 # Check Module style is EDK or EDKII.\r
221 # Only append build option for the matched style module.\r
222 if ModuleStyle == EDK_NAME and Key[2] != EDK_NAME:\r
223 continue\r
224 elif ModuleStyle == EDKII_NAME and Key[2] != EDKII_NAME:\r
225 continue\r
226 Family = Key[0]\r
227 Target, Tag, Arch, Tool, Attr = Key[1].split("_")\r
228 # if tool chain family doesn't match, skip it\r
ab957f03 229 if Family == "":\r
e8449e1d
FB
230 continue\r
231 # option has been added before\r
ab957f03
MK
232 Found = False\r
233 if Tool in ToolDef:\r
234 if TAB_TOD_DEFINES_FAMILY in ToolDef[Tool]:\r
235 if Family == ToolDef[Tool][TAB_TOD_DEFINES_FAMILY]:\r
236 Found = True\r
237 if TAB_STAR in ToolDef:\r
238 if TAB_TOD_DEFINES_FAMILY in ToolDef[TAB_STAR]:\r
239 if Family == ToolDef[TAB_STAR][TAB_TOD_DEFINES_FAMILY]:\r
240 Found = True\r
241 if not Found:\r
e8449e1d
FB
242 continue\r
243\r
244 # expand any wildcard\r
245 if Target == TAB_STAR or Target == self.BuildTarget:\r
246 if Tag == TAB_STAR or Tag == self.ToolChain:\r
247 if Arch == TAB_STAR or Arch == self.Arch:\r
248 if Tool not in BuildOptions:\r
249 BuildOptions[Tool] = {}\r
250 if Attr != "FLAGS" or Attr not in BuildOptions[Tool] or Options[Key].startswith('='):\r
251 BuildOptions[Tool][Attr] = Options[Key]\r
252 else:\r
253 # append options for the same tool except PATH\r
254 if Attr != 'PATH':\r
255 BuildOptions[Tool][Attr] += " " + Options[Key]\r
256 else:\r
257 BuildOptions[Tool][Attr] = Options[Key]\r
258 return BuildOptions\r
259#\r
260#This class is the pruned WorkSpaceAutoGen for ModuleAutoGen in multiple thread\r
261#\r
262class WorkSpaceInfo(AutoGenInfo):\r
263 def __init__(self,Workspace, MetaFile, Target, ToolChain, Arch):\r
373298ca
FB
264 if not hasattr(self, "_Init"):\r
265 self.do_init(Workspace, MetaFile, Target, ToolChain, Arch)\r
266 self._Init = True\r
267 def do_init(self,Workspace, MetaFile, Target, ToolChain, Arch):\r
e8449e1d
FB
268 self._SrcTimeStamp = 0\r
269 self.Db = BuildDB\r
270 self.BuildDatabase = self.Db.BuildObject\r
271 self.Target = Target\r
272 self.ToolChain = ToolChain\r
273 self.WorkspaceDir = Workspace\r
274 self.ActivePlatform = MetaFile\r
275 self.ArchList = Arch\r
373298ca
FB
276 self.AutoGenObjectList = []\r
277 @property\r
278 def BuildDir(self):\r
279 return self.AutoGenObjectList[0].BuildDir\r
e8449e1d 280\r
373298ca
FB
281 @property\r
282 def Name(self):\r
283 return self.AutoGenObjectList[0].Platform.PlatformName\r
284\r
285 @property\r
286 def FlashDefinition(self):\r
287 return self.AutoGenObjectList[0].Platform.FlashDefinition\r
288 @property\r
289 def GenFdsCommandDict(self):\r
290 FdsCommandDict = self.AutoGenObjectList[0].DataPipe.Get("FdsCommandDict")\r
291 if FdsCommandDict:\r
292 return FdsCommandDict\r
293 return {}\r
294\r
295 @cached_property\r
296 def FvDir(self):\r
297 return os.path.join(self.BuildDir, TAB_FV_DIRECTORY)\r
e8449e1d
FB
298\r
299class PlatformInfo(AutoGenInfo):\r
300 def __init__(self, Workspace, MetaFile, Target, ToolChain, Arch,DataPipe):\r
373298ca
FB
301 if not hasattr(self, "_Init"):\r
302 self.do_init(Workspace, MetaFile, Target, ToolChain, Arch,DataPipe)\r
303 self._Init = True\r
304 def do_init(self,Workspace, MetaFile, Target, ToolChain, Arch,DataPipe):\r
e8449e1d
FB
305 self.Wa = Workspace\r
306 self.WorkspaceDir = self.Wa.WorkspaceDir\r
307 self.MetaFile = MetaFile\r
308 self.Arch = Arch\r
309 self.Target = Target\r
310 self.BuildTarget = Target\r
311 self.ToolChain = ToolChain\r
312 self.Platform = self.Wa.BuildDatabase[self.MetaFile, self.Arch, self.Target, self.ToolChain]\r
313\r
314 self.SourceDir = MetaFile.SubDir\r
315 self.DataPipe = DataPipe\r
316 @cached_property\r
317 def _AsBuildModuleList(self):\r
318 retVal = self.DataPipe.Get("AsBuildModuleList")\r
319 if retVal is None:\r
320 retVal = {}\r
321 return retVal\r
322\r
323 ## Test if a module is supported by the platform\r
324 #\r
325 # An error will be raised directly if the module or its arch is not supported\r
326 # by the platform or current configuration\r
327 #\r
328 def ValidModule(self, Module):\r
329 return Module in self.Platform.Modules or Module in self.Platform.LibraryInstances \\r
330 or Module in self._AsBuildModuleList\r
331\r
332 @cached_property\r
333 def ToolChainFamily(self):\r
334 retVal = self.DataPipe.Get("ToolChainFamily")\r
335 if retVal is None:\r
336 retVal = {}\r
337 return retVal\r
338\r
339 @cached_property\r
340 def BuildRuleFamily(self):\r
341 retVal = self.DataPipe.Get("BuildRuleFamily")\r
342 if retVal is None:\r
343 retVal = {}\r
344 return retVal\r
345\r
346 @cached_property\r
347 def _MbList(self):\r
348 return [self.Wa.BuildDatabase[m, self.Arch, self.BuildTarget, self.ToolChain] for m in self.Platform.Modules]\r
349\r
350 @cached_property\r
351 def PackageList(self):\r
352 RetVal = set()\r
353 for dec_file,Arch in self.DataPipe.Get("PackageList"):\r
354 RetVal.add(self.Wa.BuildDatabase[dec_file,Arch,self.BuildTarget, self.ToolChain])\r
355 return list(RetVal)\r
356\r
357 ## Return the directory to store all intermediate and final files built\r
358 @cached_property\r
359 def BuildDir(self):\r
360 if os.path.isabs(self.OutputDir):\r
361 RetVal = os.path.join(\r
362 os.path.abspath(self.OutputDir),\r
363 self.Target + "_" + self.ToolChain,\r
364 )\r
365 else:\r
366 RetVal = os.path.join(\r
367 self.WorkspaceDir,\r
368 self.OutputDir,\r
369 self.Target + "_" + self.ToolChain,\r
370 )\r
371 return RetVal\r
372\r
373 ## Return the build output directory platform specifies\r
374 @cached_property\r
375 def OutputDir(self):\r
376 return self.Platform.OutputDirectory\r
377\r
378 ## Return platform name\r
379 @cached_property\r
380 def Name(self):\r
381 return self.Platform.PlatformName\r
382\r
383 ## Return meta-file GUID\r
384 @cached_property\r
385 def Guid(self):\r
386 return self.Platform.Guid\r
387\r
388 ## Return platform version\r
389 @cached_property\r
390 def Version(self):\r
391 return self.Platform.Version\r
392\r
393 ## Return paths of tools\r
394 @cached_property\r
395 def ToolDefinition(self):\r
396 retVal = self.DataPipe.Get("TOOLDEF")\r
397 if retVal is None:\r
398 retVal = {}\r
399 return retVal\r
400\r
401 ## Return build command string\r
402 #\r
403 # @retval string Build command string\r
404 #\r
405 @cached_property\r
406 def BuildCommand(self):\r
407 retVal = self.DataPipe.Get("BuildCommand")\r
408 if retVal is None:\r
409 retVal = []\r
410 return retVal\r
411\r
412 @cached_property\r
413 def PcdTokenNumber(self):\r
414 retVal = self.DataPipe.Get("PCD_TNUM")\r
415 if retVal is None:\r
416 retVal = {}\r
417 return retVal\r
418\r
419 ## Override PCD setting (type, value, ...)\r
420 #\r
421 # @param ToPcd The PCD to be overridden\r
422 # @param FromPcd The PCD overriding from\r
423 #\r
424 def _OverridePcd(self, ToPcd, FromPcd, Module="", Msg="", Library=""):\r
425 #\r
426 # in case there's PCDs coming from FDF file, which have no type given.\r
427 # at this point, ToPcd.Type has the type found from dependent\r
428 # package\r
429 #\r
430 TokenCName = ToPcd.TokenCName\r
431 for PcdItem in self.MixedPcd:\r
432 if (ToPcd.TokenCName, ToPcd.TokenSpaceGuidCName) in self.MixedPcd[PcdItem]:\r
433 TokenCName = PcdItem[0]\r
434 break\r
435 if FromPcd is not None:\r
436 if ToPcd.Pending and FromPcd.Type:\r
437 ToPcd.Type = FromPcd.Type\r
438 elif ToPcd.Type and FromPcd.Type\\r
439 and ToPcd.Type != FromPcd.Type and ToPcd.Type in FromPcd.Type:\r
440 if ToPcd.Type.strip() == TAB_PCDS_DYNAMIC_EX:\r
441 ToPcd.Type = FromPcd.Type\r
442 elif ToPcd.Type and FromPcd.Type \\r
443 and ToPcd.Type != FromPcd.Type:\r
444 if Library:\r
445 Module = str(Module) + " 's library file (" + str(Library) + ")"\r
446 EdkLogger.error("build", OPTION_CONFLICT, "Mismatched PCD type",\r
447 ExtraData="%s.%s is used as [%s] in module %s, but as [%s] in %s."\\r
448 % (ToPcd.TokenSpaceGuidCName, TokenCName,\r
449 ToPcd.Type, Module, FromPcd.Type, Msg),\r
450 File=self.MetaFile)\r
451\r
452 if FromPcd.MaxDatumSize:\r
453 ToPcd.MaxDatumSize = FromPcd.MaxDatumSize\r
454 ToPcd.MaxSizeUserSet = FromPcd.MaxDatumSize\r
455 if FromPcd.DefaultValue:\r
456 ToPcd.DefaultValue = FromPcd.DefaultValue\r
457 if FromPcd.TokenValue:\r
458 ToPcd.TokenValue = FromPcd.TokenValue\r
459 if FromPcd.DatumType:\r
460 ToPcd.DatumType = FromPcd.DatumType\r
461 if FromPcd.SkuInfoList:\r
462 ToPcd.SkuInfoList = FromPcd.SkuInfoList\r
463 if FromPcd.UserDefinedDefaultStoresFlag:\r
464 ToPcd.UserDefinedDefaultStoresFlag = FromPcd.UserDefinedDefaultStoresFlag\r
465 # Add Flexible PCD format parse\r
466 if ToPcd.DefaultValue:\r
467 try:\r
468 ToPcd.DefaultValue = ValueExpressionEx(ToPcd.DefaultValue, ToPcd.DatumType, self._GuidDict)(True)\r
469 except BadExpression as Value:\r
470 EdkLogger.error('Parser', FORMAT_INVALID, 'PCD [%s.%s] Value "%s", %s' %(ToPcd.TokenSpaceGuidCName, ToPcd.TokenCName, ToPcd.DefaultValue, Value),\r
471 File=self.MetaFile)\r
472\r
473 # check the validation of datum\r
474 IsValid, Cause = CheckPcdDatum(ToPcd.DatumType, ToPcd.DefaultValue)\r
475 if not IsValid:\r
476 EdkLogger.error('build', FORMAT_INVALID, Cause, File=self.MetaFile,\r
477 ExtraData="%s.%s" % (ToPcd.TokenSpaceGuidCName, TokenCName))\r
478 ToPcd.validateranges = FromPcd.validateranges\r
479 ToPcd.validlists = FromPcd.validlists\r
480 ToPcd.expressions = FromPcd.expressions\r
481 ToPcd.CustomAttribute = FromPcd.CustomAttribute\r
482\r
483 if FromPcd is not None and ToPcd.DatumType == TAB_VOID and not ToPcd.MaxDatumSize:\r
484 EdkLogger.debug(EdkLogger.DEBUG_9, "No MaxDatumSize specified for PCD %s.%s" \\r
485 % (ToPcd.TokenSpaceGuidCName, TokenCName))\r
486 Value = ToPcd.DefaultValue\r
487 if not Value:\r
488 ToPcd.MaxDatumSize = '1'\r
489 elif Value[0] == 'L':\r
490 ToPcd.MaxDatumSize = str((len(Value) - 2) * 2)\r
491 elif Value[0] == '{':\r
492 ToPcd.MaxDatumSize = str(len(Value.split(',')))\r
493 else:\r
494 ToPcd.MaxDatumSize = str(len(Value) - 1)\r
495\r
496 # apply default SKU for dynamic PCDS if specified one is not available\r
497 if (ToPcd.Type in PCD_DYNAMIC_TYPE_SET or ToPcd.Type in PCD_DYNAMIC_EX_TYPE_SET) \\r
498 and not ToPcd.SkuInfoList:\r
499 if self.Platform.SkuName in self.Platform.SkuIds:\r
500 SkuName = self.Platform.SkuName\r
501 else:\r
502 SkuName = TAB_DEFAULT\r
503 ToPcd.SkuInfoList = {\r
504 SkuName : SkuInfoClass(SkuName, self.Platform.SkuIds[SkuName][0], '', '', '', '', '', ToPcd.DefaultValue)\r
505 }\r
506\r
09af9bd9 507 def ApplyPcdSetting(self, Ma, Pcds, Library=""):\r
e8449e1d 508 # for each PCD in module\r
09af9bd9 509 Module=Ma.Module\r
e8449e1d
FB
510 for Name, Guid in Pcds:\r
511 PcdInModule = Pcds[Name, Guid]\r
512 # find out the PCD setting in platform\r
513 if (Name, Guid) in self.Pcds:\r
514 PcdInPlatform = self.Pcds[Name, Guid]\r
515 else:\r
516 PcdInPlatform = None\r
517 # then override the settings if any\r
518 self._OverridePcd(PcdInModule, PcdInPlatform, Module, Msg="DSC PCD sections", Library=Library)\r
519 # resolve the VariableGuid value\r
520 for SkuId in PcdInModule.SkuInfoList:\r
521 Sku = PcdInModule.SkuInfoList[SkuId]\r
522 if Sku.VariableGuid == '': continue\r
523 Sku.VariableGuidValue = GuidValue(Sku.VariableGuid, self.PackageList, self.MetaFile.Path)\r
524 if Sku.VariableGuidValue is None:\r
525 PackageList = "\n\t".join(str(P) for P in self.PackageList)\r
526 EdkLogger.error(\r
527 'build',\r
528 RESOURCE_NOT_AVAILABLE,\r
529 "Value of GUID [%s] is not found in" % Sku.VariableGuid,\r
530 ExtraData=PackageList + "\n\t(used with %s.%s from module %s)" \\r
531 % (Guid, Name, str(Module)),\r
532 File=self.MetaFile\r
533 )\r
534\r
535 # override PCD settings with module specific setting\r
09af9bd9 536 ModuleScopePcds = self.DataPipe.Get("MOL_PCDS")\r
e8449e1d
FB
537 if Module in self.Platform.Modules:\r
538 PlatformModule = self.Platform.Modules[str(Module)]\r
09af9bd9
BF
539 PCD_DATA = ModuleScopePcds.get(Ma.Guid,{})\r
540 mPcds = {(pcd.TokenCName,pcd.TokenSpaceGuidCName): pcd for pcd in PCD_DATA}\r
541 for Key in mPcds:\r
e8449e1d
FB
542 if self.BuildOptionPcd:\r
543 for pcd in self.BuildOptionPcd:\r
544 (TokenSpaceGuidCName, TokenCName, FieldName, pcdvalue, _) = pcd\r
545 if (TokenCName, TokenSpaceGuidCName) == Key and FieldName =="":\r
546 PlatformModule.Pcds[Key].DefaultValue = pcdvalue\r
547 PlatformModule.Pcds[Key].PcdValueFromComm = pcdvalue\r
548 break\r
549 Flag = False\r
550 if Key in Pcds:\r
551 ToPcd = Pcds[Key]\r
552 Flag = True\r
553 elif Key in self.MixedPcd:\r
554 for PcdItem in self.MixedPcd[Key]:\r
555 if PcdItem in Pcds:\r
556 ToPcd = Pcds[PcdItem]\r
557 Flag = True\r
558 break\r
559 if Flag:\r
09af9bd9 560 self._OverridePcd(ToPcd, mPcds[Key], Module, Msg="DSC Components Module scoped PCD section", Library=Library)\r
e8449e1d
FB
561 # use PCD value to calculate the MaxDatumSize when it is not specified\r
562 for Name, Guid in Pcds:\r
563 Pcd = Pcds[Name, Guid]\r
564 if Pcd.DatumType == TAB_VOID and not Pcd.MaxDatumSize:\r
565 Pcd.MaxSizeUserSet = None\r
566 Value = Pcd.DefaultValue\r
567 if not Value:\r
568 Pcd.MaxDatumSize = '1'\r
569 elif Value[0] == 'L':\r
570 Pcd.MaxDatumSize = str((len(Value) - 2) * 2)\r
571 elif Value[0] == '{':\r
572 Pcd.MaxDatumSize = str(len(Value.split(',')))\r
573 else:\r
574 Pcd.MaxDatumSize = str(len(Value) - 1)\r
575 return list(Pcds.values())\r
576\r
577 @cached_property\r
578 def Pcds(self):\r
579 PlatformPcdData = self.DataPipe.Get("PLA_PCD")\r
580# for pcd in PlatformPcdData:\r
581# for skuid in pcd.SkuInfoList:\r
582# pcd.SkuInfoList[skuid] = self.CreateSkuInfoFromDict(pcd.SkuInfoList[skuid])\r
583 return {(pcddata.TokenCName,pcddata.TokenSpaceGuidCName):pcddata for pcddata in PlatformPcdData}\r
584\r
585 def CreateSkuInfoFromDict(self,SkuInfoDict):\r
586 return SkuInfoClass(\r
587 SkuInfoDict.get("SkuIdName"),\r
588 SkuInfoDict.get("SkuId"),\r
589 SkuInfoDict.get("VariableName"),\r
590 SkuInfoDict.get("VariableGuid"),\r
591 SkuInfoDict.get("VariableOffset"),\r
592 SkuInfoDict.get("HiiDefaultValue"),\r
593 SkuInfoDict.get("VpdOffset"),\r
594 SkuInfoDict.get("DefaultValue"),\r
595 SkuInfoDict.get("VariableGuidValue"),\r
596 SkuInfoDict.get("VariableAttribute",""),\r
597 SkuInfoDict.get("DefaultStore",None)\r
598 )\r
599 @cached_property\r
600 def MixedPcd(self):\r
601 return self.DataPipe.Get("MixedPcd")\r
602 @cached_property\r
603 def _GuidDict(self):\r
604 RetVal = self.DataPipe.Get("GuidDict")\r
605 if RetVal is None:\r
606 RetVal = {}\r
607 return RetVal\r
608 @cached_property\r
609 def BuildOptionPcd(self):\r
610 return self.DataPipe.Get("BuildOptPcd")\r
611 def ApplyBuildOption(self,module):\r
612 PlatformOptions = self.DataPipe.Get("PLA_BO")\r
613 ModuleBuildOptions = self.DataPipe.Get("MOL_BO")\r
614 ModuleOptionFromDsc = ModuleBuildOptions.get((module.MetaFile.File,module.MetaFile.Root))\r
615 if ModuleOptionFromDsc:\r
616 ModuleTypeOptions, PlatformModuleOptions = ModuleOptionFromDsc["ModuleTypeOptions"],ModuleOptionFromDsc["PlatformModuleOptions"]\r
617 else:\r
618 ModuleTypeOptions, PlatformModuleOptions = {}, {}\r
619 ToolDefinition = self.DataPipe.Get("TOOLDEF")\r
620 ModuleOptions = self._ExpandBuildOption(module.BuildOptions)\r
621 BuildRuleOrder = None\r
622 for Options in [ToolDefinition, ModuleOptions, PlatformOptions, ModuleTypeOptions, PlatformModuleOptions]:\r
623 for Tool in Options:\r
624 for Attr in Options[Tool]:\r
625 if Attr == TAB_TOD_DEFINES_BUILDRULEORDER:\r
626 BuildRuleOrder = Options[Tool][Attr]\r
627\r
628 AllTools = set(list(ModuleOptions.keys()) + list(PlatformOptions.keys()) +\r
629 list(PlatformModuleOptions.keys()) + list(ModuleTypeOptions.keys()) +\r
630 list(ToolDefinition.keys()))\r
631 BuildOptions = defaultdict(lambda: defaultdict(str))\r
632 for Tool in AllTools:\r
633 for Options in [ToolDefinition, ModuleOptions, PlatformOptions, ModuleTypeOptions, PlatformModuleOptions]:\r
634 if Tool not in Options:\r
635 continue\r
636 for Attr in Options[Tool]:\r
637 #\r
638 # Do not generate it in Makefile\r
639 #\r
640 if Attr == TAB_TOD_DEFINES_BUILDRULEORDER:\r
641 continue\r
642 Value = Options[Tool][Attr]\r
643 # check if override is indicated\r
644 if Value.startswith('='):\r
645 BuildOptions[Tool][Attr] = mws.handleWsMacro(Value[1:])\r
646 else:\r
647 if Attr != 'PATH':\r
648 BuildOptions[Tool][Attr] += " " + mws.handleWsMacro(Value)\r
649 else:\r
650 BuildOptions[Tool][Attr] = mws.handleWsMacro(Value)\r
651\r
652 return BuildOptions, BuildRuleOrder\r
653\r
654 def ApplyLibraryInstance(self,module):\r
655 alldeps = self.DataPipe.Get("DEPS")\r
656 if alldeps is None:\r
657 alldeps = {}\r
658 mod_libs = alldeps.get((module.MetaFile.File,module.MetaFile.Root,module.Arch,module.MetaFile.Path),[])\r
659 retVal = []\r
660 for (file_path,root,arch,abs_path) in mod_libs:\r
661 libMetaFile = PathClass(file_path,root)\r
662 libMetaFile.OriginalPath = PathClass(file_path,root)\r
663 libMetaFile.Path = abs_path\r
664 retVal.append(self.Wa.BuildDatabase[libMetaFile, arch, self.Target,self.ToolChain])\r
665 return retVal\r
666\r
667 ## Parse build_rule.txt in Conf Directory.\r
668 #\r
669 # @retval BuildRule object\r
670 #\r
671 @cached_property\r
672 def BuildRule(self):\r
673 WInfo = self.DataPipe.Get("P_Info")\r
674 RetVal = WInfo.get("BuildRuleFile")\r
675 if RetVal._FileVersion == "":\r
676 RetVal._FileVersion = AutoGenReqBuildRuleVerNum\r
677 return RetVal\r