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