1## @file 2# Common routines used by workspace 3# 4# Copyright (c) 2012 - 2016, Intel Corporation. All rights reserved.<BR> 5# This program and the accompanying materials 6# are licensed and made available under the terms and conditions of the BSD License 7# which accompanies this distribution. The full text of the license may be found at 8# http://opensource.org/licenses/bsd-license.php 9# 10# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 11# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 12# 13 14from Common.Misc import sdict 15from Common.DataType import SUP_MODULE_USER_DEFINED 16from BuildClassObject import LibraryClassObject 17import Common.GlobalData as GlobalData 18 19## Get all packages from platform for specified arch, target and toolchain 20# 21# @param Platform: DscBuildData instance 22# @param BuildDatabase: The database saves all data for all metafiles 23# @param Arch: Current arch 24# @param Target: Current target 25# @param Toolchain: Current toolchain 26# @retval: List of packages which are DecBuildData instances 27# 28def GetPackageList(Platform, BuildDatabase, Arch, Target, Toolchain): 29 PkgSet = set() 30 for ModuleFile in Platform.Modules: 31 Data = BuildDatabase[ModuleFile, Arch, Target, Toolchain] 32 PkgSet.update(Data.Packages) 33 for Lib in GetLiabraryInstances(Data, Platform, BuildDatabase, Arch, Target, Toolchain): 34 PkgSet.update(Lib.Packages) 35 return list(PkgSet) 36 37## Get all declared PCD from platform for specified arch, target and toolchain 38# 39# @param Platform: DscBuildData instance 40# @param BuildDatabase: The database saves all data for all metafiles 41# @param Arch: Current arch 42# @param Target: Current target 43# @param Toolchain: Current toolchain 44# @retval: A dictionary contains instances of PcdClassObject with key (PcdCName, TokenSpaceGuid) 45# 46def GetDeclaredPcd(Platform, BuildDatabase, Arch, Target, Toolchain): 47 PkgList = GetPackageList(Platform, BuildDatabase, Arch, Target, Toolchain) 48 DecPcds = {} 49 for Pkg in PkgList: 50 for Pcd in Pkg.Pcds: 51 PcdCName = Pcd[0] 52 PcdTokenName = Pcd[1] 53 if GlobalData.MixedPcd: 54 for PcdItem in GlobalData.MixedPcd.keys(): 55 if (PcdCName, PcdTokenName) in GlobalData.MixedPcd[PcdItem]: 56 PcdCName = PcdItem[0] 57 break 58 if (PcdCName, PcdTokenName) not in DecPcds.keys(): 59 DecPcds[PcdCName, PcdTokenName] = Pkg.Pcds[Pcd] 60 return DecPcds 61 62## Get all dependent libraries for a module 63# 64# @param Module: InfBuildData instance 65# @param Platform: DscBuildData instance 66# @param BuildDatabase: The database saves all data for all metafiles 67# @param Arch: Current arch 68# @param Target: Current target 69# @param Toolchain: Current toolchain 70# @retval: List of dependent libraries which are InfBuildData instances 71# 72def GetLiabraryInstances(Module, Platform, BuildDatabase, Arch, Target, Toolchain): 73 if Module.AutoGenVersion >= 0x00010005: 74 return _GetModuleLibraryInstances(Module, Platform, BuildDatabase, Arch, Target, Toolchain) 75 else: 76 return _ResolveLibraryReference(Module, Platform) 77 78def _GetModuleLibraryInstances(Module, Platform, BuildDatabase, Arch, Target, Toolchain): 79 ModuleType = Module.ModuleType 80 81 # for overriding library instances with module specific setting 82 PlatformModule = Platform.Modules[str(Module)] 83 84 # add forced library instances (specified under LibraryClasses sections) 85 # 86 # If a module has a MODULE_TYPE of USER_DEFINED, 87 # do not link in NULL library class instances from the global [LibraryClasses.*] sections. 88 # 89 if Module.ModuleType != SUP_MODULE_USER_DEFINED: 90 for LibraryClass in Platform.LibraryClasses.GetKeys(): 91 if LibraryClass.startswith("NULL") and Platform.LibraryClasses[LibraryClass, Module.ModuleType]: 92 Module.LibraryClasses[LibraryClass] = Platform.LibraryClasses[LibraryClass, Module.ModuleType] 93 94 # add forced library instances (specified in module overrides) 95 for LibraryClass in PlatformModule.LibraryClasses: 96 if LibraryClass.startswith("NULL"): 97 Module.LibraryClasses[LibraryClass] = PlatformModule.LibraryClasses[LibraryClass] 98 99 # EdkII module 100 LibraryConsumerList = [Module] 101 Constructor = [] 102 ConsumedByList = sdict() 103 LibraryInstance = sdict() 104 105 while len(LibraryConsumerList) > 0: 106 M = LibraryConsumerList.pop() 107 for LibraryClassName in M.LibraryClasses: 108 if LibraryClassName not in LibraryInstance: 109 # override library instance for this module 110 if LibraryClassName in PlatformModule.LibraryClasses: 111 LibraryPath = PlatformModule.LibraryClasses[LibraryClassName] 112 else: 113 LibraryPath = Platform.LibraryClasses[LibraryClassName, ModuleType] 114 if LibraryPath == None or LibraryPath == "": 115 LibraryPath = M.LibraryClasses[LibraryClassName] 116 if LibraryPath == None or LibraryPath == "": 117 return [] 118 119 LibraryModule = BuildDatabase[LibraryPath, Arch, Target, Toolchain] 120 # for those forced library instance (NULL library), add a fake library class 121 if LibraryClassName.startswith("NULL"): 122 LibraryModule.LibraryClass.append(LibraryClassObject(LibraryClassName, [ModuleType])) 123 elif LibraryModule.LibraryClass == None \ 124 or len(LibraryModule.LibraryClass) == 0 \ 125 or (ModuleType != 'USER_DEFINED' 126 and ModuleType not in LibraryModule.LibraryClass[0].SupModList): 127 # only USER_DEFINED can link against any library instance despite of its SupModList 128 return [] 129 130 LibraryInstance[LibraryClassName] = LibraryModule 131 LibraryConsumerList.append(LibraryModule) 132 else: 133 LibraryModule = LibraryInstance[LibraryClassName] 134 135 if LibraryModule == None: 136 continue 137 138 if LibraryModule.ConstructorList != [] and LibraryModule not in Constructor: 139 Constructor.append(LibraryModule) 140 141 if LibraryModule not in ConsumedByList: 142 ConsumedByList[LibraryModule] = [] 143 # don't add current module itself to consumer list 144 if M != Module: 145 if M in ConsumedByList[LibraryModule]: 146 continue 147 ConsumedByList[LibraryModule].append(M) 148 # 149 # Initialize the sorted output list to the empty set 150 # 151 SortedLibraryList = [] 152 # 153 # Q <- Set of all nodes with no incoming edges 154 # 155 LibraryList = [] #LibraryInstance.values() 156 Q = [] 157 for LibraryClassName in LibraryInstance: 158 M = LibraryInstance[LibraryClassName] 159 LibraryList.append(M) 160 if ConsumedByList[M] == []: 161 Q.append(M) 162 163 # 164 # start the DAG algorithm 165 # 166 while True: 167 EdgeRemoved = True 168 while Q == [] and EdgeRemoved: 169 EdgeRemoved = False 170 # for each node Item with a Constructor 171 for Item in LibraryList: 172 if Item not in Constructor: 173 continue 174 # for each Node without a constructor with an edge e from Item to Node 175 for Node in ConsumedByList[Item]: 176 if Node in Constructor: 177 continue 178 # remove edge e from the graph if Node has no constructor 179 ConsumedByList[Item].remove(Node) 180 EdgeRemoved = True 181 if ConsumedByList[Item] == []: 182 # insert Item into Q 183 Q.insert(0, Item) 184 break 185 if Q != []: 186 break 187 # DAG is done if there's no more incoming edge for all nodes 188 if Q == []: 189 break 190 191 # remove node from Q 192 Node = Q.pop() 193 # output Node 194 SortedLibraryList.append(Node) 195 196 # for each node Item with an edge e from Node to Item do 197 for Item in LibraryList: 198 if Node not in ConsumedByList[Item]: 199 continue 200 # remove edge e from the graph 201 ConsumedByList[Item].remove(Node) 202 203 if ConsumedByList[Item] != []: 204 continue 205 # insert Item into Q, if Item has no other incoming edges 206 Q.insert(0, Item) 207 208 # 209 # if any remaining node Item in the graph has a constructor and an incoming edge, then the graph has a cycle 210 # 211 for Item in LibraryList: 212 if ConsumedByList[Item] != [] and Item in Constructor and len(Constructor) > 1: 213 return [] 214 if Item not in SortedLibraryList: 215 SortedLibraryList.append(Item) 216 217 # 218 # Build the list of constructor and destructir names 219 # The DAG Topo sort produces the destructor order, so the list of constructors must generated in the reverse order 220 # 221 SortedLibraryList.reverse() 222 return SortedLibraryList 223 224def _ResolveLibraryReference(Module, Platform): 225 LibraryConsumerList = [Module] 226 227 # "CompilerStub" is a must for Edk modules 228 if Module.Libraries: 229 Module.Libraries.append("CompilerStub") 230 LibraryList = [] 231 while len(LibraryConsumerList) > 0: 232 M = LibraryConsumerList.pop() 233 for LibraryName in M.Libraries: 234 Library = Platform.LibraryClasses[LibraryName, ':dummy:'] 235 if Library == None: 236 for Key in Platform.LibraryClasses.data.keys(): 237 if LibraryName.upper() == Key.upper(): 238 Library = Platform.LibraryClasses[Key, ':dummy:'] 239 break 240 if Library == None: 241 continue 242 243 if Library not in LibraryList: 244 LibraryList.append(Library) 245 LibraryConsumerList.append(Library) 246 return LibraryList 247