--- /dev/null
+/** @file\r
+ This file is for single module thread definition. \r
+\r
+Copyright (c) 2006, Intel Corporation\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution. The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+**/\r
+package org.tianocore.build;\r
+\r
+import java.util.Hashtable;\r
+import java.util.Iterator;\r
+import java.util.LinkedHashSet;\r
+import java.util.Set;\r
+import java.util.Vector;\r
+\r
+import org.apache.tools.ant.BuildListener;\r
+import org.apache.tools.ant.Project;\r
+import org.apache.tools.ant.taskdefs.Property;\r
+import org.tianocore.build.GenBuildTask;\r
+import org.tianocore.build.fpd.FpdParserForThread;\r
+import org.tianocore.build.id.FpdModuleIdentification;\r
+import org.tianocore.build.id.ModuleIdentification;\r
+\r
+/**\r
+ Add more comment here. \r
+\r
+ @since GenBuild 1.0\r
+**/\r
+public class GenBuildThread implements Runnable {\r
+\r
+ private ModuleIdentification parentModuleId = null;\r
+\r
+ private ModuleIdentification moduleId = null;\r
+\r
+ private Set<FpdModuleIdentification> dependencies = new LinkedHashSet<FpdModuleIdentification>();\r
+ \r
+ private int status = FpdParserForThread.STATUS_DEPENDENCY_NOT_READY;\r
+\r
+ private Project project = null;\r
+\r
+ public Object semaphore = new Object();\r
+\r
+ private String arch = null;\r
+\r
+ private boolean highPriority = false;\r
+\r
+ private Thread thread;\r
+\r
+ public GenBuildThread() {\r
+ thread = new Thread(this);\r
+ }\r
+\r
+ public boolean start() {\r
+ if (highPriority) {\r
+ thread.setPriority(Thread.MAX_PRIORITY);\r
+ }\r
+ \r
+ status = FpdParserForThread.STATUS_START_RUN;\r
+ thread.start();\r
+ return true;\r
+ }\r
+\r
+ public void run() {\r
+ \r
+ FpdModuleIdentification fpdModuleId = new FpdModuleIdentification(moduleId, arch);\r
+\r
+ //\r
+ // Prepare pass down properties\r
+ // ARCH, MODULE_GUID, MODULE_VERSION, PACKAGE_GUID, PACKAGE_VERSION, PLATFORM_FILE\r
+ //\r
+ Vector<Property> properties = new Vector<Property>();\r
+ Property property = new Property();\r
+ property.setName("ARCH");\r
+ property.setValue(arch);\r
+ properties.add(property);\r
+\r
+ property = new Property();\r
+ property.setName("MODULE_GUID");\r
+ property.setValue(moduleId.getGuid());\r
+ properties.add(property);\r
+\r
+ property = new Property();\r
+ property.setName("MODULE_VERSION");\r
+ if (moduleId.getVersion() == null) {\r
+ property.setValue("");\r
+ } else {\r
+ property.setValue(moduleId.getVersion());\r
+ }\r
+ properties.add(property);\r
+\r
+ property = new Property();\r
+ property.setName("PACKAGE_GUID");\r
+ property.setValue(moduleId.getPackage().getGuid());\r
+ properties.add(property);\r
+\r
+ property = new Property();\r
+ property.setName("PACKAGE_VERSION");\r
+ if (moduleId.getPackage().getVersion() == null) {\r
+ property.setValue("");\r
+ } else {\r
+ property.setValue(moduleId.getPackage().getVersion());\r
+ }\r
+ properties.add(property);\r
+\r
+ // property = new Property();\r
+ // property.setName("PLATFORM_FILE");\r
+ // property.setValue(arch);\r
+ // properties.add(property);\r
+\r
+ //\r
+ // Build the Module\r
+ //\r
+ GenBuildTask genBuildTask = new GenBuildTask();\r
+\r
+ Project newProject = new Project();\r
+\r
+ Hashtable passdownProperties = project.getProperties();\r
+ Iterator iter = passdownProperties.keySet().iterator();\r
+ while (iter.hasNext()) {\r
+ String item = (String) iter.next();\r
+ newProject.setProperty(item, (String) passdownProperties.get(item));\r
+ }\r
+\r
+ newProject.setInputHandler(project.getInputHandler());\r
+\r
+ Iterator listenerIter = project.getBuildListeners().iterator();\r
+ while (listenerIter.hasNext()) {\r
+ newProject.addBuildListener((BuildListener) listenerIter.next());\r
+ }\r
+\r
+ project.initSubProject(newProject);\r
+\r
+ genBuildTask.setProject(newProject);\r
+\r
+ genBuildTask.setExternalProperties(properties);\r
+\r
+ genBuildTask.parentId = parentModuleId;\r
+\r
+ genBuildTask.perform();\r
+\r
+ status = FpdParserForThread.STATUS_END_RUN;\r
+ \r
+ System.out.println(fpdModuleId + " build finished. ");\r
+ \r
+ //\r
+ // \r
+ //\r
+ synchronized (FpdParserForThread.deamonSemaphore) {\r
+ FpdParserForThread.subCount();\r
+ FpdParserForThread.deamonSemaphore.notifyAll();\r
+ }\r
+ }\r
+\r
+ public void setArch(String arch) {\r
+ this.arch = arch;\r
+ }\r
+\r
+ public void setDependencies(Set<FpdModuleIdentification> dependencies) {\r
+ this.dependencies = dependencies;\r
+ }\r
+\r
+ public void setModuleId(ModuleIdentification moduleId) {\r
+ this.moduleId = moduleId;\r
+ }\r
+\r
+ public void setParentModuleId(ModuleIdentification parentModuleId) {\r
+ this.parentModuleId = parentModuleId;\r
+ }\r
+\r
+ public void setProject(Project project) {\r
+ this.project = project;\r
+ }\r
+\r
+ public void setHighPriority(boolean highPriority) {\r
+ this.highPriority = highPriority;\r
+ }\r
+\r
+\r
+ public Set<FpdModuleIdentification> getDependencies() {\r
+ return dependencies;\r
+ }\r
+\r
+ public ModuleIdentification getModuleId() {\r
+ return moduleId;\r
+ }\r
+\r
+ public int getStatus() {\r
+ //\r
+ // Add code here to judge dependency\r
+ //\r
+ if (status == FpdParserForThread.STATUS_DEPENDENCY_NOT_READY) {\r
+ Iterator<FpdModuleIdentification> iter = dependencies.iterator();\r
+ boolean flag = true;\r
+ while (iter.hasNext()) {\r
+ FpdModuleIdentification item = iter.next();\r
+ if (FpdParserForThread.allThreads.get(item).getStatus() == 1) {\r
+ flag = false;\r
+ break ;\r
+ }\r
+ }\r
+ if (flag) {\r
+ status = FpdParserForThread.STATUS_DEPENDENCY_READY;\r
+ }\r
+ }\r
+ return status;\r
+ }\r
+\r
+ public void setStatus(int status) {\r
+ this.status = status;\r
+ }\r
+ \r
+}\r
--- /dev/null
+/** @file\r
+ This file is ANT task FpdParserTask. \r
+ \r
+ FpdParserTask is used to parse FPD (Framework Platform Description) and generate\r
+ build.out.xml. It is for Package or Platform build use. \r
+ \r
+ Copyright (c) 2006, Intel Corporation\r
+ All rights reserved. This program and the accompanying materials\r
+ are licensed and made available under the terms and conditions of the BSD License\r
+ which accompanies this distribution. The full text of the license may be found at\r
+ http://opensource.org/licenses/bsd-license.php\r
+\r
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+ **/\r
+package org.tianocore.build.fpd;\r
+\r
+import java.io.File;\r
+import java.util.ArrayList;\r
+import java.util.Iterator;\r
+import java.util.LinkedHashMap;\r
+import java.util.LinkedHashSet;\r
+import java.util.List;\r
+import java.util.Map;\r
+import java.util.Set;\r
+\r
+import org.apache.tools.ant.BuildException;\r
+import org.apache.tools.ant.taskdefs.Ant;\r
+import org.apache.xmlbeans.XmlObject;\r
+\r
+import org.tianocore.build.global.GlobalData;\r
+import org.tianocore.build.global.OutputManager;\r
+import org.tianocore.build.id.FpdModuleIdentification;\r
+import org.tianocore.build.id.ModuleIdentification;\r
+import org.tianocore.build.FrameworkBuildTask;\r
+import org.tianocore.build.GenBuildThread;\r
+import org.tianocore.common.exception.EdkException;\r
+\r
+/**\r
+ <code>FpdParserTask</code> is an ANT task. The main function is parsing Framework\r
+ Platform Descritpion (FPD) XML file and generating its ANT build script for \r
+ corresponding platform. \r
+\r
+ <p>The task sets global properties PLATFORM, PLATFORM_DIR, PLATFORM_RELATIVE_DIR\r
+ and BUILD_DIR. </p>\r
+ \r
+ <p>The task generates ${PLATFORM}_build.xml file which will be called by top level\r
+ build.xml. The task also generate Fv.inf files (File is for Tool GenFvImage) \r
+ and flash definition file (File is for Tool FlashMap) if necessary. </p>\r
+ \r
+ <p>FpdParserTask task stores all FPD information to GlobalData. And parse\r
+ tools definition file to set up compiler options for different Target and\r
+ different ToolChainTag. </p>\r
+ \r
+ <p>The method parseFpdFile is also prepared for single module build. </p>\r
+ \r
+ <p>The usage is (take NT32 Platform for example):</p>\r
+\r
+ <pre>\r
+ <FPDParser platformName="Nt32" />\r
+ </pre>\r
+\r
+ <p>The task will initialize all information through parsing Framework Database, \r
+ SPD, Tool chain configuration files. </p>\r
+\r
+ @since GenBuild 1.0\r
+**/\r
+public class FpdParserForThread extends FpdParserTask {\r
+ \r
+ public static Map<FpdModuleIdentification, GenBuildThread> allThreads = new LinkedHashMap<FpdModuleIdentification, GenBuildThread>();\r
+ \r
+ List<String> queueList = new ArrayList<String>();\r
+ \r
+ public static Object deamonSemaphore = new Object();\r
+ \r
+ static Object countSemaphore = new Object();\r
+ \r
+ public static int STATUS_DEPENDENCY_NOT_READY = 1;\r
+ \r
+ public static int STATUS_DEPENDENCY_READY = 2;\r
+ \r
+ public static int STATUS_START_RUN = 3;\r
+ \r
+ public static int STATUS_END_RUN = 4;\r
+ \r
+ private int currentQueueCode = 0;\r
+ \r
+ public static int currentRunNumber = 0;\r
+ \r
+ /**\r
+ Public construct method. It is necessary for ANT task.\r
+ **/\r
+ public FpdParserForThread() {\r
+ }\r
+\r
+ /**\r
+ ANT task's entry method. The main steps is described as following: \r
+ \r
+ <ul>\r
+ <li>Initialize global information (Framework DB, SPD files and all MSA files \r
+ listed in SPD). This step will execute only once in whole build process;</li>\r
+ <li>Parse specified FPD file; </li>\r
+ <li>Generate FV.inf files; </li>\r
+ <li>Generate PlatformName_build.xml file for Flatform build; </li>\r
+ <li>Collect PCD information. </li>\r
+ </ul>\r
+ \r
+ @throws BuildException\r
+ Surface area is not valid. \r
+ **/\r
+ public void execute() throws BuildException {\r
+ //\r
+ // Parse FPD file\r
+ //\r
+ parseFpdFile();\r
+\r
+ //\r
+ // Prepare BUILD_DIR\r
+ //\r
+ isUnified = OutputManager.getInstance().prepareBuildDir(getProject());\r
+\r
+ //\r
+ // For every Target and ToolChain\r
+ //\r
+ String[] targetList = GlobalData.getToolChainInfo().getTargets();\r
+ for (int i = 0; i < targetList.length; i++) {\r
+ String[] toolchainList = GlobalData.getToolChainInfo().getTagnames();\r
+ for(int j = 0; j < toolchainList.length; j++) {\r
+ //\r
+ // Prepare FV_DIR\r
+ //\r
+ String ffsCommonDir = getProject().getProperty("BUILD_DIR") + File.separatorChar\r
+ + targetList[i] + File.separatorChar\r
+ + toolchainList[j];\r
+ File fvDir = new File(ffsCommonDir + File.separatorChar + "FV");\r
+ fvDir.mkdirs();\r
+ getProject().setProperty("FV_DIR", fvDir.getPath().replaceAll("(\\\\)", "/"));\r
+\r
+ //\r
+ // Gen Fv.inf files\r
+ //\r
+ genFvInfFiles(ffsCommonDir);\r
+ }\r
+ }\r
+\r
+ //\r
+ // Gen build.xml\r
+ //\r
+ PlatformBuildFileGenerator fileGenerator = new PlatformBuildFileGenerator(getProject(), outfiles, fvs, isUnified, saq);\r
+ fileGenerator.genBuildFile();\r
+ \r
+ //\r
+ // Prepare Queue\r
+ //\r
+ queueList.add("libqueue");\r
+ \r
+ String[] validFv = saq.getFpdValidImageNames();\r
+ \r
+ for (int i = 0; i < validFv.length; i++) {\r
+ queueList.add(validFv[i]);\r
+ }\r
+ \r
+ Iterator<String> fvsNameIter = fvs.keySet().iterator();\r
+ \r
+ while (fvsNameIter.hasNext()) {\r
+ String fvName = fvsNameIter.next();\r
+ if (!isContain(validFv, fvName)) {\r
+ queueList.add(fvName);\r
+ }\r
+ }\r
+ \r
+ //\r
+ // Ant call ${PLATFORM}_build.xml\r
+ //\r
+ Ant ant = new Ant();\r
+ ant.setProject(getProject());\r
+ ant.setAntfile(platformId.getFpdFile().getParent() + File.separatorChar + platformId.getName() + "_build.xml");\r
+ ant.setTarget("prebuild");\r
+ ant.setInheritAll(true);\r
+ ant.init();\r
+ ant.execute();\r
+ \r
+ System.out.println("Task number is " + allThreads.size());\r
+ \r
+ //\r
+ // Waiting for all thread over, or time out\r
+ //\r
+ synchronized (deamonSemaphore) {\r
+ //\r
+ // Initialize BUGBUG\r
+ //\r
+ \r
+ while (true) {\r
+ //\r
+ // If all modules are already built\r
+ //\r
+ if (currentQueueCode >= queueList.size()) {\r
+ break ;\r
+ }\r
+\r
+ Set<FpdModuleIdentification> currentQueueModules = fvs.get(queueList.get(currentQueueCode));\r
+ \r
+ if (currentQueueModules == null) {\r
+ ++currentQueueCode;\r
+ continue ;\r
+ }\r
+ Iterator<FpdModuleIdentification> currentIter = currentQueueModules.iterator();\r
+\r
+ GenBuildThread a = null;\r
+\r
+ boolean existNoneReady = false;\r
+\r
+ while (currentIter.hasNext()) {\r
+ GenBuildThread item = allThreads.get(currentIter.next()); \r
+ if (item.getStatus() == STATUS_DEPENDENCY_NOT_READY) {\r
+ existNoneReady = true;\r
+ } else if (item.getStatus() == STATUS_DEPENDENCY_READY) {\r
+ a = item;\r
+ addCount();\r
+ a.start();\r
+ if (currentRunNumber == FrameworkBuildTask.MAX_CONCURRENT_THREAD_NUMBER) {\r
+ break ;\r
+ }\r
+ }\r
+ }\r
+\r
+ if (a != null) {\r
+ //\r
+ // Exist ready thread\r
+ //\r
+ System.out.println("## Exist ready thread");\r
+\r
+ } else if (existNoneReady && currentRunNumber == 0) {\r
+ //\r
+ // No active thread, but still have dependency not read thread\r
+ //\r
+ throw new BuildException("Found can't resolve dependencies. ");\r
+ } else if (!existNoneReady && currentRunNumber == 0) {\r
+ //\r
+ // Current queue build finish, move to next\r
+ //\r
+ System.out.println("## Current queue build finish, move to next");\r
+ ++currentQueueCode;\r
+ continue ;\r
+ } else {\r
+ //\r
+ // active thread exist, but no ready thread\r
+ //\r
+ System.out.println("## active thread exist, but no ready thread" + currentRunNumber);\r
+ }\r
+\r
+ try {\r
+ deamonSemaphore.wait();\r
+ } catch (InterruptedException e) {\r
+ e.printStackTrace();\r
+ }\r
+ }\r
+ }\r
+ \r
+ //\r
+ // call fvs, postbuild\r
+ //\r
+ ant = new Ant();\r
+ ant.setProject(getProject());\r
+ ant.setAntfile(platformId.getFpdFile().getParent() + File.separatorChar + platformId.getName() + "_build.xml");\r
+ ant.setTarget("fvs");\r
+ ant.setInheritAll(true);\r
+ ant.init();\r
+ ant.execute();\r
+ \r
+ ant = new Ant();\r
+ ant.setProject(getProject());\r
+ ant.setAntfile(platformId.getFpdFile().getParent() + File.separatorChar + platformId.getName() + "_build.xml");\r
+ ant.setTarget("postbuild");\r
+ ant.setInheritAll(true);\r
+ ant.init();\r
+ ant.execute();\r
+ \r
+ }\r
+\r
+ \r
+ /**\r
+ Parse all modules listed in FPD file. \r
+ **/\r
+ void parseModuleSAFiles() throws EdkException{\r
+ \r
+ Map<FpdModuleIdentification, Map<String, XmlObject>> moduleSAs = saq.getFpdModules();\r
+\r
+ //\r
+ // For every Module lists in FPD file.\r
+ //\r
+ Set<FpdModuleIdentification> keys = moduleSAs.keySet();\r
+ Iterator<FpdModuleIdentification> iter = keys.iterator();\r
+ while (iter.hasNext()) {\r
+ FpdModuleIdentification fpdModuleId = iter.next();\r
+ \r
+ //\r
+ // Generate GenBuildThread\r
+ //\r
+ GenBuildThread genBuildThread = new GenBuildThread();\r
+ genBuildThread.setArch(fpdModuleId.getArch());\r
+ genBuildThread.setParentModuleId(null);\r
+ genBuildThread.setModuleId(fpdModuleId.getModule());\r
+ genBuildThread.setProject(getProject());\r
+ \r
+ Set<FpdModuleIdentification> dependencies = new LinkedHashSet<FpdModuleIdentification>();\r
+ \r
+ GlobalData.registerFpdModuleSA(fpdModuleId, moduleSAs.get(fpdModuleId));\r
+ \r
+ //\r
+ // Add all dependent Library Instance\r
+ //\r
+ saq.push(GlobalData.getDoc(fpdModuleId));\r
+\r
+ ModuleIdentification[] libinstances = saq.getLibraryInstance(fpdModuleId.getArch());\r
+ saq.pop();\r
+ \r
+ for (int i = 0; i < libinstances.length; i++) {\r
+ FpdModuleIdentification libFpdModuleId = new FpdModuleIdentification(libinstances[i], fpdModuleId.getArch());\r
+ //\r
+ // Add to dependencies\r
+ //\r
+ dependencies.add(libFpdModuleId);\r
+ \r
+ //\r
+ // Create thread for library instances\r
+ //\r
+ GenBuildThread liBuildThread = new GenBuildThread();\r
+ liBuildThread.setArch(fpdModuleId.getArch());\r
+ liBuildThread.setParentModuleId(fpdModuleId.getModule());\r
+ liBuildThread.setModuleId(libinstances[i]);\r
+ liBuildThread.setProject(getProject());\r
+ liBuildThread.setStatus(STATUS_DEPENDENCY_READY);\r
+ liBuildThread.setHighPriority(true);\r
+ allThreads.put(libFpdModuleId, liBuildThread);\r
+ \r
+ updateFvs("libqueue", libFpdModuleId);\r
+ }\r
+ \r
+ genBuildThread.setDependencies(dependencies); \r
+// if (dependencies.size() == 0) {\r
+ genBuildThread.setStatus(STATUS_DEPENDENCY_READY);\r
+// }\r
+ \r
+ allThreads.put(fpdModuleId, genBuildThread);\r
+ \r
+ //\r
+ // Put fpdModuleId to the corresponding FV\r
+ //\r
+ saq.push(GlobalData.getDoc(fpdModuleId));\r
+ String fvBinding = saq.getModuleFvBindingKeyword();\r
+\r
+ fpdModuleId.setFvBinding(fvBinding);\r
+ updateFvs(fvBinding, fpdModuleId);\r
+\r
+ //\r
+ // Prepare for out put file name\r
+ //\r
+ ModuleIdentification moduleId = fpdModuleId.getModule();\r
+\r
+ String baseName = saq.getModuleOutputFileBasename();\r
+ \r
+ if (baseName == null) {\r
+ baseName = moduleId.getName();\r
+ }\r
+ outfiles.put(fpdModuleId, fpdModuleId.getArch() + File.separatorChar\r
+ + moduleId.getGuid() + "-" + baseName\r
+ + getSuffix(moduleId.getModuleType()));\r
+\r
+ //\r
+ // parse module build options, if any\r
+ //\r
+ GlobalData.addModuleToolChainOption(fpdModuleId, parseModuleBuildOptions(false));\r
+ GlobalData.addModuleToolChainFamilyOption(fpdModuleId, parseModuleBuildOptions(true));\r
+ saq.pop();\r
+ }\r
+ }\r
+ \r
+ private boolean isContain(String[] list, String item) {\r
+ for (int i = 0; i < list.length; i++) {\r
+ if (list[i].equalsIgnoreCase(item)) {\r
+ return true;\r
+ }\r
+ }\r
+ return false;\r
+ }\r
+ \r
+ public synchronized static void addCount() {\r
+ synchronized (countSemaphore) {\r
+ ++currentRunNumber;\r
+ }\r
+ }\r
+ \r
+ public synchronized static void subCount() {\r
+ synchronized (countSemaphore) {\r
+ --currentRunNumber;\r
+ }\r
+ }\r
+}\r