]> git.proxmox.com Git - mirror_edk2.git/blame - Tools/Source/GenBuild/org/tianocore/build/fpd/FpdParserForThread.java
Add thread control classes. (2)
[mirror_edk2.git] / Tools / Source / GenBuild / org / tianocore / build / fpd / FpdParserForThread.java
CommitLineData
abce9cbd 1/** @file\r
2 This file is ANT task FpdParserTask. \r
3 \r
4 FpdParserTask is used to parse FPD (Framework Platform Description) and generate\r
5 build.out.xml. It is for Package or Platform build use. \r
6 \r
7 Copyright (c) 2006, Intel Corporation\r
8 All rights reserved. This program and the accompanying materials\r
9 are licensed and made available under the terms and conditions of the BSD License\r
10 which accompanies this distribution. The full text of the license may be found at\r
11 http://opensource.org/licenses/bsd-license.php\r
12\r
13 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
14 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
15 **/\r
16package org.tianocore.build.fpd;\r
17\r
18import java.io.File;\r
19import java.util.ArrayList;\r
20import java.util.Iterator;\r
21import java.util.LinkedHashMap;\r
22import java.util.LinkedHashSet;\r
23import java.util.List;\r
24import java.util.Map;\r
25import java.util.Set;\r
26\r
27import org.apache.tools.ant.BuildException;\r
28import org.apache.tools.ant.taskdefs.Ant;\r
29import org.apache.xmlbeans.XmlObject;\r
30\r
31import org.tianocore.build.global.GlobalData;\r
32import org.tianocore.build.global.OutputManager;\r
33import org.tianocore.build.id.FpdModuleIdentification;\r
34import org.tianocore.build.id.ModuleIdentification;\r
35import org.tianocore.build.FrameworkBuildTask;\r
36import org.tianocore.build.GenBuildThread;\r
37import org.tianocore.common.exception.EdkException;\r
38\r
39/**\r
40 <code>FpdParserTask</code> is an ANT task. The main function is parsing Framework\r
41 Platform Descritpion (FPD) XML file and generating its ANT build script for \r
42 corresponding platform. \r
43\r
44 <p>The task sets global properties PLATFORM, PLATFORM_DIR, PLATFORM_RELATIVE_DIR\r
45 and BUILD_DIR. </p>\r
46 \r
47 <p>The task generates ${PLATFORM}_build.xml file which will be called by top level\r
48 build.xml. The task also generate Fv.inf files (File is for Tool GenFvImage) \r
49 and flash definition file (File is for Tool FlashMap) if necessary. </p>\r
50 \r
51 <p>FpdParserTask task stores all FPD information to GlobalData. And parse\r
52 tools definition file to set up compiler options for different Target and\r
53 different ToolChainTag. </p>\r
54 \r
55 <p>The method parseFpdFile is also prepared for single module build. </p>\r
56 \r
57 <p>The usage is (take NT32 Platform for example):</p>\r
58\r
59 <pre>\r
60 &lt;FPDParser platformName="Nt32" /&gt;\r
61 </pre>\r
62\r
63 <p>The task will initialize all information through parsing Framework Database, \r
64 SPD, Tool chain configuration files. </p>\r
65\r
66 @since GenBuild 1.0\r
67**/\r
68public class FpdParserForThread extends FpdParserTask {\r
69 \r
70 public static Map<FpdModuleIdentification, GenBuildThread> allThreads = new LinkedHashMap<FpdModuleIdentification, GenBuildThread>();\r
71 \r
72 List<String> queueList = new ArrayList<String>();\r
73 \r
74 public static Object deamonSemaphore = new Object();\r
75 \r
76 static Object countSemaphore = new Object();\r
77 \r
78 public static int STATUS_DEPENDENCY_NOT_READY = 1;\r
79 \r
80 public static int STATUS_DEPENDENCY_READY = 2;\r
81 \r
82 public static int STATUS_START_RUN = 3;\r
83 \r
84 public static int STATUS_END_RUN = 4;\r
85 \r
86 private int currentQueueCode = 0;\r
87 \r
88 public static int currentRunNumber = 0;\r
89 \r
90 /**\r
91 Public construct method. It is necessary for ANT task.\r
92 **/\r
93 public FpdParserForThread() {\r
94 }\r
95\r
96 /**\r
97 ANT task's entry method. The main steps is described as following: \r
98 \r
99 <ul>\r
100 <li>Initialize global information (Framework DB, SPD files and all MSA files \r
101 listed in SPD). This step will execute only once in whole build process;</li>\r
102 <li>Parse specified FPD file; </li>\r
103 <li>Generate FV.inf files; </li>\r
104 <li>Generate PlatformName_build.xml file for Flatform build; </li>\r
105 <li>Collect PCD information. </li>\r
106 </ul>\r
107 \r
108 @throws BuildException\r
109 Surface area is not valid. \r
110 **/\r
111 public void execute() throws BuildException {\r
112 //\r
113 // Parse FPD file\r
114 //\r
115 parseFpdFile();\r
116\r
117 //\r
118 // Prepare BUILD_DIR\r
119 //\r
120 isUnified = OutputManager.getInstance().prepareBuildDir(getProject());\r
121\r
122 //\r
123 // For every Target and ToolChain\r
124 //\r
125 String[] targetList = GlobalData.getToolChainInfo().getTargets();\r
126 for (int i = 0; i < targetList.length; i++) {\r
127 String[] toolchainList = GlobalData.getToolChainInfo().getTagnames();\r
128 for(int j = 0; j < toolchainList.length; j++) {\r
129 //\r
130 // Prepare FV_DIR\r
131 //\r
132 String ffsCommonDir = getProject().getProperty("BUILD_DIR") + File.separatorChar\r
133 + targetList[i] + File.separatorChar\r
134 + toolchainList[j];\r
135 File fvDir = new File(ffsCommonDir + File.separatorChar + "FV");\r
136 fvDir.mkdirs();\r
137 getProject().setProperty("FV_DIR", fvDir.getPath().replaceAll("(\\\\)", "/"));\r
138\r
139 //\r
140 // Gen Fv.inf files\r
141 //\r
142 genFvInfFiles(ffsCommonDir);\r
143 }\r
144 }\r
145\r
146 //\r
147 // Gen build.xml\r
148 //\r
149 PlatformBuildFileGenerator fileGenerator = new PlatformBuildFileGenerator(getProject(), outfiles, fvs, isUnified, saq);\r
150 fileGenerator.genBuildFile();\r
151 \r
152 //\r
153 // Prepare Queue\r
154 //\r
155 queueList.add("libqueue");\r
156 \r
157 String[] validFv = saq.getFpdValidImageNames();\r
158 \r
159 for (int i = 0; i < validFv.length; i++) {\r
160 queueList.add(validFv[i]);\r
161 }\r
162 \r
163 Iterator<String> fvsNameIter = fvs.keySet().iterator();\r
164 \r
165 while (fvsNameIter.hasNext()) {\r
166 String fvName = fvsNameIter.next();\r
167 if (!isContain(validFv, fvName)) {\r
168 queueList.add(fvName);\r
169 }\r
170 }\r
171 \r
172 //\r
173 // Ant call ${PLATFORM}_build.xml\r
174 //\r
175 Ant ant = new Ant();\r
176 ant.setProject(getProject());\r
177 ant.setAntfile(platformId.getFpdFile().getParent() + File.separatorChar + platformId.getName() + "_build.xml");\r
178 ant.setTarget("prebuild");\r
179 ant.setInheritAll(true);\r
180 ant.init();\r
181 ant.execute();\r
182 \r
183 System.out.println("Task number is " + allThreads.size());\r
184 \r
185 //\r
186 // Waiting for all thread over, or time out\r
187 //\r
188 synchronized (deamonSemaphore) {\r
189 //\r
190 // Initialize BUGBUG\r
191 //\r
192 \r
193 while (true) {\r
194 //\r
195 // If all modules are already built\r
196 //\r
197 if (currentQueueCode >= queueList.size()) {\r
198 break ;\r
199 }\r
200\r
201 Set<FpdModuleIdentification> currentQueueModules = fvs.get(queueList.get(currentQueueCode));\r
202 \r
203 if (currentQueueModules == null) {\r
204 ++currentQueueCode;\r
205 continue ;\r
206 }\r
207 Iterator<FpdModuleIdentification> currentIter = currentQueueModules.iterator();\r
208\r
209 GenBuildThread a = null;\r
210\r
211 boolean existNoneReady = false;\r
212\r
213 while (currentIter.hasNext()) {\r
214 GenBuildThread item = allThreads.get(currentIter.next()); \r
215 if (item.getStatus() == STATUS_DEPENDENCY_NOT_READY) {\r
216 existNoneReady = true;\r
217 } else if (item.getStatus() == STATUS_DEPENDENCY_READY) {\r
218 a = item;\r
219 addCount();\r
220 a.start();\r
221 if (currentRunNumber == FrameworkBuildTask.MAX_CONCURRENT_THREAD_NUMBER) {\r
222 break ;\r
223 }\r
224 }\r
225 }\r
226\r
227 if (a != null) {\r
228 //\r
229 // Exist ready thread\r
230 //\r
231 System.out.println("## Exist ready thread");\r
232\r
233 } else if (existNoneReady && currentRunNumber == 0) {\r
234 //\r
235 // No active thread, but still have dependency not read thread\r
236 //\r
237 throw new BuildException("Found can't resolve dependencies. ");\r
238 } else if (!existNoneReady && currentRunNumber == 0) {\r
239 //\r
240 // Current queue build finish, move to next\r
241 //\r
242 System.out.println("## Current queue build finish, move to next");\r
243 ++currentQueueCode;\r
244 continue ;\r
245 } else {\r
246 //\r
247 // active thread exist, but no ready thread\r
248 //\r
249 System.out.println("## active thread exist, but no ready thread" + currentRunNumber);\r
250 }\r
251\r
252 try {\r
253 deamonSemaphore.wait();\r
254 } catch (InterruptedException e) {\r
255 e.printStackTrace();\r
256 }\r
257 }\r
258 }\r
259 \r
260 //\r
261 // call fvs, postbuild\r
262 //\r
263 ant = new Ant();\r
264 ant.setProject(getProject());\r
265 ant.setAntfile(platformId.getFpdFile().getParent() + File.separatorChar + platformId.getName() + "_build.xml");\r
266 ant.setTarget("fvs");\r
267 ant.setInheritAll(true);\r
268 ant.init();\r
269 ant.execute();\r
270 \r
271 ant = new Ant();\r
272 ant.setProject(getProject());\r
273 ant.setAntfile(platformId.getFpdFile().getParent() + File.separatorChar + platformId.getName() + "_build.xml");\r
274 ant.setTarget("postbuild");\r
275 ant.setInheritAll(true);\r
276 ant.init();\r
277 ant.execute();\r
278 \r
279 }\r
280\r
281 \r
282 /**\r
283 Parse all modules listed in FPD file. \r
284 **/\r
285 void parseModuleSAFiles() throws EdkException{\r
286 \r
287 Map<FpdModuleIdentification, Map<String, XmlObject>> moduleSAs = saq.getFpdModules();\r
288\r
289 //\r
290 // For every Module lists in FPD file.\r
291 //\r
292 Set<FpdModuleIdentification> keys = moduleSAs.keySet();\r
293 Iterator<FpdModuleIdentification> iter = keys.iterator();\r
294 while (iter.hasNext()) {\r
295 FpdModuleIdentification fpdModuleId = iter.next();\r
296 \r
297 //\r
298 // Generate GenBuildThread\r
299 //\r
300 GenBuildThread genBuildThread = new GenBuildThread();\r
301 genBuildThread.setArch(fpdModuleId.getArch());\r
302 genBuildThread.setParentModuleId(null);\r
303 genBuildThread.setModuleId(fpdModuleId.getModule());\r
304 genBuildThread.setProject(getProject());\r
305 \r
306 Set<FpdModuleIdentification> dependencies = new LinkedHashSet<FpdModuleIdentification>();\r
307 \r
308 GlobalData.registerFpdModuleSA(fpdModuleId, moduleSAs.get(fpdModuleId));\r
309 \r
310 //\r
311 // Add all dependent Library Instance\r
312 //\r
313 saq.push(GlobalData.getDoc(fpdModuleId));\r
314\r
315 ModuleIdentification[] libinstances = saq.getLibraryInstance(fpdModuleId.getArch());\r
316 saq.pop();\r
317 \r
318 for (int i = 0; i < libinstances.length; i++) {\r
319 FpdModuleIdentification libFpdModuleId = new FpdModuleIdentification(libinstances[i], fpdModuleId.getArch());\r
320 //\r
321 // Add to dependencies\r
322 //\r
323 dependencies.add(libFpdModuleId);\r
324 \r
325 //\r
326 // Create thread for library instances\r
327 //\r
328 GenBuildThread liBuildThread = new GenBuildThread();\r
329 liBuildThread.setArch(fpdModuleId.getArch());\r
330 liBuildThread.setParentModuleId(fpdModuleId.getModule());\r
331 liBuildThread.setModuleId(libinstances[i]);\r
332 liBuildThread.setProject(getProject());\r
333 liBuildThread.setStatus(STATUS_DEPENDENCY_READY);\r
334 liBuildThread.setHighPriority(true);\r
335 allThreads.put(libFpdModuleId, liBuildThread);\r
336 \r
337 updateFvs("libqueue", libFpdModuleId);\r
338 }\r
339 \r
340 genBuildThread.setDependencies(dependencies); \r
341// if (dependencies.size() == 0) {\r
342 genBuildThread.setStatus(STATUS_DEPENDENCY_READY);\r
343// }\r
344 \r
345 allThreads.put(fpdModuleId, genBuildThread);\r
346 \r
347 //\r
348 // Put fpdModuleId to the corresponding FV\r
349 //\r
350 saq.push(GlobalData.getDoc(fpdModuleId));\r
351 String fvBinding = saq.getModuleFvBindingKeyword();\r
352\r
353 fpdModuleId.setFvBinding(fvBinding);\r
354 updateFvs(fvBinding, fpdModuleId);\r
355\r
356 //\r
357 // Prepare for out put file name\r
358 //\r
359 ModuleIdentification moduleId = fpdModuleId.getModule();\r
360\r
361 String baseName = saq.getModuleOutputFileBasename();\r
362 \r
363 if (baseName == null) {\r
364 baseName = moduleId.getName();\r
365 }\r
366 outfiles.put(fpdModuleId, fpdModuleId.getArch() + File.separatorChar\r
367 + moduleId.getGuid() + "-" + baseName\r
368 + getSuffix(moduleId.getModuleType()));\r
369\r
370 //\r
371 // parse module build options, if any\r
372 //\r
373 GlobalData.addModuleToolChainOption(fpdModuleId, parseModuleBuildOptions(false));\r
374 GlobalData.addModuleToolChainFamilyOption(fpdModuleId, parseModuleBuildOptions(true));\r
375 saq.pop();\r
376 }\r
377 }\r
378 \r
379 private boolean isContain(String[] list, String item) {\r
380 for (int i = 0; i < list.length; i++) {\r
381 if (list[i].equalsIgnoreCase(item)) {\r
382 return true;\r
383 }\r
384 }\r
385 return false;\r
386 }\r
387 \r
388 public synchronized static void addCount() {\r
389 synchronized (countSemaphore) {\r
390 ++currentRunNumber;\r
391 }\r
392 }\r
393 \r
394 public synchronized static void subCount() {\r
395 synchronized (countSemaphore) {\r
396 --currentRunNumber;\r
397 }\r
398 }\r
399}\r