Fix a bug that can't add library MSA specific build option in multi-thread build...
[mirror_edk2.git] / Tools / Java / Source / GenBuild / org / tianocore / build / fpd / FpdParserForThread.java
CommitLineData
abce9cbd 1/** @file\r
2 This file is ANT task FpdParserTask. \r
3 \r
abce9cbd 4 Copyright (c) 2006, Intel Corporation\r
5 All rights reserved. This program and the accompanying materials\r
6 are licensed and made available under the terms and conditions of the BSD License\r
7 which accompanies this distribution. The full text of the license may be found at\r
8 http://opensource.org/licenses/bsd-license.php\r
9\r
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
12 **/\r
13package org.tianocore.build.fpd;\r
14\r
15import java.io.File;\r
16import java.util.ArrayList;\r
17import java.util.Iterator;\r
18import java.util.LinkedHashMap;\r
19import java.util.LinkedHashSet;\r
20import java.util.List;\r
21import java.util.Map;\r
22import java.util.Set;\r
23\r
24import org.apache.tools.ant.BuildException;\r
25import org.apache.tools.ant.taskdefs.Ant;\r
26import org.apache.xmlbeans.XmlObject;\r
27\r
2eb7d78d 28import org.tianocore.build.global.GenBuildLogger;\r
abce9cbd 29import org.tianocore.build.global.GlobalData;\r
30import org.tianocore.build.global.OutputManager;\r
31import org.tianocore.build.id.FpdModuleIdentification;\r
32import org.tianocore.build.id.ModuleIdentification;\r
33import org.tianocore.build.FrameworkBuildTask;\r
34import org.tianocore.build.GenBuildThread;\r
35import org.tianocore.common.exception.EdkException;\r
02c768ee 36import org.tianocore.common.logger.EdkLog;\r
abce9cbd 37\r
38/**\r
abce9cbd 39\r
40 @since GenBuild 1.0\r
41**/\r
42public class FpdParserForThread extends FpdParserTask {\r
43 \r
44 public static Map<FpdModuleIdentification, GenBuildThread> allThreads = new LinkedHashMap<FpdModuleIdentification, GenBuildThread>();\r
45 \r
46 List<String> queueList = new ArrayList<String>();\r
47 \r
3067c4b0 48 public final static Object deamonSemaphore = new Object();\r
abce9cbd 49 \r
3067c4b0 50 private final static Object countSemaphore = new Object();\r
abce9cbd 51 \r
52 public static int STATUS_DEPENDENCY_NOT_READY = 1;\r
53 \r
54 public static int STATUS_DEPENDENCY_READY = 2;\r
55 \r
56 public static int STATUS_START_RUN = 3;\r
57 \r
58 public static int STATUS_END_RUN = 4;\r
59 \r
60 private int currentQueueCode = 0;\r
61 \r
62 public static int currentRunNumber = 0;\r
63 \r
2eb7d78d 64 public static int totalNumber = 0;\r
65 \r
66 public static int remainNumber = 0;\r
67 \r
3067c4b0 68 public static ThreadGroup tg = new ThreadGroup("Framework");\r
69 \r
498e9021 70 public static FpdModuleIdentification errorModule = null;\r
3067c4b0 71 \r
abce9cbd 72 /**\r
73 Public construct method. It is necessary for ANT task.\r
74 **/\r
75 public FpdParserForThread() {\r
76 }\r
77\r
78 /**\r
abce9cbd 79 \r
c8df018e 80\r
abce9cbd 81 **/\r
82 public void execute() throws BuildException {\r
2eb7d78d 83 \r
84 this.setTaskName(".........");\r
abce9cbd 85 //\r
86 // Parse FPD file\r
87 //\r
88 parseFpdFile();\r
89\r
90 //\r
91 // Prepare BUILD_DIR\r
92 //\r
93 isUnified = OutputManager.getInstance().prepareBuildDir(getProject());\r
02c768ee 94 String buildDir = getProject().getProperty("BUILD_DIR");\r
95 \r
abce9cbd 96 //\r
97 // For every Target and ToolChain\r
98 //\r
99 String[] targetList = GlobalData.getToolChainInfo().getTargets();\r
100 for (int i = 0; i < targetList.length; i++) {\r
101 String[] toolchainList = GlobalData.getToolChainInfo().getTagnames();\r
102 for(int j = 0; j < toolchainList.length; j++) {\r
103 //\r
104 // Prepare FV_DIR\r
105 //\r
02c768ee 106 String ffsCommonDir = buildDir + File.separatorChar\r
2eb7d78d 107 + targetList[i] + "_"\r
abce9cbd 108 + toolchainList[j];\r
109 File fvDir = new File(ffsCommonDir + File.separatorChar + "FV");\r
110 fvDir.mkdirs();\r
111 getProject().setProperty("FV_DIR", fvDir.getPath().replaceAll("(\\\\)", "/"));\r
112\r
113 //\r
114 // Gen Fv.inf files\r
115 //\r
116 genFvInfFiles(ffsCommonDir);\r
117 }\r
118 }\r
119\r
120 //\r
121 // Gen build.xml\r
122 //\r
02c768ee 123 String platformBuildFile = buildDir + File.separatorChar + platformId.getName() + "_build.xml";\r
124 PlatformBuildFileGenerator fileGenerator = new PlatformBuildFileGenerator(getProject(), outfiles, fvs, isUnified, saq, platformBuildFile);\r
abce9cbd 125 fileGenerator.genBuildFile();\r
126 \r
127 //\r
128 // Prepare Queue\r
129 //\r
130 queueList.add("libqueue");\r
131 \r
132 String[] validFv = saq.getFpdValidImageNames();\r
133 \r
134 for (int i = 0; i < validFv.length; i++) {\r
135 queueList.add(validFv[i]);\r
136 }\r
137 \r
138 Iterator<String> fvsNameIter = fvs.keySet().iterator();\r
139 \r
140 while (fvsNameIter.hasNext()) {\r
141 String fvName = fvsNameIter.next();\r
142 if (!isContain(validFv, fvName)) {\r
143 queueList.add(fvName);\r
144 }\r
145 }\r
146 \r
147 //\r
148 // Ant call ${PLATFORM}_build.xml\r
149 //\r
150 Ant ant = new Ant();\r
151 ant.setProject(getProject());\r
02c768ee 152 ant.setAntfile(platformBuildFile);\r
abce9cbd 153 ant.setTarget("prebuild");\r
154 ant.setInheritAll(true);\r
155 ant.init();\r
156 ant.execute();\r
157 \r
2eb7d78d 158 remainNumber = totalNumber = allThreads.size();\r
abce9cbd 159 \r
2eb7d78d 160 EdkLog.log(this, EdkLog.EDK_ALWAYS, "Total thread number is " + totalNumber);\r
161 GenBuildLogger.setCacheEnable(true);\r
abce9cbd 162 //\r
163 // Waiting for all thread over, or time out\r
164 //\r
165 synchronized (deamonSemaphore) {\r
498e9021 166\r
abce9cbd 167 while (true) {\r
168 //\r
169 // If all modules are already built\r
170 //\r
171 if (currentQueueCode >= queueList.size()) {\r
172 break ;\r
173 }\r
2eb7d78d 174 \r
175 int percentage = (totalNumber - remainNumber) * 100 / totalNumber;\r
1a0d7262 176 updateTaskName(percentage);\r
2eb7d78d 177 EdkLog.log(this, EdkLog.EDK_ALWAYS, percentage + "% finished. Has built " + (totalNumber - remainNumber) + " modules of " + totalNumber + " total. ");\r
abce9cbd 178\r
179 Set<FpdModuleIdentification> currentQueueModules = fvs.get(queueList.get(currentQueueCode));\r
180 \r
181 if (currentQueueModules == null) {\r
182 ++currentQueueCode;\r
183 continue ;\r
184 }\r
185 Iterator<FpdModuleIdentification> currentIter = currentQueueModules.iterator();\r
186\r
187 GenBuildThread a = null;\r
188\r
189 boolean existNoneReady = false;\r
190\r
191 while (currentIter.hasNext()) {\r
192 GenBuildThread item = allThreads.get(currentIter.next()); \r
193 if (item.getStatus() == STATUS_DEPENDENCY_NOT_READY) {\r
194 existNoneReady = true;\r
195 } else if (item.getStatus() == STATUS_DEPENDENCY_READY) {\r
196 a = item;\r
197 addCount();\r
198 a.start();\r
199 if (currentRunNumber == FrameworkBuildTask.MAX_CONCURRENT_THREAD_NUMBER) {\r
200 break ;\r
201 }\r
202 }\r
203 }\r
204\r
205 if (a != null) {\r
206 //\r
207 // Exist ready thread\r
208 //\r
bb511931 209 EdkLog.log(this, EdkLog.EDK_DEBUG, "Exist ready thread");\r
abce9cbd 210\r
211 } else if (existNoneReady && currentRunNumber == 0) {\r
212 //\r
213 // No active thread, but still have dependency not read thread\r
214 //\r
2eb7d78d 215 throw new BuildException("Existing some modules can't resolve depedencies. ");\r
abce9cbd 216 } else if (!existNoneReady && currentRunNumber == 0) {\r
217 //\r
218 // Current queue build finish, move to next\r
219 //\r
bb511931 220 EdkLog.log(this, EdkLog.EDK_DEBUG, "Current queue build finish, move to next");\r
abce9cbd 221 ++currentQueueCode;\r
222 continue ;\r
223 } else {\r
224 //\r
225 // active thread exist, but no ready thread\r
226 //\r
bb511931 227 EdkLog.log(this, EdkLog.EDK_DEBUG, "Active thread exist, but no ready thread. Current running number is " + currentRunNumber);\r
abce9cbd 228 }\r
229\r
230 try {\r
231 deamonSemaphore.wait();\r
498e9021 232 \r
233 //\r
bb511931 234 // if find error. Waiting running threads to finish\r
498e9021 235 //\r
236 if (errorModule != null) {\r
237 while (currentRunNumber > 0) {\r
238 deamonSemaphore.wait();\r
239 }\r
240 \r
3067c4b0 241 GenBuildLogger.setCacheEnable(false);\r
3067c4b0 242 \r
498e9021 243 GenBuildLogger.flushErrorModuleLog(errorModule);\r
244 \r
245 EdkLog.flushLogToFile(new File(buildDir + File.separatorChar + "build.log"));\r
3067c4b0 246 \r
498e9021 247 throw new BuildException(errorModule + " build error. ");\r
3067c4b0 248 }\r
2eb7d78d 249 } catch (InterruptedException ex) {\r
250 BuildException e = new BuildException("Thread wait Error. \n" + ex.getMessage());\r
251 e.setStackTrace(ex.getStackTrace());\r
252 throw e;\r
abce9cbd 253 }\r
254 }\r
255 }\r
3067c4b0 256 \r
2eb7d78d 257 GenBuildLogger.setCacheEnable(false);\r
abce9cbd 258 //\r
259 // call fvs, postbuild\r
260 //\r
261 ant = new Ant();\r
262 ant.setProject(getProject());\r
02c768ee 263 ant.setAntfile(platformBuildFile);\r
abce9cbd 264 ant.setTarget("fvs");\r
265 ant.setInheritAll(true);\r
266 ant.init();\r
267 ant.execute();\r
268 \r
269 ant = new Ant();\r
270 ant.setProject(getProject());\r
02c768ee 271 ant.setAntfile(platformBuildFile);\r
abce9cbd 272 ant.setTarget("postbuild");\r
273 ant.setInheritAll(true);\r
274 ant.init();\r
275 ant.execute();\r
276 \r
2eb7d78d 277 EdkLog.flushLogToFile(new File(buildDir + File.separatorChar + "build.log"));\r
abce9cbd 278 }\r
279\r
280 \r
281 /**\r
282 Parse all modules listed in FPD file. \r
283 **/\r
284 void parseModuleSAFiles() throws EdkException{\r
285 \r
286 Map<FpdModuleIdentification, Map<String, XmlObject>> moduleSAs = saq.getFpdModules();\r
287\r
288 //\r
289 // For every Module lists in FPD file.\r
290 //\r
291 Set<FpdModuleIdentification> keys = moduleSAs.keySet();\r
292 Iterator<FpdModuleIdentification> iter = keys.iterator();\r
293 while (iter.hasNext()) {\r
294 FpdModuleIdentification fpdModuleId = iter.next();\r
295 \r
296 //\r
297 // Generate GenBuildThread\r
298 //\r
3067c4b0 299 GenBuildThread genBuildThread = new GenBuildThread(fpdModuleId.getModule(), fpdModuleId.getArch());\r
abce9cbd 300 genBuildThread.setParentModuleId(null);\r
abce9cbd 301 genBuildThread.setProject(getProject());\r
302 \r
303 Set<FpdModuleIdentification> dependencies = new LinkedHashSet<FpdModuleIdentification>();\r
304 \r
305 GlobalData.registerFpdModuleSA(fpdModuleId, moduleSAs.get(fpdModuleId));\r
306 \r
307 //\r
308 // Add all dependent Library Instance\r
309 //\r
310 saq.push(GlobalData.getDoc(fpdModuleId));\r
311\r
312 ModuleIdentification[] libinstances = saq.getLibraryInstance(fpdModuleId.getArch());\r
313 saq.pop();\r
314 \r
315 for (int i = 0; i < libinstances.length; i++) {\r
316 FpdModuleIdentification libFpdModuleId = new FpdModuleIdentification(libinstances[i], fpdModuleId.getArch());\r
317 //\r
318 // Add to dependencies\r
319 //\r
320 dependencies.add(libFpdModuleId);\r
321 \r
322 //\r
323 // Create thread for library instances\r
324 //\r
3067c4b0 325 GenBuildThread liBuildThread = new GenBuildThread(libinstances[i], fpdModuleId.getArch());\r
abce9cbd 326 liBuildThread.setParentModuleId(fpdModuleId.getModule());\r
abce9cbd 327 liBuildThread.setProject(getProject());\r
328 liBuildThread.setStatus(STATUS_DEPENDENCY_READY);\r
329 liBuildThread.setHighPriority(true);\r
330 allThreads.put(libFpdModuleId, liBuildThread);\r
331 \r
332 updateFvs("libqueue", libFpdModuleId);\r
e4764dae 333 \r
334 saq.push(GlobalData.getDoc(libinstances[i], fpdModuleId.getArch()));\r
335 GlobalData.addMsaBuildOption(libinstances[i], parseMsaBuildOptions(false));\r
336 GlobalData.addMsaFamilyBuildOption(libinstances[i], parseMsaBuildOptions(true));\r
337 saq.pop();\r
abce9cbd 338 }\r
339 \r
3067c4b0 340 genBuildThread.setDependencies(dependencies);\r
341 \r
abce9cbd 342// if (dependencies.size() == 0) {\r
343 genBuildThread.setStatus(STATUS_DEPENDENCY_READY);\r
344// }\r
345 \r
346 allThreads.put(fpdModuleId, genBuildThread);\r
347 \r
348 //\r
349 // Put fpdModuleId to the corresponding FV\r
350 //\r
351 saq.push(GlobalData.getDoc(fpdModuleId));\r
352 String fvBinding = saq.getModuleFvBindingKeyword();\r
353\r
354 fpdModuleId.setFvBinding(fvBinding);\r
355 updateFvs(fvBinding, fpdModuleId);\r
356\r
357 //\r
358 // Prepare for out put file name\r
359 //\r
360 ModuleIdentification moduleId = fpdModuleId.getModule();\r
361\r
362 String baseName = saq.getModuleOutputFileBasename();\r
363 \r
364 if (baseName == null) {\r
365 baseName = moduleId.getName();\r
366 }\r
367 outfiles.put(fpdModuleId, fpdModuleId.getArch() + File.separatorChar\r
368 + moduleId.getGuid() + "-" + baseName\r
369 + getSuffix(moduleId.getModuleType()));\r
370\r
371 //\r
372 // parse module build options, if any\r
373 //\r
374 GlobalData.addModuleToolChainOption(fpdModuleId, parseModuleBuildOptions(false));\r
375 GlobalData.addModuleToolChainFamilyOption(fpdModuleId, parseModuleBuildOptions(true));\r
b69bb9ba 376 \r
377 //\r
378 // parse MSA build options\r
379 //\r
380 GlobalData.addMsaBuildOption(moduleId, parseMsaBuildOptions(false));\r
381 GlobalData.addMsaFamilyBuildOption(moduleId, parseMsaBuildOptions(true));\r
382\r
abce9cbd 383 saq.pop();\r
384 }\r
385 }\r
386 \r
387 private boolean isContain(String[] list, String item) {\r
388 for (int i = 0; i < list.length; i++) {\r
389 if (list[i].equalsIgnoreCase(item)) {\r
390 return true;\r
391 }\r
392 }\r
393 return false;\r
394 }\r
395 \r
396 public synchronized static void addCount() {\r
397 synchronized (countSemaphore) {\r
398 ++currentRunNumber;\r
399 }\r
400 }\r
401 \r
402 public synchronized static void subCount() {\r
403 synchronized (countSemaphore) {\r
404 --currentRunNumber;\r
2eb7d78d 405 --remainNumber;\r
abce9cbd 406 }\r
407 }\r
1a0d7262 408 \r
409 private void updateTaskName(int percentage){\r
410 int number = percentage/10;\r
411 StringBuffer str = new StringBuffer(9);\r
412 for(int i = 0; i < 9; i++) {\r
413 if (i < number) {\r
414 str.append('>');\r
415 } else {\r
416 str.append('.');\r
417 }\r
418 }\r
419 this.setTaskName(str.toString());\r
420 }\r
abce9cbd 421}\r