mirror of
https://github.com/CloverHackyColor/CloverBootloader.git
synced 2024-12-04 13:23:26 +01:00
217 lines
7.2 KiB
Python
217 lines
7.2 KiB
Python
|
## @file
|
||
|
# This file is used to create a database used by build tool
|
||
|
#
|
||
|
# Copyright (c) 2008 - 2018, Intel Corporation. All rights reserved.<BR>
|
||
|
# (C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>
|
||
|
# SPDX-License-Identifier: BSD-2-Clause-Patent
|
||
|
#
|
||
|
|
||
|
##
|
||
|
# Import Modules
|
||
|
#
|
||
|
from __future__ import absolute_import
|
||
|
from Common.StringUtils import *
|
||
|
from Common.DataType import *
|
||
|
from Common.Misc import *
|
||
|
from types import *
|
||
|
|
||
|
from .MetaDataTable import *
|
||
|
from .MetaFileTable import *
|
||
|
from .MetaFileParser import *
|
||
|
|
||
|
from Workspace.DecBuildData import DecBuildData
|
||
|
from Workspace.DscBuildData import DscBuildData
|
||
|
from Workspace.InfBuildData import InfBuildData
|
||
|
|
||
|
## Database
|
||
|
#
|
||
|
# This class defined the build database for all modules, packages and platform.
|
||
|
# It will call corresponding parser for the given file if it cannot find it in
|
||
|
# the database.
|
||
|
#
|
||
|
# @param DbPath Path of database file
|
||
|
# @param GlobalMacros Global macros used for replacement during file parsing
|
||
|
# @param RenewDb=False Create new database file if it's already there
|
||
|
#
|
||
|
class WorkspaceDatabase(object):
|
||
|
|
||
|
#
|
||
|
# internal class used for call corresponding file parser and caching the result
|
||
|
# to avoid unnecessary re-parsing
|
||
|
#
|
||
|
class BuildObjectFactory(object):
|
||
|
|
||
|
_FILE_TYPE_ = {
|
||
|
".inf" : MODEL_FILE_INF,
|
||
|
".dec" : MODEL_FILE_DEC,
|
||
|
".dsc" : MODEL_FILE_DSC,
|
||
|
}
|
||
|
|
||
|
# file parser
|
||
|
_FILE_PARSER_ = {
|
||
|
MODEL_FILE_INF : InfParser,
|
||
|
MODEL_FILE_DEC : DecParser,
|
||
|
MODEL_FILE_DSC : DscParser,
|
||
|
}
|
||
|
|
||
|
# convert to xxxBuildData object
|
||
|
_GENERATOR_ = {
|
||
|
MODEL_FILE_INF : InfBuildData,
|
||
|
MODEL_FILE_DEC : DecBuildData,
|
||
|
MODEL_FILE_DSC : DscBuildData,
|
||
|
}
|
||
|
|
||
|
_CACHE_ = {} # (FilePath, Arch) : <object>
|
||
|
def GetCache(self):
|
||
|
return self._CACHE_
|
||
|
|
||
|
# constructor
|
||
|
def __init__(self, WorkspaceDb):
|
||
|
self.WorkspaceDb = WorkspaceDb
|
||
|
|
||
|
# key = (FilePath, Arch=None)
|
||
|
def __contains__(self, Key):
|
||
|
FilePath = Key[0]
|
||
|
if len(Key) > 1:
|
||
|
Arch = Key[1]
|
||
|
else:
|
||
|
Arch = None
|
||
|
return (FilePath, Arch) in self._CACHE_
|
||
|
|
||
|
# key = (FilePath, Arch=None, Target=None, Toolchain=None)
|
||
|
def __getitem__(self, Key):
|
||
|
FilePath = Key[0]
|
||
|
KeyLength = len(Key)
|
||
|
if KeyLength > 1:
|
||
|
Arch = Key[1]
|
||
|
else:
|
||
|
Arch = None
|
||
|
if KeyLength > 2:
|
||
|
Target = Key[2]
|
||
|
else:
|
||
|
Target = None
|
||
|
if KeyLength > 3:
|
||
|
Toolchain = Key[3]
|
||
|
else:
|
||
|
Toolchain = None
|
||
|
|
||
|
# if it's generated before, just return the cached one
|
||
|
Key = (FilePath, Arch, Target, Toolchain)
|
||
|
if Key in self._CACHE_:
|
||
|
return self._CACHE_[Key]
|
||
|
|
||
|
# check file type
|
||
|
BuildObject = self.CreateBuildObject(FilePath, Arch, Target, Toolchain)
|
||
|
self._CACHE_[Key] = BuildObject
|
||
|
return BuildObject
|
||
|
def CreateBuildObject(self,FilePath, Arch, Target, Toolchain):
|
||
|
Ext = FilePath.Type
|
||
|
if Ext not in self._FILE_TYPE_:
|
||
|
return None
|
||
|
FileType = self._FILE_TYPE_[Ext]
|
||
|
if FileType not in self._GENERATOR_:
|
||
|
return None
|
||
|
|
||
|
# get the parser ready for this file
|
||
|
MetaFile = self._FILE_PARSER_[FileType](
|
||
|
FilePath,
|
||
|
FileType,
|
||
|
Arch,
|
||
|
MetaFileStorage(self.WorkspaceDb, FilePath, FileType)
|
||
|
)
|
||
|
# always do post-process, in case of macros change
|
||
|
MetaFile.DoPostProcess()
|
||
|
# object the build is based on
|
||
|
BuildObject = self._GENERATOR_[FileType](
|
||
|
FilePath,
|
||
|
MetaFile,
|
||
|
self,
|
||
|
Arch,
|
||
|
Target,
|
||
|
Toolchain
|
||
|
)
|
||
|
return BuildObject
|
||
|
|
||
|
# placeholder for file format conversion
|
||
|
class TransformObjectFactory:
|
||
|
def __init__(self, WorkspaceDb):
|
||
|
self.WorkspaceDb = WorkspaceDb
|
||
|
|
||
|
# key = FilePath, Arch
|
||
|
def __getitem__(self, Key):
|
||
|
pass
|
||
|
|
||
|
## Constructor of WorkspaceDatabase
|
||
|
#
|
||
|
# @param DbPath Path of database file
|
||
|
# @param GlobalMacros Global macros used for replacement during file parsing
|
||
|
# @param RenewDb=False Create new database file if it's already there
|
||
|
#
|
||
|
def __init__(self):
|
||
|
self.DB = dict()
|
||
|
# create table for internal uses
|
||
|
self.TblDataModel = DataClass.MODEL_LIST
|
||
|
self.TblFile = []
|
||
|
self.Platform = None
|
||
|
|
||
|
# conversion object for build or file format conversion purpose
|
||
|
self.BuildObject = WorkspaceDatabase.BuildObjectFactory(self)
|
||
|
self.TransformObject = WorkspaceDatabase.TransformObjectFactory(self)
|
||
|
|
||
|
def SetFileTimeStamp(self,FileId,TimeStamp):
|
||
|
self.TblFile[FileId-1][6] = TimeStamp
|
||
|
|
||
|
def GetFileTimeStamp(self,FileId):
|
||
|
return self.TblFile[FileId-1][6]
|
||
|
|
||
|
|
||
|
## Summarize all packages in the database
|
||
|
def GetPackageList(self, Platform, Arch, TargetName, ToolChainTag):
|
||
|
self.Platform = Platform
|
||
|
PackageList = []
|
||
|
Pa = self.BuildObject[self.Platform, Arch, TargetName, ToolChainTag]
|
||
|
#
|
||
|
# Get Package related to Modules
|
||
|
#
|
||
|
for Module in Pa.Modules:
|
||
|
ModuleObj = self.BuildObject[Module, Arch, TargetName, ToolChainTag]
|
||
|
for Package in ModuleObj.Packages:
|
||
|
if Package not in PackageList:
|
||
|
PackageList.append(Package)
|
||
|
#
|
||
|
# Get Packages related to Libraries
|
||
|
#
|
||
|
for Lib in Pa.LibraryInstances:
|
||
|
LibObj = self.BuildObject[Lib, Arch, TargetName, ToolChainTag]
|
||
|
for Package in LibObj.Packages:
|
||
|
if Package not in PackageList:
|
||
|
PackageList.append(Package)
|
||
|
|
||
|
return PackageList
|
||
|
|
||
|
## Summarize all platforms in the database
|
||
|
def PlatformList(self):
|
||
|
RetVal = []
|
||
|
for PlatformFile in [item[3] for item in self.TblFile if item[5] == MODEL_FILE_DSC]:
|
||
|
try:
|
||
|
RetVal.append(self.BuildObject[PathClass(PlatformFile), TAB_COMMON])
|
||
|
except:
|
||
|
pass
|
||
|
return RetVal
|
||
|
|
||
|
def MapPlatform(self, Dscfile):
|
||
|
Platform = self.BuildObject[PathClass(Dscfile), TAB_COMMON]
|
||
|
if Platform is None:
|
||
|
EdkLogger.error('build', PARSER_ERROR, "Failed to parser DSC file: %s" % Dscfile)
|
||
|
return Platform
|
||
|
|
||
|
BuildDB = WorkspaceDatabase()
|
||
|
##
|
||
|
#
|
||
|
# This acts like the main() function for the script, unless it is 'import'ed into another
|
||
|
# script.
|
||
|
#
|
||
|
if __name__ == '__main__':
|
||
|
pass
|
||
|
|