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
{
117 GenBuildLogger logger
= new GenBuildLogger(getProject());
118 EdkLog
.setLogLevel(getProject().getProperty("env.LOGLEVEL"));
119 EdkLog
.setLogger(logger
);
122 processFrameworkBuild();
123 } catch (PcdAutogenException e
) {
125 // Add more logic process here
127 throw new BuildException(e
.getMessage());
128 } catch (AutoGenException e
) {
130 // Add more logic process here
132 throw new BuildException(e
.getMessage());
133 } catch (PlatformPcdPreprocessBuildException e
) {
135 // Add more logic process here
137 throw new BuildException(e
.getMessage());
138 } catch (GenBuildException e
) {
140 // Add more logic process here
142 throw new BuildException(e
.getMessage());
143 } catch (EdkException e
) {
145 // Add more logic process here
147 throw new BuildException(e
.getMessage());
151 private void processFrameworkBuild() throws EdkException
, GenBuildException
, AutoGenException
, PcdAutogenException
, PlatformPcdPreprocessBuildException
{
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 ex
) {
184 BuildException buildException
= new BuildException("Scanning current directory error. \n" + ex
.getMessage());
185 buildException
.setStackTrace(ex
.getStackTrace());
186 throw buildException
;
190 // Deal with all environment variable (Add them to properties)
192 backupSystemProperties();
195 // Read target.txt file
200 // Global Data initialization
202 File workspacePath
= new File(getProject().getProperty("WORKSPACE"));
203 getProject().setProperty("WORKSPACE_DIR", workspacePath
.getPath().replaceAll("(\\\\)", "/"));
204 GlobalData
.initInfo(dbFilename
, workspacePath
.getPath(), toolsDefFilename
);
207 // If find MSA file and ACTIVE_PLATFORM is set, build the module;
209 // If without MSA file, and ACTIVE_PLATFORM is set, build the ACTIVE_PLATFORM.
210 // If ACTIVE_PLATFORM is not set, and only find one FPD file, build the platform;
211 // If find more than one FPD files, let user select one.
213 File buildFile
= null;
214 if (msaFiles
.size() > 1) {
215 throw new BuildException("Having more than one MSA file in a directory is not allowed!");
216 } else if (msaFiles
.size() == 1 && activePlatform
== null) {
217 throw new BuildException("If trying to build a single module, please set ACTIVE_PLATFORM in file [" + targetFilename
+ "]. ");
218 } else if (msaFiles
.size() == 1 && activePlatform
!= null) {
220 // Build the single module
222 buildFile
= msaFiles
.toArray(new File
[1])[0];
223 } else if (activePlatform
!= null) {
224 buildFile
= new File(GlobalData
.getWorkspacePath() + File
.separatorChar
+ activePlatform
);
225 } else if (fpdFiles
.size() == 1) {
226 buildFile
= fpdFiles
.toArray(new File
[1])[0];
227 } else if (fpdFiles
.size() > 1) {
228 buildFile
= intercommuniteWithUser();
231 // If there is no build files or FPD files or MSA files, stop build
234 throw new BuildException("Can't find any FPD or MSA files in the current directory. ");
238 // Build every FPD files (PLATFORM build)
240 if (buildFile
.getName().endsWith(ToolDefinitions
.FPD_EXTENSION
)) {
241 EdkLog
.log(this, "Processing the FPD file [" + buildFile
.getPath() + "] ..>> ");
243 // Iff for platform build will enable the multi-thread if set in target.txt
245 if (multithread
&& type
.equalsIgnoreCase("all")) {
246 EdkLog
.log(this, "Multi-thread build is enabled. ");
247 FpdParserForThread fpdParserForThread
= new FpdParserForThread();
248 fpdParserForThread
.setType(type
);
249 fpdParserForThread
.setProject(getProject());
250 fpdParserForThread
.setFpdFile(buildFile
);
251 fpdParserForThread
.perform();
255 FpdParserTask fpdParserTask
= new FpdParserTask();
256 fpdParserTask
.setType(type
);
257 fpdParserTask
.setProject(getProject());
258 fpdParserTask
.setFpdFile(buildFile
);
259 fpdParserTask
.perform();
262 // If cleanall delete the Platform_build.xml
264 if (type
.compareTo("cleanall") == 0) {
265 File platformBuildFile
=
266 new File(getProject().getProperty("PLATFORM_DIR")
268 + getProject().getProperty("PLATFORM")
270 platformBuildFile
.deleteOnExit();
275 // Build every MSA files (SINGLE MODULE BUILD)
277 else if (buildFile
.getName().endsWith(ToolDefinitions
.MSA_EXTENSION
)) {
278 File tmpFile
= new File(GlobalData
.getWorkspacePath() + File
.separatorChar
+ activePlatform
);
279 EdkLog
.log(this, "Using the FPD file [" + tmpFile
.getPath() + "] for the active platform. ");
280 EdkLog
.log(this, "Processing the MSA file [" + buildFile
.getPath() + "] ..>> ");
281 GenBuildTask genBuildTask
= new GenBuildTask();
282 genBuildTask
.setSingleModuleBuild(true);
283 genBuildTask
.setType(type
);
284 getProject().setProperty("PLATFORM_FILE", activePlatform
);
286 originalProperties
.put("PLATFORM_FILE", activePlatform
);
288 genBuildTask
.setProject(getProject());
289 genBuildTask
.setMsaFile(buildFile
);
290 genBuildTask
.perform();
295 Transfer system environment variables to ANT properties. If system variable
296 already exiests in ANT properties, skip it.
299 private void backupSystemProperties() {
300 Map
<String
, String
> sysProperties
= System
.getenv();
301 Iterator
<String
> iter
= sysProperties
.keySet().iterator();
302 while (iter
.hasNext()) {
303 String name
= iter
.next();
306 // If system environment variable is not in ANT properties, add it
308 if (getProject().getProperty(name
) == null) {
309 getProject().setProperty(name
, sysProperties
.get(name
));
313 Hashtable allProperties
= getProject().getProperties();
314 Iterator piter
= allProperties
.keySet().iterator();
315 while (piter
.hasNext()) {
316 String name
= (String
)piter
.next();
317 originalProperties
.put(new String(name
), new String((String
)allProperties
.get(name
)));
321 private File
intercommuniteWithUser(){
323 if (fpdFiles
.size() > 1) {
324 File
[] allFiles
= new File
[fpdFiles
.size()];
326 Iterator
<File
> iter
= fpdFiles
.iterator();
327 while (iter
.hasNext()) {
328 allFiles
[index
] = iter
.next();
332 EdkLog
.log(this, "Finding " + allFiles
.length
+ " FPD files: ");
333 for (int i
= 0; i
< allFiles
.length
; i
++) {
334 System
.out
.println("[" + (i
+ 1) + "]: " + allFiles
[i
].getName());
338 EdkLog
.log(this, "Please select one of the following FPD files to build:[1] ");
340 BufferedReader br
= new BufferedReader(new InputStreamReader(System
.in
));
342 String str
= br
.readLine();
343 if (str
.trim().length() == 0) {
348 int indexSelect
= Integer
.parseInt(str
);
349 if (indexSelect
<=0 || indexSelect
> allFiles
.length
) {
350 EdkLog
.log(this, "Please enter a number between [1.." + allFiles
.length
+ "]:[1] ");
353 file
= allFiles
[indexSelect
- 1];
357 } catch (Exception e
) {
358 EdkLog
.log(this, "Please enter a valid number:[1] ");
362 } else if (fpdFiles
.size() == 1) {
363 file
= fpdFiles
.toArray(new File
[1])[0];
369 public void setType(String type
) {
370 if (type
.equalsIgnoreCase("clean") || type
.equalsIgnoreCase("cleanall")) {
371 this.type
= type
.toLowerCase();
377 private void readTargetFile() throws EdkException
{
378 String targetFile
= getProject().getProperty("WORKSPACE_DIR") + File
.separatorChar
+ targetFilename
;
380 String
[][] targetFileInfo
= ConfigReader
.parse(targetFile
);
383 // Get ToolChain Info from target.txt
385 ToolChainInfo envToolChainInfo
= new ToolChainInfo();
386 String str
= getValue(ToolDefinitions
.TARGET_KEY_TARGET
, targetFileInfo
);
387 if (str
== null || str
.trim().equals("")) {
388 envToolChainInfo
.addTargets("*");
390 envToolChainInfo
.addTargets(str
);
392 str
= getValue(ToolDefinitions
.TARGET_KEY_TOOLCHAIN
, targetFileInfo
);
393 if (str
== null || str
.trim().equals("")) {
394 envToolChainInfo
.addTagnames("*");
396 envToolChainInfo
.addTagnames(str
);
398 str
= getValue(ToolDefinitions
.TARGET_KEY_ARCH
, targetFileInfo
);
399 if (str
== null || str
.trim().equals("")) {
400 envToolChainInfo
.addArchs("*");
402 envToolChainInfo
.addArchs(str
);
404 GlobalData
.setToolChainEnvInfo(envToolChainInfo
);
406 str
= getValue(ToolDefinitions
.TARGET_KEY_TOOLS_DEF
, targetFileInfo
);
407 if (str
!= null && str
.trim().length() > 0) {
408 toolsDefFilename
= str
;
411 str
= getValue(ToolDefinitions
.TARGET_KEY_ACTIVE_PLATFORM
, targetFileInfo
);
412 if (str
!= null && ! str
.trim().equals("")) {
413 if ( ! str
.endsWith(".fpd")) {
414 throw new BuildException("FPD file's extension must be \"" + ToolDefinitions
.FPD_EXTENSION
+ "\"!");
416 activePlatform
= str
;
419 str
= getValue(ToolDefinitions
.TARGET_KEY_MULTIPLE_THREAD
, targetFileInfo
);
420 if (str
!= null && str
.trim().equalsIgnoreCase("Enable")) {
424 str
= getValue(ToolDefinitions
.TARGET_KEY_MAX_CONCURRENT_THREAD_NUMBER
, targetFileInfo
);
427 int threadNum
= Integer
.parseInt(str
);
429 MAX_CONCURRENT_THREAD_NUMBER
= threadNum
;
431 } catch (Exception ex
) {
436 private String
getValue(String key
, String
[][] map
) {
437 for (int i
= 0; i
< map
[0].length
; i
++){
438 if (key
.equalsIgnoreCase(map
[0][i
])) {