The file name is in lower case.
[mirror_edk2.git] / Tools / Source / GenBuild / org / tianocore / build / toolchain / ToolChainFactory.java
CommitLineData
878ddf1f 1/** @file\r
2 ToolChainFactory class.\r
3 \r
4 ToolChainFactory class parse all config files and get STD_FLAGS, GLOBAL_FLAGS,\r
5 and also command path + name.\r
6 \r
7Copyright (c) 2006, Intel Corporation\r
8All rights reserved. This program and the accompanying materials\r
9are licensed and made available under the terms and conditions of the BSD License\r
10which accompanies this distribution. The full text of the license may be found at\r
11http://opensource.org/licenses/bsd-license.php\r
12\r
13THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
14WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
15\r
16**/\r
17package org.tianocore.build.toolchain;\r
18\r
19import java.util.HashMap;\r
20import java.util.Iterator;\r
21import java.util.Map;\r
22import java.util.Set;\r
23import java.util.StringTokenizer;\r
24import java.io.File;\r
25\r
26import org.apache.tools.ant.Project;\r
27\r
28\r
29/**\r
30 This class parse all config files and get STD_FLAGS, GLOBAL_FLAGS, and also \r
31 command path + name.\r
32 \r
33 @since GenBuild 1.0\r
34**/\r
35public class ToolChainFactory {\r
36 ///\r
37 /// list of Arch: EBC, ARM, IA32, X64, IPF, PPC\r
38 ///\r
39 public final static String[] arch = { "EBC", "ARM", "IA32", "X64", "IPF",\r
40 "PPC"};\r
41\r
42 ///\r
43 /// list of OS: Linux, Windows\r
44 ///\r
45 public final static String[] os = { "WINDOWS", "LINUX" };\r
46\r
47 ///\r
48 /// list of Command Type: CC, LIB, LINK, ASL, ASM, ASMLINK, PP\r
49 ///\r
50 public final static String[] commandType = { "CC", "LIB", "LINK", "ASL",\r
51 "ASM", "ASMLINK", "PP" };\r
52\r
53 ///\r
54 /// default command name for every command\r
55 ///\r
56 public final static String[][] defaultCmdName = { { "CC", "cl" },\r
57 { "LIB", "lib" }, { "LINK", "link" }, { "ASL", "iasl" },\r
58 { "ASM", "ml" }, { "ASMLINK", "link" }, { "PP", "cl" } };\r
59\r
60 private String confPath = ".";\r
61 \r
62 private String toolChainName = "MSFT";\r
63\r
64 private String sTargetFilename = "target.txt";\r
65\r
66 private String sToolsdefFilename = "tools_def.txt";\r
67\r
68 private String sWorkspaceTarget = "WORKSPACE_TARGET";\r
69\r
70 private String sTargetArch = "TARGET_ARCH";\r
71\r
72 private HashMap<String,String[][]> filesMap = new HashMap<String,String[][]>();\r
73 \r
74 private HashMap<String,String> globalFlagsMap = new HashMap<String,String>();\r
75 \r
76 private String[][] globalFlagTable;\r
77 \r
78 private String currentTarget = "RELEASE";\r
79\r
80 ///\r
81 /// toolchain array list all results by parsing config files\r
82 ///\r
83 public static String[][] toolchain = null;\r
84 \r
85 /**\r
86 Public construct method.\r
87 **/\r
88 public ToolChainFactory () {\r
89 }\r
90\r
91 /**\r
92 Public construct method.\r
93 \r
94 @param project current ANT Project.\r
95 **/\r
96 public ToolChainFactory (Project project) {\r
97 this.confPath = project.replaceProperties("${WORKSPACE_DIR}" + File.separatorChar + "Tools" + File.separatorChar + "Conf");\r
98 }\r
99 \r
100 /**\r
101 Public construct method.\r
102 \r
103 @param confPath the path of config files\r
104 @param toolChainName TOOL_CHAIN name\r
105 **/\r
106 public ToolChainFactory (String confPath, String toolChainName) {\r
107 this.confPath = confPath;\r
108 //\r
109 // If set tool used the set one, otherwise use default one.\r
110 // toolChain used to define open tools define txt file.\r
111 //\r
112 if (toolChainName != null && toolChainName.length() > 0){\r
113 this.toolChainName = toolChainName;\r
114 }\r
115 }\r
116\r
117 /**\r
118 Parse all config files, following are the detail steps:\r
119 \r
120 <ul>\r
121 <li>Parse target.txt file. This file define the current build TARGET \r
122 and supported ARCH list. </li>\r
123 <li>Parse tools_def.txt file. This file define every command name, path\r
124 and vendor. </li>\r
125 <li>For every supported ARCH and Command Type, find out STD_FLAGS, \r
126 GLOBAL_ADD_FLAGS, GLOBAL_SUB_FLAGS. </li>\r
127 </ul>\r
128 \r
129 <p>Note that this method will be called only once during the whole build\r
130 process. </p>\r
131 **/\r
132 public void setupToolChain() {\r
133 if (toolchain != null) {\r
134 return ;\r
135 }\r
136 Map<String, String> map = new HashMap<String, String>(40);\r
137 //\r
138 // parse target.txt\r
139 //\r
140 String[][] target = ConfigReader.parse(confPath, sTargetFilename);\r
141 //\r
142 // get workspace_target and initialize global flags setting\r
143 //\r
144 currentTarget = getValue(sWorkspaceTarget, target);\r
145 parseGlobalSetting(currentTarget);\r
146 String[] archList = getArchs(getValue(sTargetArch, target));\r
147 \r
148 //\r
149 // If user write the ${toolChain}_Tools_Def.txt use this one,\r
150 // otherwise used "tools_def.txt" file.\r
151 //\r
152 File tempFile = new File (confPath + File.separator + toolChainName.toLowerCase() + "_tools_def.txt");\r
153 if (tempFile.exists()){\r
154 sToolsdefFilename = toolChainName.toLowerCase() + "_tools_def.txt";\r
155 }\r
156 \r
157 System.out.println("Tools definition file is: " + sToolsdefFilename);\r
158 //\r
159 // parse tools_def.txt\r
160 //\r
161 String[][] tools_def = ConfigReader.parse(confPath, sToolsdefFilename);\r
162 //\r
163 // for each arch find all command's path&name and flags\r
164 //\r
165 for (int i = 0; i < archList.length; i++) {\r
166 for (int j = 0; j < commandType.length; j++) {\r
167 //\r
168 // Path & Name\r
169 //\r
170 map.put(archList[i] + "_" + commandType[j], getAbsoluteCmdPath(\r
171 archList[i], commandType[j], tools_def));\r
172 //\r
173 // Flags: CMD_STD_FLAGS + CMD_GLOBAL_FLAGS + CMD_PROJ_FLAGS\r
174 // ARCH_CMD_STD_FLAGS\r
175 //\r
176 map.put(archList[i] + "_" + commandType[j] + "_STD_FLAGS",\r
177 getStdFlags(archList[i], commandType[j],\r
178 tools_def));\r
179 //\r
180 // Flags:ARCH_CMD_VENDOR or ARCH_VENDOR\r
181 //\r
182 map.put(archList[i]+ "_"+commandType[j]+"_VENDOR", getVendorFlag(archList[i],\r
183 commandType[j], tools_def));\r
184 //\r
185 // ARCH_CMD_GLOBAL_FLAGS\r
186 //\r
187 String[] globalFlags = getGlobalFlags(archList[i], commandType[j],\r
188 tools_def);\r
189 map.put(archList[i] + "_" + commandType[j] + "_GLOBAL_ADD_FLAGS",\r
190 globalFlags[0]);\r
191 map.put(archList[i] + "_" + commandType[j] + "_GLOBAL_SUB_FLAGS",\r
192 globalFlags[1]);\r
193 //\r
194 // ARCH_CMD_GLOBAL_FLAGS, default is "".\r
195 //\r
196 map.put(archList[i] + "_" + commandType[j] + "_PROJ_FLAGS", "");\r
197 }\r
198 map.put(archList[i]+"_VENDOR", getVendorFlag(archList[i], null, tools_def));\r
199 }\r
200 Set keyset = map.keySet();\r
201 Iterator iter = keyset.iterator();\r
202 String[][] result = new String[map.size()][2];\r
203 int i = 0;\r
204 while (iter.hasNext()) {\r
205 String key = (String) iter.next();\r
206 result[i][0] = key;\r
207 result[i++][1] = (String) map.get(key);\r
208 }\r
209 toolchain = result;\r
210 }\r
211\r
212 /**\r
213 Get the standard flags (STD_FLAGS) for specified arch and command type. \r
214 \r
215 <ul>\r
216 <li>Find out Vendor that cmd Command Type with arch ARCH used. The \r
217 search sequence is ARCH_CMD_VENDOR -> ARCH_VENDOR -> "MSFT". Here\r
218 we suppose default Vendor is MSFT.</li>\r
219 <li>Search ${Vendor}_tools.txt file, and get the corrsponding flags. \r
220 </li>\r
221 </ul>\r
222 \r
223 @param arch the ARCH\r
224 @param cmd the command type\r
225 @param map detail flags information of tools_def.txt\r
226 @return the standard flags of arch ARCH and cmd Command Type \r
227 **/\r
228 private String getStdFlags(String arch, String cmd, String[][] map) {\r
229 //\r
230 // first is to find out its Vendor in map\r
231 // ARCH_CMD_VENDOR -> ARCH_VENDOR -> "MSFT"\r
232 // Here we suppose default Vendor is MSFT.\r
233 //\r
234 String vendor = "MSFT";\r
235 String str;\r
236 if ((str = getValue(arch + "_" + cmd + "_VENDOR", map)) != null) {\r
237 vendor = str;\r
238 } else if ((str = getValue(arch + "_VENDOR", map)) != null) {\r
239 vendor = str;\r
240 }\r
241 //\r
242 // change to low letter\r
243 //\r
244 vendor = vendor.toLowerCase();\r
245 //\r
246 // parse the corresponding file and get arch_cmd value\r
247 //\r
248 String filename = vendor + "_tools.txt";\r
249 String[][] flagsMap;\r
250 if (filesMap.containsKey(filename)) {\r
251 flagsMap = (String[][]) filesMap.get(filename);\r
252 } else {\r
253 //\r
254 // read file and store in filesMap\r
255 //\r
256 flagsMap = ConfigReader.parse(confPath, vendor + "_tools.txt");\r
257 filesMap.put(filename, flagsMap);\r
258 }\r
259 if ((str = getValue(arch + "_" + cmd, flagsMap)) != null) {\r
260 return str;\r
261 }\r
262 return "";\r
263 }\r
264\r
265 /**\r
266 Get the global flags (GLOBAL_ADD_FLAGS & GLOBAL_SUB_FLAGS) for specified \r
267 arch and command type. \r
268 \r
269 <ul>\r
270 <li>Find out Vendor that cmd Command Type with arch ARCH used. The \r
271 search sequence is ARCH_CMD_VENDOR -> ARCH_VENDOR -> "MSFT". Here\r
272 we suppose default Vendor is MSFT.</li>\r
273 <li>Search efi_flags_table.txt file, and get the corrsponding flags. \r
274 </li>\r
275 </ul>\r
276 \r
277 @param arch the ARCH\r
278 @param cmd the command type\r
279 @param map detail flags information of tools_def.txt\r
280 @return two values, first is GLOBAL_ADD_FLAGS and another value is \r
281 GLOBAL_SUB_FLAGS\r
282 **/\r
283 private String[] getGlobalFlags(String arch, String cmd, String[][] map) {\r
284 String addStr = "";\r
285 String subStr = "";\r
286 //\r
287 // first is to find out its Vendor in map\r
288 // ARCH_CMD_VENDOR -> ARCH_VENDOR -> "MSFT"\r
289 // Here we suppose default Vendor is MSFT.\r
290 //\r
291 String vendor = "MSFT";\r
292 String str;\r
293 if ((str = getValue(arch + "_" + cmd + "_VENDOR", map)) != null) {\r
294 vendor = str;\r
295 } else if ((str = getValue(arch + "_VENDOR", map)) != null) {\r
296 vendor = str;\r
297 }\r
298 //\r
299 // parse global flags table\r
300 //\r
301 if (globalFlagTable == null) {\r
302 globalFlagTable = ConfigReader.parseTable(confPath, "efi_flags_table.txt");\r
303 }\r
304 for (int i=0; i < globalFlagTable.length; i++){\r
305 String[] item = globalFlagTable[i];\r
306 if (item[2].equalsIgnoreCase(vendor + "_" + arch + "_" + cmd)){\r
307 //\r
308 // if item[0] == item[1] is existed in globalFlagsMap\r
309 //\r
310 if (globalFlagsMap.containsKey(item[0])){\r
311 if( item[1].equalsIgnoreCase((String)globalFlagsMap.get(item[0]))){\r
312 addStr += item[3] + " ";\r
313 subStr += item[4] + " ";\r
314 }\r
315 }\r
316 }\r
317 }\r
318 \r
319 return new String[]{addStr, subStr};\r
320 }\r
321\r
322 /**\r
323 Find out command path and command name. \r
324 \r
325 <pre>\r
326 Command path searching sequence in tools_def.txt file:\r
327 Path: ARCH_CMD_PATH -> ARCH_PATH -> Set to "".\r
328 \r
329 Command name searching sequence in tools_def.txt file:\r
330 Name: ARCH_CMD_NAME -> CMD_NAME -> Default Value.\r
331 </pre>\r
332 \r
333 @param arch the ARCH\r
334 @param cmd the Command Type\r
335 @param map detail flags information of tools_def.txt\r
336 @return the absolute command path and name\r
337 **/\r
338 private String getAbsoluteCmdPath(String arch, String cmd, String[][] map) {\r
339 String path = "";\r
340 String name = "";\r
341 String str;\r
342 //\r
343 // find Path\r
344 //\r
345 if ((str = getValue(arch + "_" + cmd + "_PATH", map)) != null) {\r
346 path = str;\r
347 } else if ((str = getValue(arch + "_PATH", map)) != null) {\r
348 path = str;\r
349 }\r
350 //\r
351 // find Name\r
352 //\r
353 if ((str = getValue(arch + "_" + cmd + "_NAME", map)) != null) {\r
354 name = str;\r
355 } else if ((str = getValue(cmd + "_NAME", map)) != null) {\r
356 name = str;\r
357 } else {\r
358 name = getValue(cmd, defaultCmdName);\r
359 }\r
360 if (path.equalsIgnoreCase("")) {\r
361 return name;\r
362 }\r
363 return path + File.separatorChar + name;\r
364 }\r
365\r
366 /**\r
367 Find out all global flags value, such as EFI_DEBUG equal YES or NO. Here \r
368 are three type files: global_efi_flags.txt, ${TARGET}_efi_flags.txt, \r
369 my_efi_flags.txt. global_efi_flags.txt with the highest priority while \r
370 my_efi_flags.txt with the lowest priority. \r
371 \r
372 <p>All global flags value will store in <code>globalFlagsMap</code> for \r
373 getGlobalFlags using. </p> \r
374 \r
375 @param target current build TARGET value\r
376 **/\r
377 private void parseGlobalSetting(String target){\r
378 //\r
379 // parse global_efi_flags -> ${TARGET}_efi_flags -> my_efi_flags\r
380 // parse global_efi_flags\r
381 //\r
382 String[][] map = ConfigReader.parse(confPath, "global_efi_flags.txt");\r
383 for (int i = 0; i < map.length; i++){\r
384 if(globalFlagsMap.containsKey(map[i][0])){\r
385 globalFlagsMap.remove(map[i][0]);\r
386 }\r
387 globalFlagsMap.put(map[i][0], map[i][1]);\r
388 }\r
389 //\r
390 // parse ${TARGET}_efi_flags\r
391 //\r
c4e0f33e 392 map = ConfigReader.parse(confPath, target.toLowerCase() + "_efi_flags.txt");\r
878ddf1f 393 for (int i = 0; i < map.length; i++){\r
394 if(globalFlagsMap.containsKey(map[i][0])){\r
395 globalFlagsMap.remove(map[i][0]);\r
396 }\r
397 globalFlagsMap.put(map[i][0], map[i][1]);\r
398 }\r
399 //\r
400 // parse my_efi_flags.txt\r
401 //\r
402 map = ConfigReader.parse(confPath, "my_efi_flags.txt");\r
403 for (int i = 0; i < map.length; i++){\r
404 if(globalFlagsMap.containsKey(map[i][0])){\r
405 globalFlagsMap.remove(map[i][0]);\r
406 }\r
407 globalFlagsMap.put(map[i][0], map[i][1]);\r
408 }\r
409 }\r
410 \r
411 /**\r
412 Find value with key from map. If not found, return null. \r
413 \r
414 <p>Note that default is case-insensitive</p>\r
415 \r
416 @param key key value\r
417 @param map mapping information\r
418 @return the related value of key\r
419 **/\r
420 private String getValue(String key, String[][] map) {\r
421 return getValue(key, map, false);\r
422 }\r
423\r
424 /**\r
425 Find value with key from map. If not found, return null. \r
426 \r
427 @param key key value\r
428 @param map mapping information\r
429 @param caseSensitive whether case sesitive or not\r
430 @return the related value of key\r
431 **/\r
432 private String getValue(String key, String[][] map, boolean caseSensitive) {\r
433 for (int i = 0; i < map.length; i++) {\r
434 if (caseSensitive) {\r
435 if (key.compareTo(map[i][0]) == 0) {\r
436 return map[i][1];\r
437 }\r
438 } else {\r
439 if (key.compareToIgnoreCase(map[i][0]) == 0) {\r
440 return map[i][1];\r
441 }\r
442 }\r
443 }\r
444 return null;\r
445 }\r
446\r
447 /**\r
448 Find value with key from <code>toolchain</code>. If not found, return null. \r
449 \r
450 @param key key value\r
451 @return the related value of key\r
452 **/\r
453 public static String getValue(String key){\r
454 for (int i = 0; i < toolchain.length; i++) {\r
455 if (key.compareToIgnoreCase(toolchain[i][0]) == 0) {\r
456 return toolchain[i][1];\r
457 }\r
458 }\r
459 return null;\r
460 }\r
461 \r
462 /**\r
463 Get Arch list from a string separated with comma. \r
464 \r
465 <pre>\r
466 For example:\r
467 If the arch string is "IA32, X64, EBC".\r
468 Then the result is {"IA32", "X64", "EBC"}. \r
469 </pre>\r
470 \r
471 @param arch string separated with comma\r
472 @return Arch list\r
473 **/\r
474 public String[] getArchs(String arch) {\r
475 if (arch == null) {\r
476 return new String[0];\r
477 }\r
478 StringTokenizer st = new StringTokenizer(arch, " \t,");\r
479 String[] archs = new String[st.countTokens()];\r
480 int i = 0;\r
481 while (st.hasMoreTokens()) {\r
482 archs[i++] = st.nextToken().toUpperCase();\r
483 }\r
484 return archs;\r
485 }\r
486\r
487 /**\r
488 Get current target value.\r
489 \r
490 @return current target value\r
491 **/\r
492 public String getCurrentTarget() {\r
493 return currentTarget;\r
494 }\r
495\r
496 /**\r
497 Find out Vendor that cmd Command Type with arch ARCH used. The \r
498 search sequence is ARCH_CMD_VENDOR -> ARCH_VENDOR -> "MSFT". Here\r
499 we suppose default Vendor is MSFT.\r
500 \r
501 @param arch the ARCH\r
502 @param cmd the Command Type\r
503 @param map detail flags information of tools_def.txt\r
504 @return the related vendor name\r
505 **/\r
506 public String getVendorFlag (String arch, String cmdType, String[][] map){\r
507 //\r
508 // ARCH_CMD_VENDOR -> ARCH_VENDOR -> "MSFT"\r
509 // Here we suppose default Vendor is MSFT.\r
510 //\r
511 String str;\r
512 String vendor = "";\r
513 if (cmdType != null){\r
514 if ((str = getValue(arch + "_" + cmdType + "_VENDOR", map)) != null) {\r
515 vendor = str; \r
516 }else {\r
517 vendor = "";\r
518 }\r
519 }else if (arch != null){\r
520 if ((str = getValue(arch + "_VENDOR", map)) != null) {\r
521 vendor = str; \r
522 }else {\r
523 vendor = "";\r
524 }\r
525 }\r
526 return vendor;\r
527 }\r
528 \r
529}\r