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
;
17 import java
.io
.IOException
;
18 import java
.util
.Hashtable
;
19 import java
.util
.Iterator
;
20 import java
.util
.LinkedHashSet
;
24 import org
.apache
.tools
.ant
.BuildException
;
25 import org
.apache
.tools
.ant
.Task
;
26 import org
.tianocore
.build
.exception
.AutoGenException
;
27 import org
.tianocore
.build
.exception
.GenBuildException
;
28 import org
.tianocore
.build
.exception
.PcdAutogenException
;
29 import org
.tianocore
.build
.exception
.PlatformPcdPreprocessBuildException
;
30 import org
.tianocore
.build
.fpd
.FpdParserForThread
;
31 import org
.tianocore
.build
.fpd
.FpdParserTask
;
32 import org
.tianocore
.build
.global
.GenBuildLogger
;
33 import org
.tianocore
.build
.global
.GlobalData
;
34 import org
.tianocore
.build
.toolchain
.ConfigReader
;
35 import org
.tianocore
.build
.toolchain
.ToolChainInfo
;
36 import org
.tianocore
.common
.definitions
.ToolDefinitions
;
37 import org
.tianocore
.common
.exception
.EdkException
;
38 import org
.tianocore
.common
.logger
.EdkLog
;
42 <code>FrameworkBuildTask</code> is an Ant task. The main function is finding
43 and processing a FPD or MSA file, then building a platform or stand-alone
47 The task search current directory and find out all MSA and FPD files by file
48 extension. Base on ACTIVE_PLATFORM policy, decide to build a platform or a
49 stand-alone module. The ACTIVE_PLATFORM policy is:
52 1. More than one MSA files, report error;
53 2. Only one MSA file, but ACTIVE_PLATFORM is not specified, report error;
54 3. Only one MSA file, and ACTIVE_PLATFORM is also specified, build this module;
55 4. No MSA file, and ACTIVE_PLATFORM is specified, build the active platform;
56 5. No MSA file, no ACTIVE_PLATFORM, and no FPD file, report error;
57 6. No MSA file, no ACTIVE_PLATFORM, and only one FPD file, build the platform;
58 7. No MSA file, no ACTIVE_PLATFORM, and more than one FPD files, Report Error!
62 Framework build task also parse target file [${WORKSPACE_DIR}/Tools/Conf/target.txt].
63 And load all system environment variables to Ant properties.
66 The usage for this task is :
69 <FrameworkBuild type="cleanall" />
74 public class FrameworkBuildTask
extends Task
{
76 private Set
<File
> fpdFiles
= new LinkedHashSet
<File
>();
78 private Set
<File
> msaFiles
= new LinkedHashSet
<File
>();
81 // This is only for none-multi-thread build to reduce overriding message
83 public static Hashtable
<String
, String
> originalProperties
= new Hashtable
<String
, String
>();
85 String toolsDefFilename
= ToolDefinitions
.DEFAULT_TOOLS_DEF_FILE_PATH
;
87 String targetFilename
= ToolDefinitions
.TARGET_FILE_PATH
;
89 String dbFilename
= ToolDefinitions
.FRAMEWORK_DATABASE_FILE_PATH
;
91 String activePlatform
= null;
94 /// The flag to present current is multi-thread enabled
96 public static boolean multithread
= false;
99 /// The concurrent thread number
101 public static int MAX_CONCURRENT_THREAD_NUMBER
= 2;
104 /// there are three type: all (build), clean and cleanall
106 private String type
= "all";
108 public void execute() throws BuildException
{
112 GenBuildLogger logger
= new GenBuildLogger(getProject());
113 EdkLog
.setLogLevel(EdkLog
.EDK_DEBUG
);
114 EdkLog
.setLogLevel(getProject().getProperty("env.LOGLEVEL"));
115 EdkLog
.setLogger(logger
);
118 processFrameworkBuild();
119 }catch (BuildException e
) {
121 // Add more logic process here
123 throw new BuildException(e
.getMessage());
124 } catch (PcdAutogenException e
) {
126 // Add more logic process here
128 throw new BuildException(e
.getMessage());
129 } catch (AutoGenException e
) {
131 // Add more logic process here
133 throw new BuildException(e
.getMessage());
134 } catch (PlatformPcdPreprocessBuildException e
) {
136 // Add more logic process here
138 throw new BuildException(e
.getMessage());
139 } catch (GenBuildException e
) {
141 // Add more logic process here
143 throw new BuildException(e
.getMessage());
144 } catch (EdkException e
) {
146 // Add more logic process here
148 throw new BuildException(e
.getMessage());
152 private void processFrameworkBuild() throws EdkException
, GenBuildException
, AutoGenException
, PcdAutogenException
, PlatformPcdPreprocessBuildException
{
155 // Get current working dir
157 File dummyFile
= new File(".");
158 File cwd
= dummyFile
.getCanonicalFile();
159 File
[] files
= cwd
.listFiles();
162 // Scan current dir, and find out all .FPD and .MSA files
164 for (int i
= 0; i
< files
.length
; i
++) {
165 if (files
[i
].isFile()) {
166 if (files
[i
].getName().endsWith(ToolDefinitions
.FPD_EXTENSION
)) {
170 fpdFiles
.add(files
[i
]);
171 } else if (files
[i
].getName().endsWith(ToolDefinitions
.MSA_EXTENSION
)) {
175 msaFiles
.add(files
[i
]);
179 } catch (IOException ex
) {
180 BuildException buildException
= new BuildException("Scanning current directory error. \n" + ex
.getMessage());
181 buildException
.setStackTrace(ex
.getStackTrace());
182 throw buildException
;
186 // Import all system environment variables to ANT properties
188 importSystemEnvVariables();
191 // Read target.txt file
196 // Global Data initialization
198 File workspacePath
= new File(getProject().getProperty("WORKSPACE"));
199 getProject().setProperty("WORKSPACE_DIR", workspacePath
.getPath().replaceAll("(\\\\)", "/"));
200 GlobalData
.initInfo(dbFilename
, workspacePath
.getPath(), toolsDefFilename
);
203 // If find MSA file and ACTIVE_PLATFORM is set, build the module;
205 // If without MSA file, and ACTIVE_PLATFORM is set, build the ACTIVE_PLATFORM.
206 // If ACTIVE_PLATFORM is not set, and only find one FPD file, build the platform;
207 // If find more than one FPD files, report error.
209 File buildFile
= null;
210 if (msaFiles
.size() > 1) {
211 throw new BuildException("Found " + msaFiles
.size() + " MSA files in current dir. ");
212 } else if (msaFiles
.size() == 1 && activePlatform
== null) {
213 throw new BuildException("If trying to build a single module, please set ACTIVE_PLATFORM in file [" + targetFilename
+ "]. ");
214 } else if (msaFiles
.size() == 1 && activePlatform
!= null) {
216 // Build the single module
218 buildFile
= msaFiles
.toArray(new File
[1])[0];
219 } else if (activePlatform
!= null) {
220 buildFile
= new File(GlobalData
.getWorkspacePath() + File
.separatorChar
+ activePlatform
);
221 } else if (fpdFiles
.size() == 1) {
222 buildFile
= fpdFiles
.toArray(new File
[1])[0];
223 } else if (fpdFiles
.size() > 1) {
224 throw new BuildException("Found " + fpdFiles
.size() + " FPD files in current dir. ");
228 // If there is no build files or FPD files or MSA files, stop build
231 throw new BuildException("Can't find any FPD or MSA files in the current directory. ");
235 // Build every FPD files (PLATFORM build)
237 if (buildFile
.getName().endsWith(ToolDefinitions
.FPD_EXTENSION
)) {
238 EdkLog
.log(this, "Processing the FPD file [" + buildFile
.getPath() + "] ..>> ");
240 // Iff for platform build will enable the multi-thread if set in target.txt
242 if (multithread
&& type
.equalsIgnoreCase("all")) {
243 EdkLog
.log(this, "Multi-thread build is enabled. ");
244 FpdParserForThread fpdParserForThread
= new FpdParserForThread();
245 fpdParserForThread
.setType(type
);
246 fpdParserForThread
.setProject(getProject());
247 fpdParserForThread
.setFpdFile(buildFile
);
248 fpdParserForThread
.perform();
252 FpdParserTask fpdParserTask
= new FpdParserTask();
253 fpdParserTask
.setType(type
);
254 fpdParserTask
.setProject(getProject());
255 fpdParserTask
.setFpdFile(buildFile
);
256 fpdParserTask
.perform();
259 // If cleanall delete the Platform_build.xml
261 if (type
.compareTo("cleanall") == 0) {
262 File platformBuildFile
=
263 new File(getProject().getProperty("BUILD_DIR")
265 + getProject().getProperty("PLATFORM")
267 platformBuildFile
.deleteOnExit();
272 // Build every MSA files (SINGLE MODULE BUILD)
274 else if (buildFile
.getName().endsWith(ToolDefinitions
.MSA_EXTENSION
)) {
276 EdkLog
.log(this, EdkLog
.EDK_WARNING
, "Multi-Thead do not take effect on Stand-Alone (Single) module build. ");
279 File tmpFile
= new File(GlobalData
.getWorkspacePath() + File
.separatorChar
+ activePlatform
);
280 EdkLog
.log(this, "Using the FPD file [" + tmpFile
.getPath() + "] for the active platform. ");
281 EdkLog
.log(this, "Processing the MSA file [" + buildFile
.getPath() + "] ..>> ");
282 GenBuildTask genBuildTask
= new GenBuildTask();
283 genBuildTask
.setSingleModuleBuild(true);
284 genBuildTask
.setType(type
);
285 getProject().setProperty("PLATFORM_FILE", activePlatform
);
287 originalProperties
.put("PLATFORM_FILE", activePlatform
);
289 genBuildTask
.setProject(getProject());
290 genBuildTask
.setMsaFile(buildFile
);
291 genBuildTask
.perform();
296 Import system environment variables to ANT properties. If system variable
297 already exiests in ANT properties, skip it.
300 private void importSystemEnvVariables() {
301 Map
<String
, String
> sysProperties
= System
.getenv();
302 Iterator
<String
> iter
= sysProperties
.keySet().iterator();
303 while (iter
.hasNext()) {
304 String name
= iter
.next();
307 // If system environment variable is not in ANT properties, add it
309 if (getProject().getProperty(name
) == null) {
310 getProject().setProperty(name
, sysProperties
.get(name
));
314 Hashtable allProperties
= getProject().getProperties();
315 Iterator piter
= allProperties
.keySet().iterator();
316 while (piter
.hasNext()) {
317 String name
= (String
)piter
.next();
318 originalProperties
.put(new String(name
), new String((String
)allProperties
.get(name
)));
322 public void setType(String type
) {
323 if (type
.equalsIgnoreCase("clean") || type
.equalsIgnoreCase("cleanall")) {
324 this.type
= type
.toLowerCase();
330 private void readTargetFile() throws EdkException
{
331 String targetFile
= getProject().getProperty("WORKSPACE_DIR") + File
.separatorChar
+ targetFilename
;
333 String
[][] targetFileInfo
= ConfigReader
.parse(targetFile
);
336 // Get ToolChain Info from target.txt
338 ToolChainInfo envToolChainInfo
= new ToolChainInfo();
339 String str
= getValue(ToolDefinitions
.TARGET_KEY_TARGET
, targetFileInfo
);
340 if (str
== null || str
.trim().equals("")) {
341 envToolChainInfo
.addTargets("*");
343 envToolChainInfo
.addTargets(str
);
345 str
= getValue(ToolDefinitions
.TARGET_KEY_TOOLCHAIN
, targetFileInfo
);
346 if (str
== null || str
.trim().equals("")) {
347 envToolChainInfo
.addTagnames("*");
349 envToolChainInfo
.addTagnames(str
);
351 str
= getValue(ToolDefinitions
.TARGET_KEY_ARCH
, targetFileInfo
);
352 if (str
== null || str
.trim().equals("")) {
353 envToolChainInfo
.addArchs("*");
355 envToolChainInfo
.addArchs(str
);
357 GlobalData
.setToolChainEnvInfo(envToolChainInfo
);
359 str
= getValue(ToolDefinitions
.TARGET_KEY_TOOLS_DEF
, targetFileInfo
);
360 if (str
!= null && str
.trim().length() > 0) {
361 toolsDefFilename
= str
;
364 str
= getValue(ToolDefinitions
.TARGET_KEY_ACTIVE_PLATFORM
, targetFileInfo
);
365 if (str
!= null && ! str
.trim().equals("")) {
366 if ( ! str
.endsWith(".fpd")) {
367 throw new BuildException("FPD file's extension must be \"" + ToolDefinitions
.FPD_EXTENSION
+ "\"!");
369 activePlatform
= str
;
372 str
= getValue(ToolDefinitions
.TARGET_KEY_MULTIPLE_THREAD
, targetFileInfo
);
373 if (str
!= null && str
.trim().equalsIgnoreCase("Enable")) {
377 str
= getValue(ToolDefinitions
.TARGET_KEY_MAX_CONCURRENT_THREAD_NUMBER
, targetFileInfo
);
379 // Need to check the # of threads iff multithread is enabled.
381 if ((multithread
) && (str
!= null )) {
383 int threadNum
= Integer
.parseInt(str
);
385 MAX_CONCURRENT_THREAD_NUMBER
= threadNum
;
387 } catch (Exception ex
) {
389 // Give a warning message, and keep the default value
391 EdkLog
.log(this, EdkLog
.EDK_WARNING
, "Incorrent number specified for MAX_CONCURRENT_THREAD_NUMBER in file [" + targetFilename
+ "]");
396 private String
getValue(String key
, String
[][] map
) {
397 for (int i
= 0; i
< map
[0].length
; i
++){
398 if (key
.equalsIgnoreCase(map
[0][i
])) {