Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Yingke Liu <yingke.d.liu@intel.com> Reviewed-by: Liming Gao <liming.gao@intel.com> git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@15971 6f19259b-4bc3-4df7-8a09-765794883524
		
			
				
	
	
		
			226 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			226 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| ## @file
 | |
| # This file is used to define each component of tools_def.txt file
 | |
| #
 | |
| # Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.<BR>
 | |
| # 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 Common.LongFilePathOs as os
 | |
| import re
 | |
| import EdkLogger
 | |
| 
 | |
| from Dictionary import *
 | |
| from BuildToolError import *
 | |
| from TargetTxtClassObject import *
 | |
| from Common.LongFilePathSupport import OpenLongFilePath as open
 | |
| 
 | |
| ##
 | |
| # Static variables used for pattern
 | |
| #
 | |
| gMacroRefPattern = re.compile('(DEF\([^\(\)]+\))')
 | |
| gEnvRefPattern = re.compile('(ENV\([^\(\)]+\))')
 | |
| gMacroDefPattern = re.compile("DEFINE\s+([^\s]+)")
 | |
| gDefaultToolsDefFile = "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:
 | |
|                 Value = Value.replace(Ref, "")
 | |
|             else:
 | |
|                 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 Conf dir
 | |
| #
 | |
| # @param ConfDir:  Conf dir
 | |
| #
 | |
| # @retval ToolDef An instance of ToolDefClassObject() with loaded tools_def.txt
 | |
| #
 | |
| def ToolDefDict(ConfDir):
 | |
|     Target = TargetTxtDict(ConfDir)
 | |
|     ToolDef = ToolDefClassObject()
 | |
|     if DataType.TAB_TAT_DEFINES_TOOL_CHAIN_CONF in Target.TargetTxtDictionary:
 | |
|         ToolsDefFile = Target.TargetTxtDictionary[DataType.TAB_TAT_DEFINES_TOOL_CHAIN_CONF]
 | |
|         if ToolsDefFile:
 | |
|             ToolDef.LoadToolDefFile(os.path.normpath(ToolsDefFile))
 | |
|         else:
 | |
|             ToolDef.LoadToolDefFile(os.path.normpath(os.path.join(ConfDir, gDefaultToolsDefFile)))
 | |
|     else:
 | |
|         ToolDef.LoadToolDefFile(os.path.normpath(os.path.join(ConfDir, 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
 |