diff --git a/Tools/Source/Common/org/tianocore/common/cache/FileTimeStamp.java b/Tools/Source/Common/org/tianocore/common/cache/FileTimeStamp.java new file mode 100644 index 0000000000..968d31f15c --- /dev/null +++ b/Tools/Source/Common/org/tianocore/common/cache/FileTimeStamp.java @@ -0,0 +1,83 @@ +/** @file +This file is to define the FileTimeStamp class for speeding up the dependency check. + +Copyright (c) 2006, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ +package org.tianocore.common.cache; + +import java.io.File; +import java.util.Map; +import java.util.TreeMap; +import java.util.HashMap; + +/** + FileTimeStamp class is used to cache the time stamp of accessing file, which + will speed up the dependency check for build + **/ +public class FileTimeStamp { + // + // cache the modified timestamp of files accessed, to speed up the depencey check + // + private static Map timeStampCache = new HashMap(); + + /** + Get the time stamp of given file. It will try the cache first and then + get from file system if no time stamp of the file is cached. + + @param file File name + + @return long The time stamp of the file + **/ + synchronized public static long get(String file) { + long timeStamp = 0; + + Long value = timeStampCache.get(file); + if (value != null) { + timeStamp = value.longValue(); + } else { + timeStamp = new File(file).lastModified(); + timeStampCache.put(file, new Long(timeStamp)); + } + + return timeStamp; + } + + /** + Force update the time stamp for the given file + + @param file File name + @param timeStamp The time stamp of the file + **/ + synchronized public static void update(String file, long timeStamp) { + timeStampCache.put(file, new Long(timeStamp)); + } + + /** + Force update the time stamp for the given file + + @param file File name + **/ + synchronized public static void update(String file) { + long timeStamp = new File(file).lastModified(); + timeStampCache.put(file, new Long(timeStamp)); + } + + /** + Check if the time stamp of given file has been cached for not + + @param file The file name + + @return boolean + **/ + synchronized public static boolean containsKey(String file) { + return timeStampCache.containsKey(file); + } +} diff --git a/Tools/Source/FrameworkTasks/org/tianocore/framework/tasks/FlashMapTask.java b/Tools/Source/FrameworkTasks/org/tianocore/framework/tasks/FlashMapTask.java index 5c3e88920a..c6f5099afa 100644 --- a/Tools/Source/FrameworkTasks/org/tianocore/framework/tasks/FlashMapTask.java +++ b/Tools/Source/FrameworkTasks/org/tianocore/framework/tasks/FlashMapTask.java @@ -17,6 +17,14 @@ package org.tianocore.framework.tasks; import java.io.File; +import java.io.FileReader; +import java.io.BufferedReader; + +import java.util.List; +import java.util.ArrayList; +import java.util.regex.Pattern; +import java.util.regex.Matcher; + import org.apache.tools.ant.Task; import org.apache.tools.ant.Project; import org.apache.tools.ant.BuildException; @@ -35,8 +43,14 @@ public class FlashMapTask extends Task implements EfiDefine { // // tool name // - private final String toolName = "FlashMap"; + private static final String toolName = "FlashMap"; + // + // + // + private static Pattern fileBlock = Pattern.compile("\\s*File\\s*\\{([^\\{\\}]+)\\}"); + private static Pattern fileNameDef = Pattern.compile("\\bName\\s*=\\s*\"([^\"]+)\""); + // // Flash definition file // @@ -135,7 +149,6 @@ public class FlashMapTask extends Task implements EfiDefine { @throws BuidException **/ public void execute() throws BuildException { - /* if (isUptodate()) { EdkLog.log(this, EdkLog.EDK_VERBOSE, headerFile.toFileList() + imageOutFile.toFileList() @@ -143,10 +156,9 @@ public class FlashMapTask extends Task implements EfiDefine { + dscFile.toFileList() + asmIncFile.toFileList() + outStrFile - + " is/are up-to-date!"); + + " is up-to-date!"); return; } - */ Project project = this.getOwningTarget().getProject(); // @@ -689,6 +701,13 @@ public class FlashMapTask extends Task implements EfiDefine { EdkLog.log(this, EdkLog.EDK_VERBOSE, srcName + " has been changed since last build!"); return false; } + + // + // we need to check the time stamp of each FV file specified in fdf file + // + if (!isFdUptodate(dstName, getFvFiles(flashDefFile.getValue()))) { + return false; + } } if (!mcoFile.isEmpty()) { @@ -749,4 +768,82 @@ public class FlashMapTask extends Task implements EfiDefine { return true; } + + // + // Parse the flash definition file and find out the FV file names + // + private List getFvFiles(String fdfFileName) { + File fdfFile = new File(fdfFileName); + int fileLength = (int)fdfFile.length(); + char[] fdfContent = new char[fileLength]; + List fileList = new ArrayList(); + + try { + FileReader reader = new FileReader(fdfFile); + BufferedReader in = new BufferedReader(reader); + + in.read(fdfContent, 0, fileLength); + String str = new String(fdfContent); + + // + // match the + // File { + // ... + // } + // block + // + Matcher matcher = fileBlock.matcher(str); + while (matcher.find()) { + String fileBlockContent = str.substring(matcher.start(1), matcher.end(1)); + // + // match the definition like + // Name = "..." + // + Matcher nameMatcher = fileNameDef.matcher(fileBlockContent); + if (nameMatcher.find()) { + fileList.add(fileBlockContent.substring(nameMatcher.start(1), nameMatcher.end(1))); + } + } + + in.close(); + reader.close(); + } catch (Exception ex) { + throw new BuildException(ex.getMessage()); + } + + return fileList; + } + + private boolean isFdUptodate(String fdFile, List fvFileList) { + String fvDir = "."; + File fd = new File(fdFile); + + if (outputDir.equals(".")) { + if (!fd.isAbsolute()) { + // + // If we cannot get the absolute path of fd file, we caanot + // get its time stamp. Re-generate it always in such situation. + // + EdkLog.log(this, EdkLog.EDK_VERBOSE, "Cannot retrieve the time stamp of " + fdFile); + return false; + } + fvDir = fd.getParent(); + } else { + fvDir = outputDir; + if (!fd.isAbsolute()) { + fd = new File(fvDir + File.separator + fdFile); + } + } + + long fdTimeStamp = fd.lastModified(); + for (int i = 0; i < fvFileList.size(); ++i) { + File fv = new File(fvDir + File.separator + fvFileList.get(i)); + if (fv.lastModified() > fdTimeStamp) { + EdkLog.log(this, EdkLog.EDK_VERBOSE, fv.getPath() + " has been changed since last build!"); + return false; + } + } + + return true; + } } diff --git a/Tools/Source/FrameworkTasks/org/tianocore/framework/tasks/MakeDeps.java b/Tools/Source/FrameworkTasks/org/tianocore/framework/tasks/MakeDeps.java index bd305fa079..1486bd384e 100644 --- a/Tools/Source/FrameworkTasks/org/tianocore/framework/tasks/MakeDeps.java +++ b/Tools/Source/FrameworkTasks/org/tianocore/framework/tasks/MakeDeps.java @@ -31,6 +31,7 @@ import org.apache.tools.ant.types.Commandline; import org.apache.tools.ant.types.Path; import org.tianocore.common.logger.EdkLog; +import org.tianocore.common.cache.FileTimeStamp; /** Class MakeDeps is used to wrap MakeDeps.exe as an ANT task. @@ -233,12 +234,12 @@ 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 = df.lastModified(); + long depsFileTimeStamp = FileTimeStamp.get(dfName); List fileList = inputFileList.getNameList(); for (int i = 0, length = fileList.size(); i < length; ++i) { - File sf = new File(fileList.get(i)); - if (sf.lastModified() > depsFileTimeStamp) { - EdkLog.log(this, EdkLog.EDK_VERBOSE, sf.getPath() + " has been changed since last build!"); + String sf = fileList.get(i); + if (FileTimeStamp.get(sf) > depsFileTimeStamp) { + EdkLog.log(this, EdkLog.EDK_VERBOSE, sf + " has been changed since last build!"); return false; } } @@ -279,7 +280,7 @@ public class MakeDeps extends Task { // If a file cannot be found (moved or removed) or newer, regenerate the dep file // File sourceFile = new File(line); - if ((!sourceFile.exists()) || (sourceFile.lastModified() > depsFileTimeStamp)) { + if ((!sourceFile.exists()) || (FileTimeStamp.get(line) > depsFileTimeStamp)) { EdkLog.log(this, EdkLog.EDK_VERBOSE, sourceFile.getPath() + " has been (re)moved or changed since last build!"); ret = false; break; diff --git a/Tools/Source/GenBuild/org/tianocore/build/global/OnDependency.java b/Tools/Source/GenBuild/org/tianocore/build/global/OnDependency.java index 173528ab39..fbffb3bcb7 100644 --- a/Tools/Source/GenBuild/org/tianocore/build/global/OnDependency.java +++ b/Tools/Source/GenBuild/org/tianocore/build/global/OnDependency.java @@ -22,6 +22,7 @@ import org.apache.tools.ant.BuildException; import org.apache.tools.ant.Task; import org.apache.tools.ant.taskdefs.Sequential; import org.tianocore.common.logger.EdkLog; +import org.tianocore.common.cache.FileTimeStamp; /** Class OnDepdendency is used to check the timestamp between source files and @@ -29,26 +30,24 @@ import org.tianocore.common.logger.EdkLog; be re-generated from source files. **/ public class OnDependency extends Task { - /// - /// cache the modified timestamp of files accessed, to speed up the depencey check - /// - private Map timeStampCache = new HashMap(); - /// - /// source files list - /// + // + // source files list + // private DpFileList sources = null; - /// - /// target files list - /// + + // + // target files list + // private DpFileList targets = null; - /// - /// tasks to be performed to generate target files - /// + + // + // tasks to be performed to generate target files + // private Sequential task = null; - /// - /// An empty constructor for an ANT task can avoid some potential issues - /// + /** + An empty constructor for an ANT task can avoid some potential issues + **/ public OnDependency(){ } @@ -59,11 +58,18 @@ public class OnDependency extends Task { if (isOutOfDate() && task != null) { task.perform(); } + + // + // Update the time stamp of target files since they are just re-generated + // + for (Iterator dstIt = targets.nameList.iterator(); dstIt.hasNext();) { + FileTimeStamp.update((String)dstIt.next()); + } } - /// - /// check if the target files are outofdate - /// + // + // check if the target files are outofdate + // private boolean isOutOfDate() { /// /// if no source files specified, take it as a fresh start @@ -87,21 +93,17 @@ public class OnDependency extends Task { return true; } - long dstTimeStamp = dstFile.lastModified(); + long dstTimeStamp = FileTimeStamp.get(dstFileName); Iterator srcIt = sources.nameList.iterator(); while (srcIt.hasNext()) { String srcFileName = (String)srcIt.next(); - long srcTimeStamp; + long srcTimeStamp = FileTimeStamp.get(srcFileName); - if (timeStampCache.containsKey(srcFileName)) { - srcTimeStamp = ((Long)timeStampCache.get(srcFileName)).longValue(); - } else { - File srcFile = new File(srcFileName); - if (!srcFile.exists()) { - throw new BuildException("Source File name: " + srcFileName + " doesn't exist!!!"); - } - srcTimeStamp = srcFile.lastModified(); - timeStampCache.put(srcFileName, new Long(srcTimeStamp)); + if (srcTimeStamp == 0) { + // + // time stamp 0 means that the file doesn't exist + // + throw new BuildException("Source File name: " + srcFileName + " doesn't exist!!!"); } if (dstTimeStamp < srcTimeStamp) {