+++ /dev/null
-/** @file\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.io.File;\r
-import java.util.LinkedHashMap;\r
-import java.util.Map;\r
-import java.io.FileNotFoundException;\r
-import java.io.FileOutputStream;\r
-import java.io.OutputStreamWriter;\r
-\r
-import javax.xml.parsers.DocumentBuilder;\r
-import javax.xml.parsers.DocumentBuilderFactory;\r
-import javax.xml.parsers.ParserConfigurationException;\r
-import javax.xml.transform.OutputKeys;\r
-import javax.xml.transform.Result;\r
-import javax.xml.transform.Source;\r
-import javax.xml.transform.Transformer;\r
-import javax.xml.transform.TransformerConfigurationException;\r
-import javax.xml.transform.TransformerException;\r
-import javax.xml.transform.TransformerFactory;\r
-import javax.xml.transform.dom.DOMSource;\r
-import javax.xml.transform.stream.StreamResult;\r
-\r
-import org.apache.tools.ant.BuildException;\r
-import org.apache.tools.ant.Project;\r
-import org.tianocore.build.exception.GenBuildException;\r
-import org.tianocore.build.fpd.FpdParserTask;\r
-import org.tianocore.build.global.SurfaceAreaQuery;\r
-import org.tianocore.build.id.FpdModuleIdentification;\r
-import org.tianocore.build.id.ModuleIdentification;\r
-import org.tianocore.build.id.PackageIdentification;\r
-import org.tianocore.common.exception.EdkException;\r
-import org.w3c.dom.Comment;\r
-import org.w3c.dom.Document;\r
-import org.w3c.dom.Element;\r
-import org.w3c.dom.Node;\r
-\r
-public class ModuleBuildFileGenerator {\r
-\r
- ///\r
- /// Pass: TARGET, TOOLCHAIN, ARCH\r
- /// PACKAGE, PACKAGE_GUID, PACKAGE_VERSION\r
- ///\r
- String[] inheritProperties = {"ARCH", "MODULE_GUID", "MODULE_VERSION", "PACKAGE_GUID", "PACKAGE_VERSION"};\r
-\r
- ///\r
- /// The information at the header of <em>build.xml</em>.\r
- ///\r
- private String info = "DO NOT EDIT \n"\r
- + "This file is auto-generated by the build utility\n"\r
- + "\n"\r
- + "Abstract:\n"\r
- + "Auto-generated ANT build file for build EFI Modules and Platforms\n";\r
-\r
- private FpdModuleIdentification fpdModuleId;\r
- \r
- private Project project;\r
- \r
- private String ffsKeyword;\r
- \r
- private String[] includes;\r
- \r
- private SurfaceAreaQuery saq = null;\r
- \r
- public ModuleBuildFileGenerator(Project project, String ffsKeyword, FpdModuleIdentification fpdModuleId, String[] includes, SurfaceAreaQuery saq) {\r
- this.project = project;\r
- this.fpdModuleId = fpdModuleId;\r
- this.ffsKeyword = ffsKeyword;\r
- this.includes = includes;\r
- this.saq = saq;\r
- }\r
- \r
- /**\r
- The whole BaseName_build.xml is composed of seven part. \r
- <ul>\r
- <li> ANT properties; </li>\r
- <li> Dependent module (dependent library instances in most case); </li>\r
- <li> Source files; </li>\r
- <li> Sections if module is not library; </li>\r
- <li> Output (different for library module and driver module); </li>\r
- <li> Clean; </li>\r
- <li> Clean all. </li>\r
- </ul>\r
- \r
- @throws BuildException\r
- Error throws during BaseName_build.xml generating. \r
- **/\r
- public void genBuildFile(String buildFilename) throws GenBuildException, EdkException {\r
- FfsProcess fp = new FfsProcess();\r
- DocumentBuilderFactory domfac = DocumentBuilderFactory.newInstance();\r
- try {\r
- DocumentBuilder dombuilder = domfac.newDocumentBuilder();\r
- Document document = dombuilder.newDocument();\r
- Comment rootComment = document.createComment(info);\r
- \r
- //\r
- // create root element and its attributes\r
- //\r
- Element root = document.createElement("project");\r
- root.setAttribute("name", fpdModuleId.getModule().getName());\r
- root.setAttribute("default", "all");\r
- root.setAttribute("basedir", ".");\r
- \r
- //\r
- // element for External ANT tasks\r
- //\r
- root.appendChild(document.createComment("Apply external ANT tasks"));\r
- Element ele = document.createElement("taskdef");\r
- ele.setAttribute("resource", "frameworktasks.tasks");\r
- root.appendChild(ele);\r
- ele = document.createElement("taskdef");\r
- ele.setAttribute("resource", "cpptasks.tasks");\r
- root.appendChild(ele);\r
- ele = document.createElement("typedef");\r
- ele.setAttribute("resource", "cpptasks.types");\r
- root.appendChild(ele);\r
- ele = document.createElement("taskdef");\r
- ele.setAttribute("resource", "net/sf/antcontrib/antlib.xml");\r
- root.appendChild(ele);\r
-\r
- //\r
- // Generate the default target,\r
- // which depends on init, sections and output target\r
- //\r
- root.appendChild(document.createComment("Default target"));\r
- ele = document.createElement("target");\r
- ele.setAttribute("name", "all");\r
- ele.setAttribute("depends", "libraries, sourcefiles, sections, output");\r
- root.appendChild(ele);\r
- \r
- //\r
- // compile all source files\r
- //\r
- root.appendChild(document.createComment("Compile all dependency Library instances."));\r
- ele = document.createElement("target");\r
- ele.setAttribute("name", "libraries");\r
-\r
- //\r
- // Parse all sourfiles but files specified in sections\r
- //\r
- if (!FrameworkBuildTask.multithread) {\r
- applyLibraryInstance(document, ele);\r
- }\r
- root.appendChild(ele);\r
-\r
- //\r
- // compile all source files\r
- //\r
- root.appendChild(document.createComment("sourcefiles target"));\r
- ele = document.createElement("target");\r
- ele.setAttribute("name", "sourcefiles");\r
- \r
- //\r
- // Parse all sourfiles but files specified in sections\r
- //\r
- applyCompileElement(document, ele);\r
- root.appendChild(ele);\r
-\r
- //\r
- // generate the init target\r
- // main purpose is create all nessary pathes\r
- // generate the sections target\r
- //\r
- root.appendChild(document.createComment("sections target"));\r
- ele = document.createElement("target");\r
- ele.setAttribute("name", "sections");\r
- applySectionsElement(document, ele, fp);\r
- root.appendChild(ele);\r
-\r
- //\r
- // generate the output target\r
- //\r
- root.appendChild(document.createComment("output target"));\r
- ele = document.createElement("target");\r
- ele.setAttribute("name", "output");\r
- applyOutputElement(document, ele, fp);\r
- root.appendChild(ele);\r
-\r
- \r
- //\r
- // generate the clean target\r
- //\r
- root.appendChild(document.createComment("clean target"));\r
- ele = document.createElement("target");\r
- ele.setAttribute("name", "clean");\r
- applyCleanElement(document, ele);\r
- root.appendChild(ele);\r
- \r
- //\r
- // generate the Clean All target\r
- //\r
- root.appendChild(document.createComment("Clean All target"));\r
- ele = document.createElement("target");\r
- ele.setAttribute("name", "cleanall");\r
- applyDeepcleanElement(document, ele);\r
- root.appendChild(ele);\r
- \r
- //\r
- // add the root element to the document\r
- //\r
- document.appendChild(rootComment);\r
- document.appendChild(root);\r
- //\r
- // Prepare the DOM document for writing\r
- //\r
- Source source = new DOMSource(document);\r
-\r
- //\r
- // Prepare the output file\r
- //\r
- File file = new File(buildFilename);\r
-\r
- //\r
- // generate all directory path\r
- //\r
- (new File(file.getParent())).mkdirs();\r
- FileOutputStream outputStream = new FileOutputStream(file);\r
- Result result = new StreamResult(new OutputStreamWriter(outputStream));\r
- \r
- //\r
- // Write the DOM document to the file\r
- //\r
- Transformer xformer = TransformerFactory.newInstance().newTransformer();\r
- xformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");\r
- xformer.setOutputProperty(OutputKeys.INDENT, "yes");\r
- xformer.transform(source, result);\r
- } catch (ParserConfigurationException ex) {\r
- GenBuildException e = new GenBuildException("Generating the module [" + fpdModuleId.getModule().getName() + "] build.xml file failed!.\n" + ex.getMessage());\r
- e.setStackTrace(ex.getStackTrace());\r
- throw e;\r
- } catch (FileNotFoundException ex) {\r
- GenBuildException e = new GenBuildException("Generating the module [" + fpdModuleId.getModule().getName() + "] build.xml file failed!.\n" + ex.getMessage());\r
- e.setStackTrace(ex.getStackTrace());\r
- throw e;\r
- } catch (TransformerConfigurationException ex) {\r
- GenBuildException e = new GenBuildException("Generating the module [" + fpdModuleId.getModule().getName() + "] build.xml file failed!.\n" + ex.getMessage());\r
- e.setStackTrace(ex.getStackTrace());\r
- throw e;\r
- } catch (TransformerException ex) {\r
- GenBuildException e = new GenBuildException("Generating the module [" + fpdModuleId.getModule().getName() + "] build.xml file failed!.\n" + ex.getMessage());\r
- e.setStackTrace(ex.getStackTrace());\r
- throw e;\r
- }\r
- }\r
-\r
- /**\r
- Generate the clean elements for BaseName_build.xml. \r
- \r
- @param document current BaseName_build.xml XML document\r
- @param root Root element for current\r
- **/\r
- private void applyCleanElement(Document document, Node root) {\r
- //\r
- // <delete includeemptydirs="true">\r
- // <fileset dir="${DEST_DIR_OUTPUT}" includes="" excludes="" />\r
- // </delete>\r
- //\r
- Element deleteEle = document.createElement("delete");\r
- deleteEle.setAttribute("includeemptydirs", "true");\r
- Element filesetEle = document.createElement("fileset");\r
- filesetEle.setAttribute("dir", "${DEST_DIR_OUTPUT}");\r
- filesetEle.setAttribute("includes", "**/*");\r
- filesetEle.setAttribute("excludes", "*.xml");\r
- deleteEle.appendChild(filesetEle);\r
- root.appendChild(deleteEle);\r
- }\r
-\r
- /**\r
- Generate the cleanall elements for BaseName_build.xml. \r
- \r
- @param document current BaseName_build.xml XML document\r
- @param root Root element for current\r
- **/\r
- private void applyDeepcleanElement(Document document, Node root) {\r
- //\r
- // <delete includeemptydirs="true">\r
- // <fileset dir="${DEST_DIR_OUTPUT}" includes="" excludes="" />\r
- // </delete>\r
- //\r
- Element deleteEle = document.createElement("delete");\r
- deleteEle.setAttribute("includeemptydirs", "true");\r
- Element filesetEle = document.createElement("fileset");\r
- filesetEle.setAttribute("dir", "${DEST_DIR_OUTPUT}");\r
- filesetEle.setAttribute("includes", "**/*");\r
- filesetEle.setAttribute("excludes", "*.xml");\r
- deleteEle.appendChild(filesetEle);\r
- root.appendChild(deleteEle);\r
- \r
- //\r
- // <delete includeemptydirs="true">\r
- // <fileset dir="${DEST_DIR_DEBUG}" includes="" />\r
- // </delete>\r
- //\r
- deleteEle = document.createElement("delete");\r
- deleteEle.setAttribute("includeemptydirs", "true");\r
- filesetEle = document.createElement("fileset");\r
- filesetEle.setAttribute("dir", "${DEST_DIR_DEBUG}");\r
- filesetEle.setAttribute("includes", "**/*");\r
- deleteEle.appendChild(filesetEle);\r
- root.appendChild(deleteEle);\r
- }\r
-\r
- /**\r
- Generate the dependent library instances elements for BaseName_build.xml. \r
- \r
- @param document current BaseName_build.xml XML document\r
- @param root Root element for current\r
- **/\r
- private void applyLibraryInstance(Document document, Node root) throws EdkException {\r
- ModuleIdentification[] libinstances = saq.getLibraryInstance(fpdModuleId.getArch());\r
- for (int i = 0; i < libinstances.length; i++) {\r
- //\r
- // Put package file path to module identification\r
- //\r
- PackageIdentification packageId = libinstances[i].getPackage();\r
- \r
- //\r
- // Generate ANT script to build library instances\r
- //\r
- Element ele = document.createElement("GenBuild");\r
- ele.setAttribute("type", "build");\r
- \r
- //\r
- // Prepare pass down information\r
- //\r
- Map<String, String> passDownMap = new LinkedHashMap<String, String>();\r
- for (int j = 0; j < inheritProperties.length; j ++){\r
- passDownMap.put(inheritProperties[j], "${" + inheritProperties[j] + "}");\r
- }\r
- \r
- passDownMap.put("MODULE_GUID", libinstances[i].getGuid());\r
- passDownMap.put("MODULE_VERSION", libinstances[i].getVersion());\r
- \r
- passDownMap.put("PACKAGE_GUID", packageId.getGuid());\r
- passDownMap.put("PACKAGE_VERSION", packageId.getVersion());\r
- \r
- for (int j = 0; j < inheritProperties.length; j ++){\r
- Element property = document.createElement("property");\r
- property.setAttribute("name", inheritProperties[j]);\r
- property.setAttribute("value", passDownMap.get(inheritProperties[j]));\r
- ele.appendChild(property);\r
- }\r
- \r
- root.appendChild(ele);\r
- }\r
- }\r
-\r
- /**\r
- Generate the build source files elements for BaseName_build.xml. \r
- \r
- @param document current BaseName_build.xml XML document\r
- @param root Root element for current\r
- **/\r
- private void applyCompileElement(Document document, Node root) {\r
- //\r
- // sourceFiles[][0] is FileType, \r
- // [][1] is File name relative to Module_Dir, \r
- // [][2] is ToolChainFamily\r
- //\r
- String[][] sourceFiles = saq.getSourceFiles(fpdModuleId.getArch());\r
-\r
- FileProcess fileProcess = new FileProcess();\r
- fileProcess.init(project, includes, document);\r
-\r
- boolean isBinaryModule = fpdModuleId.getModule().isBinary();\r
- boolean isLibraryModule = fpdModuleId.getModule().isLibrary();\r
-\r
- if (!isBinaryModule) {\r
- //\r
- // Initialize some properties by user\r
- //\r
- Element initEle = document.createElement("Build_Init");\r
- Element initIncEle = document.createElement("EXTRA.INC");\r
- for (int i = 0; i < includes.length; i++) {\r
- Element includeEle = document.createElement("includepath");\r
- includeEle.setAttribute("path", includes[i]);\r
- initIncEle.appendChild(includeEle);\r
- }\r
- initEle.appendChild(initIncEle);\r
- root.appendChild(initEle);\r
- }\r
-\r
- String moduleDir = project.getProperty("MODULE_DIR");\r
- //\r
- // Parse all Unicode files\r
- //\r
- for (int i = 0; i < sourceFiles.length; i++) {\r
- //\r
- // Go through all source files. Add MODULE_DIR to preffix\r
- //\r
- File sourceFile = new File(moduleDir + File.separatorChar + sourceFiles[i][1]);\r
- sourceFiles[i][1] = sourceFile.getPath();\r
- String filetype = sourceFiles[i][0];\r
- if (filetype != null) {\r
- fileProcess.parseFile(sourceFiles[i][1], filetype, sourceFiles[i][2], root, true);\r
- } else {\r
- fileProcess.parseFile(sourceFiles[i][1], sourceFiles[i][2], root, true);\r
- }\r
- }\r
- \r
- //\r
- // If exist Unicode file\r
- //\r
- if (fileProcess.isUnicodeExist()) {\r
- Element ele = document.createElement("Build_Unicode_Database");\r
- ele.setAttribute("FILEPATH", ".");\r
- ele.setAttribute("FILENAME", "${BASE_NAME}");\r
- Element includesEle = document.createElement("EXTRA.INC");\r
- for (int i = 0; i < includes.length; i++) {\r
- Element includeEle = document.createElement("includepath");\r
- includeEle.setAttribute("path", includes[i]);\r
- includesEle.appendChild(includeEle);\r
- }\r
- ele.appendChild(includesEle);\r
- root.appendChild(ele);\r
- }\r
-\r
- //\r
- // Don't build AutoGen.c for library and binary module\r
- //\r
- if (!isLibraryModule && !isBinaryModule) {\r
- fileProcess.parseFile(project.getProperty("DEST_DIR_DEBUG") + File.separatorChar + "AutoGen.c", null, root, false);\r
- }\r
- \r
- //\r
- // Parse all source files but Unicode files\r
- //\r
- for (int i = 0; i < sourceFiles.length; i++) {\r
- String filetype = sourceFiles[i][0];\r
- if (filetype != null) {\r
- fileProcess.parseFile(sourceFiles[i][1], filetype, sourceFiles[i][2], root, false);\r
- } else {\r
- fileProcess.parseFile(sourceFiles[i][1], sourceFiles[i][2], root, false);\r
- }\r
- }\r
- \r
- //\r
- // Initialize SOURCE_FILES for dependcy check use\r
- //\r
- String str = "";\r
- for (int i = 0; i < sourceFiles.length; i++) {\r
- str += " " + sourceFiles[i][1];\r
- }\r
- project.setProperty("SOURCE_FILES", str.replaceAll("(\\\\)", "/"));\r
- }\r
-\r
- /**\r
- Generate the section elements for BaseName_build.xml. Library module will\r
- skip this process. \r
- \r
- @param document current BaseName_build.xml XML document\r
- @param root Root element for current\r
- **/\r
- private void applySectionsElement(Document document, Node root, FfsProcess fp) {\r
- if (fpdModuleId.getModule().isLibrary()) {\r
- return ;\r
- }\r
- if (fp.initSections(ffsKeyword, project, fpdModuleId)) {\r
- String targetFilename = fpdModuleId.getModule().getGuid() + "-" + "${BASE_NAME}" + FpdParserTask.getSuffix(fpdModuleId.getModule().getModuleType());\r
- String[] list = fp.getGenSectionElements(document, "${BASE_NAME}", fpdModuleId.getModule().getGuid(), targetFilename);\r
-\r
- for (int i = 0; i < list.length; i++) {\r
- String sectiontype = list[i];\r
- if (sectiontype.equalsIgnoreCase("EFI_SECTION_RAW") && project.getProperty("MODULE_TYPE").equalsIgnoreCase("SEC")) {\r
- sectiontype += "_SEC";\r
- }\r
- if ((sectiontype.equalsIgnoreCase("EFI_SECTION_PE32") || \r
- sectiontype.equalsIgnoreCase("EFI_SECTION_TE"))\r
- && !fpdModuleId.getModule().isLibrary()\r
- && !fpdModuleId.getModule().isBinary()) {\r
- //\r
- // Generate code to generate efi file\r
- // \r
- Element ele = document.createElement("GenEfi");\r
- ele.setAttribute("FILEPATH", ".");\r
- ele.setAttribute("FILENAME", "${BASE_NAME}");\r
- root.appendChild(ele);\r
- }\r
- Element ele = document.createElement(sectiontype);\r
- ele.setAttribute("FILEPATH", ".");\r
- ele.setAttribute("FILENAME", "${BASE_NAME}");\r
- root.appendChild(ele);\r
- }\r
- }\r
- }\r
-\r
- /**\r
- Generate the output elements for BaseName_build.xml. If module is library,\r
- call the <em>LIB</em> command, else call the <em>GenFfs</em> command. \r
- \r
- @param document current BaseName_build.xml XML document\r
- @param root Root element for current\r
- **/\r
- private void applyOutputElement(Document document, Node root, FfsProcess fp) {\r
- if (fpdModuleId.getModule().isLibrary()) {\r
- //\r
- // call Lib command\r
- //\r
- Element cc = document.createElement("Build_Library");\r
- cc.setAttribute("FILENAME", fpdModuleId.getModule().getName());\r
- root.appendChild(cc);\r
- }\r
- //\r
- // if it is a module but library\r
- //\r
- else {\r
- if (fp.getFfsNode() != null) {\r
- root.appendChild(fp.getFfsNode());\r
- }\r
- }\r
- }\r
-\r
-}\r