]> git.proxmox.com Git - mirror_edk2.git/blame_incremental - Tools/Java/Source/GenBuild/org/tianocore/build/FrameworkBuildTask.java
Fixed EDKT482. Added support for multiple msa files in the same directory.
[mirror_edk2.git] / Tools / Java / Source / GenBuild / org / tianocore / build / FrameworkBuildTask.java
... / ...
CommitLineData
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
14package org.tianocore.build;\r
15\r
16import java.io.File;\r
17import java.io.IOException;\r
18import java.util.Hashtable;\r
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
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
30import org.tianocore.build.fpd.FpdParserForThread;\r
31import org.tianocore.build.fpd.FpdParserTask;\r
32import org.tianocore.build.global.GenBuildLogger;\r
33import org.tianocore.build.global.GlobalData;\r
34import org.tianocore.build.toolchain.ConfigReader;\r
35import org.tianocore.build.toolchain.ToolChainInfo;\r
36import org.tianocore.common.definitions.ToolDefinitions;\r
37import org.tianocore.common.exception.EdkException;\r
38import org.tianocore.common.logger.EdkLog;\r
39\r
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
58 7. No MSA file, no ACTIVE_PLATFORM, and more than one FPD files, Report Error!\r
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
74public class FrameworkBuildTask extends Task{\r
75\r
76 private Set<File> fpdFiles = new LinkedHashSet<File>();\r
77 \r
78 private Set<File> msaFiles = new LinkedHashSet<File>();\r
79 \r
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
85 String toolsDefFilename = ToolDefinitions.DEFAULT_TOOLS_DEF_FILE_PATH;\r
86 \r
87 String targetFilename = ToolDefinitions.TARGET_FILE_PATH;\r
88 \r
89 String dbFilename = ToolDefinitions.FRAMEWORK_DATABASE_FILE_PATH;\r
90 \r
91 String activePlatform = null;\r
92\r
93 ///\r
94 /// The flag to present current is multi-thread enabled\r
95 ///\r
96 public static boolean multithread = false;\r
97\r
98 ///\r
99 /// The concurrent thread number\r
100 ///\r
101 public static int MAX_CONCURRENT_THREAD_NUMBER = 2;\r
102\r
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
109 //\r
110 // set Logger\r
111 //\r
112 GenBuildLogger logger = new GenBuildLogger(getProject());\r
113 EdkLog.setLogLevel(EdkLog.EDK_DEBUG);\r
114 EdkLog.setLogLevel(getProject().getProperty("env.LOGLEVEL"));\r
115 EdkLog.setLogger(logger);\r
116 \r
117 try {\r
118 processFrameworkBuild();\r
119 }catch (BuildException e) {\r
120 //\r
121 // Add more logic process here\r
122 //\r
123 throw new BuildException(e.getMessage());\r
124 } catch (PcdAutogenException e) {\r
125 //\r
126 // Add more logic process here\r
127 //\r
128 throw new BuildException(e.getMessage());\r
129 } catch (AutoGenException e) {\r
130 //\r
131 // Add more logic process here\r
132 //\r
133 throw new BuildException(e.getMessage());\r
134 } catch (PlatformPcdPreprocessBuildException e) {\r
135 //\r
136 // Add more logic process here\r
137 //\r
138 throw new BuildException(e.getMessage());\r
139 } catch (GenBuildException e) {\r
140 //\r
141 // Add more logic process here\r
142 //\r
143 throw new BuildException(e.getMessage());\r
144 } catch (EdkException e) {\r
145 //\r
146 // Add more logic process here\r
147 //\r
148 throw new BuildException(e.getMessage());\r
149 }\r
150 }\r
151 \r
152 private void processFrameworkBuild() throws EdkException, GenBuildException, AutoGenException, PcdAutogenException, PlatformPcdPreprocessBuildException {\r
153 try {\r
154 //\r
155 // Get current working dir\r
156 //\r
157 File dummyFile = new File(".");\r
158 File cwd = dummyFile.getCanonicalFile();\r
159 File[] files = cwd.listFiles();\r
160 \r
161 //\r
162 // Scan current dir, and find out all .FPD and .MSA files\r
163 //\r
164 for (int i = 0; i < files.length; i++) {\r
165 if (files[i].isFile()) {\r
166 if (files[i].getName().endsWith(ToolDefinitions.FPD_EXTENSION)) {\r
167 //\r
168 // Found FPD file\r
169 //\r
170 fpdFiles.add(files[i]);\r
171 } else if (files[i].getName().endsWith(ToolDefinitions.MSA_EXTENSION)) {\r
172 //\r
173 // Found MSA file\r
174 //\r
175 msaFiles.add(files[i]);\r
176 }\r
177 }\r
178 }\r
179 } catch (IOException ex) {\r
180 BuildException buildException = new BuildException("Scanning current directory error. \n" + ex.getMessage());\r
181 buildException.setStackTrace(ex.getStackTrace());\r
182 throw buildException;\r
183 }\r
184 \r
185 //\r
186 // Import all system environment variables to ANT properties\r
187 //\r
188 importSystemEnvVariables();\r
189 \r
190 //\r
191 // Read target.txt file\r
192 //\r
193 readTargetFile();\r
194\r
195 //\r
196 // Global Data initialization\r
197 //\r
198 File workspacePath = new File(getProject().getProperty("WORKSPACE"));\r
199 getProject().setProperty("WORKSPACE_DIR", workspacePath.getPath().replaceAll("(\\\\)", "/"));\r
200 GlobalData.initInfo(dbFilename, workspacePath.getPath(), toolsDefFilename);\r
201 \r
202 //\r
203 // If find MSA file and ACTIVE_PLATFORM is set, build the module; \r
204 // else fail build. \r
205 // If without MSA file, and ACTIVE_PLATFORM is set, build the ACTIVE_PLATFORM. \r
206 // If ACTIVE_PLATFORM is not set, and only find one FPD file, build the platform; \r
207 // If find more than one FPD files, report error. \r
208 //\r
209 File buildFile = null;\r
210 if (msaFiles.size() > 0) {\r
211 if (activePlatform == null) {\r
212 throw new BuildException("If trying to build a single module, please set ACTIVE_PLATFORM in file [" + targetFilename + "]. ");\r
213 }\r
214 //\r
215 // Build the single module\r
216 //\r
217 buildFile = msaFiles.toArray(new File[1])[0];\r
218 } else if (activePlatform != null) {\r
219 buildFile = new File(GlobalData.getWorkspacePath() + File.separatorChar + activePlatform);\r
220 } else if (fpdFiles.size() == 1) {\r
221 buildFile = fpdFiles.toArray(new File[1])[0];\r
222 } else if (fpdFiles.size() > 1) {\r
223 throw new BuildException("Found " + fpdFiles.size() + " FPD files in current dir. ");\r
224 }\r
225 \r
226 //\r
227 // If there is no build files or FPD files or MSA files, stop build\r
228 //\r
229 else {\r
230 throw new BuildException("Can't find any FPD or MSA files in the current directory. ");\r
231 }\r
232\r
233 //\r
234 // Build every FPD files (PLATFORM build)\r
235 //\r
236 if (buildFile.getName().endsWith(ToolDefinitions.FPD_EXTENSION)) {\r
237 EdkLog.log(this, "Processing the FPD file [" + buildFile.getPath() + "] ..>> ");\r
238 //\r
239 // Iff for platform build will enable the multi-thread if set in target.txt\r
240 //\r
241 if (multithread && type.equalsIgnoreCase("all")) {\r
242 EdkLog.log(this, "Multi-thread build is enabled. ");\r
243 FpdParserForThread fpdParserForThread = new FpdParserForThread();\r
244 fpdParserForThread.setType(type);\r
245 fpdParserForThread.setProject(getProject());\r
246 fpdParserForThread.setFpdFile(buildFile);\r
247 fpdParserForThread.perform();\r
248 return ;\r
249 }\r
250 \r
251 FpdParserTask fpdParserTask = new FpdParserTask();\r
252 fpdParserTask.setType(type);\r
253 fpdParserTask.setProject(getProject());\r
254 fpdParserTask.setFpdFile(buildFile);\r
255 fpdParserTask.perform();\r
256 \r
257 //\r
258 // If cleanall delete the Platform_build.xml\r
259 //\r
260 if (type.compareTo("cleanall") == 0) {\r
261 File platformBuildFile = \r
262 new File(getProject().getProperty("BUILD_DIR") \r
263 + File.separatorChar \r
264 + getProject().getProperty("PLATFORM") \r
265 + "_build.xml");\r
266 platformBuildFile.deleteOnExit();\r
267 }\r
268 }\r
269 \r
270 //\r
271 // Build every MSA files (SINGLE MODULE BUILD)\r
272 //\r
273 else if (buildFile.getName().endsWith(ToolDefinitions.MSA_EXTENSION)) {\r
274 if (multithread) {\r
275 EdkLog.log(this, EdkLog.EDK_WARNING, "Multi-Thead do not take effect on Stand-Alone (Single) module build. ");\r
276 multithread = false;\r
277 }\r
278 File tmpFile = new File(GlobalData.getWorkspacePath() + File.separatorChar + activePlatform);\r
279 EdkLog.log(this, "Using the FPD file [" + tmpFile.getPath() + "] for the active platform. ");\r
280\r
281 File[] moduleFiles = msaFiles.toArray(new File[msaFiles.size()]);\r
282 for (int i = 0; i < moduleFiles.length; ++i) {\r
283 EdkLog.log(this, "Processing the MSA file [" + moduleFiles[i].getPath() + "] ..>> ");\r
284 GenBuildTask genBuildTask = new GenBuildTask();\r
285 genBuildTask.setSingleModuleBuild(true);\r
286 genBuildTask.setType(type);\r
287 getProject().setProperty("PLATFORM_FILE", activePlatform);\r
288 if( !multithread) {\r
289 originalProperties.put("PLATFORM_FILE", activePlatform);\r
290 }\r
291 genBuildTask.setProject(getProject());\r
292 genBuildTask.setMsaFile(moduleFiles[i]);\r
293 genBuildTask.perform();\r
294 }\r
295 }\r
296 }\r
297 \r
298 /**\r
299 Import system environment variables to ANT properties. If system variable \r
300 already exiests in ANT properties, skip it.\r
301 \r
302 **/\r
303 private void importSystemEnvVariables() {\r
304 Map<String, String> sysProperties = System.getenv();\r
305 Iterator<String> iter = sysProperties.keySet().iterator();\r
306 while (iter.hasNext()) {\r
307 String name = iter.next();\r
308 \r
309 //\r
310 // If system environment variable is not in ANT properties, add it\r
311 //\r
312 if (getProject().getProperty(name) == null) {\r
313 getProject().setProperty(name, sysProperties.get(name));\r
314 }\r
315 }\r
316 \r
317 Hashtable allProperties = getProject().getProperties();\r
318 Iterator piter = allProperties.keySet().iterator();\r
319 while (piter.hasNext()) {\r
320 String name = (String)piter.next();\r
321 originalProperties.put(new String(name), new String((String)allProperties.get(name)));\r
322 }\r
323 }\r
324\r
325 public void setType(String type) {\r
326 if (type.equalsIgnoreCase("clean") || type.equalsIgnoreCase("cleanall")) {\r
327 this.type = type.toLowerCase();\r
328 } else {\r
329 this.type = "all";\r
330 }\r
331 }\r
332 \r
333 private void readTargetFile() throws EdkException{\r
334 String targetFile = getProject().getProperty("WORKSPACE_DIR") + File.separatorChar + targetFilename;\r
335 \r
336 String[][] targetFileInfo = ConfigReader.parse(targetFile);\r
337 \r
338 //\r
339 // Get ToolChain Info from target.txt\r
340 //\r
341 ToolChainInfo envToolChainInfo = new ToolChainInfo(); \r
342 String str = getValue(ToolDefinitions.TARGET_KEY_TARGET, targetFileInfo);\r
343 if (str == null || str.trim().equals("")) {\r
344 envToolChainInfo.addTargets("*");\r
345 } else {\r
346 envToolChainInfo.addTargets(str);\r
347 }\r
348 str = getValue(ToolDefinitions.TARGET_KEY_TOOLCHAIN, targetFileInfo);\r
349 if (str == null || str.trim().equals("")) {\r
350 envToolChainInfo.addTagnames("*");\r
351 } else {\r
352 envToolChainInfo.addTagnames(str);\r
353 }\r
354 str = getValue(ToolDefinitions.TARGET_KEY_ARCH, targetFileInfo);\r
355 if (str == null || str.trim().equals("")) {\r
356 envToolChainInfo.addArchs("*");\r
357 } else {\r
358 envToolChainInfo.addArchs(str);\r
359 }\r
360 GlobalData.setToolChainEnvInfo(envToolChainInfo);\r
361 \r
362 str = getValue(ToolDefinitions.TARGET_KEY_TOOLS_DEF, targetFileInfo);\r
363 if (str != null && str.trim().length() > 0) {\r
364 toolsDefFilename = str;\r
365 }\r
366 \r
367 str = getValue(ToolDefinitions.TARGET_KEY_ACTIVE_PLATFORM, targetFileInfo);\r
368 if (str != null && ! str.trim().equals("")) {\r
369 if ( ! str.endsWith(".fpd")) {\r
370 throw new BuildException("FPD file's extension must be \"" + ToolDefinitions.FPD_EXTENSION + "\"!");\r
371 }\r
372 activePlatform = str;\r
373 }\r
374 \r
375 str = getValue(ToolDefinitions.TARGET_KEY_MULTIPLE_THREAD, targetFileInfo);\r
376 if (str != null && str.trim().equalsIgnoreCase("Enable")) {\r
377 multithread = true;\r
378 }\r
379\r
380 str = getValue(ToolDefinitions.TARGET_KEY_MAX_CONCURRENT_THREAD_NUMBER, targetFileInfo);\r
381 //\r
382 // Need to check the # of threads iff multithread is enabled.\r
383 //\r
384 if ((multithread) && (str != null )) {\r
385 try {\r
386 int threadNum = Integer.parseInt(str);\r
387 if (threadNum > 0) {\r
388 MAX_CONCURRENT_THREAD_NUMBER = threadNum;\r
389 }\r
390 } catch (Exception ex) {\r
391 //\r
392 // Give a warning message, and keep the default value\r
393 //\r
394 EdkLog.log(this, EdkLog.EDK_WARNING, "Incorrent number specified for MAX_CONCURRENT_THREAD_NUMBER in file [" + targetFilename + "]");\r
395 }\r
396 }\r
397 }\r
398 \r
399 private String getValue(String key, String[][] map) {\r
400 for (int i = 0; i < map[0].length; i++){\r
401 if (key.equalsIgnoreCase(map[0][i])) {\r
402 return map[1][i];\r
403 }\r
404 }\r
405 return null;\r
406 }\r
407}\r