git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@8964 6f19259b-4bc3-4df7-8a09-765794883524
		
			
				
	
	
		
			218 lines
		
	
	
		
			9.9 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			218 lines
		
	
	
		
			9.9 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
## @file
 | 
						|
# This file is used to define each component of tools_def.txt file
 | 
						|
#
 | 
						|
# Copyright (c) 2007, 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
 | 
						|
# http://opensource.org/licenses/bsd-license.php
 | 
						|
#
 | 
						|
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
 | 
						|
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 | 
						|
#
 | 
						|
 | 
						|
##
 | 
						|
# Import Modules
 | 
						|
#
 | 
						|
import os
 | 
						|
import re
 | 
						|
import EdkLogger
 | 
						|
 | 
						|
from Dictionary import *
 | 
						|
from BuildToolError import *
 | 
						|
from TargetTxtClassObject import *
 | 
						|
 | 
						|
##
 | 
						|
# Static vailabes used for pattern
 | 
						|
#
 | 
						|
gMacroRefPattern = re.compile('(DEF\([^\(\)]+\))')
 | 
						|
gEnvRefPattern = re.compile('(ENV\([^\(\)]+\))')
 | 
						|
gMacroDefPattern = re.compile("DEFINE\s+([^\s]+)")
 | 
						|
gDefaultToolsDefFile = "Conf/tools_def.txt"
 | 
						|
 | 
						|
## ToolDefClassObject
 | 
						|
#
 | 
						|
# This class defined content used in file tools_def.txt
 | 
						|
#
 | 
						|
# @param object:               Inherited from object class
 | 
						|
# @param Filename:             Input value for full path of tools_def.txt
 | 
						|
#
 | 
						|
# @var ToolsDefTxtDictionary:  To store keys and values defined in target.txt
 | 
						|
# @var MacroDictionary:        To store keys and values defined in DEFINE statement
 | 
						|
#
 | 
						|
class ToolDefClassObject(object):
 | 
						|
    def __init__(self, FileName = None):
 | 
						|
        self.ToolsDefTxtDictionary = {}
 | 
						|
        self.MacroDictionary = {}
 | 
						|
        for Env in os.environ:
 | 
						|
            self.MacroDictionary["ENV(%s)" % Env] = os.environ[Env]
 | 
						|
 | 
						|
        if FileName != None:
 | 
						|
            self.LoadToolDefFile(FileName)
 | 
						|
 | 
						|
    ## LoadToolDefFile
 | 
						|
    #
 | 
						|
    # Load target.txt file and parse it, return a set structure to store keys and values
 | 
						|
    #
 | 
						|
    # @param Filename:  Input value for full path of tools_def.txt
 | 
						|
    #
 | 
						|
    def LoadToolDefFile(self, FileName):
 | 
						|
        FileContent = []
 | 
						|
        if os.path.isfile(FileName):
 | 
						|
            try:
 | 
						|
                F = open(FileName,'r')
 | 
						|
                FileContent = F.readlines()
 | 
						|
            except:
 | 
						|
                EdkLogger.error("tools_def.txt parser", FILE_OPEN_FAILURE, ExtraData=FileName)
 | 
						|
        else:
 | 
						|
            EdkLogger.error("tools_def.txt parser", FILE_NOT_FOUND, ExtraData=FileName)
 | 
						|
 | 
						|
        self.ToolsDefTxtDatabase = {
 | 
						|
            TAB_TOD_DEFINES_TARGET          :   [],
 | 
						|
            TAB_TOD_DEFINES_TOOL_CHAIN_TAG  :   [],
 | 
						|
            TAB_TOD_DEFINES_TARGET_ARCH     :   [],
 | 
						|
            TAB_TOD_DEFINES_COMMAND_TYPE    :   []
 | 
						|
        }
 | 
						|
 | 
						|
        for Index in range(len(FileContent)):
 | 
						|
            Line = FileContent[Index].strip()
 | 
						|
            if Line == "" or Line[0] == '#':
 | 
						|
                continue
 | 
						|
            NameValuePair = Line.split("=", 1)
 | 
						|
            if len(NameValuePair) != 2:
 | 
						|
                EdkLogger.warn("tools_def.txt parser", "Line %d: not correct assignment statement, skipped" % (Index + 1))
 | 
						|
                continue
 | 
						|
 | 
						|
            Name = NameValuePair[0].strip()
 | 
						|
            Value = NameValuePair[1].strip()
 | 
						|
 | 
						|
            if Name == "IDENTIFIER":
 | 
						|
                EdkLogger.debug(EdkLogger.DEBUG_8, "Line %d: Found identifier statement, skipped: %s" % ((Index + 1), Value))
 | 
						|
                continue
 | 
						|
 | 
						|
            MacroDefinition = gMacroDefPattern.findall(Name)
 | 
						|
            if MacroDefinition != []:
 | 
						|
                Done, Value = self.ExpandMacros(Value)
 | 
						|
                if not Done:
 | 
						|
                    EdkLogger.error("tools_def.txt parser", ATTRIBUTE_NOT_AVAILABLE,
 | 
						|
                                    "Macro or Environment has not been defined",
 | 
						|
                                ExtraData=Value[4:-1], File=FileName, Line=Index+1)
 | 
						|
 | 
						|
                MacroName = MacroDefinition[0].strip()
 | 
						|
                self.MacroDictionary["DEF(%s)" % MacroName] = Value
 | 
						|
                EdkLogger.debug(EdkLogger.DEBUG_8, "Line %d: Found macro: %s = %s" % ((Index + 1), MacroName, Value))
 | 
						|
                continue
 | 
						|
 | 
						|
            Done, Value = self.ExpandMacros(Value)
 | 
						|
            if not Done:
 | 
						|
                EdkLogger.error("tools_def.txt parser", ATTRIBUTE_NOT_AVAILABLE,
 | 
						|
                                "Macro or Environment has not been defined",
 | 
						|
                                ExtraData=Value[4:-1], File=FileName, Line=Index+1)
 | 
						|
 | 
						|
            List = Name.split('_')
 | 
						|
            if len(List) != 5:
 | 
						|
                EdkLogger.verbose("Line %d: Not a valid name of definition: %s" % ((Index + 1), Name))
 | 
						|
                continue
 | 
						|
            elif List[4] == '*':
 | 
						|
                EdkLogger.verbose("Line %d: '*' is not allowed in last field: %s" % ((Index + 1), Name))
 | 
						|
                continue
 | 
						|
            else:
 | 
						|
                self.ToolsDefTxtDictionary[Name] = Value
 | 
						|
                if List[0] != '*':
 | 
						|
                    self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_TARGET] += [List[0]]
 | 
						|
                if List[1] != '*':
 | 
						|
                    self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_TOOL_CHAIN_TAG] += [List[1]]
 | 
						|
                if List[2] != '*':
 | 
						|
                    self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_TARGET_ARCH] += [List[2]]
 | 
						|
                if List[3] != '*':
 | 
						|
                    self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_COMMAND_TYPE] += [List[3]]
 | 
						|
                if List[4] == TAB_TOD_DEFINES_FAMILY and List[2] == '*' and List[3] == '*':
 | 
						|
                    if TAB_TOD_DEFINES_FAMILY not in self.ToolsDefTxtDatabase:
 | 
						|
                        self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_FAMILY] = {}
 | 
						|
                        self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_FAMILY][List[1]] = Value
 | 
						|
                        self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_BUILDRULEFAMILY] = {}
 | 
						|
                        self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_BUILDRULEFAMILY][List[1]] = Value
 | 
						|
                    elif List[1] not in self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_FAMILY]:
 | 
						|
                        self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_FAMILY][List[1]] = Value
 | 
						|
                        self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_BUILDRULEFAMILY][List[1]] = Value
 | 
						|
                    elif self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_FAMILY][List[1]] != Value:
 | 
						|
                        EdkLogger.verbose("Line %d: No override allowed for the family of a tool chain: %s" % ((Index + 1), Name))
 | 
						|
                if List[4] == TAB_TOD_DEFINES_BUILDRULEFAMILY and List[2] == '*' and List[3] == '*':
 | 
						|
                    if TAB_TOD_DEFINES_BUILDRULEFAMILY not in self.ToolsDefTxtDatabase \
 | 
						|
                       or List[1] not in self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_FAMILY]:
 | 
						|
                        EdkLogger.verbose("Line %d: The family is not specified, but BuildRuleFamily is specified for the tool chain: %s" % ((Index + 1), Name))
 | 
						|
                    self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_BUILDRULEFAMILY][List[1]] = Value
 | 
						|
 | 
						|
        self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_TARGET] = list(set(self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_TARGET]))
 | 
						|
        self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_TOOL_CHAIN_TAG] = list(set(self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_TOOL_CHAIN_TAG]))
 | 
						|
        self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_TARGET_ARCH] = list(set(self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_TARGET_ARCH]))
 | 
						|
        self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_COMMAND_TYPE] = list(set(self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_COMMAND_TYPE]))
 | 
						|
 | 
						|
        self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_TARGET].sort()
 | 
						|
        self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_TOOL_CHAIN_TAG].sort()
 | 
						|
        self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_TARGET_ARCH].sort()
 | 
						|
        self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_COMMAND_TYPE].sort()
 | 
						|
 | 
						|
        KeyList = [TAB_TOD_DEFINES_TARGET, TAB_TOD_DEFINES_TOOL_CHAIN_TAG, TAB_TOD_DEFINES_TARGET_ARCH, TAB_TOD_DEFINES_COMMAND_TYPE]
 | 
						|
        for Index in range(3,-1,-1):
 | 
						|
            for Key in dict(self.ToolsDefTxtDictionary):
 | 
						|
                List = Key.split('_')
 | 
						|
                if List[Index] == '*':
 | 
						|
                    for String in self.ToolsDefTxtDatabase[KeyList[Index]]:
 | 
						|
                        List[Index] = String
 | 
						|
                        NewKey = '%s_%s_%s_%s_%s' % tuple(List)
 | 
						|
                        if NewKey not in self.ToolsDefTxtDictionary:
 | 
						|
                            self.ToolsDefTxtDictionary[NewKey] = self.ToolsDefTxtDictionary[Key]
 | 
						|
                        continue
 | 
						|
                    del self.ToolsDefTxtDictionary[Key]
 | 
						|
                elif List[Index] not in self.ToolsDefTxtDatabase[KeyList[Index]]:
 | 
						|
                    del self.ToolsDefTxtDictionary[Key]
 | 
						|
 | 
						|
    ## ExpandMacros
 | 
						|
    #
 | 
						|
    # Replace defined macros with real value
 | 
						|
    #
 | 
						|
    # @param Value:   The string with unreplaced macros
 | 
						|
    #
 | 
						|
    # @retval Value:  The string which has been replaced with real value
 | 
						|
    #
 | 
						|
    def ExpandMacros(self, Value):
 | 
						|
        EnvReference = gEnvRefPattern.findall(Value)
 | 
						|
        for Ref in EnvReference:
 | 
						|
            if Ref not in self.MacroDictionary:
 | 
						|
                return False, Ref
 | 
						|
            Value = Value.replace(Ref, self.MacroDictionary[Ref])
 | 
						|
 | 
						|
        MacroReference = gMacroRefPattern.findall(Value)
 | 
						|
        for Ref in MacroReference:
 | 
						|
            if Ref not in self.MacroDictionary:
 | 
						|
                return False, Ref
 | 
						|
            Value = Value.replace(Ref, self.MacroDictionary[Ref])
 | 
						|
 | 
						|
        return True, Value
 | 
						|
 | 
						|
## ToolDefDict
 | 
						|
#
 | 
						|
# Load tools_def.txt in input workspace dir
 | 
						|
#
 | 
						|
# @param WorkSpace:  Workspace dir
 | 
						|
#
 | 
						|
# @retval ToolDef An instance of ToolDefClassObject() with loaded tools_def.txt
 | 
						|
#
 | 
						|
def ToolDefDict(WorkSpace):
 | 
						|
    Target = TargetTxtDict(WorkSpace)
 | 
						|
    ToolDef = ToolDefClassObject()
 | 
						|
    if DataType.TAB_TAT_DEFINES_TOOL_CHAIN_CONF in Target.TargetTxtDictionary:
 | 
						|
        gDefaultToolsDefFile = Target.TargetTxtDictionary[DataType.TAB_TAT_DEFINES_TOOL_CHAIN_CONF]
 | 
						|
    ToolDef.LoadToolDefFile(os.path.normpath(os.path.join(WorkSpace, gDefaultToolsDefFile)))
 | 
						|
    return ToolDef
 | 
						|
 | 
						|
##
 | 
						|
#
 | 
						|
# This acts like the main() function for the script, unless it is 'import'ed into another
 | 
						|
# script.
 | 
						|
#
 | 
						|
if __name__ == '__main__':
 | 
						|
    ToolDef = ToolDefDict(os.getenv("WORKSPACE"))
 | 
						|
    pass
 |