From 5a4c434254011a0d193f884c5b608a3331df4aee Mon Sep 17 00:00:00 2001 From: jwang36 Date: Sun, 8 Oct 2006 06:28:06 +0000 Subject: [PATCH 1/1] Removed the need of external MakeDeps.exe. Now parsing include files is built in makedeps task. git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@1683 6f19259b-4bc3-4df7-8a09-765794883524 --- .../tianocore/framework/tasks/MakeDeps.java | 301 +++++++++++------- .../framework/tasks/NestElement.java | 18 ++ 2 files changed, 197 insertions(+), 122 deletions(-) diff --git a/Tools/Java/Source/FrameworkTasks/org/tianocore/framework/tasks/MakeDeps.java b/Tools/Java/Source/FrameworkTasks/org/tianocore/framework/tasks/MakeDeps.java index 8f5664f01d..27e0ed7be5 100644 --- a/Tools/Java/Source/FrameworkTasks/org/tianocore/framework/tasks/MakeDeps.java +++ b/Tools/Java/Source/FrameworkTasks/org/tianocore/framework/tasks/MakeDeps.java @@ -14,11 +14,22 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. **/ package org.tianocore.framework.tasks; +import java.io.BufferedReader; +import java.io.BufferedWriter; import java.io.File; import java.io.FileReader; +import java.io.FileWriter; import java.io.IOException; import java.io.LineNumberReader; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.LinkedHashSet; import java.util.List; +import java.util.Set; +import java.util.Stack; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import org.apache.tools.ant.BuildException; import org.apache.tools.ant.Project; @@ -26,9 +37,8 @@ import org.apache.tools.ant.Task; import org.apache.tools.ant.taskdefs.Execute; import org.apache.tools.ant.taskdefs.LogStreamHandler; import org.apache.tools.ant.types.Commandline; - -import org.tianocore.common.logger.EdkLog; import org.tianocore.common.cache.FileTimeStamp; +import org.tianocore.common.logger.EdkLog; /** Class MakeDeps is used to wrap MakeDeps.exe as an ANT task. @@ -38,14 +48,17 @@ public class MakeDeps extends Task { // // private members, use set/get to access them // - private static final String toolName = "MakeDeps"; - private FileArg depsFile = new FileArg(); - private ToolArg subDir = new ToolArg(); - private ToolArg quietMode = new ToolArg(" -", "q"); - private ToolArg ignoreError = new ToolArg(" -", "ignorenotfound"); - private IncludePath includePathList = new IncludePath(); - private Input inputFileList = new Input(); - private ToolArg target = new FileArg(" -target ", "dummy"); + private String depsFilePath = ""; + private IncludePath includePathList = new IncludePath(); + private Input inputFileList = new Input(); + // + // cache the including files to speed up dependency check + // + private static HashMap> includesCache = new HashMap>(); + // + // regular expression for "#include ..." directive + // + private static final Pattern incPattern = Pattern.compile("[\n\r \t]*#[ \t]*include[ \t\"<]+([^\n\r\"<>]+)"); public MakeDeps() { @@ -60,63 +73,59 @@ public class MakeDeps extends Task { @throws BuildException **/ public void execute() throws BuildException { - /// - /// check if the dependency list file is uptodate or not - /// + // + // check if the dependency list file is uptodate or not + // if (isUptodate()) { return; } - Project prj = this.getOwningTarget().getProject(); - String toolPath = prj.getProperty("env.FRAMEWORK_TOOLS_PATH"); - - /// - /// compose full tool path - /// - if (toolPath == null || toolPath.length() == 0) { - toolPath = toolName; - } else { - if (toolPath.endsWith("/") || toolPath.endsWith("\\")) { - toolPath = toolPath + toolName; - } else { - toolPath = toolPath + File.separator + toolName; - } + // + // if no include path is specified, try locally + // + if (includePathList.isEmpty()) { + includePathList.insPath("."); } - /// - /// compose tool arguments - /// - String argument = "" + inputFileList + includePathList + subDir - + quietMode + ignoreError + target + depsFile; + Set depFiles = getDependencies(inputFileList.toArray()); - /// - /// prepare to execute the tool - /// - Commandline cmd = new Commandline(); - cmd.setExecutable(toolPath); - cmd.createArgument().setLine(argument); + File depsFile = new File(depsFilePath); + FileWriter fileWriter = null; + BufferedWriter bufWriter = null; - LogStreamHandler streamHandler = new LogStreamHandler(this, Project.MSG_INFO, Project.MSG_WARN); - Execute runner = new Execute(streamHandler, null); - - runner.setAntRun(prj); - runner.setCommandline(cmd.getCommandline()); + try { + fileWriter = new FileWriter(depsFile); + bufWriter = new BufferedWriter(fileWriter); - EdkLog.log(this, EdkLog.EDK_VERBOSE, Commandline.toString(cmd.getCommandline())); - int result = 0; - try { - result = runner.execute(); - } catch (IOException e) { + for (Iterator it = depFiles.iterator(); it.hasNext();) { + String depFile = (String)it.next(); + bufWriter.write(depFile, 0, depFile.length()); + bufWriter.write("\n", 0, 1); + } + // + // put a "tab" at the end of file as file ending flag + // + bufWriter.write("\t", 0, 1); + } catch (Exception e) { throw new BuildException(e.getMessage()); + } finally { + try { + if (bufWriter != null) { + bufWriter.close(); + } + if (fileWriter != null) { + fileWriter.close(); + } + } catch (Exception e) { + throw new BuildException(e.getMessage()); + } } - if (result != 0) { - EdkLog.log(this, EdkLog.EDK_INFO, toolName + " failed!"); - throw new BuildException(toolName + ": failed to generate dependency file!"); - } else { - EdkLog.log(this, EdkLog.EDK_VERBOSE, toolName + " succeeded!"); - } + // + // update time stamp of dependency file + // + FileTimeStamp.update(depsFilePath, depsFile.lastModified()); } /** @@ -125,7 +134,7 @@ public class MakeDeps extends Task { @param name The name of dependency list file **/ public void setDepsFile(String name) { - depsFile.setArg(" -o ", name); + depsFilePath = name; } /** @@ -134,65 +143,7 @@ public class MakeDeps extends Task { @returns The name of dependency list file **/ public String getDepsFile() { - return depsFile.getValue(); - } - - /** - Set method for "IgnoreError" attribute - - @param ignore flag to control error handling (true/false) - **/ - public void setIgnoreError(boolean ignore) { - if (!ignore) { - ignoreError.setArg(" ", " "); - } - } - - /** - Get method for "IgnoreError" attribute - - @returns The value of current IgnoreError flag - **/ - public boolean getIgnoreError() { - return ignoreError.getValue().length() > 0; - } - - /** - Set method for "QuietMode" attribute - - @param quiet flag to control the output information (true/false) - **/ - public void setQuietMode(boolean quiet) { - if (!quiet) { - quietMode.setArg(" ", " "); - } - } - - /** - Get method for "QuietMode" attribute - - @returns value of current QuietMode flag - **/ - public boolean getQuietMode() { - return quietMode.getValue().length() > 0; - } - - /** - Set method for "SubDir" attribute - - @param dir The name of sub-directory in which source files will be scanned - **/ - public void setSubDir(String dir) { - subDir.setArg(" -s ", dir); - } - - /** - Get method for "SubDir" attribute - - @returns The name of sub-directory - **/ - public String getSubDir() { - return subDir.getValue(); + return depsFilePath; } /** @@ -220,10 +171,9 @@ public class MakeDeps extends Task { @returns false The dependency list file is outofdate. Re-generation is needed. **/ private boolean isUptodate() { - String dfName = depsFile.getValue(); - File df = new File(dfName); + File df = new File(depsFilePath); if (!df.exists()) { - EdkLog.log(this, EdkLog.EDK_VERBOSE, dfName + " doesn't exist!"); + EdkLog.log(this, EdkLog.EDK_VERBOSE, depsFilePath + " doesn't exist!"); return false; } @@ -231,7 +181,7 @@ public class MakeDeps extends Task { // If the source file(s) is newer than dependency list file, we need to // re-generate the dependency list file // - long depsFileTimeStamp = FileTimeStamp.get(dfName); + long depsFileTimeStamp = FileTimeStamp.get(depsFilePath); List fileList = inputFileList.getNameList(); for (int i = 0, length = fileList.size(); i < length; ++i) { String sf = fileList.get(i); @@ -288,17 +238,124 @@ public class MakeDeps extends Task { // check if the .dep file is empty // if (lines == 0) { - EdkLog.log(this, EdkLog.EDK_VERBOSE, dfName + " is empty!"); + EdkLog.log(this, EdkLog.EDK_VERBOSE, depsFilePath + " is empty!"); ret = false; } - - lineReader.close(); - fileReader.close(); } catch (IOException e) { throw new BuildException(e.getMessage()); + } finally { + try { + if (lineReader != null) { + lineReader.close(); + } + if (fileReader != null) { + fileReader.close(); + } + } catch (Exception e) { + throw new BuildException(e.getMessage()); + } } return ret; } + + // + // get dependent files list by parsing "#include" directive + // + private synchronized Set getDependencies(String[] sourceFiles) { + Set dependencies = new LinkedHashSet(); + String[] searchPathList = includePathList.toArray(); + + Stack pendingFiles = new Stack(); + for (int i = 0; i < sourceFiles.length; ++i) { + File srcFile = new File(sourceFiles[i]); + if (srcFile.exists()) { + // + // a file must depend itself + // + dependencies.add(srcFile.getAbsolutePath()); + pendingFiles.push(sourceFiles[i]); + } + } + + while (!pendingFiles.empty()) { + String src = pendingFiles.pop(); + File srcFile = new File(src); + if (!srcFile.exists()) { + continue; + } + + // + // try cache first + // + Set incFiles = includesCache.get(src); + if (incFiles == null) { + incFiles = new HashSet(); + FileReader fileReader = null; + BufferedReader bufReader = null; + String fileContent = ""; + int fileLength = (int)srcFile.length(); + + try { + fileReader = new FileReader(srcFile); + bufReader = new BufferedReader(fileReader); + char[] buf = new char[fileLength]; + + bufReader.read(buf, 0, fileLength); + fileContent = new String(buf); + } catch (IOException e) { + throw new BuildException(e.getMessage()); + } finally { + try { + if (bufReader != null) { + bufReader.close(); + } + if (fileReader != null) { + fileReader.close(); + } + } catch (Exception e) { + throw new BuildException(e.getMessage()); + } + } + + // + // find out all "#include" lines + // + Matcher matcher = incPattern.matcher(fileContent); + while (matcher.find()) { + String incFilePath = fileContent.substring(matcher.start(1), matcher.end(1)); + incFiles.add(incFilePath); + } + + // + // put the includes in cache to avoid re-parsing + // + includesCache.put(src, incFiles); + } + + // + // try each include search path to see if the include file exists or not + // + for (Iterator it = incFiles.iterator(); it.hasNext();) { + String depFilePath = it.next(); + + for (int i = 0; i < searchPathList.length; ++i) { + File depFile = new File(searchPathList[i] + File.separator + depFilePath); + String filePath = depFile.getAbsolutePath(); + // + // following check is a must. it can prevent dead loop if two + // files include each other + // + if (depFile.exists() && !dependencies.contains(filePath)) { + dependencies.add(filePath); + pendingFiles.push(filePath); + break; + } + } + } + } + + return dependencies; + } } diff --git a/Tools/Java/Source/FrameworkTasks/org/tianocore/framework/tasks/NestElement.java b/Tools/Java/Source/FrameworkTasks/org/tianocore/framework/tasks/NestElement.java index 271dee6c88..dd36c9127b 100644 --- a/Tools/Java/Source/FrameworkTasks/org/tianocore/framework/tasks/NestElement.java +++ b/Tools/Java/Source/FrameworkTasks/org/tianocore/framework/tasks/NestElement.java @@ -333,6 +333,24 @@ public class NestElement extends DataType { return toFileList(" "); } + /** + Get the array of names + + @return String[] The array contains the names + **/ + public String[] toArray() { + return nameList.toArray(new String[nameList.size()]); + } + + /** + Check if we have any name or not + + @return boolean + **/ + public boolean isEmpty() { + return nameList.isEmpty(); + } + // // Remove any duplicated path separator or inconsistent path separator // -- 2.39.2