Modify code according suggestion from code review meeting.
[mirror_edk2.git] / Tools / Source / FrameworkTasks / org / tianocore / framework / tasks / MakeDeps.java
CommitLineData
878ddf1f 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
878ddf1f 17import java.io.File;\r
18import java.io.FileReader;\r
19import java.io.FileWriter;\r
20import java.io.IOException;\r
21import java.io.LineNumberReader;\r
22import java.util.ArrayList;\r
196ad8d7 23import java.util.HashSet;\r
878ddf1f 24import java.util.Iterator;\r
25import java.util.List;\r
196ad8d7 26import java.util.Set;\r
878ddf1f 27import java.util.StringTokenizer;\r
878ddf1f 28\r
196ad8d7 29import org.apache.tools.ant.BuildException;\r
30import org.apache.tools.ant.Project;\r
31import org.apache.tools.ant.Task;\r
32import org.apache.tools.ant.taskdefs.Execute;\r
33import org.apache.tools.ant.taskdefs.LogStreamHandler;\r
34import org.apache.tools.ant.types.Commandline;\r
35import org.apache.tools.ant.types.Path;\r
ff225cbb 36\r
37import org.tianocore.common.logger.EdkLog;\r
196ad8d7 38\r
878ddf1f 39/**\r
40 Class MakeDeps is used to wrap MakeDeps.exe as an ANT task.\r
41 **/\r
42public class MakeDeps extends Task {\r
43\r
44 //\r
45 // private members, use set/get to access them\r
46 //\r
47 private static final String cmdName = "MakeDeps";\r
878ddf1f 48 private String includePath = null;\r
49 private String depsFile = null;\r
50 private String subDir = null;\r
51 private boolean quietMode = true;\r
52 private boolean ignoreError = true;\r
53 private String extraDeps = "";\r
54 private List<IncludePath> includePathList = new ArrayList<IncludePath>();\r
55 private List<Input> inputFileList = new ArrayList<Input>();\r
56\r
57 public MakeDeps() {\r
58\r
59 }\r
60\r
61 /**\r
62 The Standard execute method for ANT task. It will check if it's necessary\r
63 to generate the dependency list file. If no file is found or the dependency\r
64 is changed, it will compose the command line and call MakeDeps.exe to\r
65 generate the dependency list file.\r
66\r
67 @throws BuildException\r
68 **/\r
69 public void execute() throws BuildException {\r
70 ///\r
71 /// check if the dependency list file is uptodate or not\r
72 ///\r
73 if (isUptodate()) {\r
74 return;\r
75 }\r
76\r
77 Project prj = this.getOwningTarget().getProject();\r
2da8968b 78 String toolPath = prj.getProperty("env.FRAMEWORK_TOOLS_PATH");\r
219e2247 79 FrameworkLogger logger = new FrameworkLogger(prj, "makedeps");\r
80 EdkLog.setLogLevel(prj.getProperty("env.LOGLEVEL"));\r
81 EdkLog.setLogger(logger);\r
82\r
878ddf1f 83 ///\r
84 /// compose full tool path\r
85 ///\r
86 if (toolPath == null || toolPath.length() == 0) {\r
87 toolPath = "./" + cmdName;\r
88 } else {\r
89 if (toolPath.endsWith("/") || toolPath.endsWith("\\")) {\r
90 toolPath = toolPath + cmdName;\r
91 } else {\r
92 toolPath = toolPath + "/" + cmdName;\r
93 }\r
94 }\r
95\r
96 ///\r
97 /// compose tool arguments\r
98 ///\r
99 StringBuffer args = new StringBuffer(4096);\r
100 if (ignoreError) {\r
101 args.append(" -ignorenotfound");\r
102 }\r
103 if (quietMode) {\r
104 args.append(" -q");\r
105 }\r
106 if (subDir != null && subDir.length() > 0) {\r
107 args.append(" -s ");\r
108 args.append(subDir);\r
109 }\r
110\r
111 ///\r
112 /// if there's no source files, we can do nothing about dependency\r
ff225cbb 113 ///\r
878ddf1f 114 if (inputFileList.size() == 0) {\r
115 throw new BuildException("No source files specified to scan");\r
116 }\r
117\r
118 ///\r
119 /// compose source file arguments\r
120 ///\r
121 Iterator iterator = inputFileList.iterator();\r
122 while (iterator.hasNext()) {\r
123 Input inputFile = (Input)iterator.next();\r
219e2247 124 String inputFileString = cleanupPathName(inputFile.getFile());\r
878ddf1f 125 args.append(" -f ");\r
219e2247 126 args.append(inputFileString);\r
878ddf1f 127 }\r
128\r
129 ///\r
130 /// compose search pathes argument\r
131 ///\r
132 StringBuffer includePathArg = new StringBuffer(4096);\r
133 if (includePath != null && includePath.length() > 0) {\r
134 StringTokenizer pathTokens = new StringTokenizer(includePath, ";");\r
135 while (pathTokens.hasMoreTokens()) {\r
136 String tmpPath = pathTokens.nextToken().trim();\r
137 if (tmpPath.length() == 0) {\r
138 continue;\r
139 }\r
140\r
141 includePathArg.append(" -i ");\r
142 includePathArg.append(cleanupPathName(tmpPath));\r
143 }\r
144 }\r
145 iterator = includePathList.iterator();\r
146 while (iterator.hasNext()) {\r
147 IncludePath path = (IncludePath)iterator.next();\r
148 includePathArg.append(cleanupPathName(path.getPath()));\r
149 }\r
150 args.append(includePathArg);\r
151\r
152 ///\r
153 /// We don't need a real target. So just a "dummy" is given\r
154 ///\r
155 args.append(" -target dummy");\r
156 args.append(" -o ");\r
157 args.append(cleanupPathName(depsFile));\r
158\r
159 ///\r
160 /// prepare to execute the tool\r
161 ///\r
162 Commandline cmd = new Commandline();\r
163 cmd.setExecutable(toolPath);\r
164 cmd.createArgument().setLine(args.toString());\r
165\r
166 LogStreamHandler streamHandler = new LogStreamHandler(this, Project.MSG_INFO, Project.MSG_WARN);\r
167 Execute runner = new Execute(streamHandler, null);\r
168\r
169 runner.setAntRun(prj);\r
170 runner.setCommandline(cmd.getCommandline());\r
171\r
219e2247 172 EdkLog.log(EdkLog.EDK_VERBOSE, Commandline.toString(cmd.getCommandline()));\r
219e2247 173\r
878ddf1f 174 int result = 0;\r
175 try {\r
176 result = runner.execute();\r
177 } catch (IOException e) {\r
178 throw new BuildException(e.getMessage());\r
179 }\r
180\r
181 if (result != 0) {\r
219e2247 182 EdkLog.log(EdkLog.EDK_INFO, "MakeDeps failed!");\r
878ddf1f 183 return;\r
184 }\r
878ddf1f 185 }\r
186\r
187 ///\r
188 /// Remove any duplicated path separator or inconsistent path separator\r
189 ///\r
190 private String cleanupPathName(String path) {\r
52cbbdbc 191 String separator = "\\" + File.separator;\r
192 String duplicateSeparator = separator + "{2}";\r
193 path = Path.translateFile(path);\r
194 path = path.replaceAll(duplicateSeparator, separator);\r
878ddf1f 195 return path;\r
196 }\r
197\r
198 /**\r
199 Set method for "DepsFile" attribute\r
200\r
201 @param name The name of dependency list file\r
202 **/\r
203 public void setDepsFile(String name) {\r
204 depsFile = cleanupPathName(name);\r
205 }\r
206\r
207 /**\r
208 Get method for "DepsFile" attribute\r
209\r
210 @returns The name of dependency list file\r
211 **/\r
212 public String getDepsFile() {\r
213 return depsFile;\r
214 }\r
215\r
216 /**\r
217 Set method for "IgnoreError" attribute\r
218\r
219 @param ignore flag to control error handling (true/false)\r
220 **/\r
221 public void setIgnoreError(boolean ignore) {\r
222 ignoreError = ignore;\r
223 }\r
224\r
225 /**\r
226 Get method for "IgnoreError" attribute\r
227\r
228 @returns The value of current IgnoreError flag\r
229 **/\r
230 public boolean getIgnoreError() {\r
231 return ignoreError;\r
232 }\r
233\r
234 /**\r
235 Set method for "QuietMode" attribute\r
236\r
237 @param quiet flag to control the output information (true/false)\r
238 **/\r
239 public void setQuietMode(boolean quiet) {\r
240 quietMode = quiet;\r
241 }\r
242\r
243 /**\r
244 Get method for "QuietMode" attribute\r
245\r
246 @returns value of current QuietMode flag\r
247 **/\r
248 public boolean getQuietMode() {\r
249 return quietMode;\r
250 }\r
251\r
252 /**\r
253 Set method for "SubDir" attribute\r
254\r
255 @param dir The name of sub-directory in which source files will be scanned\r
256 **/\r
257 public void setSubDir(String dir) {\r
258 subDir = dir;\r
259 }\r
260\r
261 /**\r
262 Get method for "SubDir" attribute\r
263\r
264 @returns The name of sub-directory\r
265 **/\r
266 public String getSubDir() {\r
267 return subDir;\r
268 }\r
269\r
270 /**\r
271 Set method for "IncludePath" attribute\r
272\r
273 @param path The name of include path\r
274 **/\r
275 public void setIncludePath(String path) {\r
276 includePath = cleanupPathName(path);\r
277 }\r
278\r
279 /**\r
280 Get method for "IncludePath" attribute\r
281\r
282 @returns The name of include path\r
283 **/\r
284 public String getIncludePath() {\r
285 return includePath;\r
286 }\r
287\r
288 /**\r
289 Set method for "ExtraDeps" attribute\r
290\r
291 @param deps The name of dependency file specified separately\r
292 **/\r
293 public void setExtraDeps(String deps) {\r
294 extraDeps = deps;\r
295 }\r
296\r
297 /**\r
298 Get method for "ExtraDeps" attribute\r
299\r
300 @returns The name of dependency file specified separately\r
301 **/\r
302 public String getExtraDeps () {\r
303 return extraDeps;\r
304 }\r
305\r
306 /**\r
307 Add method for "IncludePath" nested element\r
308\r
309 @param path The IncludePath object from nested IncludePath type of element\r
310 **/\r
311 public void addIncludepath(IncludePath path) {\r
312 includePathList.add(path);\r
313 }\r
314\r
315 /**\r
316 Add method for "Input" nested element\r
317\r
318 @param input The Input object from nested Input type of element\r
319 **/\r
320 public void addInput(Input inputFile) {\r
321 inputFileList.add(inputFile);\r
322 }\r
323\r
878ddf1f 324 /**\r
325 Check if the dependency list file should be (re-)generated or not.\r
326\r
327 @returns true The dependency list file is uptodate. No re-generation is needed.\r
328 @returns false The dependency list file is outofdate. Re-generation is needed.\r
329 **/\r
330 private boolean isUptodate() {\r
331 File df = new File(depsFile);\r
332 if (!df.exists()) {\r
333 return false;\r
334 }\r
335\r
336 ///\r
337 /// If the source file(s) is newer than dependency list file, we need to\r
338 /// re-generate the dependency list file\r
339 ///\r
340 long depsFileTimeStamp = df.lastModified();\r
341 Iterator iterator = inputFileList.iterator();\r
342 while (iterator.hasNext()) {\r
343 Input inputFile = (Input)iterator.next();\r
344 File sf = new File(inputFile.getFile());\r
345 if (sf.lastModified() > depsFileTimeStamp) {\r
346 return false;\r
347 }\r
348 }\r
349\r
350 ///\r
351 /// If the source files haven't been changed since last time the dependency\r
352 /// list file was generated, we need to check each file in the file list to\r
353 /// see if any of them is changed or not. If anyone of them is newer than\r
354 /// the dependency list file, MakeDeps.exe is needed to run again.\r
355 ///\r
356 LineNumberReader lineReader = null;\r
357 FileReader fileReader = null;\r
358 boolean ret = true;\r
359 try {\r
360 fileReader = new FileReader(df);\r
361 lineReader = new LineNumberReader(fileReader);\r
362\r
363 String line = null;\r
364 while ((line = lineReader.readLine()) != null) {\r
365 File sourceFile = new File(line);\r
1f08e795 366 //\r
367 // If a file cannot be found (moved or removed) or newer, regenerate the dep file\r
368 // \r
369 if ((!sourceFile.exists()) || (sourceFile.lastModified() > depsFileTimeStamp)) {\r
878ddf1f 370 ret = false;\r
371 break;\r
372 }\r
373 }\r
374 lineReader.close();\r
375 fileReader.close();\r
376 } catch (IOException e) {\r
377 log (e.getMessage());\r
378 }\r
379\r
380 return ret;\r
381 }\r
382}\r
383\r