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