Files
slimbootloader/BaseTools/Source/Python/Common/ToolDefClassObject.py

291 lines
12 KiB
Python
Raw Normal View History

Use LF line endings in the repository Convert the line endings stored for all text files in the repository to LF. The majority previously used DOS-style CRLF line endings. Add a .gitattributes file to enforce this and treat certain extensions as never being text files. Update PatchCheck.py to insist on LF line endings rather than CRLF. However, its other checks fail on this commit due to lots of pre-existing complaints that it only notices because the line endings have changed. Silicon/QemuSocPkg/FspBin/Patches/0001-Build-QEMU-FSP-2.0-binaries.patch needs to be treated as binary since it contains a mixture of line endings. This change has implications depending on the client platform you are using the repository from: * Windows The usual configuration for Git on Windows means that text files will be checked out to the work tree with DOS-style CRLF line endings. If that's not the case then you can configure Git to do so for the entire machine with: git config --global core.autocrlf true or for just the repository with: git config core.autocrlf true Line endings will be normalised to LF when they are committed to the repository. If you commit a text file with only LF line endings then it will be converted to CRLF line endings in your work tree. * Linux, MacOS and other Unices The usual configuration for Git on such platforms is to check files out of the repository with LF line endings. This is probably the right thing for you. In the unlikely even that you are using Git on Unix but editing or compiling on Windows for some reason then you may need to tweak your configuration to force the use of CRLF line endings as described above. * General For more information see https://docs.github.com/en/get-started/getting-started-with-git/configuring-git-to-handle-line-endings . Fixes: https://github.com/slimbootloader/slimbootloader/issues/1400 Signed-off-by: Mike Crowe <mac@mcrowe.com>
2021-11-10 11:36:23 +00:00
## @file
# This file is used to define each component of tools_def.txt file
#
# Copyright (c) 2007 - 2021, Intel Corporation. All rights reserved.<BR>
Use LF line endings in the repository Convert the line endings stored for all text files in the repository to LF. The majority previously used DOS-style CRLF line endings. Add a .gitattributes file to enforce this and treat certain extensions as never being text files. Update PatchCheck.py to insist on LF line endings rather than CRLF. However, its other checks fail on this commit due to lots of pre-existing complaints that it only notices because the line endings have changed. Silicon/QemuSocPkg/FspBin/Patches/0001-Build-QEMU-FSP-2.0-binaries.patch needs to be treated as binary since it contains a mixture of line endings. This change has implications depending on the client platform you are using the repository from: * Windows The usual configuration for Git on Windows means that text files will be checked out to the work tree with DOS-style CRLF line endings. If that's not the case then you can configure Git to do so for the entire machine with: git config --global core.autocrlf true or for just the repository with: git config core.autocrlf true Line endings will be normalised to LF when they are committed to the repository. If you commit a text file with only LF line endings then it will be converted to CRLF line endings in your work tree. * Linux, MacOS and other Unices The usual configuration for Git on such platforms is to check files out of the repository with LF line endings. This is probably the right thing for you. In the unlikely even that you are using Git on Unix but editing or compiling on Windows for some reason then you may need to tweak your configuration to force the use of CRLF line endings as described above. * General For more information see https://docs.github.com/en/get-started/getting-started-with-git/configuring-git-to-handle-line-endings . Fixes: https://github.com/slimbootloader/slimbootloader/issues/1400 Signed-off-by: Mike Crowe <mac@mcrowe.com>
2021-11-10 11:36:23 +00:00
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
##
# Import Modules
#
from __future__ import absolute_import
import Common.LongFilePathOs as os
import re
from . import EdkLogger
from .BuildToolError import *
from Common.TargetTxtClassObject import TargetTxtDict
from Common.LongFilePathSupport import OpenLongFilePath as open
from Common.Misc import PathClass
from Common.StringUtils import NormPath
import Common.GlobalData as GlobalData
from Common import GlobalData
from Common.MultipleWorkspace import MultipleWorkspace as mws
from .DataType import TAB_TOD_DEFINES_TARGET, TAB_TOD_DEFINES_TOOL_CHAIN_TAG,\
TAB_TOD_DEFINES_TARGET_ARCH, TAB_TOD_DEFINES_COMMAND_TYPE\
, TAB_TOD_DEFINES_FAMILY, TAB_TOD_DEFINES_BUILDRULEFAMILY,\
TAB_STAR, TAB_TAT_DEFINES_TOOL_CHAIN_CONF
##
# 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 is not None:
self.LoadToolDefFile(FileName)
## LoadToolDefFile
#
# Load target.txt file and parse it
#
# @param Filename: Input value for full path of tools_def.txt
#
def LoadToolDefFile(self, FileName):
# set multiple workspace
PackagesPath = os.getenv("PACKAGES_PATH")
mws.setWs(GlobalData.gWorkspace, PackagesPath)
self.ToolsDefTxtDatabase = {
TAB_TOD_DEFINES_TARGET : [],
TAB_TOD_DEFINES_TOOL_CHAIN_TAG : [],
TAB_TOD_DEFINES_TARGET_ARCH : [],
TAB_TOD_DEFINES_COMMAND_TYPE : []
}
self.IncludeToolDefFile(FileName)
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()
## IncludeToolDefFile
#
# Load target.txt file and parse it as if its contents were inside the main file
#
# @param Filename: Input value for full path of tools_def.txt
#
def IncludeToolDefFile(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)
for Index in range(len(FileContent)):
Line = FileContent[Index].strip()
if Line == "" or Line[0] == '#':
continue
if Line.startswith("!include"):
IncFile = Line[8:].strip()
Done, IncFile = self.ExpandMacros(IncFile)
if not Done:
EdkLogger.error("tools_def.txt parser", ATTRIBUTE_NOT_AVAILABLE,
"Macro or Environment has not been defined",
ExtraData=IncFile[4:-1], File=FileName, Line=Index+1)
IncFile = NormPath(IncFile)
if not os.path.isabs(IncFile):
#
# try WORKSPACE
#
IncFileTmp = PathClass(IncFile, GlobalData.gWorkspace)
ErrorCode = IncFileTmp.Validate()[0]
if ErrorCode != 0:
#
# try PACKAGES_PATH
#
IncFileTmp = mws.join(GlobalData.gWorkspace, IncFile)
if not os.path.exists(IncFileTmp):
#
# try directory of current file
#
IncFileTmp = PathClass(IncFile, os.path.dirname(FileName))
ErrorCode = IncFileTmp.Validate()[0]
if ErrorCode != 0:
EdkLogger.error("tools_def.txt parser", FILE_NOT_FOUND, ExtraData=IncFile)
if isinstance(IncFileTmp, PathClass):
IncFile = IncFileTmp.Path
else:
IncFile = IncFileTmp
self.IncludeToolDefFile(IncFile)
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] == TAB_STAR:
EdkLogger.verbose("Line %d: '*' is not allowed in last field: %s" % ((Index + 1), Name))
continue
else:
self.ToolsDefTxtDictionary[Name] = Value
if List[0] != TAB_STAR:
self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_TARGET] += [List[0]]
if List[1] != TAB_STAR:
self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_TOOL_CHAIN_TAG] += [List[1]]
if List[2] != TAB_STAR:
self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_TARGET_ARCH] += [List[2]]
if List[3] != TAB_STAR:
self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_COMMAND_TYPE] += [List[3]]
if List[4] == TAB_TOD_DEFINES_FAMILY and List[2] == TAB_STAR and List[3] == TAB_STAR:
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] == TAB_STAR and List[3] == TAB_STAR:
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
## 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):
# os.environ contains all environment variables uppercase on Windows which cause the key in the self.MacroDictionary is uppercase, but Ref may not
EnvReference = gEnvRefPattern.findall(Value)
for Ref in EnvReference:
if Ref not in self.MacroDictionary and Ref.upper() not in self.MacroDictionary:
Value = Value.replace(Ref, "")
else:
if Ref in self.MacroDictionary:
Value = Value.replace(Ref, self.MacroDictionary[Ref])
else:
Value = Value.replace(Ref, self.MacroDictionary[Ref.upper()])
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
#
class ToolDefDict():
def __new__(cls, ConfDir, *args, **kw):
if not hasattr(cls, '_instance'):
orig = super(ToolDefDict, cls)
cls._instance = orig.__new__(cls, *args, **kw)
return cls._instance
def __init__(self, ConfDir):
self.ConfDir = ConfDir
if not hasattr(self, 'ToolDef'):
self._ToolDef = None
@property
def ToolDef(self):
if not self._ToolDef:
self._GetToolDef()
return self._ToolDef
def _GetToolDef(self):
TargetObj = TargetTxtDict()
Target = TargetObj.Target
ToolDef = ToolDefClassObject()
if TAB_TAT_DEFINES_TOOL_CHAIN_CONF in Target.TargetTxtDictionary:
ToolsDefFile = Target.TargetTxtDictionary[TAB_TAT_DEFINES_TOOL_CHAIN_CONF]
if ToolsDefFile:
ToolDef.LoadToolDefFile(os.path.normpath(ToolsDefFile))
else:
ToolDef.LoadToolDefFile(os.path.normpath(os.path.join(self.ConfDir, gDefaultToolsDefFile)))
else:
ToolDef.LoadToolDefFile(os.path.normpath(os.path.join(self.ConfDir, gDefaultToolsDefFile)))
self._ToolDef = 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