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