]>
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 | |
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 | |
262 | class 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 |
299 | class 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 |