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