]>
Commit | Line | Data |
---|---|---|
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 | |
7 | from __future__ import absolute_import\r | |
8 | from Workspace.WorkspaceDatabase import WorkspaceDatabase,BuildDB\r | |
9 | from Common.caching import cached_property\r | |
10 | from AutoGen.BuildEngine import BuildRule,AutoGenReqBuildRuleVerNum\r | |
11 | from AutoGen.AutoGen import CalculatePriorityValue\r | |
12 | from Common.Misc import CheckPcdDatum,GuidValue\r | |
13 | from Common.Expression import ValueExpressionEx\r | |
14 | from Common.DataType import *\r | |
15 | from CommonDataClass.Exceptions import *\r | |
16 | from CommonDataClass.CommonClass import SkuInfoClass\r | |
17 | import Common.EdkLogger as EdkLogger\r | |
18 | from Common.BuildToolError import OPTION_CONFLICT,FORMAT_INVALID,RESOURCE_NOT_AVAILABLE\r | |
19 | from Common.MultipleWorkspace import MultipleWorkspace as mws\r | |
20 | from collections import defaultdict\r | |
21 | from Common.Misc import PathClass\r | |
22 | import os\r | |
23 | \r | |
24 | \r | |
25 | #\r | |
26 | # The priority list while override build option\r | |
27 | #\r | |
28 | PrioList = {"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 | |
48 | class 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 | |
ab957f03 MK |
184 | if TAB_STAR in ToolDef:\r |
185 | FamilyIsNull = False\r | |
186 | if TAB_TOD_DEFINES_BUILDRULEFAMILY in ToolDef[TAB_STAR]:\r | |
187 | if Family == ToolDef[TAB_STAR][TAB_TOD_DEFINES_BUILDRULEFAMILY]:\r | |
188 | FamilyMatch = True\r | |
189 | Found = True\r | |
ab957f03 MK |
190 | if not Found:\r |
191 | continue\r | |
e8449e1d FB |
192 | # expand any wildcard\r |
193 | if Target == TAB_STAR or Target == self.BuildTarget:\r | |
194 | if Tag == TAB_STAR or Tag == self.ToolChain:\r | |
195 | if Arch == TAB_STAR or Arch == self.Arch:\r | |
196 | if Tool not in BuildOptions:\r | |
197 | BuildOptions[Tool] = {}\r | |
198 | if Attr != "FLAGS" or Attr not in BuildOptions[Tool] or Options[Key].startswith('='):\r | |
199 | BuildOptions[Tool][Attr] = Options[Key]\r | |
200 | else:\r | |
201 | # append options for the same tool except PATH\r | |
202 | if Attr != 'PATH':\r | |
203 | BuildOptions[Tool][Attr] += " " + Options[Key]\r | |
204 | else:\r | |
205 | BuildOptions[Tool][Attr] = Options[Key]\r | |
206 | # Build Option Family has been checked, which need't to be checked again for family.\r | |
207 | if FamilyMatch or FamilyIsNull:\r | |
208 | return BuildOptions\r | |
209 | \r | |
210 | for Key in Options:\r | |
211 | if ModuleStyle is not None and len (Key) > 2:\r | |
212 | # Check Module style is EDK or EDKII.\r | |
213 | # Only append build option for the matched style module.\r | |
214 | if ModuleStyle == EDK_NAME and Key[2] != EDK_NAME:\r | |
215 | continue\r | |
216 | elif ModuleStyle == EDKII_NAME and Key[2] != EDKII_NAME:\r | |
217 | continue\r | |
218 | Family = Key[0]\r | |
219 | Target, Tag, Arch, Tool, Attr = Key[1].split("_")\r | |
220 | # if tool chain family doesn't match, skip it\r | |
ab957f03 | 221 | if Family == "":\r |
e8449e1d FB |
222 | continue\r |
223 | # option has been added before\r | |
ab957f03 MK |
224 | Found = False\r |
225 | if Tool in ToolDef:\r | |
226 | if TAB_TOD_DEFINES_FAMILY in ToolDef[Tool]:\r | |
227 | if Family == ToolDef[Tool][TAB_TOD_DEFINES_FAMILY]:\r | |
228 | Found = True\r | |
229 | if TAB_STAR in ToolDef:\r | |
230 | if TAB_TOD_DEFINES_FAMILY in ToolDef[TAB_STAR]:\r | |
231 | if Family == ToolDef[TAB_STAR][TAB_TOD_DEFINES_FAMILY]:\r | |
232 | Found = True\r | |
233 | if not Found:\r | |
e8449e1d FB |
234 | continue\r |
235 | \r | |
236 | # expand any wildcard\r | |
237 | if Target == TAB_STAR or Target == self.BuildTarget:\r | |
238 | if Tag == TAB_STAR or Tag == self.ToolChain:\r | |
239 | if Arch == TAB_STAR or Arch == self.Arch:\r | |
240 | if Tool not in BuildOptions:\r | |
241 | BuildOptions[Tool] = {}\r | |
242 | if Attr != "FLAGS" or Attr not in BuildOptions[Tool] or Options[Key].startswith('='):\r | |
243 | BuildOptions[Tool][Attr] = Options[Key]\r | |
244 | else:\r | |
245 | # append options for the same tool except PATH\r | |
246 | if Attr != 'PATH':\r | |
247 | BuildOptions[Tool][Attr] += " " + Options[Key]\r | |
248 | else:\r | |
249 | BuildOptions[Tool][Attr] = Options[Key]\r | |
250 | return BuildOptions\r | |
251 | #\r | |
252 | #This class is the pruned WorkSpaceAutoGen for ModuleAutoGen in multiple thread\r | |
253 | #\r | |
254 | class WorkSpaceInfo(AutoGenInfo):\r | |
255 | def __init__(self,Workspace, MetaFile, Target, ToolChain, Arch):\r | |
373298ca FB |
256 | if not hasattr(self, "_Init"):\r |
257 | self.do_init(Workspace, MetaFile, Target, ToolChain, Arch)\r | |
258 | self._Init = True\r | |
259 | def do_init(self,Workspace, MetaFile, Target, ToolChain, Arch):\r | |
e8449e1d FB |
260 | self._SrcTimeStamp = 0\r |
261 | self.Db = BuildDB\r | |
262 | self.BuildDatabase = self.Db.BuildObject\r | |
263 | self.Target = Target\r | |
264 | self.ToolChain = ToolChain\r | |
265 | self.WorkspaceDir = Workspace\r | |
266 | self.ActivePlatform = MetaFile\r | |
267 | self.ArchList = Arch\r | |
373298ca FB |
268 | self.AutoGenObjectList = []\r |
269 | @property\r | |
270 | def BuildDir(self):\r | |
271 | return self.AutoGenObjectList[0].BuildDir\r | |
e8449e1d | 272 | \r |
373298ca FB |
273 | @property\r |
274 | def Name(self):\r | |
275 | return self.AutoGenObjectList[0].Platform.PlatformName\r | |
276 | \r | |
277 | @property\r | |
278 | def FlashDefinition(self):\r | |
279 | return self.AutoGenObjectList[0].Platform.FlashDefinition\r | |
280 | @property\r | |
281 | def GenFdsCommandDict(self):\r | |
282 | FdsCommandDict = self.AutoGenObjectList[0].DataPipe.Get("FdsCommandDict")\r | |
283 | if FdsCommandDict:\r | |
284 | return FdsCommandDict\r | |
285 | return {}\r | |
286 | \r | |
287 | @cached_property\r | |
288 | def FvDir(self):\r | |
289 | return os.path.join(self.BuildDir, TAB_FV_DIRECTORY)\r | |
e8449e1d FB |
290 | \r |
291 | class PlatformInfo(AutoGenInfo):\r | |
292 | def __init__(self, Workspace, MetaFile, Target, ToolChain, Arch,DataPipe):\r | |
373298ca FB |
293 | if not hasattr(self, "_Init"):\r |
294 | self.do_init(Workspace, MetaFile, Target, ToolChain, Arch,DataPipe)\r | |
295 | self._Init = True\r | |
296 | def do_init(self,Workspace, MetaFile, Target, ToolChain, Arch,DataPipe):\r | |
e8449e1d FB |
297 | self.Wa = Workspace\r |
298 | self.WorkspaceDir = self.Wa.WorkspaceDir\r | |
299 | self.MetaFile = MetaFile\r | |
300 | self.Arch = Arch\r | |
301 | self.Target = Target\r | |
302 | self.BuildTarget = Target\r | |
303 | self.ToolChain = ToolChain\r | |
304 | self.Platform = self.Wa.BuildDatabase[self.MetaFile, self.Arch, self.Target, self.ToolChain]\r | |
305 | \r | |
306 | self.SourceDir = MetaFile.SubDir\r | |
307 | self.DataPipe = DataPipe\r | |
308 | @cached_property\r | |
309 | def _AsBuildModuleList(self):\r | |
310 | retVal = self.DataPipe.Get("AsBuildModuleList")\r | |
311 | if retVal is None:\r | |
312 | retVal = {}\r | |
313 | return retVal\r | |
314 | \r | |
315 | ## Test if a module is supported by the platform\r | |
316 | #\r | |
317 | # An error will be raised directly if the module or its arch is not supported\r | |
318 | # by the platform or current configuration\r | |
319 | #\r | |
320 | def ValidModule(self, Module):\r | |
321 | return Module in self.Platform.Modules or Module in self.Platform.LibraryInstances \\r | |
322 | or Module in self._AsBuildModuleList\r | |
323 | \r | |
324 | @cached_property\r | |
325 | def ToolChainFamily(self):\r | |
326 | retVal = self.DataPipe.Get("ToolChainFamily")\r | |
327 | if retVal is None:\r | |
328 | retVal = {}\r | |
329 | return retVal\r | |
330 | \r | |
331 | @cached_property\r | |
332 | def BuildRuleFamily(self):\r | |
333 | retVal = self.DataPipe.Get("BuildRuleFamily")\r | |
334 | if retVal is None:\r | |
335 | retVal = {}\r | |
336 | return retVal\r | |
337 | \r | |
338 | @cached_property\r | |
339 | def _MbList(self):\r | |
340 | return [self.Wa.BuildDatabase[m, self.Arch, self.BuildTarget, self.ToolChain] for m in self.Platform.Modules]\r | |
341 | \r | |
342 | @cached_property\r | |
343 | def PackageList(self):\r | |
344 | RetVal = set()\r | |
345 | for dec_file,Arch in self.DataPipe.Get("PackageList"):\r | |
346 | RetVal.add(self.Wa.BuildDatabase[dec_file,Arch,self.BuildTarget, self.ToolChain])\r | |
347 | return list(RetVal)\r | |
348 | \r | |
349 | ## Return the directory to store all intermediate and final files built\r | |
350 | @cached_property\r | |
351 | def BuildDir(self):\r | |
352 | if os.path.isabs(self.OutputDir):\r | |
353 | RetVal = os.path.join(\r | |
354 | os.path.abspath(self.OutputDir),\r | |
355 | self.Target + "_" + self.ToolChain,\r | |
356 | )\r | |
357 | else:\r | |
358 | RetVal = os.path.join(\r | |
359 | self.WorkspaceDir,\r | |
360 | self.OutputDir,\r | |
361 | self.Target + "_" + self.ToolChain,\r | |
362 | )\r | |
363 | return RetVal\r | |
364 | \r | |
365 | ## Return the build output directory platform specifies\r | |
366 | @cached_property\r | |
367 | def OutputDir(self):\r | |
368 | return self.Platform.OutputDirectory\r | |
369 | \r | |
370 | ## Return platform name\r | |
371 | @cached_property\r | |
372 | def Name(self):\r | |
373 | return self.Platform.PlatformName\r | |
374 | \r | |
375 | ## Return meta-file GUID\r | |
376 | @cached_property\r | |
377 | def Guid(self):\r | |
378 | return self.Platform.Guid\r | |
379 | \r | |
380 | ## Return platform version\r | |
381 | @cached_property\r | |
382 | def Version(self):\r | |
383 | return self.Platform.Version\r | |
384 | \r | |
385 | ## Return paths of tools\r | |
386 | @cached_property\r | |
387 | def ToolDefinition(self):\r | |
388 | retVal = self.DataPipe.Get("TOOLDEF")\r | |
389 | if retVal is None:\r | |
390 | retVal = {}\r | |
391 | return retVal\r | |
392 | \r | |
393 | ## Return build command string\r | |
394 | #\r | |
395 | # @retval string Build command string\r | |
396 | #\r | |
397 | @cached_property\r | |
398 | def BuildCommand(self):\r | |
399 | retVal = self.DataPipe.Get("BuildCommand")\r | |
400 | if retVal is None:\r | |
401 | retVal = []\r | |
402 | return retVal\r | |
403 | \r | |
404 | @cached_property\r | |
405 | def PcdTokenNumber(self):\r | |
406 | retVal = self.DataPipe.Get("PCD_TNUM")\r | |
407 | if retVal is None:\r | |
408 | retVal = {}\r | |
409 | return retVal\r | |
410 | \r | |
411 | ## Override PCD setting (type, value, ...)\r | |
412 | #\r | |
413 | # @param ToPcd The PCD to be overridden\r | |
414 | # @param FromPcd The PCD overriding from\r | |
415 | #\r | |
416 | def _OverridePcd(self, ToPcd, FromPcd, Module="", Msg="", Library=""):\r | |
417 | #\r | |
418 | # in case there's PCDs coming from FDF file, which have no type given.\r | |
419 | # at this point, ToPcd.Type has the type found from dependent\r | |
420 | # package\r | |
421 | #\r | |
422 | TokenCName = ToPcd.TokenCName\r | |
423 | for PcdItem in self.MixedPcd:\r | |
424 | if (ToPcd.TokenCName, ToPcd.TokenSpaceGuidCName) in self.MixedPcd[PcdItem]:\r | |
425 | TokenCName = PcdItem[0]\r | |
426 | break\r | |
427 | if FromPcd is not None:\r | |
428 | if ToPcd.Pending and FromPcd.Type:\r | |
429 | ToPcd.Type = FromPcd.Type\r | |
430 | elif ToPcd.Type and FromPcd.Type\\r | |
431 | and ToPcd.Type != FromPcd.Type and ToPcd.Type in FromPcd.Type:\r | |
432 | if ToPcd.Type.strip() == TAB_PCDS_DYNAMIC_EX:\r | |
433 | ToPcd.Type = FromPcd.Type\r | |
434 | elif ToPcd.Type and FromPcd.Type \\r | |
435 | and ToPcd.Type != FromPcd.Type:\r | |
436 | if Library:\r | |
437 | Module = str(Module) + " 's library file (" + str(Library) + ")"\r | |
438 | EdkLogger.error("build", OPTION_CONFLICT, "Mismatched PCD type",\r | |
439 | ExtraData="%s.%s is used as [%s] in module %s, but as [%s] in %s."\\r | |
440 | % (ToPcd.TokenSpaceGuidCName, TokenCName,\r | |
441 | ToPcd.Type, Module, FromPcd.Type, Msg),\r | |
442 | File=self.MetaFile)\r | |
443 | \r | |
444 | if FromPcd.MaxDatumSize:\r | |
445 | ToPcd.MaxDatumSize = FromPcd.MaxDatumSize\r | |
446 | ToPcd.MaxSizeUserSet = FromPcd.MaxDatumSize\r | |
447 | if FromPcd.DefaultValue:\r | |
448 | ToPcd.DefaultValue = FromPcd.DefaultValue\r | |
449 | if FromPcd.TokenValue:\r | |
450 | ToPcd.TokenValue = FromPcd.TokenValue\r | |
451 | if FromPcd.DatumType:\r | |
452 | ToPcd.DatumType = FromPcd.DatumType\r | |
453 | if FromPcd.SkuInfoList:\r | |
454 | ToPcd.SkuInfoList = FromPcd.SkuInfoList\r | |
455 | if FromPcd.UserDefinedDefaultStoresFlag:\r | |
456 | ToPcd.UserDefinedDefaultStoresFlag = FromPcd.UserDefinedDefaultStoresFlag\r | |
457 | # Add Flexible PCD format parse\r | |
458 | if ToPcd.DefaultValue:\r | |
459 | try:\r | |
460 | ToPcd.DefaultValue = ValueExpressionEx(ToPcd.DefaultValue, ToPcd.DatumType, self._GuidDict)(True)\r | |
461 | except BadExpression as Value:\r | |
462 | EdkLogger.error('Parser', FORMAT_INVALID, 'PCD [%s.%s] Value "%s", %s' %(ToPcd.TokenSpaceGuidCName, ToPcd.TokenCName, ToPcd.DefaultValue, Value),\r | |
463 | File=self.MetaFile)\r | |
464 | \r | |
465 | # check the validation of datum\r | |
466 | IsValid, Cause = CheckPcdDatum(ToPcd.DatumType, ToPcd.DefaultValue)\r | |
467 | if not IsValid:\r | |
468 | EdkLogger.error('build', FORMAT_INVALID, Cause, File=self.MetaFile,\r | |
469 | ExtraData="%s.%s" % (ToPcd.TokenSpaceGuidCName, TokenCName))\r | |
470 | ToPcd.validateranges = FromPcd.validateranges\r | |
471 | ToPcd.validlists = FromPcd.validlists\r | |
472 | ToPcd.expressions = FromPcd.expressions\r | |
473 | ToPcd.CustomAttribute = FromPcd.CustomAttribute\r | |
474 | \r | |
475 | if FromPcd is not None and ToPcd.DatumType == TAB_VOID and not ToPcd.MaxDatumSize:\r | |
476 | EdkLogger.debug(EdkLogger.DEBUG_9, "No MaxDatumSize specified for PCD %s.%s" \\r | |
477 | % (ToPcd.TokenSpaceGuidCName, TokenCName))\r | |
478 | Value = ToPcd.DefaultValue\r | |
479 | if not Value:\r | |
480 | ToPcd.MaxDatumSize = '1'\r | |
481 | elif Value[0] == 'L':\r | |
482 | ToPcd.MaxDatumSize = str((len(Value) - 2) * 2)\r | |
483 | elif Value[0] == '{':\r | |
484 | ToPcd.MaxDatumSize = str(len(Value.split(',')))\r | |
485 | else:\r | |
486 | ToPcd.MaxDatumSize = str(len(Value) - 1)\r | |
487 | \r | |
488 | # apply default SKU for dynamic PCDS if specified one is not available\r | |
489 | if (ToPcd.Type in PCD_DYNAMIC_TYPE_SET or ToPcd.Type in PCD_DYNAMIC_EX_TYPE_SET) \\r | |
490 | and not ToPcd.SkuInfoList:\r | |
491 | if self.Platform.SkuName in self.Platform.SkuIds:\r | |
492 | SkuName = self.Platform.SkuName\r | |
493 | else:\r | |
494 | SkuName = TAB_DEFAULT\r | |
495 | ToPcd.SkuInfoList = {\r | |
496 | SkuName : SkuInfoClass(SkuName, self.Platform.SkuIds[SkuName][0], '', '', '', '', '', ToPcd.DefaultValue)\r | |
497 | }\r | |
498 | \r | |
09af9bd9 | 499 | def ApplyPcdSetting(self, Ma, Pcds, Library=""):\r |
e8449e1d | 500 | # for each PCD in module\r |
09af9bd9 | 501 | Module=Ma.Module\r |
e8449e1d FB |
502 | for Name, Guid in Pcds:\r |
503 | PcdInModule = Pcds[Name, Guid]\r | |
504 | # find out the PCD setting in platform\r | |
505 | if (Name, Guid) in self.Pcds:\r | |
506 | PcdInPlatform = self.Pcds[Name, Guid]\r | |
507 | else:\r | |
508 | PcdInPlatform = None\r | |
509 | # then override the settings if any\r | |
510 | self._OverridePcd(PcdInModule, PcdInPlatform, Module, Msg="DSC PCD sections", Library=Library)\r | |
511 | # resolve the VariableGuid value\r | |
512 | for SkuId in PcdInModule.SkuInfoList:\r | |
513 | Sku = PcdInModule.SkuInfoList[SkuId]\r | |
514 | if Sku.VariableGuid == '': continue\r | |
515 | Sku.VariableGuidValue = GuidValue(Sku.VariableGuid, self.PackageList, self.MetaFile.Path)\r | |
516 | if Sku.VariableGuidValue is None:\r | |
517 | PackageList = "\n\t".join(str(P) for P in self.PackageList)\r | |
518 | EdkLogger.error(\r | |
519 | 'build',\r | |
520 | RESOURCE_NOT_AVAILABLE,\r | |
521 | "Value of GUID [%s] is not found in" % Sku.VariableGuid,\r | |
522 | ExtraData=PackageList + "\n\t(used with %s.%s from module %s)" \\r | |
523 | % (Guid, Name, str(Module)),\r | |
524 | File=self.MetaFile\r | |
525 | )\r | |
526 | \r | |
527 | # override PCD settings with module specific setting\r | |
09af9bd9 | 528 | ModuleScopePcds = self.DataPipe.Get("MOL_PCDS")\r |
e8449e1d FB |
529 | if Module in self.Platform.Modules:\r |
530 | PlatformModule = self.Platform.Modules[str(Module)]\r | |
09af9bd9 BF |
531 | PCD_DATA = ModuleScopePcds.get(Ma.Guid,{})\r |
532 | mPcds = {(pcd.TokenCName,pcd.TokenSpaceGuidCName): pcd for pcd in PCD_DATA}\r | |
533 | for Key in mPcds:\r | |
e8449e1d FB |
534 | if self.BuildOptionPcd:\r |
535 | for pcd in self.BuildOptionPcd:\r | |
536 | (TokenSpaceGuidCName, TokenCName, FieldName, pcdvalue, _) = pcd\r | |
537 | if (TokenCName, TokenSpaceGuidCName) == Key and FieldName =="":\r | |
538 | PlatformModule.Pcds[Key].DefaultValue = pcdvalue\r | |
539 | PlatformModule.Pcds[Key].PcdValueFromComm = pcdvalue\r | |
540 | break\r | |
541 | Flag = False\r | |
542 | if Key in Pcds:\r | |
543 | ToPcd = Pcds[Key]\r | |
544 | Flag = True\r | |
545 | elif Key in self.MixedPcd:\r | |
546 | for PcdItem in self.MixedPcd[Key]:\r | |
547 | if PcdItem in Pcds:\r | |
548 | ToPcd = Pcds[PcdItem]\r | |
549 | Flag = True\r | |
550 | break\r | |
551 | if Flag:\r | |
09af9bd9 | 552 | self._OverridePcd(ToPcd, mPcds[Key], Module, Msg="DSC Components Module scoped PCD section", Library=Library)\r |
e8449e1d FB |
553 | # use PCD value to calculate the MaxDatumSize when it is not specified\r |
554 | for Name, Guid in Pcds:\r | |
555 | Pcd = Pcds[Name, Guid]\r | |
556 | if Pcd.DatumType == TAB_VOID and not Pcd.MaxDatumSize:\r | |
557 | Pcd.MaxSizeUserSet = None\r | |
558 | Value = Pcd.DefaultValue\r | |
559 | if not Value:\r | |
560 | Pcd.MaxDatumSize = '1'\r | |
561 | elif Value[0] == 'L':\r | |
562 | Pcd.MaxDatumSize = str((len(Value) - 2) * 2)\r | |
563 | elif Value[0] == '{':\r | |
564 | Pcd.MaxDatumSize = str(len(Value.split(',')))\r | |
565 | else:\r | |
566 | Pcd.MaxDatumSize = str(len(Value) - 1)\r | |
567 | return list(Pcds.values())\r | |
568 | \r | |
569 | @cached_property\r | |
570 | def Pcds(self):\r | |
571 | PlatformPcdData = self.DataPipe.Get("PLA_PCD")\r | |
572 | # for pcd in PlatformPcdData:\r | |
573 | # for skuid in pcd.SkuInfoList:\r | |
574 | # pcd.SkuInfoList[skuid] = self.CreateSkuInfoFromDict(pcd.SkuInfoList[skuid])\r | |
575 | return {(pcddata.TokenCName,pcddata.TokenSpaceGuidCName):pcddata for pcddata in PlatformPcdData}\r | |
576 | \r | |
577 | def CreateSkuInfoFromDict(self,SkuInfoDict):\r | |
578 | return SkuInfoClass(\r | |
579 | SkuInfoDict.get("SkuIdName"),\r | |
580 | SkuInfoDict.get("SkuId"),\r | |
581 | SkuInfoDict.get("VariableName"),\r | |
582 | SkuInfoDict.get("VariableGuid"),\r | |
583 | SkuInfoDict.get("VariableOffset"),\r | |
584 | SkuInfoDict.get("HiiDefaultValue"),\r | |
585 | SkuInfoDict.get("VpdOffset"),\r | |
586 | SkuInfoDict.get("DefaultValue"),\r | |
587 | SkuInfoDict.get("VariableGuidValue"),\r | |
588 | SkuInfoDict.get("VariableAttribute",""),\r | |
589 | SkuInfoDict.get("DefaultStore",None)\r | |
590 | )\r | |
591 | @cached_property\r | |
592 | def MixedPcd(self):\r | |
593 | return self.DataPipe.Get("MixedPcd")\r | |
594 | @cached_property\r | |
595 | def _GuidDict(self):\r | |
596 | RetVal = self.DataPipe.Get("GuidDict")\r | |
597 | if RetVal is None:\r | |
598 | RetVal = {}\r | |
599 | return RetVal\r | |
600 | @cached_property\r | |
601 | def BuildOptionPcd(self):\r | |
602 | return self.DataPipe.Get("BuildOptPcd")\r | |
603 | def ApplyBuildOption(self,module):\r | |
604 | PlatformOptions = self.DataPipe.Get("PLA_BO")\r | |
605 | ModuleBuildOptions = self.DataPipe.Get("MOL_BO")\r | |
606 | ModuleOptionFromDsc = ModuleBuildOptions.get((module.MetaFile.File,module.MetaFile.Root))\r | |
607 | if ModuleOptionFromDsc:\r | |
608 | ModuleTypeOptions, PlatformModuleOptions = ModuleOptionFromDsc["ModuleTypeOptions"],ModuleOptionFromDsc["PlatformModuleOptions"]\r | |
609 | else:\r | |
610 | ModuleTypeOptions, PlatformModuleOptions = {}, {}\r | |
611 | ToolDefinition = self.DataPipe.Get("TOOLDEF")\r | |
612 | ModuleOptions = self._ExpandBuildOption(module.BuildOptions)\r | |
613 | BuildRuleOrder = None\r | |
614 | for Options in [ToolDefinition, ModuleOptions, PlatformOptions, ModuleTypeOptions, PlatformModuleOptions]:\r | |
615 | for Tool in Options:\r | |
616 | for Attr in Options[Tool]:\r | |
617 | if Attr == TAB_TOD_DEFINES_BUILDRULEORDER:\r | |
618 | BuildRuleOrder = Options[Tool][Attr]\r | |
619 | \r | |
620 | AllTools = set(list(ModuleOptions.keys()) + list(PlatformOptions.keys()) +\r | |
621 | list(PlatformModuleOptions.keys()) + list(ModuleTypeOptions.keys()) +\r | |
622 | list(ToolDefinition.keys()))\r | |
623 | BuildOptions = defaultdict(lambda: defaultdict(str))\r | |
624 | for Tool in AllTools:\r | |
625 | for Options in [ToolDefinition, ModuleOptions, PlatformOptions, ModuleTypeOptions, PlatformModuleOptions]:\r | |
626 | if Tool not in Options:\r | |
627 | continue\r | |
628 | for Attr in Options[Tool]:\r | |
629 | #\r | |
630 | # Do not generate it in Makefile\r | |
631 | #\r | |
632 | if Attr == TAB_TOD_DEFINES_BUILDRULEORDER:\r | |
633 | continue\r | |
634 | Value = Options[Tool][Attr]\r | |
8c8f49f0 MK |
635 | ToolList = [Tool]\r |
636 | if Tool == TAB_STAR:\r | |
637 | ToolList = list(AllTools)\r | |
638 | ToolList.remove(TAB_STAR)\r | |
639 | for ExpandedTool in ToolList:\r | |
640 | # check if override is indicated\r | |
641 | if Value.startswith('='):\r | |
642 | BuildOptions[ExpandedTool][Attr] = mws.handleWsMacro(Value[1:])\r | |
e8449e1d | 643 | else:\r |
8c8f49f0 MK |
644 | if Attr != 'PATH':\r |
645 | BuildOptions[ExpandedTool][Attr] += " " + mws.handleWsMacro(Value)\r | |
646 | else:\r | |
647 | BuildOptions[ExpandedTool][Attr] = mws.handleWsMacro(Value)\r | |
e8449e1d FB |
648 | \r |
649 | return BuildOptions, BuildRuleOrder\r | |
650 | \r | |
651 | def ApplyLibraryInstance(self,module):\r | |
652 | alldeps = self.DataPipe.Get("DEPS")\r | |
653 | if alldeps is None:\r | |
654 | alldeps = {}\r | |
655 | mod_libs = alldeps.get((module.MetaFile.File,module.MetaFile.Root,module.Arch,module.MetaFile.Path),[])\r | |
656 | retVal = []\r | |
657 | for (file_path,root,arch,abs_path) in mod_libs:\r | |
658 | libMetaFile = PathClass(file_path,root)\r | |
659 | libMetaFile.OriginalPath = PathClass(file_path,root)\r | |
660 | libMetaFile.Path = abs_path\r | |
661 | retVal.append(self.Wa.BuildDatabase[libMetaFile, arch, self.Target,self.ToolChain])\r | |
662 | return retVal\r | |
663 | \r | |
664 | ## Parse build_rule.txt in Conf Directory.\r | |
665 | #\r | |
666 | # @retval BuildRule object\r | |
667 | #\r | |
668 | @cached_property\r | |
669 | def BuildRule(self):\r | |
670 | WInfo = self.DataPipe.Get("P_Info")\r | |
671 | RetVal = WInfo.get("BuildRuleFile")\r | |
672 | if RetVal._FileVersion == "":\r | |
673 | RetVal._FileVersion = AutoGenReqBuildRuleVerNum\r | |
674 | return RetVal\r |