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 |
7 | Copyright (c) 2006, Intel Corporation\r |
8 | All rights reserved. This program and the accompanying materials\r |
9 | are licensed and made available under the terms and conditions of the BSD License\r |
10 | which accompanies this distribution. The full text of the license may be found at\r |
11 | http://opensource.org/licenses/bsd-license.php\r |
12 | \r |
13 | THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r |
14 | WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r |
15 | \r |
16 | **/\r |
17 | package org.tianocore.build.toolchain;\r |
18 | \r |
19 | import java.util.HashMap;\r |
20 | import java.util.Iterator;\r |
21 | import java.util.Map;\r |
22 | import java.util.Set;\r |
23 | import java.util.StringTokenizer;\r |
24 | import java.io.File;\r |
25 | \r |
26 | import 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 |
35 | public 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 |
392 | map = ConfigReader.parse(confPath, target + "_efi_flags.txt");\r |
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 |