Follow up EDKT247-253
[mirror_edk2.git] / Tools / Source / GenBuild / org / tianocore / build / FrameworkBuildTask.java
CommitLineData
de4bb9f6 1/** @file FrameworkBuildTask.java\r
2 \r
3 The file is ANT task to find MSA or FPD file and build them. \r
4 \r
5 Copyright (c) 2006, Intel Corporation\r
6 All rights reserved. This program and the accompanying materials\r
7 are licensed and made available under the terms and conditions of the BSD License\r
8 which accompanies this distribution. The full text of the license may be found at\r
9 http://opensource.org/licenses/bsd-license.php\r
10\r
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
13 **/\r
a29c47e0 14package org.tianocore.build;\r
15\r
16import java.io.BufferedReader;\r
17import java.io.File;\r
18import java.io.InputStreamReader;\r
aca6c736 19import java.util.Hashtable;\r
a29c47e0 20import java.util.Iterator;\r
21import java.util.LinkedHashSet;\r
22import java.util.Map;\r
23import java.util.Set;\r
24\r
25import org.apache.tools.ant.BuildException;\r
26import org.apache.tools.ant.Task;\r
19bf6b15 27import org.tianocore.build.fpd.FpdParserForThread;\r
a29c47e0 28import org.tianocore.build.fpd.FpdParserTask;\r
29import org.tianocore.build.global.GlobalData;\r
de4bb9f6 30import org.tianocore.build.toolchain.ConfigReader;\r
a29c47e0 31import org.tianocore.build.toolchain.ToolChainInfo;\r
4a6a5026 32import org.tianocore.common.definitions.ToolDefinitions;\r
a29c47e0 33\r
2d16dcec 34/**\r
35 <p>\r
36 <code>FrameworkBuildTask</code> is an Ant task. The main function is finding\r
37 and processing a FPD or MSA file, then building a platform or stand-alone \r
38 module. \r
39 \r
40 <p>\r
41 The task search current directory and find out all MSA and FPD files by file\r
42 extension. Base on ACTIVE_PLATFORM policy, decide to build a platform or a\r
43 stand-alone module. The ACTIVE_PLATFORM policy is: \r
44 \r
45 <pre>\r
46 1. More than one MSA files, report error; \r
47 2. Only one MSA file, but ACTIVE_PLATFORM is not specified, report error;\r
48 3. Only one MSA file, and ACTIVE_PLATFORM is also specified, build this module;\r
49 4. No MSA file, and ACTIVE_PLATFORM is specified, build the active platform;\r
50 5. No MSA file, no ACTIVE_PLATFORM, and no FPD file, report error;\r
51 6. No MSA file, no ACTIVE_PLATFORM, and only one FPD file, build the platform;\r
52 7. No MSA file, no ACTIVE_PLATFORM, and more than one FPD files, list all platform\r
53 and let user choose one. \r
54 </pre>\r
55 \r
56 <p>\r
57 Framework build task also parse target file [${WORKSPACE_DIR}/Tools/Conf/target.txt].\r
58 And load all system environment variables to Ant properties. \r
59 \r
60 <p>\r
61 The usage for this task is : \r
62 \r
63 <pre>\r
64 &lt;FrameworkBuild type="cleanall" /&gt;\r
65 </pre>\r
66 \r
67 @since GenBuild 1.0\r
68**/\r
a29c47e0 69public class FrameworkBuildTask extends Task{\r
70\r
71 private Set<File> buildFiles = new LinkedHashSet<File>();\r
72 \r
73 private Set<File> fpdFiles = new LinkedHashSet<File>();\r
74 \r
75 private Set<File> msaFiles = new LinkedHashSet<File>();\r
76 \r
aca6c736 77 //\r
78 // This is only for none-multi-thread build to reduce overriding message\r
79 //\r
80 public static Hashtable<String, String> originalProperties = new Hashtable<String, String>();\r
81 \r
4a6a5026 82 String toolsDefFilename = ToolDefinitions.DEFAULT_TOOLS_DEF_FILE_PATH;\r
de4bb9f6 83 \r
4a6a5026 84 String targetFilename = ToolDefinitions.TARGET_FILE_PATH;\r
85 \r
86 String dbFilename = ToolDefinitions.FRAMEWORK_DATABASE_FILE_PATH;\r
de4bb9f6 87 \r
88 String activePlatform = null;\r
aca6c736 89\r
19bf6b15 90 ///\r
91 /// The flag to present current is multi-thread enabled\r
92 ///\r
93 public static boolean multithread = false;\r
aca6c736 94\r
19bf6b15 95 ///\r
96 /// The concurrent thread number\r
97 ///\r
98 public static int MAX_CONCURRENT_THREAD_NUMBER = 1;\r
aca6c736 99\r
a29c47e0 100 ///\r
101 /// there are three type: all (build), clean and cleanall\r
102 ///\r
103 private String type = "all";\r
104 \r
105 public void execute() throws BuildException {\r
106 //\r
107 // Seach build.xml -> .FPD -> .MSA file\r
108 //\r
109 try {\r
110 //\r
111 // Gen Current Working Directory\r
112 //\r
113 File dummyFile = new File(".");\r
114 File cwd = dummyFile.getCanonicalFile();\r
115 File[] files = cwd.listFiles();\r
116 for (int i = 0; i < files.length; i++) {\r
117 if (files[i].isFile()) {\r
118 if (files[i].getName().equalsIgnoreCase("build.xml")) {\r
119 //\r
120 // First, search build.xml, if found, ANT call it\r
121 //\r
122 buildFiles.add(files[i]);\r
123\r
4a6a5026 124 } else if (files[i].getName().endsWith(ToolDefinitions.FPD_EXTENSION)) {\r
a29c47e0 125 //\r
126 // Second, search FPD file, if found, build it\r
127 //\r
128 fpdFiles.add(files[i]);\r
4a6a5026 129 } else if (files[i].getName().endsWith(ToolDefinitions.MSA_EXTENSION)) {\r
a29c47e0 130 //\r
131 // Third, search MSA file, if found, build it\r
132 //\r
133 msaFiles.add(files[i]);\r
134 }\r
135 }\r
136 }\r
137 } catch (Exception e) {\r
a29c47e0 138 throw new BuildException(e.getMessage());\r
139 }\r
140 \r
a29c47e0 141 //\r
142 // Deal with all environment variable (Add them to properties)\r
143 //\r
144 backupSystemProperties();\r
145 \r
146 //\r
de4bb9f6 147 // Read target.txt file\r
a29c47e0 148 //\r
de4bb9f6 149 readTargetFile();\r
150\r
a29c47e0 151 //\r
152 // Global Data initialization\r
153 //\r
9cf435c2 154 File workspacePath = new File(getProject().getProperty("WORKSPACE"));\r
aca6c736 155 getProject().setProperty("WORKSPACE_DIR", workspacePath.getPath().replaceAll("(\\\\)", "/"));\r
4a6a5026 156 GlobalData.initInfo(dbFilename, workspacePath.getPath(), toolsDefFilename);\r
a29c47e0 157 \r
de4bb9f6 158 //\r
159 // If find MSA file and ACTIVE_PLATFORM is set, build the module; \r
160 // else fail build. \r
161 // If without MSA file, and ACTIVE_PLATFORM is set, build the ACTIVE_PLATFORM. \r
162 // If ACTIVE_PLATFORM is not set, and only find one FPD file, build the platform; \r
163 // If find more than one FPD files, let user select one. \r
164 //\r
165 File buildFile = null;\r
166 if (msaFiles.size() > 1) {\r
4a6a5026 167 throw new BuildException("Having more than one MSA file in a directory is not allowed!");\r
168 } else if (msaFiles.size() == 1 && activePlatform == null) {\r
169 throw new BuildException("If trying to build a single module, please set ACTIVE_PLATFORM in file [" + targetFilename + "]. ");\r
170 } else if (msaFiles.size() == 1 && activePlatform != null) {\r
de4bb9f6 171 //\r
172 // Build the single module\r
173 //\r
174 buildFile = msaFiles.toArray(new File[1])[0];\r
4a6a5026 175 } else if (activePlatform != null) {\r
de4bb9f6 176 buildFile = new File(GlobalData.getWorkspacePath() + File.separatorChar + activePlatform);\r
4a6a5026 177 } else if (fpdFiles.size() == 1) {\r
de4bb9f6 178 buildFile = fpdFiles.toArray(new File[1])[0];\r
4a6a5026 179 } else if (fpdFiles.size() > 1) {\r
de4bb9f6 180 buildFile = intercommuniteWithUser();\r
181 }\r
182 //\r
183 // If there is no build files or FPD files or MSA files, stop build\r
184 //\r
185 else {\r
4a6a5026 186 throw new BuildException("Can't find any FPD or MSA files in the current directory. ");\r
de4bb9f6 187 }\r
188\r
a29c47e0 189 //\r
190 // Build every FPD files (PLATFORM build)\r
191 //\r
4a6a5026 192 if (buildFile.getName().endsWith(ToolDefinitions.FPD_EXTENSION)) {\r
193 System.out.println("Processing the FPD file [" + buildFile.getPath() + "] ..>> ");\r
19bf6b15 194 //\r
195 // Iff for platform build will enable the multi-thread if set in target.txt\r
196 //\r
197 if (multithread && type.equalsIgnoreCase("all")) {\r
198 System.out.println("Multi-thread build is enabled. ");\r
199 FpdParserForThread fpdParserForThread = new FpdParserForThread();\r
200 fpdParserForThread.setType(type);\r
201 fpdParserForThread.setProject(getProject());\r
202 fpdParserForThread.setFpdFile(buildFile);\r
203 fpdParserForThread.execute();\r
204 return ;\r
205 }\r
206 \r
a29c47e0 207 FpdParserTask fpdParserTask = new FpdParserTask();\r
208 fpdParserTask.setType(type);\r
209 fpdParserTask.setProject(getProject());\r
210 fpdParserTask.setFpdFile(buildFile);\r
211 fpdParserTask.execute();\r
caa44816 212 \r
213 //\r
214 // If cleanall delete the Platform_build.xml\r
215 //\r
216 if (type.compareTo("cleanall") == 0) {\r
217 File platformBuildFile = \r
218 new File(getProject().getProperty("PLATFORM_DIR") \r
219 + File.separatorChar \r
220 + getProject().getProperty("PLATFORM") \r
221 + "_build.xml");\r
222 platformBuildFile.deleteOnExit();\r
223 }\r
a29c47e0 224 }\r
225 \r
226 //\r
227 // Build every MSA files (SINGLE MODULE BUILD)\r
228 //\r
4a6a5026 229 else if (buildFile.getName().endsWith(ToolDefinitions.MSA_EXTENSION)) {\r
fa2da5b1 230 File tmpFile = new File(GlobalData.getWorkspacePath() + File.separatorChar + activePlatform);\r
4a6a5026 231 System.out.println("Using the FPD file [" + tmpFile.getPath() + "] for the active platform. ");\r
232 System.out.println("Processing the MSA file [" + buildFile.getPath() + "] ..>> ");\r
a29c47e0 233 GenBuildTask genBuildTask = new GenBuildTask();\r
de4bb9f6 234 genBuildTask.setSingleModuleBuild(true);\r
a29c47e0 235 genBuildTask.setType(type);\r
aca6c736 236 getProject().setProperty("PLATFORM_FILE", activePlatform);\r
237 if( !multithread) {\r
238 originalProperties.put("PLATFORM_FILE", activePlatform);\r
239 }\r
a29c47e0 240 genBuildTask.setProject(getProject());\r
241 genBuildTask.setMsaFile(buildFile);\r
242 genBuildTask.execute();\r
243 }\r
244 }\r
245 \r
246 /**\r
247 Transfer system environment variables to ANT properties. If system variable \r
248 already exiests in ANT properties, skip it.\r
249 \r
250 **/\r
251 private void backupSystemProperties() {\r
252 Map<String, String> sysProperties = System.getenv();\r
aca6c736 253 Iterator<String> iter = sysProperties.keySet().iterator();\r
a29c47e0 254 while (iter.hasNext()) {\r
255 String name = iter.next();\r
256 \r
257 //\r
258 // If system environment variable is not in ANT properties, add it\r
259 //\r
260 if (getProject().getProperty(name) == null) {\r
aca6c736 261 getProject().setProperty(name, sysProperties.get(name));\r
a29c47e0 262 }\r
263 }\r
aca6c736 264 \r
265 Hashtable allProperties = getProject().getProperties();\r
266 Iterator piter = allProperties.keySet().iterator();\r
267 while (piter.hasNext()) {\r
268 String name = (String)piter.next();\r
269 originalProperties.put(new String(name), new String((String)allProperties.get(name)));\r
270 }\r
271 \r
a29c47e0 272 }\r
273\r
274 private File intercommuniteWithUser(){\r
275 File file = null;\r
4a6a5026 276 if (fpdFiles.size() > 1) {\r
277 File[] allFiles = new File[fpdFiles.size()];\r
a29c47e0 278 int index = 0;\r
279 Iterator<File> iter = fpdFiles.iterator();\r
280 while (iter.hasNext()) {\r
281 allFiles[index] = iter.next();\r
282 index++;\r
283 }\r
4a6a5026 284\r
285 System.out.println("Finding " + allFiles.length + " FPD files: ");\r
a29c47e0 286 for (int i = 0; i < allFiles.length; i++) {\r
287 System.out.println("[" + (i + 1) + "]: " + allFiles[i].getName());\r
288 }\r
289 \r
290 boolean flag = true;\r
4a6a5026 291 System.out.print("Please select one of the following FPD files to build:[1] ");\r
a29c47e0 292 do{\r
293 BufferedReader br = new BufferedReader(new InputStreamReader(System.in));\r
294 try {\r
295 String str = br.readLine();\r
296 if (str.trim().length() == 0) {\r
297 file = allFiles[0];\r
298 flag = false;\r
299 continue ;\r
300 }\r
301 int indexSelect = Integer.parseInt(str);\r
302 if (indexSelect <=0 || indexSelect > allFiles.length) {\r
303 System.out.print("Please enter a number between [1.." + allFiles.length + "]:[1] ");\r
304 continue ;\r
305 } else {\r
306 file = allFiles[indexSelect - 1];\r
307 flag = false;\r
308 continue ;\r
309 }\r
310 } catch (Exception e) {\r
311 System.out.print("Please enter a valid number:[1] ");\r
312 flag = true;\r
313 }\r
314 } while (flag);\r
4a6a5026 315 } else if (fpdFiles.size() == 1) {\r
a29c47e0 316 file = fpdFiles.toArray(new File[1])[0];\r
317 }\r
a29c47e0 318 return file;\r
319 }\r
320 \r
321 \r
322 public void setType(String type) {\r
323 if (type.equalsIgnoreCase("clean") || type.equalsIgnoreCase("cleanall")) {\r
324 this.type = type.toLowerCase();\r
4a6a5026 325 } else {\r
a29c47e0 326 this.type = "all";\r
327 }\r
328 }\r
de4bb9f6 329 \r
330 private void readTargetFile(){\r
331 try {\r
4a6a5026 332 String targetFile = getProject().getProperty("WORKSPACE_DIR") + File.separatorChar + targetFilename;\r
333 \r
d2059d05 334 String[][] targetFileInfo = ConfigReader.parse(targetFile);\r
de4bb9f6 335 \r
336 //\r
337 // Get ToolChain Info from target.txt\r
338 //\r
339 ToolChainInfo envToolChainInfo = new ToolChainInfo(); \r
4a6a5026 340 String str = getValue(ToolDefinitions.TARGET_KEY_TARGET, targetFileInfo);\r
de4bb9f6 341 if (str == null || str.trim().equals("")) {\r
342 envToolChainInfo.addTargets("*");\r
4a6a5026 343 } else {\r
de4bb9f6 344 envToolChainInfo.addTargets(str);\r
345 }\r
4a6a5026 346 str = getValue(ToolDefinitions.TARGET_KEY_TOOLCHAIN, targetFileInfo);\r
de4bb9f6 347 if (str == null || str.trim().equals("")) {\r
348 envToolChainInfo.addTagnames("*");\r
4a6a5026 349 } else {\r
de4bb9f6 350 envToolChainInfo.addTagnames(str);\r
351 }\r
4a6a5026 352 str = getValue(ToolDefinitions.TARGET_KEY_ARCH, targetFileInfo);\r
de4bb9f6 353 if (str == null || str.trim().equals("")) {\r
354 envToolChainInfo.addArchs("*");\r
4a6a5026 355 } else {\r
de4bb9f6 356 envToolChainInfo.addArchs(str);\r
357 }\r
358 GlobalData.setToolChainEnvInfo(envToolChainInfo);\r
359 \r
4a6a5026 360 str = getValue(ToolDefinitions.TARGET_KEY_TOOLS_DEF, targetFileInfo);\r
196ad8d7 361 if (str != null && str.trim().length() > 0) {\r
de4bb9f6 362 toolsDefFilename = str;\r
363 }\r
364 \r
4a6a5026 365 str = getValue(ToolDefinitions.TARGET_KEY_ACTIVE_PLATFORM, targetFileInfo);\r
de4bb9f6 366 if (str != null && ! str.trim().equals("")) {\r
367 if ( ! str.endsWith(".fpd")) {\r
4a6a5026 368 throw new BuildException("FPD file's extension must be \"" + ToolDefinitions.FPD_EXTENSION + "\"!");\r
de4bb9f6 369 }\r
370 activePlatform = str;\r
371 }\r
19bf6b15 372 \r
373 str = getValue("MULTIPLE_THREAD", targetFileInfo);\r
374 if (str != null && str.trim().equalsIgnoreCase("Enable")) {\r
375 multithread = true;\r
376 }\r
377 \r
378 str = getValue("MAX_CONCURRENT_THREAD_NUMBER", targetFileInfo);\r
379 if (str != null ) {\r
380 try {\r
381 int threadNum = Integer.parseInt(str);\r
382 if (threadNum > 0) {\r
383 MAX_CONCURRENT_THREAD_NUMBER = threadNum;\r
384 }\r
385 } catch (Exception enuma) {\r
386 \r
387 }\r
388 }\r
de4bb9f6 389 }\r
390 catch (Exception ex) {\r
391 throw new BuildException(ex.getMessage());\r
392 }\r
393 }\r
394 \r
395 private String getValue(String key, String[][] map) {\r
396 for (int i = 0; i < map[0].length; i++){\r
397 if (key.equalsIgnoreCase(map[0][i])) {\r
398 return map[1][i];\r
399 }\r
400 }\r
401 return null;\r
402 }\r
a29c47e0 403}\r