Maintainers.txt: Update email address
[mirror_edk2.git] / BaseTools / Source / Python / TargetTool / TargetTool.py
1 ## @file
2 # Target Tool Parser
3 #
4 # Copyright (c) 2007 - 2021, Intel Corporation. All rights reserved.<BR>
5 #
6 # SPDX-License-Identifier: BSD-2-Clause-Patent
7 #
8
9 from __future__ import print_function
10 import Common.LongFilePathOs as os
11 import sys
12 import traceback
13 from optparse import OptionParser
14
15 import Common.EdkLogger as EdkLogger
16 import Common.BuildToolError as BuildToolError
17 from Common.DataType import *
18 from Common.BuildVersion import gBUILD_VERSION
19 from Common.LongFilePathSupport import OpenLongFilePath as open
20 from Common.TargetTxtClassObject import gDefaultTargetTxtFile
21
22 # To Do 1.set clean, 2. add item, if the line is disabled.
23
24 class TargetTool():
25 def __init__(self, opt, args):
26 self.WorkSpace = os.path.normpath(os.getenv('WORKSPACE'))
27 self.Opt = opt
28 self.Arg = args[0]
29 self.FileName = os.path.normpath(os.path.join(self.WorkSpace, 'Conf', gDefaultTargetTxtFile))
30 if os.path.isfile(self.FileName) == False:
31 print("%s does not exist." % self.FileName)
32 sys.exit(1)
33 self.TargetTxtDictionary = {
34 TAB_TAT_DEFINES_ACTIVE_PLATFORM : None,
35 TAB_TAT_DEFINES_TOOL_CHAIN_CONF : None,
36 TAB_TAT_DEFINES_MAX_CONCURRENT_THREAD_NUMBER : None,
37 TAB_TAT_DEFINES_TARGET : None,
38 TAB_TAT_DEFINES_TOOL_CHAIN_TAG : None,
39 TAB_TAT_DEFINES_TARGET_ARCH : None,
40 TAB_TAT_DEFINES_BUILD_RULE_CONF : None,
41 }
42 self.LoadTargetTxtFile(self.FileName)
43
44 def LoadTargetTxtFile(self, filename):
45 if os.path.exists(filename) and os.path.isfile(filename):
46 return self.ConvertTextFileToDict(filename, '#', '=')
47 else:
48 raise ParseError('LoadTargetTxtFile() : No Target.txt file exists.')
49 return 1
50
51 #
52 # Convert a text file to a dictionary
53 #
54 def ConvertTextFileToDict(self, FileName, CommentCharacter, KeySplitCharacter):
55 """Convert a text file to a dictionary of (name:value) pairs."""
56 try:
57 f = open(FileName, 'r')
58 for Line in f:
59 if Line.startswith(CommentCharacter) or Line.strip() == '':
60 continue
61 LineList = Line.split(KeySplitCharacter, 1)
62 if len(LineList) >= 2:
63 Key = LineList[0].strip()
64 if Key.startswith(CommentCharacter) == False and Key in self.TargetTxtDictionary:
65 if Key == TAB_TAT_DEFINES_ACTIVE_PLATFORM or Key == TAB_TAT_DEFINES_TOOL_CHAIN_CONF \
66 or Key == TAB_TAT_DEFINES_MAX_CONCURRENT_THREAD_NUMBER \
67 or Key == TAB_TAT_DEFINES_ACTIVE_MODULE:
68 self.TargetTxtDictionary[Key] = LineList[1].replace('\\', '/').strip()
69 elif Key == TAB_TAT_DEFINES_TARGET or Key == TAB_TAT_DEFINES_TARGET_ARCH \
70 or Key == TAB_TAT_DEFINES_TOOL_CHAIN_TAG or Key == TAB_TAT_DEFINES_BUILD_RULE_CONF:
71 self.TargetTxtDictionary[Key] = LineList[1].split()
72 f.close()
73 return 0
74 except:
75 last_type, last_value, last_tb = sys.exc_info()
76 traceback.print_exception(last_type, last_value, last_tb)
77
78 def Print(self):
79 errMsg = ''
80 for Key in self.TargetTxtDictionary:
81 if isinstance(self.TargetTxtDictionary[Key], type([])):
82 print("%-30s = %s" % (Key, ''.join(elem + ' ' for elem in self.TargetTxtDictionary[Key])))
83 elif self.TargetTxtDictionary[Key] is None:
84 errMsg += " Missing %s configuration information, please use TargetTool to set value!" % Key + os.linesep
85 else:
86 print("%-30s = %s" % (Key, self.TargetTxtDictionary[Key]))
87
88 if errMsg != '':
89 print(os.linesep + 'Warning:' + os.linesep + errMsg)
90
91 def RWFile(self, CommentCharacter, KeySplitCharacter, Num):
92 try:
93 fr = open(self.FileName, 'r')
94 fw = open(os.path.normpath(os.path.join(self.WorkSpace, 'Conf\\targetnew.txt')), 'w')
95
96 existKeys = []
97 for Line in fr:
98 if Line.startswith(CommentCharacter) or Line.strip() == '':
99 fw.write(Line)
100 else:
101 LineList = Line.split(KeySplitCharacter, 1)
102 if len(LineList) >= 2:
103 Key = LineList[0].strip()
104 if Key.startswith(CommentCharacter) == False and Key in self.TargetTxtDictionary:
105 if Key not in existKeys:
106 existKeys.append(Key)
107 else:
108 print("Warning: Found duplicate key item in original configuration files!")
109
110 if Num == 0:
111 Line = "%-30s = \n" % Key
112 else:
113 ret = GetConfigureKeyValue(self, Key)
114 if ret is not None:
115 Line = ret
116 fw.write(Line)
117 for key in self.TargetTxtDictionary:
118 if key not in existKeys:
119 print("Warning: %s does not exist in original configuration file" % key)
120 Line = GetConfigureKeyValue(self, key)
121 if Line is None:
122 Line = "%-30s = " % key
123 fw.write(Line)
124
125 fr.close()
126 fw.close()
127 os.remove(self.FileName)
128 os.rename(os.path.normpath(os.path.join(self.WorkSpace, 'Conf\\targetnew.txt')), self.FileName)
129
130 except:
131 last_type, last_value, last_tb = sys.exc_info()
132 traceback.print_exception(last_type, last_value, last_tb)
133
134 def GetConfigureKeyValue(self, Key):
135 Line = None
136 if Key == TAB_TAT_DEFINES_ACTIVE_PLATFORM and self.Opt.DSCFILE is not None:
137 dscFullPath = os.path.join(self.WorkSpace, self.Opt.DSCFILE)
138 if os.path.exists(dscFullPath):
139 Line = "%-30s = %s\n" % (Key, self.Opt.DSCFILE)
140 else:
141 EdkLogger.error("TargetTool", BuildToolError.FILE_NOT_FOUND,
142 "DSC file %s does not exist!" % self.Opt.DSCFILE, RaiseError=False)
143 elif Key == TAB_TAT_DEFINES_TOOL_CHAIN_CONF and self.Opt.TOOL_DEFINITION_FILE is not None:
144 tooldefFullPath = os.path.join(self.WorkSpace, self.Opt.TOOL_DEFINITION_FILE)
145 if os.path.exists(tooldefFullPath):
146 Line = "%-30s = %s\n" % (Key, self.Opt.TOOL_DEFINITION_FILE)
147 else:
148 EdkLogger.error("TargetTool", BuildToolError.FILE_NOT_FOUND,
149 "Tooldef file %s does not exist!" % self.Opt.TOOL_DEFINITION_FILE, RaiseError=False)
150
151 elif self.Opt.NUM >= 2:
152 Line = "%-30s = %s\n" % (Key, 'Enable')
153 elif self.Opt.NUM <= 1:
154 Line = "%-30s = %s\n" % (Key, 'Disable')
155 elif Key == TAB_TAT_DEFINES_MAX_CONCURRENT_THREAD_NUMBER and self.Opt.NUM is not None:
156 Line = "%-30s = %s\n" % (Key, str(self.Opt.NUM))
157 elif Key == TAB_TAT_DEFINES_TARGET and self.Opt.TARGET is not None:
158 Line = "%-30s = %s\n" % (Key, ''.join(elem + ' ' for elem in self.Opt.TARGET))
159 elif Key == TAB_TAT_DEFINES_TARGET_ARCH and self.Opt.TARGET_ARCH is not None:
160 Line = "%-30s = %s\n" % (Key, ''.join(elem + ' ' for elem in self.Opt.TARGET_ARCH))
161 elif Key == TAB_TAT_DEFINES_TOOL_CHAIN_TAG and self.Opt.TOOL_CHAIN_TAG is not None:
162 Line = "%-30s = %s\n" % (Key, self.Opt.TOOL_CHAIN_TAG)
163 elif Key == TAB_TAT_DEFINES_BUILD_RULE_CONF and self.Opt.BUILD_RULE_FILE is not None:
164 buildruleFullPath = os.path.join(self.WorkSpace, self.Opt.BUILD_RULE_FILE)
165 if os.path.exists(buildruleFullPath):
166 Line = "%-30s = %s\n" % (Key, self.Opt.BUILD_RULE_FILE)
167 else:
168 EdkLogger.error("TagetTool", BuildToolError.FILE_NOT_FOUND,
169 "Build rule file %s does not exist!" % self.Opt.BUILD_RULE_FILE, RaiseError=False)
170 return Line
171
172 VersionNumber = ("0.01" + " " + gBUILD_VERSION)
173 __version__ = "%prog Version " + VersionNumber
174 __copyright__ = "Copyright (c) 2007 - 2018, Intel Corporation All rights reserved."
175 __usage__ = "%prog [options] {args} \
176 \nArgs: \
177 \n Clean clean the all default configuration of target.txt. \
178 \n Print print the all default configuration of target.txt. \
179 \n Set replace the default configuration with expected value specified by option."
180
181 gParamCheck = []
182 def SingleCheckCallback(option, opt_str, value, parser):
183 if option not in gParamCheck:
184 setattr(parser.values, option.dest, value)
185 gParamCheck.append(option)
186 else:
187 parser.error("Option %s only allows one instance in command line!" % option)
188
189 def RangeCheckCallback(option, opt_str, value, parser):
190 if option not in gParamCheck:
191 gParamCheck.append(option)
192 if value < 1 or value > 8:
193 parser.error("The count of multi-thread is not in valid range of 1 ~ 8.")
194 else:
195 setattr(parser.values, option.dest, value)
196 else:
197 parser.error("Option %s only allows one instance in command line!" % option)
198
199 def MyOptionParser():
200 parser = OptionParser(version=__version__, prog="TargetTool.exe", usage=__usage__, description=__copyright__)
201 parser.add_option("-a", "--arch", action="append", dest="TARGET_ARCH",
202 help="ARCHS is one of list: IA32, X64, ARM, AARCH64 or EBC, which replaces target.txt's TARGET_ARCH definition. To specify more archs, please repeat this option. 0 will clear this setting in target.txt and can't combine with other value.")
203 parser.add_option("-p", "--platform", action="callback", type="string", dest="DSCFILE", callback=SingleCheckCallback,
204 help="Specify a DSC file, which replace target.txt's ACTIVE_PLATFORM definition. 0 will clear this setting in target.txt and can't combine with other value.")
205 parser.add_option("-c", "--tooldef", action="callback", type="string", dest="TOOL_DEFINITION_FILE", callback=SingleCheckCallback,
206 help="Specify the WORKSPACE relative path of tool_def.txt file, which replace target.txt's TOOL_CHAIN_CONF definition. 0 will clear this setting in target.txt and can't combine with other value.")
207 parser.add_option("-t", "--target", action="append", type="choice", choices=['DEBUG', 'RELEASE', '0'], dest="TARGET",
208 help="TARGET is one of list: DEBUG, RELEASE, which replaces target.txt's TARGET definition. To specify more TARGET, please repeat this option. 0 will clear this setting in target.txt and can't combine with other value.")
209 parser.add_option("-n", "--tagname", action="callback", type="string", dest="TOOL_CHAIN_TAG", callback=SingleCheckCallback,
210 help="Specify the Tool Chain Tagname, which replaces target.txt's TOOL_CHAIN_TAG definition. 0 will clear this setting in target.txt and can't combine with other value.")
211 parser.add_option("-r", "--buildrule", action="callback", type="string", dest="BUILD_RULE_FILE", callback=SingleCheckCallback,
212 help="Specify the build rule configure file, which replaces target.txt's BUILD_RULE_CONF definition. If not specified, the default value Conf/build_rule.txt will be set.")
213 parser.add_option("-m", "--multithreadnum", action="callback", type="int", dest="NUM", callback=RangeCheckCallback,
214 help="Specify the multi-thread number which replace target.txt's MAX_CONCURRENT_THREAD_NUMBER. If the value is less than 2, MULTIPLE_THREAD will be disabled. If the value is larger than 1, MULTIPLE_THREAD will be enabled.")
215 (opt, args)=parser.parse_args()
216 return (opt, args)
217
218 if __name__ == '__main__':
219 EdkLogger.Initialize()
220 EdkLogger.SetLevel(EdkLogger.QUIET)
221 if os.getenv('WORKSPACE') is None:
222 print("ERROR: WORKSPACE should be specified or edksetup script should be executed before run TargetTool")
223 sys.exit(1)
224
225 (opt, args) = MyOptionParser()
226 if len(args) != 1 or (args[0].lower() != 'print' and args[0].lower() != 'clean' and args[0].lower() != 'set'):
227 print("The number of args isn't 1 or the value of args is invalid.")
228 sys.exit(1)
229 if opt.NUM is not None and opt.NUM < 1:
230 print("The MAX_CONCURRENT_THREAD_NUMBER must be larger than 0.")
231 sys.exit(1)
232 if opt.TARGET is not None and len(opt.TARGET) > 1:
233 for elem in opt.TARGET:
234 if elem == '0':
235 print("0 will clear the TARGET setting in target.txt and can't combine with other value.")
236 sys.exit(1)
237 if opt.TARGET_ARCH is not None and len(opt.TARGET_ARCH) > 1:
238 for elem in opt.TARGET_ARCH:
239 if elem == '0':
240 print("0 will clear the TARGET_ARCH setting in target.txt and can't combine with other value.")
241 sys.exit(1)
242
243 try:
244 FileHandle = TargetTool(opt, args)
245 if FileHandle.Arg.lower() == 'print':
246 FileHandle.Print()
247 sys.exit(0)
248 elif FileHandle.Arg.lower() == 'clean':
249 FileHandle.RWFile('#', '=', 0)
250 else:
251 FileHandle.RWFile('#', '=', 1)
252 except Exception as e:
253 last_type, last_value, last_tb = sys.exc_info()
254 traceback.print_exception(last_type, last_value, last_tb)
255