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;
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<String, Set<String>> includesCache = new HashMap<String, Set<String>>();
//
// 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");
//
// if no include path is specified, try locally
//
if (includePathList.isEmpty()) {
includePathList.insPath(".");
}
///
/// 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;
Set<String> depFiles = getDependencies(inputFileList.toArray());
File depsFile = new File(depsFilePath);
FileWriter fileWriter = null;
BufferedWriter bufWriter = null;
try {
fileWriter = new FileWriter(depsFile);
bufWriter = new BufferedWriter(fileWriter);
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
///
String argument = "" + inputFileList + includePathList + subDir
+ 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!");
}
//
// 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<String> 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<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(" ");
}
/**
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
//