Home | History | Annotate | Download | only in Workspace
      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 
     14 from Common.Misc import sdict
     15 from Common.DataType import SUP_MODULE_USER_DEFINED
     16 from BuildClassObject import LibraryClassObject
     17 import 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 #

     28 def 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 #

     46 def 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 #

     72 def 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 
     78 def _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 
    224 def _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