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
, aprioriType
);
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
);
334 saq
.push(GlobalData
.getDoc(libinstances
[i
], fpdModuleId
.getArch()));
335 GlobalData
.addMsaBuildOption(libinstances
[i
], parseMsaBuildOptions(false));
336 GlobalData
.addMsaFamilyBuildOption(libinstances
[i
], parseMsaBuildOptions(true));
340 genBuildThread
.setDependencies(dependencies
);
342 // if (dependencies.size() == 0) {
343 genBuildThread
.setStatus(STATUS_DEPENDENCY_READY
);
346 allThreads
.put(fpdModuleId
, genBuildThread
);
349 // Put fpdModuleId to the corresponding FV
351 saq
.push(GlobalData
.getDoc(fpdModuleId
));
352 String fvBinding
= saq
.getModuleFvBindingKeyword();
354 fpdModuleId
.setFvBinding(fvBinding
);
355 updateFvs(fvBinding
, fpdModuleId
);
358 // Prepare for out put file name
360 ModuleIdentification moduleId
= fpdModuleId
.getModule();
362 String baseName
= saq
.getModuleOutputFileBasename();
364 if (baseName
== null) {
365 baseName
= moduleId
.getName();
367 outfiles
.put(fpdModuleId
, fpdModuleId
.getArch() + File
.separatorChar
368 + moduleId
.getGuid() + "-" + baseName
369 + getSuffix(moduleId
.getModuleType()));
372 // parse module build options, if any
374 GlobalData
.addModuleToolChainOption(fpdModuleId
, parseModuleBuildOptions(false));
375 GlobalData
.addModuleToolChainFamilyOption(fpdModuleId
, parseModuleBuildOptions(true));
378 // parse MSA build options
380 GlobalData
.addMsaBuildOption(moduleId
, parseMsaBuildOptions(false));
381 GlobalData
.addMsaFamilyBuildOption(moduleId
, parseMsaBuildOptions(true));
387 private boolean isContain(String
[] list
, String item
) {
388 for (int i
= 0; i
< list
.length
; i
++) {
389 if (list
[i
].equalsIgnoreCase(item
)) {
396 public synchronized static void addCount() {
397 synchronized (countSemaphore
) {
402 public synchronized static void subCount() {
403 synchronized (countSemaphore
) {
409 private void updateTaskName(int percentage
){
410 int number
= percentage
/10;
411 StringBuffer str
= new StringBuffer(9);
412 for(int i
= 0; i
< 9; i
++) {
419 this.setTaskName(str
.toString());