]>
Commit | Line | Data |
---|---|---|
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 |