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
This commit is contained in:
jwang36
2006-10-08 06:28:06 +00:00
parent 5d28bc25af
commit 5a4c434254
2 changed files with 202 additions and 127 deletions

View File

@@ -14,11 +14,22 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/ **/
package org.tianocore.framework.tasks; package org.tianocore.framework.tasks;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File; import java.io.File;
import java.io.FileReader; import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException; import java.io.IOException;
import java.io.LineNumberReader; 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.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.BuildException;
import org.apache.tools.ant.Project; 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.Execute;
import org.apache.tools.ant.taskdefs.LogStreamHandler; import org.apache.tools.ant.taskdefs.LogStreamHandler;
import org.apache.tools.ant.types.Commandline; import org.apache.tools.ant.types.Commandline;
import org.tianocore.common.logger.EdkLog;
import org.tianocore.common.cache.FileTimeStamp; import org.tianocore.common.cache.FileTimeStamp;
import org.tianocore.common.logger.EdkLog;
/** /**
Class MakeDeps is used to wrap MakeDeps.exe as an ANT task. 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 members, use set/get to access them
// //
private static final String toolName = "MakeDeps"; private String depsFilePath = "";
private FileArg depsFile = new FileArg(); private IncludePath includePathList = new IncludePath();
private ToolArg subDir = new ToolArg(); private Input inputFileList = new Input();
private ToolArg quietMode = new ToolArg(" -", "q"); //
private ToolArg ignoreError = new ToolArg(" -", "ignorenotfound"); // cache the including files to speed up dependency check
private IncludePath includePathList = new IncludePath(); //
private Input inputFileList = new Input(); private static HashMap<String, Set<String>> includesCache = new HashMap<String, Set<String>>();
private ToolArg target = new FileArg(" -target ", "dummy"); //
// regular expression for "#include ..." directive
//
private static final Pattern incPattern = Pattern.compile("[\n\r \t]*#[ \t]*include[ \t\"<]+([^\n\r\"<>]+)");
public MakeDeps() { public MakeDeps() {
@@ -60,63 +73,59 @@ public class MakeDeps extends Task {
@throws BuildException @throws BuildException
**/ **/
public void execute() 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()) { if (isUptodate()) {
return; return;
} }
Project prj = this.getOwningTarget().getProject(); //
String toolPath = prj.getProperty("env.FRAMEWORK_TOOLS_PATH"); // if no include path is specified, try locally
//
if (includePathList.isEmpty()) {
includePathList.insPath(".");
}
/// Set<String> depFiles = getDependencies(inputFileList.toArray());
/// compose full tool path
/// File depsFile = new File(depsFilePath);
if (toolPath == null || toolPath.length() == 0) { FileWriter fileWriter = null;
toolPath = toolName; BufferedWriter bufWriter = null;
} else {
if (toolPath.endsWith("/") || toolPath.endsWith("\\")) { try {
toolPath = toolPath + toolName; fileWriter = new FileWriter(depsFile);
} else { bufWriter = new BufferedWriter(fileWriter);
toolPath = toolPath + File.separator + toolName;
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());
} }
} }
/// //
/// compose tool arguments // update time stamp of dependency file
/// //
String argument = "" + inputFileList + includePathList + subDir FileTimeStamp.update(depsFilePath, depsFile.lastModified());
+ quietMode + ignoreError + target + depsFile;
///
/// prepare to execute the tool
///
Commandline cmd = new Commandline();
cmd.setExecutable(toolPath);
cmd.createArgument().setLine(argument);
LogStreamHandler streamHandler = new LogStreamHandler(this, Project.MSG_INFO, Project.MSG_WARN);
Execute runner = new Execute(streamHandler, null);
runner.setAntRun(prj);
runner.setCommandline(cmd.getCommandline());
EdkLog.log(this, EdkLog.EDK_VERBOSE, Commandline.toString(cmd.getCommandline()));
int result = 0;
try {
result = runner.execute();
} catch (IOException 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!");
}
} }
/** /**
@@ -125,7 +134,7 @@ public class MakeDeps extends Task {
@param name The name of dependency list file @param name The name of dependency list file
**/ **/
public void setDepsFile(String name) { 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 @returns The name of dependency list file
**/ **/
public String getDepsFile() { public String getDepsFile() {
return depsFile.getValue(); return depsFilePath;
}
/**
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();
} }
/** /**
@@ -220,10 +171,9 @@ public class MakeDeps extends Task {
@returns false The dependency list file is outofdate. Re-generation is needed. @returns false The dependency list file is outofdate. Re-generation is needed.
**/ **/
private boolean isUptodate() { private boolean isUptodate() {
String dfName = depsFile.getValue(); File df = new File(depsFilePath);
File df = new File(dfName);
if (!df.exists()) { 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; 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 // If the source file(s) is newer than dependency list file, we need to
// re-generate the dependency list file // re-generate the dependency list file
// //
long depsFileTimeStamp = FileTimeStamp.get(dfName); long depsFileTimeStamp = FileTimeStamp.get(depsFilePath);
List<String> fileList = inputFileList.getNameList(); List<String> fileList = inputFileList.getNameList();
for (int i = 0, length = fileList.size(); i < length; ++i) { for (int i = 0, length = fileList.size(); i < length; ++i) {
String sf = fileList.get(i); String sf = fileList.get(i);
@@ -288,17 +238,124 @@ public class MakeDeps extends Task {
// check if the .dep file is empty // check if the .dep file is empty
// //
if (lines == 0) { if (lines == 0) {
EdkLog.log(this, EdkLog.EDK_VERBOSE, dfName + " is empty!"); EdkLog.log(this, EdkLog.EDK_VERBOSE, depsFilePath + " is empty!");
ret = false; ret = false;
} }
lineReader.close();
fileReader.close();
} catch (IOException e) { } catch (IOException e) {
throw new BuildException(e.getMessage()); 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; return ret;
} }
//
// get dependent files list by parsing "#include" directive
//
private synchronized Set<String> getDependencies(String[] sourceFiles) {
Set<String> dependencies = new LinkedHashSet<String>();
String[] searchPathList = includePathList.toArray();
Stack<String> pendingFiles = new Stack<String>();
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<String> incFiles = includesCache.get(src);
if (incFiles == null) {
incFiles = new HashSet<String>();
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<String> 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;
}
} }

View File

@@ -333,6 +333,24 @@ public class NestElement extends DataType {
return toFileList(" "); 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 // Remove any duplicated path separator or inconsistent path separator
// //