Change behavior if found more than one FPD files from let user choice one to report...
[mirror_edk2.git] / Tools / Java / 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
a29c47e0 16import java.io.File;\r
91f7d582 17import java.io.IOException;\r
aca6c736 18import java.util.Hashtable;\r
a29c47e0 19import java.util.Iterator;\r
20import java.util.LinkedHashSet;\r
21import java.util.Map;\r
22import java.util.Set;\r
23\r
24import org.apache.tools.ant.BuildException;\r
25import org.apache.tools.ant.Task;\r
91f7d582 26import org.tianocore.build.exception.AutoGenException;\r
27import org.tianocore.build.exception.GenBuildException;\r
28import org.tianocore.build.exception.PcdAutogenException;\r
29import org.tianocore.build.exception.PlatformPcdPreprocessBuildException;\r
19bf6b15 30import org.tianocore.build.fpd.FpdParserForThread;\r
a29c47e0 31import org.tianocore.build.fpd.FpdParserTask;\r
c8df018e 32import org.tianocore.build.global.GenBuildLogger;\r
a29c47e0 33import org.tianocore.build.global.GlobalData;\r
de4bb9f6 34import org.tianocore.build.toolchain.ConfigReader;\r
a29c47e0 35import org.tianocore.build.toolchain.ToolChainInfo;\r
4a6a5026 36import org.tianocore.common.definitions.ToolDefinitions;\r
91f7d582 37import org.tianocore.common.exception.EdkException;\r
c8df018e 38import org.tianocore.common.logger.EdkLog;\r
a29c47e0 39\r
2d16dcec 40/**\r
41 <p>\r
42 <code>FrameworkBuildTask</code> is an Ant task. The main function is finding\r
43 and processing a FPD or MSA file, then building a platform or stand-alone \r
44 module. \r
45 \r
46 <p>\r
47 The task search current directory and find out all MSA and FPD files by file\r
48 extension. Base on ACTIVE_PLATFORM policy, decide to build a platform or a\r
49 stand-alone module. The ACTIVE_PLATFORM policy is: \r
50 \r
51 <pre>\r
52 1. More than one MSA files, report error; \r
53 2. Only one MSA file, but ACTIVE_PLATFORM is not specified, report error;\r
54 3. Only one MSA file, and ACTIVE_PLATFORM is also specified, build this module;\r
55 4. No MSA file, and ACTIVE_PLATFORM is specified, build the active platform;\r
56 5. No MSA file, no ACTIVE_PLATFORM, and no FPD file, report error;\r
57 6. No MSA file, no ACTIVE_PLATFORM, and only one FPD file, build the platform;\r
0f769af1 58 7. No MSA file, no ACTIVE_PLATFORM, and more than one FPD files, Report Error!\r
2d16dcec 59 </pre>\r
60 \r
61 <p>\r
62 Framework build task also parse target file [${WORKSPACE_DIR}/Tools/Conf/target.txt].\r
63 And load all system environment variables to Ant properties. \r
64 \r
65 <p>\r
66 The usage for this task is : \r
67 \r
68 <pre>\r
69 &lt;FrameworkBuild type="cleanall" /&gt;\r
70 </pre>\r
71 \r
72 @since GenBuild 1.0\r
73**/\r
a29c47e0 74public class FrameworkBuildTask extends Task{\r
75\r
a29c47e0 76 private Set<File> fpdFiles = new LinkedHashSet<File>();\r
77 \r
78 private Set<File> msaFiles = new LinkedHashSet<File>();\r
79 \r
aca6c736 80 //\r
81 // This is only for none-multi-thread build to reduce overriding message\r
82 //\r
83 public static Hashtable<String, String> originalProperties = new Hashtable<String, String>();\r
84 \r
4a6a5026 85 String toolsDefFilename = ToolDefinitions.DEFAULT_TOOLS_DEF_FILE_PATH;\r
de4bb9f6 86 \r
4a6a5026 87 String targetFilename = ToolDefinitions.TARGET_FILE_PATH;\r
88 \r
89 String dbFilename = ToolDefinitions.FRAMEWORK_DATABASE_FILE_PATH;\r
de4bb9f6 90 \r
91 String activePlatform = null;\r
aca6c736 92\r
19bf6b15 93 ///\r
94 /// The flag to present current is multi-thread enabled\r
95 ///\r
96 public static boolean multithread = false;\r
aca6c736 97\r
19bf6b15 98 ///\r
99 /// The concurrent thread number\r
100 ///\r
498e9021 101 public static int MAX_CONCURRENT_THREAD_NUMBER = 2;\r
aca6c736 102\r
a29c47e0 103 ///\r
104 /// there are three type: all (build), clean and cleanall\r
105 ///\r
106 private String type = "all";\r
107 \r
108 public void execute() throws BuildException {\r
892b0e7a 109 //\r
110 // set Logger\r
111 //\r
112 GenBuildLogger logger = new GenBuildLogger(getProject());\r
113 EdkLog.setLogLevel(getProject().getProperty("env.LOGLEVEL"));\r
114 EdkLog.setLogger(logger);\r
115 \r
91f7d582 116 try {\r
117 processFrameworkBuild();\r
118 } catch (PcdAutogenException e) {\r
119 //\r
120 // Add more logic process here\r
121 //\r
122 throw new BuildException(e.getMessage());\r
123 } catch (AutoGenException e) {\r
124 //\r
125 // Add more logic process here\r
126 //\r
127 throw new BuildException(e.getMessage());\r
128 } catch (PlatformPcdPreprocessBuildException e) {\r
129 //\r
130 // Add more logic process here\r
131 //\r
132 throw new BuildException(e.getMessage());\r
133 } catch (GenBuildException e) {\r
134 //\r
135 // Add more logic process here\r
136 //\r
137 throw new BuildException(e.getMessage());\r
138 } catch (EdkException e) {\r
139 //\r
140 // Add more logic process here\r
141 //\r
142 throw new BuildException(e.getMessage());\r
143 }\r
144 }\r
145 \r
146 private void processFrameworkBuild() throws EdkException, GenBuildException, AutoGenException, PcdAutogenException, PlatformPcdPreprocessBuildException {\r
a29c47e0 147 try {\r
148 //\r
0f769af1 149 // Get current working dir\r
a29c47e0 150 //\r
151 File dummyFile = new File(".");\r
152 File cwd = dummyFile.getCanonicalFile();\r
153 File[] files = cwd.listFiles();\r
0f769af1 154 \r
155 //\r
156 // Scan current dir, and find out all .FPD and .MSA files\r
157 //\r
a29c47e0 158 for (int i = 0; i < files.length; i++) {\r
159 if (files[i].isFile()) {\r
0f769af1 160 if (files[i].getName().endsWith(ToolDefinitions.FPD_EXTENSION)) {\r
a29c47e0 161 //\r
0f769af1 162 // Found FPD file\r
a29c47e0 163 //\r
164 fpdFiles.add(files[i]);\r
4a6a5026 165 } else if (files[i].getName().endsWith(ToolDefinitions.MSA_EXTENSION)) {\r
a29c47e0 166 //\r
0f769af1 167 // Found MSA file\r
a29c47e0 168 //\r
169 msaFiles.add(files[i]);\r
170 }\r
171 }\r
172 }\r
892b0e7a 173 } catch (IOException ex) {\r
174 BuildException buildException = new BuildException("Scanning current directory error. \n" + ex.getMessage());\r
175 buildException.setStackTrace(ex.getStackTrace());\r
176 throw buildException;\r
a29c47e0 177 }\r
178 \r
a29c47e0 179 //\r
0f769af1 180 // Import all system environment variables to ANT properties\r
a29c47e0 181 //\r
0f769af1 182 importSystemEnvVariables();\r
a29c47e0 183 \r
184 //\r
de4bb9f6 185 // Read target.txt file\r
a29c47e0 186 //\r
de4bb9f6 187 readTargetFile();\r
188\r
a29c47e0 189 //\r
190 // Global Data initialization\r
191 //\r
9cf435c2 192 File workspacePath = new File(getProject().getProperty("WORKSPACE"));\r
aca6c736 193 getProject().setProperty("WORKSPACE_DIR", workspacePath.getPath().replaceAll("(\\\\)", "/"));\r
4a6a5026 194 GlobalData.initInfo(dbFilename, workspacePath.getPath(), toolsDefFilename);\r
a29c47e0 195 \r
de4bb9f6 196 //\r
197 // If find MSA file and ACTIVE_PLATFORM is set, build the module; \r
198 // else fail build. \r
199 // If without MSA file, and ACTIVE_PLATFORM is set, build the ACTIVE_PLATFORM. \r
200 // If ACTIVE_PLATFORM is not set, and only find one FPD file, build the platform; \r
0f769af1 201 // If find more than one FPD files, report error. \r
de4bb9f6 202 //\r
203 File buildFile = null;\r
204 if (msaFiles.size() > 1) {\r
0f769af1 205 throw new BuildException("Found " + msaFiles.size() + " MSA files in current dir. ");\r
4a6a5026 206 } else if (msaFiles.size() == 1 && activePlatform == null) {\r
207 throw new BuildException("If trying to build a single module, please set ACTIVE_PLATFORM in file [" + targetFilename + "]. ");\r
208 } else if (msaFiles.size() == 1 && activePlatform != null) {\r
de4bb9f6 209 //\r
210 // Build the single module\r
211 //\r
212 buildFile = msaFiles.toArray(new File[1])[0];\r
4a6a5026 213 } else if (activePlatform != null) {\r
de4bb9f6 214 buildFile = new File(GlobalData.getWorkspacePath() + File.separatorChar + activePlatform);\r
4a6a5026 215 } else if (fpdFiles.size() == 1) {\r
de4bb9f6 216 buildFile = fpdFiles.toArray(new File[1])[0];\r
4a6a5026 217 } else if (fpdFiles.size() > 1) {\r
0f769af1 218 throw new BuildException("Found " + fpdFiles.size() + " FPD files in current dir. ");\r
de4bb9f6 219 }\r
0f769af1 220 \r
de4bb9f6 221 //\r
222 // If there is no build files or FPD files or MSA files, stop build\r
223 //\r
224 else {\r
4a6a5026 225 throw new BuildException("Can't find any FPD or MSA files in the current directory. ");\r
de4bb9f6 226 }\r
227\r
a29c47e0 228 //\r
229 // Build every FPD files (PLATFORM build)\r
230 //\r
4a6a5026 231 if (buildFile.getName().endsWith(ToolDefinitions.FPD_EXTENSION)) {\r
91f7d582 232 EdkLog.log(this, "Processing the FPD file [" + buildFile.getPath() + "] ..>> ");\r
19bf6b15 233 //\r
234 // Iff for platform build will enable the multi-thread if set in target.txt\r
235 //\r
236 if (multithread && type.equalsIgnoreCase("all")) {\r
91f7d582 237 EdkLog.log(this, "Multi-thread build is enabled. ");\r
19bf6b15 238 FpdParserForThread fpdParserForThread = new FpdParserForThread();\r
239 fpdParserForThread.setType(type);\r
240 fpdParserForThread.setProject(getProject());\r
241 fpdParserForThread.setFpdFile(buildFile);\r
c8df018e 242 fpdParserForThread.perform();\r
19bf6b15 243 return ;\r
244 }\r
245 \r
a29c47e0 246 FpdParserTask fpdParserTask = new FpdParserTask();\r
247 fpdParserTask.setType(type);\r
248 fpdParserTask.setProject(getProject());\r
249 fpdParserTask.setFpdFile(buildFile);\r
c8df018e 250 fpdParserTask.perform();\r
caa44816 251 \r
252 //\r
253 // If cleanall delete the Platform_build.xml\r
254 //\r
255 if (type.compareTo("cleanall") == 0) {\r
256 File platformBuildFile = \r
02c768ee 257 new File(getProject().getProperty("BUILD_DIR") \r
caa44816 258 + File.separatorChar \r
259 + getProject().getProperty("PLATFORM") \r
260 + "_build.xml");\r
261 platformBuildFile.deleteOnExit();\r
262 }\r
a29c47e0 263 }\r
264 \r
265 //\r
266 // Build every MSA files (SINGLE MODULE BUILD)\r
267 //\r
4a6a5026 268 else if (buildFile.getName().endsWith(ToolDefinitions.MSA_EXTENSION)) {\r
d8956f14 269 if (multithread) {\r
270 EdkLog.log(this, EdkLog.EDK_WARNING, "Multi-Thead do not take effect on Stand-Alone (Single) module build. ");\r
271 multithread = false;\r
272 }\r
fa2da5b1 273 File tmpFile = new File(GlobalData.getWorkspacePath() + File.separatorChar + activePlatform);\r
91f7d582 274 EdkLog.log(this, "Using the FPD file [" + tmpFile.getPath() + "] for the active platform. ");\r
275 EdkLog.log(this, "Processing the MSA file [" + buildFile.getPath() + "] ..>> ");\r
a29c47e0 276 GenBuildTask genBuildTask = new GenBuildTask();\r
de4bb9f6 277 genBuildTask.setSingleModuleBuild(true);\r
a29c47e0 278 genBuildTask.setType(type);\r
aca6c736 279 getProject().setProperty("PLATFORM_FILE", activePlatform);\r
280 if( !multithread) {\r
281 originalProperties.put("PLATFORM_FILE", activePlatform);\r
282 }\r
a29c47e0 283 genBuildTask.setProject(getProject());\r
284 genBuildTask.setMsaFile(buildFile);\r
c8df018e 285 genBuildTask.perform();\r
a29c47e0 286 }\r
287 }\r
288 \r
289 /**\r
0f769af1 290 Import system environment variables to ANT properties. If system variable \r
a29c47e0 291 already exiests in ANT properties, skip it.\r
292 \r
293 **/\r
0f769af1 294 private void importSystemEnvVariables() {\r
a29c47e0 295 Map<String, String> sysProperties = System.getenv();\r
aca6c736 296 Iterator<String> iter = sysProperties.keySet().iterator();\r
a29c47e0 297 while (iter.hasNext()) {\r
298 String name = iter.next();\r
299 \r
300 //\r
301 // If system environment variable is not in ANT properties, add it\r
302 //\r
303 if (getProject().getProperty(name) == null) {\r
aca6c736 304 getProject().setProperty(name, sysProperties.get(name));\r
a29c47e0 305 }\r
306 }\r
aca6c736 307 \r
308 Hashtable allProperties = getProject().getProperties();\r
309 Iterator piter = allProperties.keySet().iterator();\r
310 while (piter.hasNext()) {\r
311 String name = (String)piter.next();\r
312 originalProperties.put(new String(name), new String((String)allProperties.get(name)));\r
313 }\r
a29c47e0 314 }\r
315\r
a29c47e0 316 public void setType(String type) {\r
317 if (type.equalsIgnoreCase("clean") || type.equalsIgnoreCase("cleanall")) {\r
318 this.type = type.toLowerCase();\r
4a6a5026 319 } else {\r
a29c47e0 320 this.type = "all";\r
321 }\r
322 }\r
de4bb9f6 323 \r
91f7d582 324 private void readTargetFile() throws EdkException{\r
325 String targetFile = getProject().getProperty("WORKSPACE_DIR") + File.separatorChar + targetFilename;\r
326 \r
327 String[][] targetFileInfo = ConfigReader.parse(targetFile);\r
328 \r
329 //\r
330 // Get ToolChain Info from target.txt\r
331 //\r
332 ToolChainInfo envToolChainInfo = new ToolChainInfo(); \r
333 String str = getValue(ToolDefinitions.TARGET_KEY_TARGET, targetFileInfo);\r
334 if (str == null || str.trim().equals("")) {\r
335 envToolChainInfo.addTargets("*");\r
336 } else {\r
337 envToolChainInfo.addTargets(str);\r
338 }\r
339 str = getValue(ToolDefinitions.TARGET_KEY_TOOLCHAIN, targetFileInfo);\r
340 if (str == null || str.trim().equals("")) {\r
341 envToolChainInfo.addTagnames("*");\r
342 } else {\r
343 envToolChainInfo.addTagnames(str);\r
344 }\r
345 str = getValue(ToolDefinitions.TARGET_KEY_ARCH, targetFileInfo);\r
346 if (str == null || str.trim().equals("")) {\r
347 envToolChainInfo.addArchs("*");\r
348 } else {\r
349 envToolChainInfo.addArchs(str);\r
350 }\r
351 GlobalData.setToolChainEnvInfo(envToolChainInfo);\r
352 \r
353 str = getValue(ToolDefinitions.TARGET_KEY_TOOLS_DEF, targetFileInfo);\r
354 if (str != null && str.trim().length() > 0) {\r
355 toolsDefFilename = str;\r
356 }\r
357 \r
358 str = getValue(ToolDefinitions.TARGET_KEY_ACTIVE_PLATFORM, targetFileInfo);\r
359 if (str != null && ! str.trim().equals("")) {\r
360 if ( ! str.endsWith(".fpd")) {\r
361 throw new BuildException("FPD file's extension must be \"" + ToolDefinitions.FPD_EXTENSION + "\"!");\r
19bf6b15 362 }\r
91f7d582 363 activePlatform = str;\r
364 }\r
365 \r
366 str = getValue(ToolDefinitions.TARGET_KEY_MULTIPLE_THREAD, targetFileInfo);\r
367 if (str != null && str.trim().equalsIgnoreCase("Enable")) {\r
368 multithread = true;\r
369 }\r
2eb7d78d 370\r
91f7d582 371 str = getValue(ToolDefinitions.TARGET_KEY_MAX_CONCURRENT_THREAD_NUMBER, targetFileInfo);\r
372 if (str != null ) {\r
373 try {\r
374 int threadNum = Integer.parseInt(str);\r
375 if (threadNum > 0) {\r
376 MAX_CONCURRENT_THREAD_NUMBER = threadNum;\r
19bf6b15 377 }\r
892b0e7a 378 } catch (Exception ex) {\r
0f769af1 379 //\r
380 // Give a warning message, and keep the default value\r
381 //\r
382 EdkLog.log(this, EdkLog.EDK_WARNING, "Incorrent number specified for MAX_CONCURRENT_THREAD_NUMBER in file [" + targetFilename + "]");\r
19bf6b15 383 }\r
de4bb9f6 384 }\r
de4bb9f6 385 }\r
386 \r
387 private String getValue(String key, String[][] map) {\r
388 for (int i = 0; i < map[0].length; i++){\r
389 if (key.equalsIgnoreCase(map[0][i])) {\r
390 return map[1][i];\r
391 }\r
392 }\r
393 return null;\r
394 }\r
a29c47e0 395}\r