mirror of https://github.com/acidanthera/audk.git
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:
parent
5d28bc25af
commit
5a4c434254
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
//
|
||||
|
|
Loading…
Reference in New Issue