2 This file is ANT task FpdParserTask.
4 Copyright (c) 2006, Intel Corporation
5 All rights reserved. This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
13 package org
.tianocore
.build
.fpd
;
16 import java
.util
.ArrayList
;
17 import java
.util
.Iterator
;
18 import java
.util
.LinkedHashMap
;
19 import java
.util
.LinkedHashSet
;
20 import java
.util
.List
;
24 import org
.apache
.tools
.ant
.BuildException
;
25 import org
.apache
.tools
.ant
.taskdefs
.Ant
;
26 import org
.apache
.xmlbeans
.XmlObject
;
28 import org
.tianocore
.build
.global
.GenBuildLogger
;
29 import org
.tianocore
.build
.global
.GlobalData
;
30 import org
.tianocore
.build
.global
.OutputManager
;
31 import org
.tianocore
.build
.id
.FpdModuleIdentification
;
32 import org
.tianocore
.build
.id
.ModuleIdentification
;
33 import org
.tianocore
.build
.FrameworkBuildTask
;
34 import org
.tianocore
.build
.GenBuildThread
;
35 import org
.tianocore
.common
.exception
.EdkException
;
36 import org
.tianocore
.common
.logger
.EdkLog
;
42 public class FpdParserForThread
extends FpdParserTask
{
44 public static Map
<FpdModuleIdentification
, GenBuildThread
> allThreads
= new LinkedHashMap
<FpdModuleIdentification
, GenBuildThread
>();
46 List
<String
> queueList
= new ArrayList
<String
>();
48 public final static Object deamonSemaphore
= new Object();
50 private final static Object countSemaphore
= new Object();
52 public static int STATUS_DEPENDENCY_NOT_READY
= 1;
54 public static int STATUS_DEPENDENCY_READY
= 2;
56 public static int STATUS_START_RUN
= 3;
58 public static int STATUS_END_RUN
= 4;
60 private int currentQueueCode
= 0;
62 public static int currentRunNumber
= 0;
64 public static int totalNumber
= 0;
66 public static int remainNumber
= 0;
68 public static ThreadGroup tg
= new ThreadGroup("Framework");
70 public static FpdModuleIdentification errorModule
= null;
73 Public construct method. It is necessary for ANT task.
75 public FpdParserForThread() {
82 public void execute() throws BuildException
{
84 this.setTaskName(".........");
93 isUnified
= OutputManager
.getInstance().prepareBuildDir(getProject());
94 String buildDir
= getProject().getProperty("BUILD_DIR");
97 // For every Target and ToolChain
99 String
[] targetList
= GlobalData
.getToolChainInfo().getTargets();
100 for (int i
= 0; i
< targetList
.length
; i
++) {
101 String
[] toolchainList
= GlobalData
.getToolChainInfo().getTagnames();
102 for(int j
= 0; j
< toolchainList
.length
; j
++) {
106 String ffsCommonDir
= buildDir
+ File
.separatorChar
107 + targetList
[i
] + "_"
109 File fvDir
= new File(ffsCommonDir
+ File
.separatorChar
+ "FV");
111 getProject().setProperty("FV_DIR", fvDir
.getPath().replaceAll("(\\\\)", "/"));
116 genFvInfFiles(ffsCommonDir
);
123 String platformBuildFile
= buildDir
+ File
.separatorChar
+ platformId
.getName() + "_build.xml";
124 PlatformBuildFileGenerator fileGenerator
= new PlatformBuildFileGenerator(getProject(), outfiles
, fvs
, isUnified
, saq
, platformBuildFile
);
125 fileGenerator
.genBuildFile();
130 queueList
.add("libqueue");
132 String
[] validFv
= saq
.getFpdValidImageNames();
134 for (int i
= 0; i
< validFv
.length
; i
++) {
135 queueList
.add(validFv
[i
]);
138 Iterator
<String
> fvsNameIter
= fvs
.keySet().iterator();
140 while (fvsNameIter
.hasNext()) {
141 String fvName
= fvsNameIter
.next();
142 if (!isContain(validFv
, fvName
)) {
143 queueList
.add(fvName
);
148 // Ant call ${PLATFORM}_build.xml
151 ant
.setProject(getProject());
152 ant
.setAntfile(platformBuildFile
);
153 ant
.setTarget("prebuild");
154 ant
.setInheritAll(true);
158 remainNumber
= totalNumber
= allThreads
.size();
160 EdkLog
.log(this, EdkLog
.EDK_ALWAYS
, "Total thread number is " + totalNumber
);
161 GenBuildLogger
.setCacheEnable(true);
163 // Waiting for all thread over, or time out
165 synchronized (deamonSemaphore
) {
169 // If all modules are already built
171 if (currentQueueCode
>= queueList
.size()) {
175 int percentage
= (totalNumber
- remainNumber
) * 100 / totalNumber
;
176 updateTaskName(percentage
);
177 EdkLog
.log(this, EdkLog
.EDK_ALWAYS
, percentage
+ "% finished. Has built " + (totalNumber
- remainNumber
) + " modules of " + totalNumber
+ " total. ");
179 Set
<FpdModuleIdentification
> currentQueueModules
= fvs
.get(queueList
.get(currentQueueCode
));
181 if (currentQueueModules
== null) {
185 Iterator
<FpdModuleIdentification
> currentIter
= currentQueueModules
.iterator();
187 GenBuildThread a
= null;
189 boolean existNoneReady
= false;
191 while (currentIter
.hasNext()) {
192 GenBuildThread item
= allThreads
.get(currentIter
.next());
193 if (item
.getStatus() == STATUS_DEPENDENCY_NOT_READY
) {
194 existNoneReady
= true;
195 } else if (item
.getStatus() == STATUS_DEPENDENCY_READY
) {
199 if (currentRunNumber
== FrameworkBuildTask
.MAX_CONCURRENT_THREAD_NUMBER
) {
207 // Exist ready thread
209 EdkLog
.log(this, EdkLog
.EDK_DEBUG
, "Exist ready thread");
211 } else if (existNoneReady
&& currentRunNumber
== 0) {
213 // No active thread, but still have dependency not read thread
215 throw new BuildException("Existing some modules can't resolve depedencies. ");
216 } else if (!existNoneReady
&& currentRunNumber
== 0) {
218 // Current queue build finish, move to next
220 EdkLog
.log(this, EdkLog
.EDK_DEBUG
, "Current queue build finish, move to next");
225 // active thread exist, but no ready thread
227 EdkLog
.log(this, EdkLog
.EDK_DEBUG
, "Active thread exist, but no ready thread. Current running number is " + currentRunNumber
);
231 deamonSemaphore
.wait();
234 // if find error. Waiting running threads to finish
236 if (errorModule
!= null) {
237 while (currentRunNumber
> 0) {
238 deamonSemaphore
.wait();
241 GenBuildLogger
.setCacheEnable(false);
243 GenBuildLogger
.flushErrorModuleLog(errorModule
);
245 EdkLog
.flushLogToFile(new File(buildDir
+ File
.separatorChar
+ "build.log"));
247 throw new BuildException(errorModule
+ " build error. ");
249 } catch (InterruptedException ex
) {
250 BuildException e
= new BuildException("Thread wait Error. \n" + ex
.getMessage());
251 e
.setStackTrace(ex
.getStackTrace());
257 GenBuildLogger
.setCacheEnable(false);
259 // call fvs, postbuild
262 ant
.setProject(getProject());
263 ant
.setAntfile(platformBuildFile
);
264 ant
.setTarget("fvs");
265 ant
.setInheritAll(true);
270 ant
.setProject(getProject());
271 ant
.setAntfile(platformBuildFile
);
272 ant
.setTarget("postbuild");
273 ant
.setInheritAll(true);
277 EdkLog
.flushLogToFile(new File(buildDir
+ File
.separatorChar
+ "build.log"));
282 Parse all modules listed in FPD file.
284 void parseModuleSAFiles() throws EdkException
{
286 Map
<FpdModuleIdentification
, Map
<String
, XmlObject
>> moduleSAs
= saq
.getFpdModules();
289 // For every Module lists in FPD file.
291 Set
<FpdModuleIdentification
> keys
= moduleSAs
.keySet();
292 Iterator
<FpdModuleIdentification
> iter
= keys
.iterator();
293 while (iter
.hasNext()) {
294 FpdModuleIdentification fpdModuleId
= iter
.next();
297 // Generate GenBuildThread
299 GenBuildThread genBuildThread
= new GenBuildThread(fpdModuleId
.getModule(), fpdModuleId
.getArch());
300 genBuildThread
.setParentModuleId(null);
301 genBuildThread
.setProject(getProject());
303 Set
<FpdModuleIdentification
> dependencies
= new LinkedHashSet
<FpdModuleIdentification
>();
305 GlobalData
.registerFpdModuleSA(fpdModuleId
, moduleSAs
.get(fpdModuleId
));
308 // Add all dependent Library Instance
310 saq
.push(GlobalData
.getDoc(fpdModuleId
));
312 ModuleIdentification
[] libinstances
= saq
.getLibraryInstance(fpdModuleId
.getArch());
315 for (int i
= 0; i
< libinstances
.length
; i
++) {
316 FpdModuleIdentification libFpdModuleId
= new FpdModuleIdentification(libinstances
[i
], fpdModuleId
.getArch());
318 // Add to dependencies
320 dependencies
.add(libFpdModuleId
);
323 // Create thread for library instances
325 GenBuildThread liBuildThread
= new GenBuildThread(libinstances
[i
], fpdModuleId
.getArch());
326 liBuildThread
.setParentModuleId(fpdModuleId
.getModule());
327 liBuildThread
.setProject(getProject());
328 liBuildThread
.setStatus(STATUS_DEPENDENCY_READY
);
329 liBuildThread
.setHighPriority(true);
330 allThreads
.put(libFpdModuleId
, liBuildThread
);
332 updateFvs("libqueue", libFpdModuleId
);
335 genBuildThread
.setDependencies(dependencies
);
337 // if (dependencies.size() == 0) {
338 genBuildThread
.setStatus(STATUS_DEPENDENCY_READY
);
341 allThreads
.put(fpdModuleId
, genBuildThread
);
344 // Put fpdModuleId to the corresponding FV
346 saq
.push(GlobalData
.getDoc(fpdModuleId
));
347 String fvBinding
= saq
.getModuleFvBindingKeyword();
349 fpdModuleId
.setFvBinding(fvBinding
);
350 updateFvs(fvBinding
, fpdModuleId
);
353 // Prepare for out put file name
355 ModuleIdentification moduleId
= fpdModuleId
.getModule();
357 String baseName
= saq
.getModuleOutputFileBasename();
359 if (baseName
== null) {
360 baseName
= moduleId
.getName();
362 outfiles
.put(fpdModuleId
, fpdModuleId
.getArch() + File
.separatorChar
363 + moduleId
.getGuid() + "-" + baseName
364 + getSuffix(moduleId
.getModuleType()));
367 // parse module build options, if any
369 GlobalData
.addModuleToolChainOption(fpdModuleId
, parseModuleBuildOptions(false));
370 GlobalData
.addModuleToolChainFamilyOption(fpdModuleId
, parseModuleBuildOptions(true));
375 private boolean isContain(String
[] list
, String item
) {
376 for (int i
= 0; i
< list
.length
; i
++) {
377 if (list
[i
].equalsIgnoreCase(item
)) {
384 public synchronized static void addCount() {
385 synchronized (countSemaphore
) {
390 public synchronized static void subCount() {
391 synchronized (countSemaphore
) {
397 private void updateTaskName(int percentage
){
398 int number
= percentage
/10;
399 StringBuffer str
= new StringBuffer(9);
400 for(int i
= 0; i
< 9; i
++) {
407 this.setTaskName(str
.toString());