Home | History | Annotate | Download | only in Common
      1 ## @file

      2 # This file is used to define each component of tools_def.txt file

      3 #

      4 # Copyright (c) 2007 - 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 ##

     15 # Import Modules

     16 #

     17 import Common.LongFilePathOs as os
     18 import re
     19 import EdkLogger
     20 
     21 from Dictionary import *
     22 from BuildToolError import *
     23 from TargetTxtClassObject import *
     24 from Common.LongFilePathSupport import OpenLongFilePath as open
     25 from Common.Misc import PathClass
     26 from Common.String import NormPath
     27 import Common.GlobalData as GlobalData
     28 from Common import GlobalData
     29 from Common.MultipleWorkspace import MultipleWorkspace as mws
     30 
     31 ##

     32 # Static variables used for pattern

     33 #

     34 gMacroRefPattern = re.compile('(DEF\([^\(\)]+\))')
     35 gEnvRefPattern = re.compile('(ENV\([^\(\)]+\))')
     36 gMacroDefPattern = re.compile("DEFINE\s+([^\s]+)")
     37 gDefaultToolsDefFile = "tools_def.txt"
     38 
     39 ## ToolDefClassObject

     40 #

     41 # This class defined content used in file tools_def.txt

     42 #

     43 # @param object:               Inherited from object class

     44 # @param Filename:             Input value for full path of tools_def.txt

     45 #

     46 # @var ToolsDefTxtDictionary:  To store keys and values defined in target.txt

     47 # @var MacroDictionary:        To store keys and values defined in DEFINE statement

     48 #

     49 class ToolDefClassObject(object):
     50     def __init__(self, FileName=None):
     51         self.ToolsDefTxtDictionary = {}
     52         self.MacroDictionary = {}
     53         for Env in os.environ:
     54             self.MacroDictionary["ENV(%s)" % Env] = os.environ[Env]
     55 
     56         if FileName != None:
     57             self.LoadToolDefFile(FileName)
     58 
     59     ## LoadToolDefFile

     60     #

     61     # Load target.txt file and parse it

     62     #

     63     # @param Filename:  Input value for full path of tools_def.txt

     64     #

     65     def LoadToolDefFile(self, FileName):
     66         # set multiple workspace

     67         PackagesPath = os.getenv("PACKAGES_PATH")
     68         mws.setWs(GlobalData.gWorkspace, PackagesPath)
     69 
     70         self.ToolsDefTxtDatabase = {
     71             TAB_TOD_DEFINES_TARGET          :   [],
     72             TAB_TOD_DEFINES_TOOL_CHAIN_TAG  :   [],
     73             TAB_TOD_DEFINES_TARGET_ARCH     :   [],
     74             TAB_TOD_DEFINES_COMMAND_TYPE    :   []
     75         }
     76 
     77         self.IncludeToolDefFile(FileName)
     78 
     79         self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_TARGET] = list(set(self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_TARGET]))
     80         self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_TOOL_CHAIN_TAG] = list(set(self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_TOOL_CHAIN_TAG]))
     81         self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_TARGET_ARCH] = list(set(self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_TARGET_ARCH]))
     82 
     83         self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_COMMAND_TYPE] = list(set(self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_COMMAND_TYPE]))
     84 
     85         self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_TARGET].sort()
     86         self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_TOOL_CHAIN_TAG].sort()
     87         self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_TARGET_ARCH].sort()
     88         self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_COMMAND_TYPE].sort()
     89 
     90         KeyList = [TAB_TOD_DEFINES_TARGET, TAB_TOD_DEFINES_TOOL_CHAIN_TAG, TAB_TOD_DEFINES_TARGET_ARCH, TAB_TOD_DEFINES_COMMAND_TYPE]
     91         for Index in range(3, -1, -1):
     92             for Key in dict(self.ToolsDefTxtDictionary):
     93                 List = Key.split('_')
     94                 if List[Index] == '*':
     95                     for String in self.ToolsDefTxtDatabase[KeyList[Index]]:
     96                         List[Index] = String
     97                         NewKey = '%s_%s_%s_%s_%s' % tuple(List)
     98                         if NewKey not in self.ToolsDefTxtDictionary:
     99                             self.ToolsDefTxtDictionary[NewKey] = self.ToolsDefTxtDictionary[Key]
    100                         continue
    101                     del self.ToolsDefTxtDictionary[Key]
    102                 elif List[Index] not in self.ToolsDefTxtDatabase[KeyList[Index]]:
    103                     del self.ToolsDefTxtDictionary[Key]
    104 
    105 
    106     ## IncludeToolDefFile

    107     #

    108     # Load target.txt file and parse it as if it's contents were inside the main file

    109     #

    110     # @param Filename:  Input value for full path of tools_def.txt

    111     #

    112     def IncludeToolDefFile(self, FileName):
    113         FileContent = []
    114         if os.path.isfile(FileName):
    115             try:
    116                 F = open(FileName, 'r')
    117                 FileContent = F.readlines()
    118             except:
    119                 EdkLogger.error("tools_def.txt parser", FILE_OPEN_FAILURE, ExtraData=FileName)
    120         else:
    121             EdkLogger.error("tools_def.txt parser", FILE_NOT_FOUND, ExtraData=FileName)
    122 
    123         for Index in range(len(FileContent)):
    124             Line = FileContent[Index].strip()
    125             if Line == "" or Line[0] == '#':
    126                 continue
    127 
    128             if Line.startswith("!include"):
    129                 IncFile = Line[8:].strip()
    130                 Done, IncFile = self.ExpandMacros(IncFile)
    131                 if not Done:
    132                     EdkLogger.error("tools_def.txt parser", ATTRIBUTE_NOT_AVAILABLE,
    133                                     "Macro or Environment has not been defined",
    134                                 ExtraData=IncFile[4:-1], File=FileName, Line=Index+1)
    135                 IncFile = NormPath(IncFile)
    136 
    137                 if not os.path.isabs(IncFile):
    138                     #

    139                     # try WORKSPACE

    140                     #

    141                     IncFileTmp = PathClass(IncFile, GlobalData.gWorkspace)
    142                     ErrorCode = IncFileTmp.Validate()[0]
    143                     if ErrorCode != 0:
    144                         #

    145                         # try PACKAGES_PATH

    146                         #

    147                         IncFileTmp = mws.join(GlobalData.gWorkspace, IncFile)
    148                         if not os.path.exists(IncFileTmp):
    149                             #

    150                             # try directory of current file

    151                             #

    152                             IncFileTmp = PathClass(IncFile, os.path.dirname(FileName))
    153                             ErrorCode = IncFileTmp.Validate()[0]
    154                             if ErrorCode != 0:
    155                                 EdkLogger.error("tools_def.txt parser", FILE_NOT_FOUND, ExtraData=IncFile)
    156 
    157                     if type(IncFileTmp) is PathClass:
    158                         IncFile = IncFileTmp.Path
    159                     else:
    160                         IncFile = IncFileTmp
    161 
    162                 self.IncludeToolDefFile(IncFile)
    163                 continue
    164 
    165             NameValuePair = Line.split("=", 1)
    166             if len(NameValuePair) != 2:
    167                 EdkLogger.warn("tools_def.txt parser", "Line %d: not correct assignment statement, skipped" % (Index + 1))
    168                 continue
    169 
    170             Name = NameValuePair[0].strip()
    171             Value = NameValuePair[1].strip()
    172 
    173             if Name == "IDENTIFIER":
    174                 EdkLogger.debug(EdkLogger.DEBUG_8, "Line %d: Found identifier statement, skipped: %s" % ((Index + 1), Value))
    175                 continue
    176 
    177             MacroDefinition = gMacroDefPattern.findall(Name)
    178             if MacroDefinition != []:
    179                 Done, Value = self.ExpandMacros(Value)
    180                 if not Done:
    181                     EdkLogger.error("tools_def.txt parser", ATTRIBUTE_NOT_AVAILABLE,
    182                                     "Macro or Environment has not been defined",
    183                                 ExtraData=Value[4:-1], File=FileName, Line=Index+1)
    184 
    185                 MacroName = MacroDefinition[0].strip()
    186                 self.MacroDictionary["DEF(%s)" % MacroName] = Value
    187                 EdkLogger.debug(EdkLogger.DEBUG_8, "Line %d: Found macro: %s = %s" % ((Index + 1), MacroName, Value))
    188                 continue
    189 
    190             Done, Value = self.ExpandMacros(Value)
    191             if not Done:
    192                 EdkLogger.error("tools_def.txt parser", ATTRIBUTE_NOT_AVAILABLE,
    193                                 "Macro or Environment has not been defined",
    194                                 ExtraData=Value[4:-1], File=FileName, Line=Index+1)
    195 
    196             List = Name.split('_')
    197             if len(List) != 5:
    198                 EdkLogger.verbose("Line %d: Not a valid name of definition: %s" % ((Index + 1), Name))
    199                 continue
    200             elif List[4] == '*':
    201                 EdkLogger.verbose("Line %d: '*' is not allowed in last field: %s" % ((Index + 1), Name))
    202                 continue
    203             else:
    204                 self.ToolsDefTxtDictionary[Name] = Value
    205                 if List[0] != '*':
    206                     self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_TARGET] += [List[0]]
    207                 if List[1] != '*':
    208                     self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_TOOL_CHAIN_TAG] += [List[1]]
    209                 if List[2] != '*':
    210                     self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_TARGET_ARCH] += [List[2]]
    211                 if List[3] != '*':
    212                     self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_COMMAND_TYPE] += [List[3]]
    213                 if List[4] == TAB_TOD_DEFINES_FAMILY and List[2] == '*' and List[3] == '*':
    214                     if TAB_TOD_DEFINES_FAMILY not in self.ToolsDefTxtDatabase:
    215                         self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_FAMILY] = {}
    216                         self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_FAMILY][List[1]] = Value
    217                         self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_BUILDRULEFAMILY] = {}
    218                         self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_BUILDRULEFAMILY][List[1]] = Value
    219                     elif List[1] not in self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_FAMILY]:
    220                         self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_FAMILY][List[1]] = Value
    221                         self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_BUILDRULEFAMILY][List[1]] = Value
    222                     elif self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_FAMILY][List[1]] != Value:
    223                         EdkLogger.verbose("Line %d: No override allowed for the family of a tool chain: %s" % ((Index + 1), Name))
    224                 if List[4] == TAB_TOD_DEFINES_BUILDRULEFAMILY and List[2] == '*' and List[3] == '*':
    225                     if TAB_TOD_DEFINES_BUILDRULEFAMILY not in self.ToolsDefTxtDatabase \
    226                        or List[1] not in self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_FAMILY]:
    227                         EdkLogger.verbose("Line %d: The family is not specified, but BuildRuleFamily is specified for the tool chain: %s" % ((Index + 1), Name))
    228                     self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_BUILDRULEFAMILY][List[1]] = Value
    229 
    230     ## ExpandMacros

    231     #

    232     # Replace defined macros with real value

    233     #

    234     # @param Value:   The string with unreplaced macros

    235     #

    236     # @retval Value:  The string which has been replaced with real value

    237     #

    238     def ExpandMacros(self, Value):
    239         # os.environ contains all environment variables uppercase on Windows which cause the key in the self.MacroDictionary is uppercase, but Ref may not

    240         EnvReference = gEnvRefPattern.findall(Value)
    241         for Ref in EnvReference:
    242             if Ref not in self.MacroDictionary and Ref.upper() not in self.MacroDictionary:
    243                 Value = Value.replace(Ref, "")
    244             else:
    245                 if Ref in self.MacroDictionary:
    246                     Value = Value.replace(Ref, self.MacroDictionary[Ref])
    247                 else:
    248                     Value = Value.replace(Ref, self.MacroDictionary[Ref.upper()])
    249 
    250         MacroReference = gMacroRefPattern.findall(Value)
    251         for Ref in MacroReference:
    252             if Ref not in self.MacroDictionary:
    253                 return False, Ref
    254             Value = Value.replace(Ref, self.MacroDictionary[Ref])
    255 
    256         return True, Value
    257 
    258 ## ToolDefDict

    259 #

    260 # Load tools_def.txt in input Conf dir

    261 #

    262 # @param ConfDir:  Conf dir

    263 #

    264 # @retval ToolDef An instance of ToolDefClassObject() with loaded tools_def.txt

    265 #

    266 def ToolDefDict(ConfDir):
    267     Target = TargetTxtDict(ConfDir)
    268     ToolDef = ToolDefClassObject()
    269     if DataType.TAB_TAT_DEFINES_TOOL_CHAIN_CONF in Target.TargetTxtDictionary:
    270         ToolsDefFile = Target.TargetTxtDictionary[DataType.TAB_TAT_DEFINES_TOOL_CHAIN_CONF]
    271         if ToolsDefFile:
    272             ToolDef.LoadToolDefFile(os.path.normpath(ToolsDefFile))
    273         else:
    274             ToolDef.LoadToolDefFile(os.path.normpath(os.path.join(ConfDir, gDefaultToolsDefFile)))
    275     else:
    276         ToolDef.LoadToolDefFile(os.path.normpath(os.path.join(ConfDir, gDefaultToolsDefFile)))
    277     return ToolDef
    278 
    279 ##

    280 #

    281 # This acts like the main() function for the script, unless it is 'import'ed into another

    282 # script.

    283 #

    284 if __name__ == '__main__':
    285     ToolDef = ToolDefDict(os.getenv("WORKSPACE"))
    286     pass
    287