]> git.proxmox.com Git - mirror_edk2.git/blame - Tools/Source/FrameworkTasks/org/tianocore/framework/tasks/MakeDeps.java
1. Wrap text by word when showing a message box
[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
28import java.util.regex.Matcher;\r
29import java.util.regex.Pattern;\r
30\r
196ad8d7 31import org.apache.tools.ant.BuildException;\r
32import org.apache.tools.ant.Project;\r
33import org.apache.tools.ant.Task;\r
34import org.apache.tools.ant.taskdefs.Execute;\r
35import org.apache.tools.ant.taskdefs.LogStreamHandler;\r
36import org.apache.tools.ant.types.Commandline;\r
37import org.apache.tools.ant.types.Path;\r
219e2247 38import org.tianocore.logger.EdkLog;\r
196ad8d7 39\r
878ddf1f 40/**\r
41 Class MakeDeps is used to wrap MakeDeps.exe as an ANT task.\r
42 **/\r
43public class MakeDeps extends Task {\r
44\r
45 //\r
46 // private members, use set/get to access them\r
47 //\r
48 private static final String cmdName = "MakeDeps";\r
49 private static final String target = "dummy";\r
50 private String includePath = null;\r
51 private String depsFile = null;\r
52 private String subDir = null;\r
53 private boolean quietMode = true;\r
54 private boolean ignoreError = true;\r
55 private String extraDeps = "";\r
56 private List<IncludePath> includePathList = new ArrayList<IncludePath>();\r
57 private List<Input> inputFileList = new ArrayList<Input>();\r
58\r
59 public MakeDeps() {\r
60\r
61 }\r
62\r
63 /**\r
64 The Standard execute method for ANT task. It will check if it's necessary\r
65 to generate the dependency list file. If no file is found or the dependency\r
66 is changed, it will compose the command line and call MakeDeps.exe to\r
67 generate the dependency list file.\r
68\r
69 @throws BuildException\r
70 **/\r
71 public void execute() throws BuildException {\r
72 ///\r
73 /// check if the dependency list file is uptodate or not\r
74 ///\r
75 if (isUptodate()) {\r
76 return;\r
77 }\r
78\r
79 Project prj = this.getOwningTarget().getProject();\r
2da8968b 80 String toolPath = prj.getProperty("env.FRAMEWORK_TOOLS_PATH");\r
219e2247 81 FrameworkLogger logger = new FrameworkLogger(prj, "makedeps");\r
82 EdkLog.setLogLevel(prj.getProperty("env.LOGLEVEL"));\r
83 EdkLog.setLogger(logger);\r
84\r
878ddf1f 85 ///\r
86 /// compose full tool path\r
87 ///\r
88 if (toolPath == null || toolPath.length() == 0) {\r
89 toolPath = "./" + cmdName;\r
90 } else {\r
91 if (toolPath.endsWith("/") || toolPath.endsWith("\\")) {\r
92 toolPath = toolPath + cmdName;\r
93 } else {\r
94 toolPath = toolPath + "/" + cmdName;\r
95 }\r
96 }\r
97\r
98 ///\r
99 /// compose tool arguments\r
100 ///\r
101 StringBuffer args = new StringBuffer(4096);\r
102 if (ignoreError) {\r
103 args.append(" -ignorenotfound");\r
104 }\r
105 if (quietMode) {\r
106 args.append(" -q");\r
107 }\r
108 if (subDir != null && subDir.length() > 0) {\r
109 args.append(" -s ");\r
110 args.append(subDir);\r
111 }\r
112\r
113 ///\r
114 /// if there's no source files, we can do nothing about dependency\r
115 /// \r
116 if (inputFileList.size() == 0) {\r
117 throw new BuildException("No source files specified to scan");\r
118 }\r
119\r
120 ///\r
121 /// compose source file arguments\r
122 ///\r
123 Iterator iterator = inputFileList.iterator();\r
124 while (iterator.hasNext()) {\r
125 Input inputFile = (Input)iterator.next();\r
219e2247 126 String inputFileString = cleanupPathName(inputFile.getFile());\r
878ddf1f 127 args.append(" -f ");\r
219e2247 128 args.append(inputFileString);\r
878ddf1f 129 }\r
130\r
131 ///\r
132 /// compose search pathes argument\r
133 ///\r
134 StringBuffer includePathArg = new StringBuffer(4096);\r
135 if (includePath != null && includePath.length() > 0) {\r
136 StringTokenizer pathTokens = new StringTokenizer(includePath, ";");\r
137 while (pathTokens.hasMoreTokens()) {\r
138 String tmpPath = pathTokens.nextToken().trim();\r
139 if (tmpPath.length() == 0) {\r
140 continue;\r
141 }\r
142\r
143 includePathArg.append(" -i ");\r
144 includePathArg.append(cleanupPathName(tmpPath));\r
145 }\r
146 }\r
147 iterator = includePathList.iterator();\r
148 while (iterator.hasNext()) {\r
149 IncludePath path = (IncludePath)iterator.next();\r
150 includePathArg.append(cleanupPathName(path.getPath()));\r
151 }\r
152 args.append(includePathArg);\r
153\r
154 ///\r
155 /// We don't need a real target. So just a "dummy" is given\r
156 ///\r
157 args.append(" -target dummy");\r
158 args.append(" -o ");\r
159 args.append(cleanupPathName(depsFile));\r
160\r
161 ///\r
162 /// prepare to execute the tool\r
163 ///\r
164 Commandline cmd = new Commandline();\r
165 cmd.setExecutable(toolPath);\r
166 cmd.createArgument().setLine(args.toString());\r
167\r
168 LogStreamHandler streamHandler = new LogStreamHandler(this, Project.MSG_INFO, Project.MSG_WARN);\r
169 Execute runner = new Execute(streamHandler, null);\r
170\r
171 runner.setAntRun(prj);\r
172 runner.setCommandline(cmd.getCommandline());\r
173\r
219e2247 174 EdkLog.log(EdkLog.EDK_VERBOSE, Commandline.toString(cmd.getCommandline()));\r
219e2247 175\r
878ddf1f 176 int result = 0;\r
177 try {\r
178 result = runner.execute();\r
179 } catch (IOException e) {\r
180 throw new BuildException(e.getMessage());\r
181 }\r
182\r
183 if (result != 0) {\r
219e2247 184 EdkLog.log(EdkLog.EDK_INFO, "MakeDeps failed!");\r
878ddf1f 185 return;\r
186 }\r
187\r
188 // change the old DEP file format (makefile compatible) to just file list\r
189 if (!cleanup()) {\r
190 throw new BuildException(depsFile + " was not generated");\r
191 }\r
192 }\r
193\r
194 ///\r
195 /// Remove any duplicated path separator or inconsistent path separator\r
196 ///\r
197 private String cleanupPathName(String path) {\r
196ad8d7 198 try {\r
199 path = (new File(path)).getCanonicalPath();\r
200 } catch (IOException e) {\r
201 String separator = "\\" + File.separator;\r
202 String duplicateSeparator = separator + "{2}";\r
203 path = Path.translateFile(path);\r
204 path = path.replaceAll(duplicateSeparator, separator);\r
205 return path;\r
206 }\r
878ddf1f 207\r
208 return path;\r
209 }\r
210\r
211 /**\r
212 Set method for "DepsFile" attribute\r
213\r
214 @param name The name of dependency list file\r
215 **/\r
216 public void setDepsFile(String name) {\r
217 depsFile = cleanupPathName(name);\r
218 }\r
219\r
220 /**\r
221 Get method for "DepsFile" attribute\r
222\r
223 @returns The name of dependency list file\r
224 **/\r
225 public String getDepsFile() {\r
226 return depsFile;\r
227 }\r
228\r
229 /**\r
230 Set method for "IgnoreError" attribute\r
231\r
232 @param ignore flag to control error handling (true/false)\r
233 **/\r
234 public void setIgnoreError(boolean ignore) {\r
235 ignoreError = ignore;\r
236 }\r
237\r
238 /**\r
239 Get method for "IgnoreError" attribute\r
240\r
241 @returns The value of current IgnoreError flag\r
242 **/\r
243 public boolean getIgnoreError() {\r
244 return ignoreError;\r
245 }\r
246\r
247 /**\r
248 Set method for "QuietMode" attribute\r
249\r
250 @param quiet flag to control the output information (true/false)\r
251 **/\r
252 public void setQuietMode(boolean quiet) {\r
253 quietMode = quiet;\r
254 }\r
255\r
256 /**\r
257 Get method for "QuietMode" attribute\r
258\r
259 @returns value of current QuietMode flag\r
260 **/\r
261 public boolean getQuietMode() {\r
262 return quietMode;\r
263 }\r
264\r
265 /**\r
266 Set method for "SubDir" attribute\r
267\r
268 @param dir The name of sub-directory in which source files will be scanned\r
269 **/\r
270 public void setSubDir(String dir) {\r
271 subDir = dir;\r
272 }\r
273\r
274 /**\r
275 Get method for "SubDir" attribute\r
276\r
277 @returns The name of sub-directory\r
278 **/\r
279 public String getSubDir() {\r
280 return subDir;\r
281 }\r
282\r
283 /**\r
284 Set method for "IncludePath" attribute\r
285\r
286 @param path The name of include path\r
287 **/\r
288 public void setIncludePath(String path) {\r
289 includePath = cleanupPathName(path);\r
290 }\r
291\r
292 /**\r
293 Get method for "IncludePath" attribute\r
294\r
295 @returns The name of include path\r
296 **/\r
297 public String getIncludePath() {\r
298 return includePath;\r
299 }\r
300\r
301 /**\r
302 Set method for "ExtraDeps" attribute\r
303\r
304 @param deps The name of dependency file specified separately\r
305 **/\r
306 public void setExtraDeps(String deps) {\r
307 extraDeps = deps;\r
308 }\r
309\r
310 /**\r
311 Get method for "ExtraDeps" attribute\r
312\r
313 @returns The name of dependency file specified separately\r
314 **/\r
315 public String getExtraDeps () {\r
316 return extraDeps;\r
317 }\r
318\r
319 /**\r
320 Add method for "IncludePath" nested element\r
321\r
322 @param path The IncludePath object from nested IncludePath type of element\r
323 **/\r
324 public void addIncludepath(IncludePath path) {\r
325 includePathList.add(path);\r
326 }\r
327\r
328 /**\r
329 Add method for "Input" nested element\r
330\r
331 @param input The Input object from nested Input type of element\r
332 **/\r
333 public void addInput(Input inputFile) {\r
334 inputFileList.add(inputFile);\r
335 }\r
336\r
337 /**\r
338 The original file generated by MakeDeps.exe is for makefile uses. The target\r
339 part (before :) is not useful for ANT. This method will do the removal.\r
340\r
341 @returns true if cleaned files is saved successfully\r
342 @returns false if error occurs in file I/O system\r
343 **/\r
344 private boolean cleanup() {\r
345 File df = new File(depsFile);\r
346\r
347 if (!df.exists()) {\r
348 return false;\r
349 }\r
350\r
351 LineNumberReader lineReader = null;\r
352 FileReader fileReader = null;\r
196ad8d7 353 Set<String> lineSet = new HashSet<String>(100); // used to remove duplicated lines\r
878ddf1f 354 try {\r
355 fileReader = new FileReader(df);\r
356 lineReader = new LineNumberReader(fileReader);\r
357\r
358 ///\r
359 /// clean-up each line in deps file\r
360 //\r
361 String line = null;\r
878ddf1f 362 while ((line = lineReader.readLine()) != null) {\r
363 Pattern pattern = Pattern.compile(target + "[ ]*:[ ]*(.+)");\r
364 Matcher matcher = pattern.matcher(line);\r
365\r
366 while (matcher.find()) {\r
367 ///\r
368 /// keep the file name after ":"\r
369 ///\r
370 String filePath = line.substring(matcher.start(1), matcher.end(1));\r
371 filePath = cleanupPathName(filePath);\r
196ad8d7 372 lineSet.add(filePath);\r
878ddf1f 373 }\r
374 }\r
375 lineReader.close();\r
376 fileReader.close();\r
377\r
378 ///\r
379 /// we may have explicitly specified dependency files\r
380 ///\r
381 StringTokenizer fileTokens = new StringTokenizer(extraDeps, ";");\r
382 while (fileTokens.hasMoreTokens()) {\r
196ad8d7 383 lineSet.add(cleanupPathName(fileTokens.nextToken()));\r
878ddf1f 384 }\r
385\r
196ad8d7 386 ///\r
387 /// compose the final file content\r
388 /// \r
389 StringBuffer cleanedLines = new StringBuffer(40960);\r
390 Iterator<String> it = lineSet.iterator();\r
391 while (it.hasNext()) {\r
392 String filePath = it.next();\r
393 cleanedLines.append(filePath);\r
394 cleanedLines.append("\n");\r
395 }\r
878ddf1f 396 ///\r
397 /// overwrite old dep file with new content\r
398 ///\r
399 FileWriter fileWriter = null;\r
400 fileWriter = new FileWriter(df);\r
401 fileWriter.write(cleanedLines.toString());\r
402 fileWriter.close();\r
403 } catch (IOException e) {\r
404 log (e.getMessage());\r
405 }\r
406\r
407 return true;\r
408 }\r
409\r
410 /**\r
411 Check if the dependency list file should be (re-)generated or not.\r
412\r
413 @returns true The dependency list file is uptodate. No re-generation is needed.\r
414 @returns false The dependency list file is outofdate. Re-generation is needed.\r
415 **/\r
416 private boolean isUptodate() {\r
417 File df = new File(depsFile);\r
418 if (!df.exists()) {\r
419 return false;\r
420 }\r
421\r
422 ///\r
423 /// If the source file(s) is newer than dependency list file, we need to\r
424 /// re-generate the dependency list file\r
425 ///\r
426 long depsFileTimeStamp = df.lastModified();\r
427 Iterator iterator = inputFileList.iterator();\r
428 while (iterator.hasNext()) {\r
429 Input inputFile = (Input)iterator.next();\r
430 File sf = new File(inputFile.getFile());\r
431 if (sf.lastModified() > depsFileTimeStamp) {\r
432 return false;\r
433 }\r
434 }\r
435\r
436 ///\r
437 /// If the source files haven't been changed since last time the dependency\r
438 /// list file was generated, we need to check each file in the file list to\r
439 /// see if any of them is changed or not. If anyone of them is newer than\r
440 /// the dependency list file, MakeDeps.exe is needed to run again.\r
441 ///\r
442 LineNumberReader lineReader = null;\r
443 FileReader fileReader = null;\r
444 boolean ret = true;\r
445 try {\r
446 fileReader = new FileReader(df);\r
447 lineReader = new LineNumberReader(fileReader);\r
448\r
449 String line = null;\r
450 while ((line = lineReader.readLine()) != null) {\r
451 File sourceFile = new File(line);\r
452 if (sourceFile.lastModified() > depsFileTimeStamp) {\r
453 ret = false;\r
454 break;\r
455 }\r
456 }\r
457 lineReader.close();\r
458 fileReader.close();\r
459 } catch (IOException e) {\r
460 log (e.getMessage());\r
461 }\r
462\r
463 return ret;\r
464 }\r
465}\r
466\r