]> git.proxmox.com Git - mirror_edk2.git/blame_incremental - Tools/Source/FrameworkTasks/org/tianocore/framework/tasks/MakeDeps.java
1) Add FileTimeStamp class to centralize the cache mechanism for file time stamp...
[mirror_edk2.git] / Tools / Source / FrameworkTasks / org / tianocore / framework / tasks / MakeDeps.java
... / ...
CommitLineData
1/** @file\r
2This file is to wrap MakeDeps.exe tool as ANT task, which is used to generate\r
3dependency files for source code.\r
4\r
5Copyright (c) 2006, Intel Corporation\r
6All rights reserved. This program and the accompanying materials\r
7are licensed and made available under the terms and conditions of the BSD License\r
8which accompanies this distribution. The full text of the license may be found at\r
9http://opensource.org/licenses/bsd-license.php\r
10\r
11THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
12WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
13\r
14**/\r
15package org.tianocore.framework.tasks;\r
16\r
17import java.io.File;\r
18import java.io.FileReader;\r
19import java.io.IOException;\r
20import java.io.LineNumberReader;\r
21import java.util.ArrayList;\r
22import java.util.Iterator;\r
23import java.util.List;\r
24\r
25import org.apache.tools.ant.BuildException;\r
26import org.apache.tools.ant.Project;\r
27import org.apache.tools.ant.Task;\r
28import org.apache.tools.ant.taskdefs.Execute;\r
29import org.apache.tools.ant.taskdefs.LogStreamHandler;\r
30import org.apache.tools.ant.types.Commandline;\r
31import org.apache.tools.ant.types.Path;\r
32\r
33import org.tianocore.common.logger.EdkLog;\r
34import org.tianocore.common.cache.FileTimeStamp;\r
35\r
36/**\r
37 Class MakeDeps is used to wrap MakeDeps.exe as an ANT task.\r
38 **/\r
39public class MakeDeps extends Task {\r
40\r
41 //\r
42 // private members, use set/get to access them\r
43 //\r
44 private static final String toolName = "MakeDeps";\r
45 private FileArg depsFile = new FileArg();\r
46 private ToolArg subDir = new ToolArg();\r
47 private ToolArg quietMode = new ToolArg(" -", "q");\r
48 private ToolArg ignoreError = new ToolArg(" -", "ignorenotfound");\r
49 private IncludePath includePathList = new IncludePath();\r
50 private Input inputFileList = new Input();\r
51 private ToolArg target = new FileArg(" -target ", "dummy");\r
52\r
53 public MakeDeps() {\r
54\r
55 }\r
56\r
57 /**\r
58 The Standard execute method for ANT task. It will check if it's necessary\r
59 to generate the dependency list file. If no file is found or the dependency\r
60 is changed, it will compose the command line and call MakeDeps.exe to\r
61 generate the dependency list file.\r
62\r
63 @throws BuildException\r
64 **/\r
65 public void execute() throws BuildException {\r
66 ///\r
67 /// check if the dependency list file is uptodate or not\r
68 ///\r
69 if (isUptodate()) {\r
70 return;\r
71 }\r
72\r
73 Project prj = this.getOwningTarget().getProject();\r
74 String toolPath = prj.getProperty("env.FRAMEWORK_TOOLS_PATH");\r
75\r
76 ///\r
77 /// compose full tool path\r
78 ///\r
79 if (toolPath == null || toolPath.length() == 0) {\r
80 toolPath = toolName;\r
81 } else {\r
82 if (toolPath.endsWith("/") || toolPath.endsWith("\\")) {\r
83 toolPath = toolPath + toolName;\r
84 } else {\r
85 toolPath = toolPath + File.separator + toolName;\r
86 }\r
87 }\r
88\r
89 ///\r
90 /// compose tool arguments\r
91 ///\r
92 String argument = "" + inputFileList + includePathList + subDir\r
93 + quietMode + ignoreError + target + depsFile;\r
94\r
95 ///\r
96 /// prepare to execute the tool\r
97 ///\r
98 Commandline cmd = new Commandline();\r
99 cmd.setExecutable(toolPath);\r
100 cmd.createArgument().setLine(argument);\r
101\r
102 LogStreamHandler streamHandler = new LogStreamHandler(this, Project.MSG_INFO, Project.MSG_WARN);\r
103 Execute runner = new Execute(streamHandler, null);\r
104\r
105 runner.setAntRun(prj);\r
106 runner.setCommandline(cmd.getCommandline());\r
107\r
108 EdkLog.log(this, EdkLog.EDK_VERBOSE, Commandline.toString(cmd.getCommandline()));\r
109\r
110 int result = 0;\r
111 try {\r
112 result = runner.execute();\r
113 } catch (IOException e) {\r
114 throw new BuildException(e.getMessage());\r
115 }\r
116\r
117 if (result != 0) {\r
118 EdkLog.log(this, EdkLog.EDK_INFO, toolName + " failed!");\r
119 throw new BuildException(toolName + ": failed to generate dependency file!");\r
120 } else {\r
121 EdkLog.log(this, EdkLog.EDK_VERBOSE, toolName + " succeeded!");\r
122 }\r
123 }\r
124\r
125 /**\r
126 Set method for "DepsFile" attribute\r
127\r
128 @param name The name of dependency list file\r
129 **/\r
130 public void setDepsFile(String name) {\r
131 depsFile.setArg(" -o ", name);\r
132 }\r
133\r
134 /**\r
135 Get method for "DepsFile" attribute\r
136\r
137 @returns The name of dependency list file\r
138 **/\r
139 public String getDepsFile() {\r
140 return depsFile.getValue();\r
141 }\r
142\r
143 /**\r
144 Set method for "IgnoreError" attribute\r
145\r
146 @param ignore flag to control error handling (true/false)\r
147 **/\r
148 public void setIgnoreError(boolean ignore) {\r
149 if (!ignore) {\r
150 ignoreError.setArg(" ", " ");\r
151 }\r
152 }\r
153\r
154 /**\r
155 Get method for "IgnoreError" attribute\r
156\r
157 @returns The value of current IgnoreError flag\r
158 **/\r
159 public boolean getIgnoreError() {\r
160 return ignoreError.getValue().length() > 0;\r
161 }\r
162\r
163 /**\r
164 Set method for "QuietMode" attribute\r
165\r
166 @param quiet flag to control the output information (true/false)\r
167 **/\r
168 public void setQuietMode(boolean quiet) {\r
169 if (!quiet) {\r
170 quietMode.setArg(" ", " ");\r
171 }\r
172 }\r
173\r
174 /**\r
175 Get method for "QuietMode" attribute\r
176\r
177 @returns value of current QuietMode flag\r
178 **/\r
179 public boolean getQuietMode() {\r
180 return quietMode.getValue().length() > 0;\r
181 }\r
182\r
183 /**\r
184 Set method for "SubDir" attribute\r
185\r
186 @param dir The name of sub-directory in which source files will be scanned\r
187 **/\r
188 public void setSubDir(String dir) {\r
189 subDir.setArg(" -s ", dir);\r
190 }\r
191\r
192 /**\r
193 Get method for "SubDir" attribute\r
194\r
195 @returns The name of sub-directory\r
196 **/\r
197 public String getSubDir() {\r
198 return subDir.getValue();\r
199 }\r
200\r
201 /**\r
202 Add method for "IncludePath" nested element\r
203\r
204 @param path The IncludePath object from nested IncludePath type of element\r
205 **/\r
206 public void addConfiguredIncludepath(IncludePath path) {\r
207 includePathList.insert(path);\r
208 }\r
209\r
210 /**\r
211 Add method for "Input" nested element\r
212\r
213 @param input The Input object from nested Input type of element\r
214 **/\r
215 public void addConfiguredInput(Input inputFile) {\r
216 inputFileList.insert(inputFile);\r
217 }\r
218\r
219 /**\r
220 Check if the dependency list file should be (re-)generated or not.\r
221\r
222 @returns true The dependency list file is uptodate. No re-generation is needed.\r
223 @returns false The dependency list file is outofdate. Re-generation is needed.\r
224 **/\r
225 private boolean isUptodate() {\r
226 String dfName = depsFile.getValue();\r
227 File df = new File(dfName);\r
228 if (!df.exists()) {\r
229 EdkLog.log(this, EdkLog.EDK_VERBOSE, dfName + " doesn't exist!");\r
230 return false;\r
231 }\r
232\r
233 //\r
234 // If the source file(s) is newer than dependency list file, we need to\r
235 // re-generate the dependency list file\r
236 //\r
237 long depsFileTimeStamp = FileTimeStamp.get(dfName);\r
238 List<String> fileList = inputFileList.getNameList();\r
239 for (int i = 0, length = fileList.size(); i < length; ++i) {\r
240 String sf = fileList.get(i);\r
241 if (FileTimeStamp.get(sf) > depsFileTimeStamp) {\r
242 EdkLog.log(this, EdkLog.EDK_VERBOSE, sf + " has been changed since last build!");\r
243 return false;\r
244 }\r
245 }\r
246\r
247 //\r
248 // If the source files haven't been changed since last time the dependency\r
249 // list file was generated, we need to check each file in the file list to\r
250 // see if any of them is changed or not. If anyone of them is newer than\r
251 // the dependency list file, MakeDeps.exe is needed to run again.\r
252 //\r
253 LineNumberReader lineReader = null;\r
254 FileReader fileReader = null;\r
255 boolean ret = false;\r
256 try {\r
257 fileReader = new FileReader(df);\r
258 lineReader = new LineNumberReader(fileReader);\r
259\r
260 String line = null;\r
261 int lines = 0;\r
262 while ((line = lineReader.readLine()) != null) {\r
263 //\r
264 // check file end flag "\t" to see if the .dep was generated correctly\r
265 // \r
266 if (line.equals("\t")) {\r
267 ret = true;\r
268 continue;\r
269 }\r
270 line = line.trim();\r
271 //\r
272 // skip empty line\r
273 // \r
274 if (line.length() == 0) {\r
275 continue;\r
276 }\r
277 ++lines;\r
278\r
279 //\r
280 // If a file cannot be found (moved or removed) or newer, regenerate the dep file\r
281 // \r
282 File sourceFile = new File(line);\r
283 if ((!sourceFile.exists()) || (FileTimeStamp.get(line) > depsFileTimeStamp)) {\r
284 EdkLog.log(this, EdkLog.EDK_VERBOSE, sourceFile.getPath() + " has been (re)moved or changed since last build!");\r
285 ret = false;\r
286 break;\r
287 }\r
288 }\r
289\r
290 //\r
291 // check if the .dep file is empty\r
292 // \r
293 if (lines == 0) {\r
294 EdkLog.log(this, EdkLog.EDK_VERBOSE, dfName + " is empty!");\r
295 ret = false;\r
296 }\r
297\r
298 lineReader.close();\r
299 fileReader.close();\r
300 } catch (IOException e) {\r
301 throw new BuildException(e.getMessage());\r
302 }\r
303\r
304 return ret;\r
305 }\r
306}\r
307\r