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