X-Git-Url: https://git.proxmox.com/?p=mirror_edk2.git;a=blobdiff_plain;f=BaseTools%2FSource%2FPython%2FWorkspace%2FWorkspaceDatabase.py;h=fd10c5dfb9a8f4d493da00cd353a788d78841f0a;hp=b4109155a63a32d4d8e49786fa2697183227763c;hb=5015bee226c293c32c9ef2cc7669826edb5a0aed;hpb=1be2ed90a20618d71ddf34b8a07d038da0b36854 diff --git a/BaseTools/Source/Python/Workspace/WorkspaceDatabase.py b/BaseTools/Source/Python/Workspace/WorkspaceDatabase.py index b4109155a6..fd10c5dfb9 100644 --- a/BaseTools/Source/Python/Workspace/WorkspaceDatabase.py +++ b/BaseTools/Source/Python/Workspace/WorkspaceDatabase.py @@ -1,7 +1,7 @@ ## @file # This file is used to create a database used by build tool # -# Copyright (c) 2008 - 2014, Intel Corporation. All rights reserved.
+# Copyright (c) 2008 - 2015, Intel Corporation. All rights reserved.
# This program and the accompanying materials # are licensed and made available under the terms and conditions of the BSD License # which accompanies this distribution. The full text of the license may be found at @@ -35,8 +35,11 @@ from MetaFileParser import * from BuildClassObject import * from WorkspaceCommon import GetDeclaredPcd from Common.Misc import AnalyzeDscPcd +from Common.Misc import ProcessDuplicatedInf import re from Common.Parsing import IsValidWord +from Common.VariableAttributes import VariableAttributes +import Common.GlobalData as GlobalData ## Platform build information from DSC file # @@ -103,6 +106,7 @@ class DscBuildData(PlatformBuildClassObject): self._Target = Target self._Toolchain = Toolchain self._Clear() + self._HandleOverridePath() ## XXX[key] = value def __setitem__(self, key, value): @@ -128,7 +132,9 @@ class DscBuildData(PlatformBuildClassObject): self._BuildTargets = None self._SkuName = None self._SkuIdentifier = None + self._AvilableSkuIds = None self._PcdInfoFlag = None + self._VarCheckFlag = None self._FlashDefinition = None self._BuildNumber = None self._MakefileName = None @@ -141,12 +147,34 @@ class DscBuildData(PlatformBuildClassObject): self._Pcds = None self._DecPcds = None self._BuildOptions = None + self._ModuleTypeOptions = None self._LoadFixAddress = None self._RFCLanguages = None self._ISOLanguages = None self._VpdToolGuid = None self.__Macros = None + + ## handle Override Path of Module + def _HandleOverridePath(self): + RecordList = self._RawData[MODEL_META_DATA_COMPONENT, self._Arch] + Macros = self._Macros + Macros["EDK_SOURCE"] = GlobalData.gEcpSource + for Record in RecordList: + ModuleId = Record[5] + LineNo = Record[6] + ModuleFile = PathClass(NormPath(Record[0]), GlobalData.gWorkspace, Arch=self._Arch) + RecordList = self._RawData[MODEL_META_DATA_COMPONENT_SOURCE_OVERRIDE_PATH, self._Arch, None, ModuleId] + if RecordList != []: + SourceOverridePath = os.path.join(GlobalData.gWorkspace, NormPath(RecordList[0][0])) + + # Check if the source override path exists + if not os.path.isdir(SourceOverridePath): + EdkLogger.error('build', FILE_NOT_FOUND, Message='Source override path does not exist:', File=self.MetaFile, ExtraData=SourceOverridePath, Line=LineNo) + + #Add to GlobalData Variables + GlobalData.gOverrideDir[ModuleFile.Key] = SourceOverridePath + ## Get current effective macros def _GetMacros(self): if self.__Macros == None: @@ -206,8 +234,11 @@ class DscBuildData(PlatformBuildClassObject): if self._SkuName == None: self._SkuName = Record[2] self._SkuIdentifier = Record[2] + self._AvilableSkuIds = Record[2] elif Name == TAB_DSC_DEFINES_PCD_INFO_GENERATION: self._PcdInfoFlag = Record[2] + elif Name == TAB_DSC_DEFINES_PCD_VAR_CHECK_GENERATION: + self._VarCheckFlag = Record[2] elif Name == TAB_FIX_LOAD_TOP_MEMORY_ADDRESS: try: self._LoadFixAddress = int (Record[2], 0) @@ -327,7 +358,17 @@ class DscBuildData(PlatformBuildClassObject): return True else: return False - + def _GetVarCheckFlag(self): + if self._VarCheckFlag == None or self._VarCheckFlag.upper() == 'FALSE': + return False + elif self._VarCheckFlag.upper() == 'TRUE': + return True + else: + return False + def _GetAviableSkuIds(self): + if self._AvilableSkuIds: + return self._AvilableSkuIds + return self.SkuIdentifier def _GetSkuIdentifier(self): if self._SkuName: return self._SkuName @@ -478,6 +519,7 @@ class DscBuildData(PlatformBuildClassObject): Macros = self._Macros Macros["EDK_SOURCE"] = GlobalData.gEcpSource for Record in RecordList: + DuplicatedFile = False ModuleFile = PathClass(NormPath(Record[0], Macros), GlobalData.gWorkspace, Arch=self._Arch) ModuleId = Record[5] LineNo = Record[6] @@ -490,23 +532,11 @@ class DscBuildData(PlatformBuildClassObject): # Check duplication # If arch is COMMON, no duplicate module is checked since all modules in all component sections are selected if self._Arch != 'COMMON' and ModuleFile in self._Modules: - EdkLogger.error('build', FILE_DUPLICATED, File=self.MetaFile, ExtraData=str(ModuleFile), Line=LineNo) + DuplicatedFile = True Module = ModuleBuildClassObject() Module.MetaFile = ModuleFile - # get module override path - RecordList = self._RawData[MODEL_META_DATA_COMPONENT_SOURCE_OVERRIDE_PATH, self._Arch, None, ModuleId] - if RecordList != []: - Module.SourceOverridePath = os.path.join(GlobalData.gWorkspace, NormPath(RecordList[0][0], Macros)) - - # Check if the source override path exists - if not os.path.isdir(Module.SourceOverridePath): - EdkLogger.error('build', FILE_NOT_FOUND, Message = 'Source override path does not exist:', File=self.MetaFile, ExtraData=Module.SourceOverridePath, Line=LineNo) - - #Add to GlobalData Variables - GlobalData.gOverrideDir[ModuleFile.Key] = Module.SourceOverridePath - # get module private library instance RecordList = self._RawData[MODEL_EFI_LIBRARY_CLASS, self._Arch, None, ModuleId] for Record in RecordList: @@ -563,6 +593,16 @@ class DscBuildData(PlatformBuildClassObject): OptionString = Module.BuildOptions[ToolChainFamily, ToolChain] Module.BuildOptions[ToolChainFamily, ToolChain] = OptionString + " " + Option + RecordList = self._RawData[MODEL_META_DATA_HEADER, self._Arch, None, ModuleId] + if DuplicatedFile and not RecordList: + EdkLogger.error('build', FILE_DUPLICATED, File=self.MetaFile, ExtraData=str(ModuleFile), Line=LineNo) + if RecordList: + if len(RecordList) != 1: + EdkLogger.error('build', OPTION_UNKNOWN, 'Only FILE_GUID can be listed in section.', + File=self.MetaFile, ExtraData=str(ModuleFile), Line=LineNo) + ModuleFile = ProcessDuplicatedInf(ModuleFile, RecordList[0][2], GlobalData.gWorkspace) + ModuleFile.Arch = self._Arch + self._Modules[ModuleFile] = Module return self._Modules @@ -641,9 +681,26 @@ class DscBuildData(PlatformBuildClassObject): def _ValidatePcd(self, PcdCName, TokenSpaceGuid, Setting, PcdType, LineNo): if self._DecPcds == None: self._DecPcds = GetDeclaredPcd(self, self._Bdb, self._Arch, self._Target, self._Toolchain) + FdfInfList = [] + if GlobalData.gFdfParser: + FdfInfList = GlobalData.gFdfParser.Profile.InfList + + PkgSet = set() + for Inf in FdfInfList: + ModuleFile = PathClass(NormPath(Inf), GlobalData.gWorkspace, Arch=self._Arch) + if ModuleFile in self._Modules: + continue + ModuleData = self._Bdb[ModuleFile, self._Arch, self._Target, self._Toolchain] + PkgSet.update(ModuleData.Packages) + DecPcds = {} + for Pkg in PkgSet: + for Pcd in Pkg.Pcds: + DecPcds[Pcd[0], Pcd[1]] = Pkg.Pcds[Pcd] + self._DecPcds.update(DecPcds) + if (PcdCName, TokenSpaceGuid) not in self._DecPcds: EdkLogger.error('build', PARSER_ERROR, - "Pcd (%s.%s) defined in DSC is not declared in DEC files." % (TokenSpaceGuid, PcdCName), + "Pcd (%s.%s) defined in DSC is not declared in DEC files. Arch: ['%s']" % (TokenSpaceGuid, PcdCName, self._Arch), File=self.MetaFile, Line=LineNo) ValueList, IsValid, Index = AnalyzeDscPcd(Setting, PcdType, self._DecPcds[PcdCName, TokenSpaceGuid].DatumType) if not IsValid and PcdType not in [MODEL_PCD_FEATURE_FLAG, MODEL_PCD_FIXED_AT_BUILD]: @@ -698,19 +755,38 @@ class DscBuildData(PlatformBuildClassObject): if self._BuildOptions == None: self._BuildOptions = sdict() # - # Retrieve build option for EDKII style module - # - RecordList = self._RawData[MODEL_META_DATA_BUILD_OPTION, self._Arch, EDKII_NAME] - for ToolChainFamily, ToolChain, Option, Dummy1, Dummy2, Dummy3, Dummy4 in RecordList: - self._BuildOptions[ToolChainFamily, ToolChain, EDKII_NAME] = Option - # - # Retrieve build option for EDK style module + # Retrieve build option for EDKII and EDK style module # - RecordList = self._RawData[MODEL_META_DATA_BUILD_OPTION, self._Arch, EDK_NAME] - for ToolChainFamily, ToolChain, Option, Dummy1, Dummy2, Dummy3, Dummy4 in RecordList: - self._BuildOptions[ToolChainFamily, ToolChain, EDK_NAME] = Option + for CodeBase in (EDKII_NAME, EDK_NAME): + RecordList = self._RawData[MODEL_META_DATA_BUILD_OPTION, self._Arch, CodeBase] + for ToolChainFamily, ToolChain, Option, Dummy1, Dummy2, Dummy3, Dummy4 in RecordList: + CurKey = (ToolChainFamily, ToolChain, CodeBase) + # + # Only flags can be appended + # + if CurKey not in self._BuildOptions or not ToolChain.endswith('_FLAGS') or Option.startswith('='): + self._BuildOptions[CurKey] = Option + else: + self._BuildOptions[CurKey] += ' ' + Option return self._BuildOptions + def GetBuildOptionsByModuleType(self, Edk, ModuleType): + if self._ModuleTypeOptions == None: + self._ModuleTypeOptions = sdict() + if (Edk, ModuleType) not in self._ModuleTypeOptions: + options = sdict() + self._ModuleTypeOptions[Edk, ModuleType] = options + DriverType = '%s.%s' % (Edk, ModuleType) + RecordList = self._RawData[MODEL_META_DATA_BUILD_OPTION, self._Arch, DriverType] + for ToolChainFamily, ToolChain, Option, Arch, Type, Dummy3, Dummy4 in RecordList: + if Type == DriverType: + Key = (ToolChainFamily, ToolChain, Edk) + if Key not in options or not ToolChain.endswith('_FLAGS') or Option.startswith('='): + options[Key] = Option + else: + options[Key] += ' ' + Option + return self._ModuleTypeOptions[Edk, ModuleType] + ## Retrieve non-dynamic PCD settings # # @param Type PCD type @@ -857,6 +933,17 @@ class DscBuildData(PlatformBuildClassObject): return Pcds + def CompareVarAttr(self, Attr1, Attr2): + if not Attr1 or not Attr2: # for empty string + return True + Attr1s = [attr.strip() for attr in Attr1.split(",")] + Attr1Set = set(Attr1s) + Attr2s = [attr.strip() for attr in Attr2.split(",")] + Attr2Set = set(Attr2s) + if Attr2Set == Attr1Set: + return True + else: + return False ## Retrieve dynamic HII PCD settings # # @param Type PCD type @@ -866,6 +953,7 @@ class DscBuildData(PlatformBuildClassObject): def _GetDynamicHiiPcd(self, Type): SkuObj = SkuClass(self.SkuIdentifier,self.SkuIds) + VariableAttrs = {} Pcds = sdict() # @@ -890,8 +978,12 @@ class DscBuildData(PlatformBuildClassObject): Setting = PcdDict[self._Arch, SkuName, PcdCName, TokenSpaceGuid] if Setting == None: continue - VariableName, VariableGuid, VariableOffset, DefaultValue = self._ValidatePcd(PcdCName, TokenSpaceGuid, Setting, Type, Dummy4) + VariableName, VariableGuid, VariableOffset, DefaultValue, VarAttribute = self._ValidatePcd(PcdCName, TokenSpaceGuid, Setting, Type, Dummy4) + rt, Msg = VariableAttributes.ValidateVarAttributes(VarAttribute) + if not rt: + EdkLogger.error("build", PCD_VARIABLE_ATTRIBUTES_ERROR, "Variable attributes settings for %s is incorrect.\n %s" % (".".join((TokenSpaceGuid, PcdCName)), Msg), + ExtraData = "[%s]" % VarAttribute) ExceedMax = False FormatCorrect = True if VariableOffset.isdigit(): @@ -914,8 +1006,14 @@ class DscBuildData(PlatformBuildClassObject): if ExceedMax: EdkLogger.error('Build', OPTION_VALUE_INVALID, "The variable offset value must not exceed the maximum value of 0xFFFF (UINT16) for %s." % ".".join((TokenSpaceGuid,PcdCName))) + if (VariableName, VariableGuid) not in VariableAttrs: + VariableAttrs[(VariableName, VariableGuid)] = VarAttribute + else: + if not self.CompareVarAttr(VariableAttrs[(VariableName, VariableGuid)], VarAttribute): + EdkLogger.error('Build', PCD_VARIABLE_ATTRIBUTES_CONFLICT_ERROR, "The variable %s.%s for DynamicHii PCDs has conflicting attributes [%s] and [%s] " % (VariableGuid, VariableName, VarAttribute, VariableAttrs[(VariableName, VariableGuid)])) - SkuInfo = SkuInfoClass(SkuName, self.SkuIds[SkuName], VariableName, VariableGuid, VariableOffset, DefaultValue) + SkuInfo = SkuInfoClass(SkuName, self.SkuIds[SkuName], VariableName, VariableGuid, VariableOffset, DefaultValue, VariableAttribute = VarAttribute) + pcdDecObject = self._DecPcds[PcdCName, TokenSpaceGuid] if (PcdCName,TokenSpaceGuid) in Pcds.keys(): pcdObject = Pcds[PcdCName,TokenSpaceGuid] pcdObject.SkuInfoList[SkuName] = SkuInfo @@ -930,7 +1028,10 @@ class DscBuildData(PlatformBuildClassObject): '', {SkuName : SkuInfo}, False, - None + None, + pcdDecObject.validateranges, + pcdDecObject.validlists, + pcdDecObject.expressions ) @@ -1035,7 +1136,7 @@ class DscBuildData(PlatformBuildClassObject): TokenSpaceGuid, self._PCD_TYPE_STRING_[Type], '', - '', + InitialValue, '', MaxDatumSize, {SkuName : SkuInfo}, @@ -1101,7 +1202,9 @@ class DscBuildData(PlatformBuildClassObject): BuildTargets = property(_GetBuildTarget) SkuName = property(_GetSkuName, _SetSkuName) SkuIdentifier = property(_GetSkuIdentifier) + AvilableSkuIds = property(_GetAviableSkuIds) PcdInfoFlag = property(_GetPcdInfoFlag) + VarCheckFlag = property(_GetVarCheckFlag) FlashDefinition = property(_GetFdfFile) BuildNumber = property(_GetBuildNumber) MakefileName = property(_GetMakefileName) @@ -1421,6 +1524,7 @@ class DecBuildData(PackageBuildClassObject): DefaultValue, DatumType, TokenNumber = AnalyzePcdData(Setting) + validateranges, validlists, expressions = self._RawData.GetValidExpression(TokenSpaceGuid, PcdCName) Pcds[PcdCName, TokenSpaceGuid, self._PCD_TYPE_STRING_[Type]] = PcdClassObject( PcdCName, TokenSpaceGuid, @@ -1431,7 +1535,10 @@ class DecBuildData(PackageBuildClassObject): '', {}, False, - None + None, + list(validateranges), + list(validlists), + list(expressions) ) return Pcds @@ -1676,6 +1783,9 @@ class InfBuildData(ModuleBuildClassObject): # items defined _PROPERTY_ don't need additional processing if Name in self: self[Name] = Value + if self._Defs == None: + self._Defs = sdict() + self._Defs[Name] = Value # some special items in [Defines] section need special treatment elif Name in ('EFI_SPECIFICATION_VERSION', 'UEFI_SPECIFICATION_VERSION', 'EDK_RELEASE_VERSION', 'PI_SPECIFICATION_VERSION'): if Name in ('EFI_SPECIFICATION_VERSION', 'UEFI_SPECIFICATION_VERSION'): @@ -1903,7 +2013,7 @@ class InfBuildData(ModuleBuildClassObject): if self._Header_ == None: self._GetHeaderInfo() if self._Guid == None: - self._Guid = '00000000-0000-0000-000000000000' + self._Guid = '00000000-0000-0000-0000-000000000000' return self._Guid ## Retrieve module version @@ -2008,7 +2118,7 @@ class InfBuildData(ModuleBuildClassObject): return self._Defs ## Retrieve binary files - def _GetBinaryFiles(self): + def _GetBinaries(self): if self._Binaries == None: self._Binaries = [] RecordList = self._RawData[MODEL_EFI_BINARY_FILE, self._Arch, self._Platform] @@ -2035,8 +2145,27 @@ class InfBuildData(ModuleBuildClassObject): self._Binaries.append(File) return self._Binaries + ## Retrieve binary files with error check. + def _GetBinaryFiles(self): + Binaries = self._GetBinaries() + if GlobalData.gIgnoreSource and Binaries == []: + ErrorInfo = "The INF file does not contain any Binaries to use in creating the image\n" + EdkLogger.error('build', RESOURCE_NOT_AVAILABLE, ExtraData=ErrorInfo, File=self.MetaFile) + + return Binaries + ## Check whether it exists the binaries with current ARCH in AsBuild INF + def _IsSupportedArch(self): + if self._GetBinaries() and not self._GetSourceFiles(): + return True + else: + return False ## Retrieve source files def _GetSourceFiles(self): + #Ignore all source files in a binary build mode + if GlobalData.gIgnoreSource: + self._Sources = [] + return self._Sources + if self._Sources == None: self._Sources = [] RecordList = self._RawData[MODEL_EFI_SOURCE_FILE, self._Arch, self._Platform] @@ -2264,7 +2393,7 @@ class InfBuildData(ModuleBuildClassObject): ToolChainFamily = Record[0] ToolChain = Record[1] Option = Record[2] - if (ToolChainFamily, ToolChain) not in self._BuildOptions: + if (ToolChainFamily, ToolChain) not in self._BuildOptions or Option.startswith('='): self._BuildOptions[ToolChainFamily, ToolChain] = Option else: # concatenate the option string if they're for the same tool @@ -2290,6 +2419,13 @@ class InfBuildData(ModuleBuildClassObject): EdkLogger.error('build', RESOURCE_NOT_AVAILABLE, "No [Depex] section or no valid expression in [Depex] section for [%s] module" \ % self.ModuleType, File=self.MetaFile) + if len(RecordList) != 0 and self.ModuleType == 'USER_DEFINED': + for Record in RecordList: + if Record[4] not in ['PEIM', 'DXE_DRIVER', 'DXE_SMM_DRIVER']: + EdkLogger.error('build', FORMAT_INVALID, + "'%s' module must specify the type of [Depex] section" % self.ModuleType, + File=self.MetaFile) + Depex = sdict() for Record in RecordList: DepexStr = ReplaceMacro(Record[0], self._Macros, False) @@ -2537,6 +2673,7 @@ class InfBuildData(ModuleBuildClassObject): Depex = property(_GetDepex) DepexExpression = property(_GetDepexExpression) IsBinaryModule = property(_IsBinaryModule) + IsSupportedArch = property(_IsSupportedArch) ## Database # @@ -2550,8 +2687,6 @@ class InfBuildData(ModuleBuildClassObject): # class WorkspaceDatabase(object): - # default database file path - _DB_PATH_ = "Conf/.cache/build.db" # # internal class used for call corresponding file parser and caching the result @@ -2662,7 +2797,7 @@ class WorkspaceDatabase(object): def __init__(self, DbPath, RenewDb=False): self._DbClosedFlag = False if not DbPath: - DbPath = os.path.normpath(os.path.join(GlobalData.gWorkspace, self._DB_PATH_)) + DbPath = os.path.normpath(os.path.join(GlobalData.gWorkspace, 'Conf', GlobalData.gDatabasePath)) # don't create necessary path for db in memory if DbPath != ':memory:':