1 /** @file FrameworkBuildTask.java
3 The file is ANT task to find MSA or FPD file and build them.
5 Copyright (c) 2006, Intel Corporation
6 All rights reserved. This program and the accompanying materials
7 are licensed and made available under the terms and conditions of the BSD License
8 which accompanies this distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
14 package org
.tianocore
.build
;
16 import java
.io
.BufferedReader
;
18 import java
.io
.IOException
;
19 import java
.io
.InputStreamReader
;
20 import java
.util
.Hashtable
;
21 import java
.util
.Iterator
;
22 import java
.util
.LinkedHashSet
;
26 import org
.apache
.tools
.ant
.BuildException
;
27 import org
.apache
.tools
.ant
.Task
;
28 import org
.tianocore
.build
.exception
.AutoGenException
;
29 import org
.tianocore
.build
.exception
.GenBuildException
;
30 import org
.tianocore
.build
.exception
.PcdAutogenException
;
31 import org
.tianocore
.build
.exception
.PlatformPcdPreprocessBuildException
;
32 import org
.tianocore
.build
.fpd
.FpdParserForThread
;
33 import org
.tianocore
.build
.fpd
.FpdParserTask
;
34 import org
.tianocore
.build
.global
.GenBuildLogger
;
35 import org
.tianocore
.build
.global
.GlobalData
;
36 import org
.tianocore
.build
.toolchain
.ConfigReader
;
37 import org
.tianocore
.build
.toolchain
.ToolChainInfo
;
38 import org
.tianocore
.common
.definitions
.ToolDefinitions
;
39 import org
.tianocore
.common
.exception
.EdkException
;
40 import org
.tianocore
.common
.logger
.EdkLog
;
44 <code>FrameworkBuildTask</code> is an Ant task. The main function is finding
45 and processing a FPD or MSA file, then building a platform or stand-alone
49 The task search current directory and find out all MSA and FPD files by file
50 extension. Base on ACTIVE_PLATFORM policy, decide to build a platform or a
51 stand-alone module. The ACTIVE_PLATFORM policy is:
54 1. More than one MSA files, report error;
55 2. Only one MSA file, but ACTIVE_PLATFORM is not specified, report error;
56 3. Only one MSA file, and ACTIVE_PLATFORM is also specified, build this module;
57 4. No MSA file, and ACTIVE_PLATFORM is specified, build the active platform;
58 5. No MSA file, no ACTIVE_PLATFORM, and no FPD file, report error;
59 6. No MSA file, no ACTIVE_PLATFORM, and only one FPD file, build the platform;
60 7. No MSA file, no ACTIVE_PLATFORM, and more than one FPD files, list all platform
61 and let user choose one.
65 Framework build task also parse target file [${WORKSPACE_DIR}/Tools/Conf/target.txt].
66 And load all system environment variables to Ant properties.
69 The usage for this task is :
72 <FrameworkBuild type="cleanall" />
77 public class FrameworkBuildTask
extends Task
{
79 private Set
<File
> buildFiles
= new LinkedHashSet
<File
>();
81 private Set
<File
> fpdFiles
= new LinkedHashSet
<File
>();
83 private Set
<File
> msaFiles
= new LinkedHashSet
<File
>();
86 // This is only for none-multi-thread build to reduce overriding message
88 public static Hashtable
<String
, String
> originalProperties
= new Hashtable
<String
, String
>();
90 String toolsDefFilename
= ToolDefinitions
.DEFAULT_TOOLS_DEF_FILE_PATH
;
92 String targetFilename
= ToolDefinitions
.TARGET_FILE_PATH
;
94 String dbFilename
= ToolDefinitions
.FRAMEWORK_DATABASE_FILE_PATH
;
96 String activePlatform
= null;
99 /// The flag to present current is multi-thread enabled
101 public static boolean multithread
= false;
104 /// The concurrent thread number
106 public static int MAX_CONCURRENT_THREAD_NUMBER
= 1;
109 /// there are three type: all (build), clean and cleanall
111 private String type
= "all";
113 public void execute() throws BuildException
{
115 processFrameworkBuild();
116 } catch (PcdAutogenException e
) {
118 // Add more logic process here
120 throw new BuildException(e
.getMessage());
121 } catch (AutoGenException e
) {
123 // Add more logic process here
125 throw new BuildException(e
.getMessage());
126 } catch (PlatformPcdPreprocessBuildException e
) {
128 // Add more logic process here
130 throw new BuildException(e
.getMessage());
131 } catch (GenBuildException e
) {
133 // Add more logic process here
135 throw new BuildException(e
.getMessage());
136 } catch (EdkException e
) {
138 // Add more logic process here
140 throw new BuildException(e
.getMessage());
144 private void processFrameworkBuild() throws EdkException
, GenBuildException
, AutoGenException
, PcdAutogenException
, PlatformPcdPreprocessBuildException
{
148 GenBuildLogger logger
= new GenBuildLogger(getProject());
149 EdkLog
.setLogLevel(getProject().getProperty("env.LOGLEVEL"));
150 EdkLog
.setLogger(logger
);
153 // Seach build.xml -> .FPD -> .MSA file
157 // Gen Current Working Directory
159 File dummyFile
= new File(".");
160 File cwd
= dummyFile
.getCanonicalFile();
161 File
[] files
= cwd
.listFiles();
162 for (int i
= 0; i
< files
.length
; i
++) {
163 if (files
[i
].isFile()) {
164 if (files
[i
].getName().equalsIgnoreCase("build.xml")) {
166 // First, search build.xml, if found, ANT call it
168 buildFiles
.add(files
[i
]);
170 } else if (files
[i
].getName().endsWith(ToolDefinitions
.FPD_EXTENSION
)) {
172 // Second, search FPD file, if found, build it
174 fpdFiles
.add(files
[i
]);
175 } else if (files
[i
].getName().endsWith(ToolDefinitions
.MSA_EXTENSION
)) {
177 // Third, search MSA file, if found, build it
179 msaFiles
.add(files
[i
]);
183 } catch (IOException e
) {
184 throw new BuildException(e
.getMessage());
188 // Deal with all environment variable (Add them to properties)
190 backupSystemProperties();
193 // Read target.txt file
198 // Global Data initialization
200 File workspacePath
= new File(getProject().getProperty("WORKSPACE"));
201 getProject().setProperty("WORKSPACE_DIR", workspacePath
.getPath().replaceAll("(\\\\)", "/"));
202 GlobalData
.initInfo(dbFilename
, workspacePath
.getPath(), toolsDefFilename
);
205 // If find MSA file and ACTIVE_PLATFORM is set, build the module;
207 // If without MSA file, and ACTIVE_PLATFORM is set, build the ACTIVE_PLATFORM.
208 // If ACTIVE_PLATFORM is not set, and only find one FPD file, build the platform;
209 // If find more than one FPD files, let user select one.
211 File buildFile
= null;
212 if (msaFiles
.size() > 1) {
213 throw new BuildException("Having more than one MSA file in a directory is not allowed!");
214 } else if (msaFiles
.size() == 1 && activePlatform
== null) {
215 throw new BuildException("If trying to build a single module, please set ACTIVE_PLATFORM in file [" + targetFilename
+ "]. ");
216 } else if (msaFiles
.size() == 1 && activePlatform
!= null) {
218 // Build the single module
220 buildFile
= msaFiles
.toArray(new File
[1])[0];
221 } else if (activePlatform
!= null) {
222 buildFile
= new File(GlobalData
.getWorkspacePath() + File
.separatorChar
+ activePlatform
);
223 } else if (fpdFiles
.size() == 1) {
224 buildFile
= fpdFiles
.toArray(new File
[1])[0];
225 } else if (fpdFiles
.size() > 1) {
226 buildFile
= intercommuniteWithUser();
229 // If there is no build files or FPD files or MSA files, stop build
232 throw new BuildException("Can't find any FPD or MSA files in the current directory. ");
236 // Build every FPD files (PLATFORM build)
238 if (buildFile
.getName().endsWith(ToolDefinitions
.FPD_EXTENSION
)) {
239 EdkLog
.log(this, "Processing the FPD file [" + buildFile
.getPath() + "] ..>> ");
241 // Iff for platform build will enable the multi-thread if set in target.txt
243 if (multithread
&& type
.equalsIgnoreCase("all")) {
244 EdkLog
.log(this, "Multi-thread build is enabled. ");
245 FpdParserForThread fpdParserForThread
= new FpdParserForThread();
246 fpdParserForThread
.setType(type
);
247 fpdParserForThread
.setProject(getProject());
248 fpdParserForThread
.setFpdFile(buildFile
);
249 fpdParserForThread
.perform();
253 FpdParserTask fpdParserTask
= new FpdParserTask();
254 fpdParserTask
.setType(type
);
255 fpdParserTask
.setProject(getProject());
256 fpdParserTask
.setFpdFile(buildFile
);
257 fpdParserTask
.perform();
260 // If cleanall delete the Platform_build.xml
262 if (type
.compareTo("cleanall") == 0) {
263 File platformBuildFile
=
264 new File(getProject().getProperty("PLATFORM_DIR")
266 + getProject().getProperty("PLATFORM")
268 platformBuildFile
.deleteOnExit();
273 // Build every MSA files (SINGLE MODULE BUILD)
275 else if (buildFile
.getName().endsWith(ToolDefinitions
.MSA_EXTENSION
)) {
276 File tmpFile
= new File(GlobalData
.getWorkspacePath() + File
.separatorChar
+ activePlatform
);
277 EdkLog
.log(this, "Using the FPD file [" + tmpFile
.getPath() + "] for the active platform. ");
278 EdkLog
.log(this, "Processing the MSA file [" + buildFile
.getPath() + "] ..>> ");
279 GenBuildTask genBuildTask
= new GenBuildTask();
280 genBuildTask
.setSingleModuleBuild(true);
281 genBuildTask
.setType(type
);
282 getProject().setProperty("PLATFORM_FILE", activePlatform
);
284 originalProperties
.put("PLATFORM_FILE", activePlatform
);
286 genBuildTask
.setProject(getProject());
287 genBuildTask
.setMsaFile(buildFile
);
288 genBuildTask
.perform();
293 Transfer system environment variables to ANT properties. If system variable
294 already exiests in ANT properties, skip it.
297 private void backupSystemProperties() {
298 Map
<String
, String
> sysProperties
= System
.getenv();
299 Iterator
<String
> iter
= sysProperties
.keySet().iterator();
300 while (iter
.hasNext()) {
301 String name
= iter
.next();
304 // If system environment variable is not in ANT properties, add it
306 if (getProject().getProperty(name
) == null) {
307 getProject().setProperty(name
, sysProperties
.get(name
));
311 Hashtable allProperties
= getProject().getProperties();
312 Iterator piter
= allProperties
.keySet().iterator();
313 while (piter
.hasNext()) {
314 String name
= (String
)piter
.next();
315 originalProperties
.put(new String(name
), new String((String
)allProperties
.get(name
)));
319 private File
intercommuniteWithUser(){
321 if (fpdFiles
.size() > 1) {
322 File
[] allFiles
= new File
[fpdFiles
.size()];
324 Iterator
<File
> iter
= fpdFiles
.iterator();
325 while (iter
.hasNext()) {
326 allFiles
[index
] = iter
.next();
330 EdkLog
.log(this, "Finding " + allFiles
.length
+ " FPD files: ");
331 for (int i
= 0; i
< allFiles
.length
; i
++) {
332 System
.out
.println("[" + (i
+ 1) + "]: " + allFiles
[i
].getName());
336 EdkLog
.log(this, "Please select one of the following FPD files to build:[1] ");
338 BufferedReader br
= new BufferedReader(new InputStreamReader(System
.in
));
340 String str
= br
.readLine();
341 if (str
.trim().length() == 0) {
346 int indexSelect
= Integer
.parseInt(str
);
347 if (indexSelect
<=0 || indexSelect
> allFiles
.length
) {
348 EdkLog
.log(this, "Please enter a number between [1.." + allFiles
.length
+ "]:[1] ");
351 file
= allFiles
[indexSelect
- 1];
355 } catch (Exception e
) {
356 EdkLog
.log(this, "Please enter a valid number:[1] ");
360 } else if (fpdFiles
.size() == 1) {
361 file
= fpdFiles
.toArray(new File
[1])[0];
367 public void setType(String type
) {
368 if (type
.equalsIgnoreCase("clean") || type
.equalsIgnoreCase("cleanall")) {
369 this.type
= type
.toLowerCase();
375 private void readTargetFile() throws EdkException
{
376 String targetFile
= getProject().getProperty("WORKSPACE_DIR") + File
.separatorChar
+ targetFilename
;
378 String
[][] targetFileInfo
= ConfigReader
.parse(targetFile
);
381 // Get ToolChain Info from target.txt
383 ToolChainInfo envToolChainInfo
= new ToolChainInfo();
384 String str
= getValue(ToolDefinitions
.TARGET_KEY_TARGET
, targetFileInfo
);
385 if (str
== null || str
.trim().equals("")) {
386 envToolChainInfo
.addTargets("*");
388 envToolChainInfo
.addTargets(str
);
390 str
= getValue(ToolDefinitions
.TARGET_KEY_TOOLCHAIN
, targetFileInfo
);
391 if (str
== null || str
.trim().equals("")) {
392 envToolChainInfo
.addTagnames("*");
394 envToolChainInfo
.addTagnames(str
);
396 str
= getValue(ToolDefinitions
.TARGET_KEY_ARCH
, targetFileInfo
);
397 if (str
== null || str
.trim().equals("")) {
398 envToolChainInfo
.addArchs("*");
400 envToolChainInfo
.addArchs(str
);
402 GlobalData
.setToolChainEnvInfo(envToolChainInfo
);
404 str
= getValue(ToolDefinitions
.TARGET_KEY_TOOLS_DEF
, targetFileInfo
);
405 if (str
!= null && str
.trim().length() > 0) {
406 toolsDefFilename
= str
;
409 str
= getValue(ToolDefinitions
.TARGET_KEY_ACTIVE_PLATFORM
, targetFileInfo
);
410 if (str
!= null && ! str
.trim().equals("")) {
411 if ( ! str
.endsWith(".fpd")) {
412 throw new BuildException("FPD file's extension must be \"" + ToolDefinitions
.FPD_EXTENSION
+ "\"!");
414 activePlatform
= str
;
417 str
= getValue(ToolDefinitions
.TARGET_KEY_MULTIPLE_THREAD
, targetFileInfo
);
418 if (str
!= null && str
.trim().equalsIgnoreCase("Enable")) {
422 str
= getValue(ToolDefinitions
.TARGET_KEY_MAX_CONCURRENT_THREAD_NUMBER
, targetFileInfo
);
425 int threadNum
= Integer
.parseInt(str
);
427 MAX_CONCURRENT_THREAD_NUMBER
= threadNum
;
429 } catch (Exception enuma
) {
434 private String
getValue(String key
, String
[][] map
) {
435 for (int i
= 0; i
< map
[0].length
; i
++){
436 if (key
.equalsIgnoreCase(map
[0][i
])) {