]> git.proxmox.com Git - mirror_edk2.git/blame - BaseTools/Source/Python/AutoGen/WorkspaceAutoGen.py
MdeModulePkg/NvmExpressDxe: Fix wrong queue size for async IO queues
[mirror_edk2.git] / BaseTools / Source / Python / AutoGen / WorkspaceAutoGen.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 hashlib\r
14from collections import defaultdict\r
15from GenFds.FdfParser import FdfParser\r
16from Workspace.WorkspaceCommon import GetModuleLibInstances\r
17from AutoGen import GenMake\r
18from AutoGen.AutoGen import AutoGen\r
19from AutoGen.PlatformAutoGen import PlatformAutoGen\r
20from AutoGen.BuildEngine import gDefaultBuildRuleFile\r
21from Common.ToolDefClassObject import gDefaultToolsDefFile\r
22from Common.StringUtils import NormPath\r
23from Common.BuildToolError import *\r
24from Common.DataType import *\r
25from Common.Misc import *\r
26\r
27## Regular expression for splitting Dependency Expression string into tokens\r
28gDepexTokenPattern = re.compile("(\(|\)|\w+| \S+\.inf)")\r
29\r
30## Regular expression for match: PCD(xxxx.yyy)\r
31gPCDAsGuidPattern = re.compile(r"^PCD\(.+\..+\)$")\r
32\r
33## Workspace AutoGen class\r
34#\r
35# This class is used mainly to control the whole platform build for different\r
36# architecture. This class will generate top level makefile.\r
37#\r
38class WorkspaceAutoGen(AutoGen):\r
39 # call super().__init__ then call the worker function with different parameter count\r
40 def __init__(self, Workspace, MetaFile, Target, Toolchain, Arch, *args, **kwargs):\r
41 if not hasattr(self, "_Init"):\r
42 self._InitWorker(Workspace, MetaFile, Target, Toolchain, Arch, *args, **kwargs)\r
43 self._Init = True\r
44\r
45 ## Initialize WorkspaceAutoGen\r
46 #\r
47 # @param WorkspaceDir Root directory of workspace\r
48 # @param ActivePlatform Meta-file of active platform\r
49 # @param Target Build target\r
50 # @param Toolchain Tool chain name\r
51 # @param ArchList List of architecture of current build\r
52 # @param MetaFileDb Database containing meta-files\r
53 # @param BuildConfig Configuration of build\r
54 # @param ToolDefinition Tool chain definitions\r
55 # @param FlashDefinitionFile File of flash definition\r
56 # @param Fds FD list to be generated\r
57 # @param Fvs FV list to be generated\r
58 # @param Caps Capsule list to be generated\r
59 # @param SkuId SKU id from command line\r
60 #\r
61 def _InitWorker(self, WorkspaceDir, ActivePlatform, Target, Toolchain, ArchList, MetaFileDb,\r
62 BuildConfig, ToolDefinition, FlashDefinitionFile='', Fds=None, Fvs=None, Caps=None, SkuId='', UniFlag=None,\r
63 Progress=None, BuildModule=None):\r
64 self.BuildDatabase = MetaFileDb\r
65 self.MetaFile = ActivePlatform\r
66 self.WorkspaceDir = WorkspaceDir\r
67 self.Platform = self.BuildDatabase[self.MetaFile, TAB_ARCH_COMMON, Target, Toolchain]\r
68 GlobalData.gActivePlatform = self.Platform\r
69 self.BuildTarget = Target\r
70 self.ToolChain = Toolchain\r
71 self.ArchList = ArchList\r
72 self.SkuId = SkuId\r
73 self.UniFlag = UniFlag\r
74\r
75 self.TargetTxt = BuildConfig\r
76 self.ToolDef = ToolDefinition\r
77 self.FdfFile = FlashDefinitionFile\r
78 self.FdTargetList = Fds if Fds else []\r
79 self.FvTargetList = Fvs if Fvs else []\r
80 self.CapTargetList = Caps if Caps else []\r
81 self.AutoGenObjectList = []\r
82 self._GuidDict = {}\r
83\r
84 # there's many relative directory operations, so ...\r
85 os.chdir(self.WorkspaceDir)\r
86\r
87 self.MergeArch()\r
88 self.ValidateBuildTarget()\r
89\r
90 EdkLogger.info("")\r
91 if self.ArchList:\r
92 EdkLogger.info('%-16s = %s' % ("Architecture(s)", ' '.join(self.ArchList)))\r
93 EdkLogger.info('%-16s = %s' % ("Build target", self.BuildTarget))\r
94 EdkLogger.info('%-16s = %s' % ("Toolchain", self.ToolChain))\r
95\r
96 EdkLogger.info('\n%-24s = %s' % ("Active Platform", self.Platform))\r
97 if BuildModule:\r
98 EdkLogger.info('%-24s = %s' % ("Active Module", BuildModule))\r
99\r
100 if self.FdfFile:\r
101 EdkLogger.info('%-24s = %s' % ("Flash Image Definition", self.FdfFile))\r
102\r
103 EdkLogger.verbose("\nFLASH_DEFINITION = %s" % self.FdfFile)\r
104\r
105 if Progress:\r
106 Progress.Start("\nProcessing meta-data")\r
107 #\r
108 # Mark now build in AutoGen Phase\r
109 #\r
110 GlobalData.gAutoGenPhase = True\r
111 self.ProcessModuleFromPdf()\r
112 self.ProcessPcdType()\r
113 self.ProcessMixedPcd()\r
114 self.VerifyPcdsFromFDF()\r
115 self.CollectAllPcds()\r
673d09a2
FB
116 for Pa in self.AutoGenObjectList:\r
117 Pa.FillData_LibConstPcd()\r
e8449e1d
FB
118 self.GeneratePkgLevelHash()\r
119 #\r
120 # Check PCDs token value conflict in each DEC file.\r
121 #\r
122 self._CheckAllPcdsTokenValueConflict()\r
123 #\r
124 # Check PCD type and definition between DSC and DEC\r
125 #\r
126 self._CheckPcdDefineAndType()\r
127\r
128 self.CreateBuildOptionsFile()\r
129 self.CreatePcdTokenNumberFile()\r
130 self.CreateModuleHashInfo()\r
e8449e1d
FB
131\r
132 #\r
133 # Merge Arch\r
134 #\r
135 def MergeArch(self):\r
136 if not self.ArchList:\r
137 ArchList = set(self.Platform.SupArchList)\r
138 else:\r
139 ArchList = set(self.ArchList) & set(self.Platform.SupArchList)\r
140 if not ArchList:\r
141 EdkLogger.error("build", PARAMETER_INVALID,\r
142 ExtraData = "Invalid ARCH specified. [Valid ARCH: %s]" % (" ".join(self.Platform.SupArchList)))\r
143 elif self.ArchList and len(ArchList) != len(self.ArchList):\r
144 SkippedArchList = set(self.ArchList).symmetric_difference(set(self.Platform.SupArchList))\r
145 EdkLogger.verbose("\nArch [%s] is ignored because the platform supports [%s] only!"\r
146 % (" ".join(SkippedArchList), " ".join(self.Platform.SupArchList)))\r
147 self.ArchList = tuple(ArchList)\r
148\r
149 # Validate build target\r
150 def ValidateBuildTarget(self):\r
151 if self.BuildTarget not in self.Platform.BuildTargets:\r
152 EdkLogger.error("build", PARAMETER_INVALID,\r
153 ExtraData="Build target [%s] is not supported by the platform. [Valid target: %s]"\r
154 % (self.BuildTarget, " ".join(self.Platform.BuildTargets)))\r
155 @cached_property\r
156 def FdfProfile(self):\r
157 if not self.FdfFile:\r
158 self.FdfFile = self.Platform.FlashDefinition\r
159\r
160 FdfProfile = None\r
161 if self.FdfFile:\r
162 Fdf = FdfParser(self.FdfFile.Path)\r
163 Fdf.ParseFile()\r
164 GlobalData.gFdfParser = Fdf\r
165 if Fdf.CurrentFdName and Fdf.CurrentFdName in Fdf.Profile.FdDict:\r
166 FdDict = Fdf.Profile.FdDict[Fdf.CurrentFdName]\r
167 for FdRegion in FdDict.RegionList:\r
168 if str(FdRegion.RegionType) is 'FILE' and self.Platform.VpdToolGuid in str(FdRegion.RegionDataList):\r
169 if int(FdRegion.Offset) % 8 != 0:\r
170 EdkLogger.error("build", FORMAT_INVALID, 'The VPD Base Address %s must be 8-byte aligned.' % (FdRegion.Offset))\r
171 FdfProfile = Fdf.Profile\r
172 else:\r
173 if self.FdTargetList:\r
174 EdkLogger.info("No flash definition file found. FD [%s] will be ignored." % " ".join(self.FdTargetList))\r
175 self.FdTargetList = []\r
176 if self.FvTargetList:\r
177 EdkLogger.info("No flash definition file found. FV [%s] will be ignored." % " ".join(self.FvTargetList))\r
178 self.FvTargetList = []\r
179 if self.CapTargetList:\r
180 EdkLogger.info("No flash definition file found. Capsule [%s] will be ignored." % " ".join(self.CapTargetList))\r
181 self.CapTargetList = []\r
182\r
183 return FdfProfile\r
184\r
185 def ProcessModuleFromPdf(self):\r
186\r
187 if self.FdfProfile:\r
188 for fvname in self.FvTargetList:\r
189 if fvname.upper() not in self.FdfProfile.FvDict:\r
190 EdkLogger.error("build", OPTION_VALUE_INVALID,\r
191 "No such an FV in FDF file: %s" % fvname)\r
192\r
193 # In DSC file may use FILE_GUID to override the module, then in the Platform.Modules use FILE_GUIDmodule.inf as key,\r
194 # but the path (self.MetaFile.Path) is the real path\r
195 for key in self.FdfProfile.InfDict:\r
196 if key == 'ArchTBD':\r
197 MetaFile_cache = defaultdict(set)\r
198 for Arch in self.ArchList:\r
199 Current_Platform_cache = self.BuildDatabase[self.MetaFile, Arch, self.BuildTarget, self.ToolChain]\r
200 for Pkey in Current_Platform_cache.Modules:\r
201 MetaFile_cache[Arch].add(Current_Platform_cache.Modules[Pkey].MetaFile)\r
202 for Inf in self.FdfProfile.InfDict[key]:\r
203 ModuleFile = PathClass(NormPath(Inf), GlobalData.gWorkspace, Arch)\r
204 for Arch in self.ArchList:\r
205 if ModuleFile in MetaFile_cache[Arch]:\r
206 break\r
207 else:\r
208 ModuleData = self.BuildDatabase[ModuleFile, Arch, self.BuildTarget, self.ToolChain]\r
209 if not ModuleData.IsBinaryModule:\r
210 EdkLogger.error('build', PARSER_ERROR, "Module %s NOT found in DSC file; Is it really a binary module?" % ModuleFile)\r
211\r
212 else:\r
213 for Arch in self.ArchList:\r
214 if Arch == key:\r
215 Platform = self.BuildDatabase[self.MetaFile, Arch, self.BuildTarget, self.ToolChain]\r
216 MetaFileList = set()\r
217 for Pkey in Platform.Modules:\r
218 MetaFileList.add(Platform.Modules[Pkey].MetaFile)\r
219 for Inf in self.FdfProfile.InfDict[key]:\r
220 ModuleFile = PathClass(NormPath(Inf), GlobalData.gWorkspace, Arch)\r
221 if ModuleFile in MetaFileList:\r
222 continue\r
223 ModuleData = self.BuildDatabase[ModuleFile, Arch, self.BuildTarget, self.ToolChain]\r
224 if not ModuleData.IsBinaryModule:\r
225 EdkLogger.error('build', PARSER_ERROR, "Module %s NOT found in DSC file; Is it really a binary module?" % ModuleFile)\r
226\r
227\r
228\r
229 # parse FDF file to get PCDs in it, if any\r
230 def VerifyPcdsFromFDF(self):\r
231\r
232 if self.FdfProfile:\r
233 PcdSet = self.FdfProfile.PcdDict\r
234 self.VerifyPcdDeclearation(PcdSet)\r
235\r
236 def ProcessPcdType(self):\r
237 for Arch in self.ArchList:\r
238 Platform = self.BuildDatabase[self.MetaFile, Arch, self.BuildTarget, self.ToolChain]\r
239 Platform.Pcds\r
240 # generate the SourcePcdDict and BinaryPcdDict\r
241 Libs = []\r
242 for BuildData in list(self.BuildDatabase._CACHE_.values()):\r
243 if BuildData.Arch != Arch:\r
244 continue\r
245 if BuildData.MetaFile.Ext == '.inf' and str(BuildData) in Platform.Modules :\r
246 Libs.extend(GetModuleLibInstances(BuildData, Platform,\r
247 self.BuildDatabase,\r
248 Arch,\r
249 self.BuildTarget,\r
abc0155b
FB
250 self.ToolChain,\r
251 self.Platform.MetaFile,\r
252 EdkLogger\r
e8449e1d
FB
253 ))\r
254 for BuildData in list(self.BuildDatabase._CACHE_.values()):\r
255 if BuildData.Arch != Arch:\r
256 continue\r
257 if BuildData.MetaFile.Ext == '.inf':\r
258 for key in BuildData.Pcds:\r
259 if BuildData.Pcds[key].Pending:\r
260 if key in Platform.Pcds:\r
261 PcdInPlatform = Platform.Pcds[key]\r
262 if PcdInPlatform.Type:\r
263 BuildData.Pcds[key].Type = PcdInPlatform.Type\r
264 BuildData.Pcds[key].Pending = False\r
265\r
266 if BuildData.MetaFile in Platform.Modules:\r
267 PlatformModule = Platform.Modules[str(BuildData.MetaFile)]\r
268 if key in PlatformModule.Pcds:\r
269 PcdInPlatform = PlatformModule.Pcds[key]\r
270 if PcdInPlatform.Type:\r
271 BuildData.Pcds[key].Type = PcdInPlatform.Type\r
272 BuildData.Pcds[key].Pending = False\r
273 else:\r
274 #Pcd used in Library, Pcd Type from reference module if Pcd Type is Pending\r
275 if BuildData.Pcds[key].Pending:\r
276 if bool(BuildData.LibraryClass):\r
277 if BuildData in set(Libs):\r
278 ReferenceModules = BuildData.ReferenceModules\r
279 for ReferenceModule in ReferenceModules:\r
280 if ReferenceModule.MetaFile in Platform.Modules:\r
281 RefPlatformModule = Platform.Modules[str(ReferenceModule.MetaFile)]\r
282 if key in RefPlatformModule.Pcds:\r
283 PcdInReferenceModule = RefPlatformModule.Pcds[key]\r
284 if PcdInReferenceModule.Type:\r
285 BuildData.Pcds[key].Type = PcdInReferenceModule.Type\r
286 BuildData.Pcds[key].Pending = False\r
287 break\r
288\r
289 def ProcessMixedPcd(self):\r
290 for Arch in self.ArchList:\r
291 SourcePcdDict = {TAB_PCDS_DYNAMIC_EX:set(), TAB_PCDS_PATCHABLE_IN_MODULE:set(),TAB_PCDS_DYNAMIC:set(),TAB_PCDS_FIXED_AT_BUILD:set()}\r
292 BinaryPcdDict = {TAB_PCDS_DYNAMIC_EX:set(), TAB_PCDS_PATCHABLE_IN_MODULE:set()}\r
293 SourcePcdDict_Keys = SourcePcdDict.keys()\r
294 BinaryPcdDict_Keys = BinaryPcdDict.keys()\r
295\r
296 # generate the SourcePcdDict and BinaryPcdDict\r
297\r
298 for BuildData in list(self.BuildDatabase._CACHE_.values()):\r
299 if BuildData.Arch != Arch:\r
300 continue\r
301 if BuildData.MetaFile.Ext == '.inf':\r
302 for key in BuildData.Pcds:\r
303 if TAB_PCDS_DYNAMIC_EX in BuildData.Pcds[key].Type:\r
304 if BuildData.IsBinaryModule:\r
305 BinaryPcdDict[TAB_PCDS_DYNAMIC_EX].add((BuildData.Pcds[key].TokenCName, BuildData.Pcds[key].TokenSpaceGuidCName))\r
306 else:\r
307 SourcePcdDict[TAB_PCDS_DYNAMIC_EX].add((BuildData.Pcds[key].TokenCName, BuildData.Pcds[key].TokenSpaceGuidCName))\r
308\r
309 elif TAB_PCDS_PATCHABLE_IN_MODULE in BuildData.Pcds[key].Type:\r
310 if BuildData.MetaFile.Ext == '.inf':\r
311 if BuildData.IsBinaryModule:\r
312 BinaryPcdDict[TAB_PCDS_PATCHABLE_IN_MODULE].add((BuildData.Pcds[key].TokenCName, BuildData.Pcds[key].TokenSpaceGuidCName))\r
313 else:\r
314 SourcePcdDict[TAB_PCDS_PATCHABLE_IN_MODULE].add((BuildData.Pcds[key].TokenCName, BuildData.Pcds[key].TokenSpaceGuidCName))\r
315\r
316 elif TAB_PCDS_DYNAMIC in BuildData.Pcds[key].Type:\r
317 SourcePcdDict[TAB_PCDS_DYNAMIC].add((BuildData.Pcds[key].TokenCName, BuildData.Pcds[key].TokenSpaceGuidCName))\r
318 elif TAB_PCDS_FIXED_AT_BUILD in BuildData.Pcds[key].Type:\r
319 SourcePcdDict[TAB_PCDS_FIXED_AT_BUILD].add((BuildData.Pcds[key].TokenCName, BuildData.Pcds[key].TokenSpaceGuidCName))\r
320\r
321 #\r
322 # A PCD can only use one type for all source modules\r
323 #\r
324 for i in SourcePcdDict_Keys:\r
325 for j in SourcePcdDict_Keys:\r
326 if i != j:\r
327 Intersections = SourcePcdDict[i].intersection(SourcePcdDict[j])\r
328 if len(Intersections) > 0:\r
329 EdkLogger.error(\r
330 'build',\r
331 FORMAT_INVALID,\r
332 "Building modules from source INFs, following PCD use %s and %s access method. It must be corrected to use only one access method." % (i, j),\r
333 ExtraData='\n\t'.join(str(P[1]+'.'+P[0]) for P in Intersections)\r
334 )\r
335\r
336 #\r
337 # intersection the BinaryPCD for Mixed PCD\r
338 #\r
339 for i in BinaryPcdDict_Keys:\r
340 for j in BinaryPcdDict_Keys:\r
341 if i != j:\r
342 Intersections = BinaryPcdDict[i].intersection(BinaryPcdDict[j])\r
343 for item in Intersections:\r
344 NewPcd1 = (item[0] + '_' + i, item[1])\r
345 NewPcd2 = (item[0] + '_' + j, item[1])\r
346 if item not in GlobalData.MixedPcd:\r
347 GlobalData.MixedPcd[item] = [NewPcd1, NewPcd2]\r
348 else:\r
349 if NewPcd1 not in GlobalData.MixedPcd[item]:\r
350 GlobalData.MixedPcd[item].append(NewPcd1)\r
351 if NewPcd2 not in GlobalData.MixedPcd[item]:\r
352 GlobalData.MixedPcd[item].append(NewPcd2)\r
353\r
354 #\r
355 # intersection the SourcePCD and BinaryPCD for Mixed PCD\r
356 #\r
357 for i in SourcePcdDict_Keys:\r
358 for j in BinaryPcdDict_Keys:\r
359 if i != j:\r
360 Intersections = SourcePcdDict[i].intersection(BinaryPcdDict[j])\r
361 for item in Intersections:\r
362 NewPcd1 = (item[0] + '_' + i, item[1])\r
363 NewPcd2 = (item[0] + '_' + j, item[1])\r
364 if item not in GlobalData.MixedPcd:\r
365 GlobalData.MixedPcd[item] = [NewPcd1, NewPcd2]\r
366 else:\r
367 if NewPcd1 not in GlobalData.MixedPcd[item]:\r
368 GlobalData.MixedPcd[item].append(NewPcd1)\r
369 if NewPcd2 not in GlobalData.MixedPcd[item]:\r
370 GlobalData.MixedPcd[item].append(NewPcd2)\r
371\r
372 BuildData = self.BuildDatabase[self.MetaFile, Arch, self.BuildTarget, self.ToolChain]\r
373 for key in BuildData.Pcds:\r
374 for SinglePcd in GlobalData.MixedPcd:\r
375 if (BuildData.Pcds[key].TokenCName, BuildData.Pcds[key].TokenSpaceGuidCName) == SinglePcd:\r
376 for item in GlobalData.MixedPcd[SinglePcd]:\r
377 Pcd_Type = item[0].split('_')[-1]\r
378 if (Pcd_Type == BuildData.Pcds[key].Type) or (Pcd_Type == TAB_PCDS_DYNAMIC_EX and BuildData.Pcds[key].Type in PCD_DYNAMIC_EX_TYPE_SET) or \\r
379 (Pcd_Type == TAB_PCDS_DYNAMIC and BuildData.Pcds[key].Type in PCD_DYNAMIC_TYPE_SET):\r
380 Value = BuildData.Pcds[key]\r
381 Value.TokenCName = BuildData.Pcds[key].TokenCName + '_' + Pcd_Type\r
382 if len(key) == 2:\r
383 newkey = (Value.TokenCName, key[1])\r
384 elif len(key) == 3:\r
385 newkey = (Value.TokenCName, key[1], key[2])\r
386 del BuildData.Pcds[key]\r
387 BuildData.Pcds[newkey] = Value\r
388 break\r
389 break\r
390\r
391 if self.FdfProfile:\r
392 PcdSet = self.FdfProfile.PcdDict\r
393 # handle the mixed pcd in FDF file\r
394 for key in PcdSet:\r
395 if key in GlobalData.MixedPcd:\r
396 Value = PcdSet[key]\r
397 del PcdSet[key]\r
398 for item in GlobalData.MixedPcd[key]:\r
399 PcdSet[item] = Value\r
400\r
401 #Collect package set information from INF of FDF\r
402 @cached_property\r
403 def PkgSet(self):\r
404 if not self.FdfFile:\r
405 self.FdfFile = self.Platform.FlashDefinition\r
406\r
407 if self.FdfFile:\r
408 ModuleList = self.FdfProfile.InfList\r
409 else:\r
410 ModuleList = []\r
411 Pkgs = {}\r
412 for Arch in self.ArchList:\r
413 Platform = self.BuildDatabase[self.MetaFile, Arch, self.BuildTarget, self.ToolChain]\r
414 PkgSet = set()\r
415 for mb in [self.BuildDatabase[m, Arch, self.BuildTarget, self.ToolChain] for m in Platform.Modules]:\r
416 PkgSet.update(mb.Packages)\r
417 for Inf in ModuleList:\r
418 ModuleFile = PathClass(NormPath(Inf), GlobalData.gWorkspace, Arch)\r
419 if ModuleFile in Platform.Modules:\r
420 continue\r
421 ModuleData = self.BuildDatabase[ModuleFile, Arch, self.BuildTarget, self.ToolChain]\r
422 PkgSet.update(ModuleData.Packages)\r
423 Pkgs[Arch] = list(PkgSet)\r
424 return Pkgs\r
425\r
426 def VerifyPcdDeclearation(self,PcdSet):\r
427 for Arch in self.ArchList:\r
428 Platform = self.BuildDatabase[self.MetaFile, Arch, self.BuildTarget, self.ToolChain]\r
429 Pkgs = self.PkgSet[Arch]\r
430 DecPcds = set()\r
431 DecPcdsKey = set()\r
432 for Pkg in Pkgs:\r
433 for Pcd in Pkg.Pcds:\r
434 DecPcds.add((Pcd[0], Pcd[1]))\r
435 DecPcdsKey.add((Pcd[0], Pcd[1], Pcd[2]))\r
436\r
437 Platform.SkuName = self.SkuId\r
438 for Name, Guid,Fileds in PcdSet:\r
439 if (Name, Guid) not in DecPcds:\r
440 EdkLogger.error(\r
441 'build',\r
442 PARSER_ERROR,\r
443 "PCD (%s.%s) used in FDF is not declared in DEC files." % (Guid, Name),\r
444 File = self.FdfProfile.PcdFileLineDict[Name, Guid, Fileds][0],\r
445 Line = self.FdfProfile.PcdFileLineDict[Name, Guid, Fileds][1]\r
446 )\r
447 else:\r
448 # Check whether Dynamic or DynamicEx PCD used in FDF file. If used, build break and give a error message.\r
449 if (Name, Guid, TAB_PCDS_FIXED_AT_BUILD) in DecPcdsKey \\r
450 or (Name, Guid, TAB_PCDS_PATCHABLE_IN_MODULE) in DecPcdsKey \\r
451 or (Name, Guid, TAB_PCDS_FEATURE_FLAG) in DecPcdsKey:\r
452 continue\r
453 elif (Name, Guid, TAB_PCDS_DYNAMIC) in DecPcdsKey or (Name, Guid, TAB_PCDS_DYNAMIC_EX) in DecPcdsKey:\r
454 EdkLogger.error(\r
455 'build',\r
456 PARSER_ERROR,\r
457 "Using Dynamic or DynamicEx type of PCD [%s.%s] in FDF file is not allowed." % (Guid, Name),\r
458 File = self.FdfProfile.PcdFileLineDict[Name, Guid, Fileds][0],\r
459 Line = self.FdfProfile.PcdFileLineDict[Name, Guid, Fileds][1]\r
460 )\r
461 def CollectAllPcds(self):\r
462\r
463 for Arch in self.ArchList:\r
464 Pa = PlatformAutoGen(self, self.MetaFile, self.BuildTarget, self.ToolChain, Arch)\r
465 #\r
466 # Explicitly collect platform's dynamic PCDs\r
467 #\r
468 Pa.CollectPlatformDynamicPcds()\r
469 Pa.CollectFixedAtBuildPcds()\r
470 self.AutoGenObjectList.append(Pa)\r
471 # We need to calculate the PcdTokenNumber after all Arch Pcds are collected.\r
472 for Arch in self.ArchList:\r
473 #Pcd TokenNumber\r
474 Pa = PlatformAutoGen(self, self.MetaFile, self.BuildTarget, self.ToolChain, Arch)\r
475 self.UpdateModuleDataPipe(Arch, {"PCD_TNUM":Pa.PcdTokenNumber})\r
476\r
477 def UpdateModuleDataPipe(self,arch, attr_dict):\r
478 for (Target, Toolchain, Arch, MetaFile) in AutoGen.Cache():\r
479 if Arch != arch:\r
480 continue\r
481 try:\r
482 AutoGen.Cache()[(Target, Toolchain, Arch, MetaFile)].DataPipe.DataContainer = attr_dict\r
483 except Exception:\r
484 pass\r
485 #\r
486 # Generate Package level hash value\r
487 #\r
488 def GeneratePkgLevelHash(self):\r
489 for Arch in self.ArchList:\r
490 GlobalData.gPackageHash = {}\r
491 if GlobalData.gUseHashCache:\r
492 for Pkg in self.PkgSet[Arch]:\r
493 self._GenPkgLevelHash(Pkg)\r
494\r
495\r
496 def CreateBuildOptionsFile(self):\r
497 #\r
498 # Create BuildOptions Macro & PCD metafile, also add the Active Platform and FDF file.\r
499 #\r
500 content = 'gCommandLineDefines: '\r
501 content += str(GlobalData.gCommandLineDefines)\r
502 content += TAB_LINE_BREAK\r
503 content += 'BuildOptionPcd: '\r
504 content += str(GlobalData.BuildOptionPcd)\r
505 content += TAB_LINE_BREAK\r
506 content += 'Active Platform: '\r
507 content += str(self.Platform)\r
508 content += TAB_LINE_BREAK\r
509 if self.FdfFile:\r
510 content += 'Flash Image Definition: '\r
511 content += str(self.FdfFile)\r
512 content += TAB_LINE_BREAK\r
513 SaveFileOnChange(os.path.join(self.BuildDir, 'BuildOptions'), content, False)\r
514\r
515 def CreatePcdTokenNumberFile(self):\r
516 #\r
517 # Create PcdToken Number file for Dynamic/DynamicEx Pcd.\r
518 #\r
519 PcdTokenNumber = 'PcdTokenNumber: '\r
520 Pa = self.AutoGenObjectList[0]\r
521 if Pa.PcdTokenNumber:\r
522 if Pa.DynamicPcdList:\r
523 for Pcd in Pa.DynamicPcdList:\r
524 PcdTokenNumber += TAB_LINE_BREAK\r
525 PcdTokenNumber += str((Pcd.TokenCName, Pcd.TokenSpaceGuidCName))\r
526 PcdTokenNumber += ' : '\r
527 PcdTokenNumber += str(Pa.PcdTokenNumber[Pcd.TokenCName, Pcd.TokenSpaceGuidCName])\r
528 SaveFileOnChange(os.path.join(self.BuildDir, 'PcdTokenNumber'), PcdTokenNumber, False)\r
529\r
530 def CreateModuleHashInfo(self):\r
531 #\r
532 # Get set of workspace metafiles\r
533 #\r
534 AllWorkSpaceMetaFiles = self._GetMetaFiles(self.BuildTarget, self.ToolChain)\r
535\r
536 #\r
537 # Retrieve latest modified time of all metafiles\r
538 #\r
539 SrcTimeStamp = 0\r
540 for f in AllWorkSpaceMetaFiles:\r
541 if os.stat(f)[8] > SrcTimeStamp:\r
542 SrcTimeStamp = os.stat(f)[8]\r
543 self._SrcTimeStamp = SrcTimeStamp\r
544\r
545 if GlobalData.gUseHashCache:\r
546 m = hashlib.md5()\r
547 for files in AllWorkSpaceMetaFiles:\r
548 if files.endswith('.dec'):\r
549 continue\r
550 f = open(files, 'rb')\r
551 Content = f.read()\r
552 f.close()\r
553 m.update(Content)\r
554 SaveFileOnChange(os.path.join(self.BuildDir, 'AutoGen.hash'), m.hexdigest(), False)\r
555 GlobalData.gPlatformHash = m.hexdigest()\r
556\r
557 #\r
558 # Write metafile list to build directory\r
559 #\r
560 AutoGenFilePath = os.path.join(self.BuildDir, 'AutoGen')\r
561 if os.path.exists (AutoGenFilePath):\r
562 os.remove(AutoGenFilePath)\r
563 if not os.path.exists(self.BuildDir):\r
564 os.makedirs(self.BuildDir)\r
565 with open(os.path.join(self.BuildDir, 'AutoGen'), 'w+') as file:\r
566 for f in AllWorkSpaceMetaFiles:\r
567 print(f, file=file)\r
568 return True\r
569\r
570 def _GenPkgLevelHash(self, Pkg):\r
571 if Pkg.PackageName in GlobalData.gPackageHash:\r
572 return\r
573\r
574 PkgDir = os.path.join(self.BuildDir, Pkg.Arch, Pkg.PackageName)\r
575 CreateDirectory(PkgDir)\r
576 HashFile = os.path.join(PkgDir, Pkg.PackageName + '.hash')\r
577 m = hashlib.md5()\r
578 # Get .dec file's hash value\r
579 f = open(Pkg.MetaFile.Path, 'rb')\r
580 Content = f.read()\r
581 f.close()\r
582 m.update(Content)\r
583 # Get include files hash value\r
584 if Pkg.Includes:\r
585 for inc in sorted(Pkg.Includes, key=lambda x: str(x)):\r
586 for Root, Dirs, Files in os.walk(str(inc)):\r
587 for File in sorted(Files):\r
588 File_Path = os.path.join(Root, File)\r
589 f = open(File_Path, 'rb')\r
590 Content = f.read()\r
591 f.close()\r
592 m.update(Content)\r
593 SaveFileOnChange(HashFile, m.hexdigest(), False)\r
594 GlobalData.gPackageHash[Pkg.PackageName] = m.hexdigest()\r
595\r
596 def _GetMetaFiles(self, Target, Toolchain):\r
597 AllWorkSpaceMetaFiles = set()\r
598 #\r
599 # add fdf\r
600 #\r
601 if self.FdfFile:\r
602 AllWorkSpaceMetaFiles.add (self.FdfFile.Path)\r
603 for f in GlobalData.gFdfParser.GetAllIncludedFile():\r
604 AllWorkSpaceMetaFiles.add (f.FileName)\r
605 #\r
606 # add dsc\r
607 #\r
608 AllWorkSpaceMetaFiles.add(self.MetaFile.Path)\r
609\r
610 #\r
611 # add build_rule.txt & tools_def.txt\r
612 #\r
613 AllWorkSpaceMetaFiles.add(os.path.join(GlobalData.gConfDirectory, gDefaultBuildRuleFile))\r
614 AllWorkSpaceMetaFiles.add(os.path.join(GlobalData.gConfDirectory, gDefaultToolsDefFile))\r
615\r
616 # add BuildOption metafile\r
617 #\r
618 AllWorkSpaceMetaFiles.add(os.path.join(self.BuildDir, 'BuildOptions'))\r
619\r
620 # add PcdToken Number file for Dynamic/DynamicEx Pcd\r
621 #\r
622 AllWorkSpaceMetaFiles.add(os.path.join(self.BuildDir, 'PcdTokenNumber'))\r
623\r
624 for Pa in self.AutoGenObjectList:\r
625 AllWorkSpaceMetaFiles.add(Pa.ToolDefinitionFile)\r
626\r
627 for Arch in self.ArchList:\r
628 #\r
629 # add dec\r
630 #\r
631 for Package in PlatformAutoGen(self, self.MetaFile, Target, Toolchain, Arch).PackageList:\r
632 AllWorkSpaceMetaFiles.add(Package.MetaFile.Path)\r
633\r
634 #\r
635 # add included dsc\r
636 #\r
637 for filePath in self.BuildDatabase[self.MetaFile, Arch, Target, Toolchain]._RawData.IncludedFiles:\r
638 AllWorkSpaceMetaFiles.add(filePath.Path)\r
639\r
640 return AllWorkSpaceMetaFiles\r
641\r
642 def _CheckPcdDefineAndType(self):\r
643 PcdTypeSet = {TAB_PCDS_FIXED_AT_BUILD,\r
644 TAB_PCDS_PATCHABLE_IN_MODULE,\r
645 TAB_PCDS_FEATURE_FLAG,\r
646 TAB_PCDS_DYNAMIC,\r
647 TAB_PCDS_DYNAMIC_EX}\r
648\r
649 # This dict store PCDs which are not used by any modules with specified arches\r
650 UnusedPcd = OrderedDict()\r
651 for Pa in self.AutoGenObjectList:\r
652 # Key of DSC's Pcds dictionary is PcdCName, TokenSpaceGuid\r
653 for Pcd in Pa.Platform.Pcds:\r
654 PcdType = Pa.Platform.Pcds[Pcd].Type\r
655\r
656 # If no PCD type, this PCD comes from FDF\r
657 if not PcdType:\r
658 continue\r
659\r
660 # Try to remove Hii and Vpd suffix\r
661 if PcdType.startswith(TAB_PCDS_DYNAMIC_EX):\r
662 PcdType = TAB_PCDS_DYNAMIC_EX\r
663 elif PcdType.startswith(TAB_PCDS_DYNAMIC):\r
664 PcdType = TAB_PCDS_DYNAMIC\r
665\r
666 for Package in Pa.PackageList:\r
667 # Key of DEC's Pcds dictionary is PcdCName, TokenSpaceGuid, PcdType\r
668 if (Pcd[0], Pcd[1], PcdType) in Package.Pcds:\r
669 break\r
670 for Type in PcdTypeSet:\r
671 if (Pcd[0], Pcd[1], Type) in Package.Pcds:\r
672 EdkLogger.error(\r
673 'build',\r
674 FORMAT_INVALID,\r
675 "Type [%s] of PCD [%s.%s] in DSC file doesn't match the type [%s] defined in DEC file." \\r
676 % (Pa.Platform.Pcds[Pcd].Type, Pcd[1], Pcd[0], Type),\r
677 ExtraData=None\r
678 )\r
679 return\r
680 else:\r
681 UnusedPcd.setdefault(Pcd, []).append(Pa.Arch)\r
682\r
683 for Pcd in UnusedPcd:\r
684 EdkLogger.warn(\r
685 'build',\r
686 "The PCD was not specified by any INF module in the platform for the given architecture.\n"\r
687 "\tPCD: [%s.%s]\n\tPlatform: [%s]\n\tArch: %s"\r
688 % (Pcd[1], Pcd[0], os.path.basename(str(self.MetaFile)), str(UnusedPcd[Pcd])),\r
689 ExtraData=None\r
690 )\r
691\r
692 def __repr__(self):\r
693 return "%s [%s]" % (self.MetaFile, ", ".join(self.ArchList))\r
694\r
695 ## Return the directory to store FV files\r
696 @cached_property\r
697 def FvDir(self):\r
698 return path.join(self.BuildDir, TAB_FV_DIRECTORY)\r
699\r
700 ## Return the directory to store all intermediate and final files built\r
701 @cached_property\r
702 def BuildDir(self):\r
703 return self.AutoGenObjectList[0].BuildDir\r
704\r
705 ## Return the build output directory platform specifies\r
706 @cached_property\r
707 def OutputDir(self):\r
708 return self.Platform.OutputDirectory\r
709\r
710 ## Return platform name\r
711 @cached_property\r
712 def Name(self):\r
713 return self.Platform.PlatformName\r
714\r
715 ## Return meta-file GUID\r
716 @cached_property\r
717 def Guid(self):\r
718 return self.Platform.Guid\r
719\r
720 ## Return platform version\r
721 @cached_property\r
722 def Version(self):\r
723 return self.Platform.Version\r
724\r
725 ## Return paths of tools\r
726 @cached_property\r
727 def ToolDefinition(self):\r
728 return self.AutoGenObjectList[0].ToolDefinition\r
729\r
730 ## Return directory of platform makefile\r
731 #\r
732 # @retval string Makefile directory\r
733 #\r
734 @cached_property\r
735 def MakeFileDir(self):\r
736 return self.BuildDir\r
737\r
738 ## Return build command string\r
739 #\r
740 # @retval string Build command string\r
741 #\r
742 @cached_property\r
743 def BuildCommand(self):\r
744 # BuildCommand should be all the same. So just get one from platform AutoGen\r
745 return self.AutoGenObjectList[0].BuildCommand\r
746\r
747 ## Check the PCDs token value conflict in each DEC file.\r
748 #\r
749 # Will cause build break and raise error message while two PCDs conflict.\r
750 #\r
751 # @return None\r
752 #\r
753 def _CheckAllPcdsTokenValueConflict(self):\r
754 for Pa in self.AutoGenObjectList:\r
755 for Package in Pa.PackageList:\r
756 PcdList = list(Package.Pcds.values())\r
757 PcdList.sort(key=lambda x: int(x.TokenValue, 0))\r
758 Count = 0\r
759 while (Count < len(PcdList) - 1) :\r
760 Item = PcdList[Count]\r
761 ItemNext = PcdList[Count + 1]\r
762 #\r
763 # Make sure in the same token space the TokenValue should be unique\r
764 #\r
765 if (int(Item.TokenValue, 0) == int(ItemNext.TokenValue, 0)):\r
766 SameTokenValuePcdList = []\r
767 SameTokenValuePcdList.append(Item)\r
768 SameTokenValuePcdList.append(ItemNext)\r
769 RemainPcdListLength = len(PcdList) - Count - 2\r
770 for ValueSameCount in range(RemainPcdListLength):\r
771 if int(PcdList[len(PcdList) - RemainPcdListLength + ValueSameCount].TokenValue, 0) == int(Item.TokenValue, 0):\r
772 SameTokenValuePcdList.append(PcdList[len(PcdList) - RemainPcdListLength + ValueSameCount])\r
773 else:\r
774 break;\r
775 #\r
776 # Sort same token value PCD list with TokenGuid and TokenCName\r
777 #\r
778 SameTokenValuePcdList.sort(key=lambda x: "%s.%s" % (x.TokenSpaceGuidCName, x.TokenCName))\r
779 SameTokenValuePcdListCount = 0\r
780 while (SameTokenValuePcdListCount < len(SameTokenValuePcdList) - 1):\r
781 Flag = False\r
782 TemListItem = SameTokenValuePcdList[SameTokenValuePcdListCount]\r
783 TemListItemNext = SameTokenValuePcdList[SameTokenValuePcdListCount + 1]\r
784\r
785 if (TemListItem.TokenSpaceGuidCName == TemListItemNext.TokenSpaceGuidCName) and (TemListItem.TokenCName != TemListItemNext.TokenCName):\r
786 for PcdItem in GlobalData.MixedPcd:\r
787 if (TemListItem.TokenCName, TemListItem.TokenSpaceGuidCName) in GlobalData.MixedPcd[PcdItem] or \\r
788 (TemListItemNext.TokenCName, TemListItemNext.TokenSpaceGuidCName) in GlobalData.MixedPcd[PcdItem]:\r
789 Flag = True\r
790 if not Flag:\r
791 EdkLogger.error(\r
792 'build',\r
793 FORMAT_INVALID,\r
794 "The TokenValue [%s] of PCD [%s.%s] is conflict with: [%s.%s] in %s"\\r
795 % (TemListItem.TokenValue, TemListItem.TokenSpaceGuidCName, TemListItem.TokenCName, TemListItemNext.TokenSpaceGuidCName, TemListItemNext.TokenCName, Package),\r
796 ExtraData=None\r
797 )\r
798 SameTokenValuePcdListCount += 1\r
799 Count += SameTokenValuePcdListCount\r
800 Count += 1\r
801\r
802 PcdList = list(Package.Pcds.values())\r
803 PcdList.sort(key=lambda x: "%s.%s" % (x.TokenSpaceGuidCName, x.TokenCName))\r
804 Count = 0\r
805 while (Count < len(PcdList) - 1) :\r
806 Item = PcdList[Count]\r
807 ItemNext = PcdList[Count + 1]\r
808 #\r
809 # Check PCDs with same TokenSpaceGuidCName.TokenCName have same token value as well.\r
810 #\r
811 if (Item.TokenSpaceGuidCName == ItemNext.TokenSpaceGuidCName) and (Item.TokenCName == ItemNext.TokenCName) and (int(Item.TokenValue, 0) != int(ItemNext.TokenValue, 0)):\r
812 EdkLogger.error(\r
813 'build',\r
814 FORMAT_INVALID,\r
815 "The TokenValue [%s] of PCD [%s.%s] in %s defined in two places should be same as well."\\r
816 % (Item.TokenValue, Item.TokenSpaceGuidCName, Item.TokenCName, Package),\r
817 ExtraData=None\r
818 )\r
819 Count += 1\r
820 ## Generate fds command\r
821 @property\r
822 def GenFdsCommand(self):\r
823 return (GenMake.TopLevelMakefile(self)._TEMPLATE_.Replace(GenMake.TopLevelMakefile(self)._TemplateDict)).strip()\r
824\r
825 @property\r
826 def GenFdsCommandDict(self):\r
827 FdsCommandDict = {}\r
828 LogLevel = EdkLogger.GetLevel()\r
829 if LogLevel == EdkLogger.VERBOSE:\r
830 FdsCommandDict["verbose"] = True\r
831 elif LogLevel <= EdkLogger.DEBUG_9:\r
832 FdsCommandDict["debug"] = LogLevel - 1\r
833 elif LogLevel == EdkLogger.QUIET:\r
834 FdsCommandDict["quiet"] = True\r
835\r
7809492c 836 FdsCommandDict["GenfdsMultiThread"] = GlobalData.gEnableGenfdsMultiThread\r
e8449e1d
FB
837 if GlobalData.gIgnoreSource:\r
838 FdsCommandDict["IgnoreSources"] = True\r
839\r
840 FdsCommandDict["OptionPcd"] = []\r
841 for pcd in GlobalData.BuildOptionPcd:\r
842 if pcd[2]:\r
843 pcdname = '.'.join(pcd[0:3])\r
844 else:\r
845 pcdname = '.'.join(pcd[0:2])\r
846 if pcd[3].startswith('{'):\r
847 FdsCommandDict["OptionPcd"].append(pcdname + '=' + 'H' + '"' + pcd[3] + '"')\r
848 else:\r
849 FdsCommandDict["OptionPcd"].append(pcdname + '=' + pcd[3])\r
850\r
851 MacroList = []\r
852 # macros passed to GenFds\r
853 MacroDict = {}\r
854 MacroDict.update(GlobalData.gGlobalDefines)\r
855 MacroDict.update(GlobalData.gCommandLineDefines)\r
856 for MacroName in MacroDict:\r
857 if MacroDict[MacroName] != "":\r
858 MacroList.append('"%s=%s"' % (MacroName, MacroDict[MacroName].replace('\\', '\\\\')))\r
859 else:\r
860 MacroList.append('"%s"' % MacroName)\r
861 FdsCommandDict["macro"] = MacroList\r
862\r
863 FdsCommandDict["fdf_file"] = [self.FdfFile]\r
864 FdsCommandDict["build_target"] = self.BuildTarget\r
865 FdsCommandDict["toolchain_tag"] = self.ToolChain\r
866 FdsCommandDict["active_platform"] = str(self)\r
867\r
868 FdsCommandDict["conf_directory"] = GlobalData.gConfDirectory\r
869 FdsCommandDict["build_architecture_list"] = ','.join(self.ArchList)\r
870 FdsCommandDict["platform_build_directory"] = self.BuildDir\r
871\r
872 FdsCommandDict["fd"] = self.FdTargetList\r
873 FdsCommandDict["fv"] = self.FvTargetList\r
874 FdsCommandDict["cap"] = self.CapTargetList\r
875 return FdsCommandDict\r
876\r
877 ## Create makefile for the platform and modules in it\r
878 #\r
879 # @param CreateDepsMakeFile Flag indicating if the makefile for\r
880 # modules will be created as well\r
881 #\r
882 def CreateMakeFile(self, CreateDepsMakeFile=False):\r
883 if not CreateDepsMakeFile:\r
884 return\r
885 for Pa in self.AutoGenObjectList:\r
673d09a2 886 Pa.CreateMakeFile(CreateDepsMakeFile)\r
e8449e1d
FB
887\r
888 ## Create autogen code for platform and modules\r
889 #\r
890 # Since there's no autogen code for platform, this method will do nothing\r
891 # if CreateModuleCodeFile is set to False.\r
892 #\r
893 # @param CreateDepsCodeFile Flag indicating if creating module's\r
894 # autogen code file or not\r
895 #\r
896 def CreateCodeFile(self, CreateDepsCodeFile=False):\r
897 if not CreateDepsCodeFile:\r
898 return\r
899 for Pa in self.AutoGenObjectList:\r
673d09a2 900 Pa.CreateCodeFile(CreateDepsCodeFile)\r
e8449e1d
FB
901\r
902 ## Create AsBuilt INF file the platform\r
903 #\r
904 def CreateAsBuiltInf(self):\r
905 return\r
906\r