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