2 This file is to wrap MakeDeps.exe tool as ANT task, which is used to generate
3 dependency files for source code.
5 Copyright (c) 2006, Intel Corporation
6 All rights reserved. This program and the accompanying materials
7 are licensed and made available under the terms and conditions of the BSD License
8 which accompanies this distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
15 package org
.tianocore
.framework
.tasks
;
18 import java
.io
.FileReader
;
19 import java
.io
.FileWriter
;
20 import java
.io
.IOException
;
21 import java
.io
.LineNumberReader
;
22 import java
.util
.ArrayList
;
23 import java
.util
.HashSet
;
24 import java
.util
.Iterator
;
25 import java
.util
.List
;
27 import java
.util
.StringTokenizer
;
28 import java
.util
.regex
.Matcher
;
29 import java
.util
.regex
.Pattern
;
31 import org
.apache
.tools
.ant
.BuildException
;
32 import org
.apache
.tools
.ant
.Project
;
33 import org
.apache
.tools
.ant
.Task
;
34 import org
.apache
.tools
.ant
.taskdefs
.Execute
;
35 import org
.apache
.tools
.ant
.taskdefs
.LogStreamHandler
;
36 import org
.apache
.tools
.ant
.types
.Commandline
;
37 import org
.apache
.tools
.ant
.types
.Path
;
38 import org
.tianocore
.logger
.EdkLog
;
41 Class MakeDeps is used to wrap MakeDeps.exe as an ANT task.
43 public class MakeDeps
extends Task
{
46 // private members, use set/get to access them
48 private static final String cmdName
= "MakeDeps";
49 private static final String target
= "dummy";
50 private String includePath
= null;
51 private String depsFile
= null;
52 private String subDir
= null;
53 private boolean quietMode
= true;
54 private boolean ignoreError
= true;
55 private String extraDeps
= "";
56 private List
<IncludePath
> includePathList
= new ArrayList
<IncludePath
>();
57 private List
<Input
> inputFileList
= new ArrayList
<Input
>();
64 The Standard execute method for ANT task. It will check if it's necessary
65 to generate the dependency list file. If no file is found or the dependency
66 is changed, it will compose the command line and call MakeDeps.exe to
67 generate the dependency list file.
69 @throws BuildException
71 public void execute() throws BuildException
{
73 /// check if the dependency list file is uptodate or not
79 Project prj
= this.getOwningTarget().getProject();
80 String toolPath
= prj
.getProperty("env.FRAMEWORK_TOOLS_PATH");
81 FrameworkLogger logger
= new FrameworkLogger(prj
, "makedeps");
82 EdkLog
.setLogLevel(prj
.getProperty("env.LOGLEVEL"));
83 EdkLog
.setLogger(logger
);
86 /// compose full tool path
88 if (toolPath
== null || toolPath
.length() == 0) {
89 toolPath
= "./" + cmdName
;
91 if (toolPath
.endsWith("/") || toolPath
.endsWith("\\")) {
92 toolPath
= toolPath
+ cmdName
;
94 toolPath
= toolPath
+ "/" + cmdName
;
99 /// compose tool arguments
101 StringBuffer args
= new StringBuffer(4096);
103 args
.append(" -ignorenotfound");
108 if (subDir
!= null && subDir
.length() > 0) {
114 /// if there's no source files, we can do nothing about dependency
116 if (inputFileList
.size() == 0) {
117 throw new BuildException("No source files specified to scan");
121 /// compose source file arguments
123 Iterator iterator
= inputFileList
.iterator();
124 while (iterator
.hasNext()) {
125 Input inputFile
= (Input
)iterator
.next();
126 String inputFileString
= cleanupPathName(inputFile
.getFile());
128 args
.append(inputFileString
);
132 /// compose search pathes argument
134 StringBuffer includePathArg
= new StringBuffer(4096);
135 if (includePath
!= null && includePath
.length() > 0) {
136 StringTokenizer pathTokens
= new StringTokenizer(includePath
, ";");
137 while (pathTokens
.hasMoreTokens()) {
138 String tmpPath
= pathTokens
.nextToken().trim();
139 if (tmpPath
.length() == 0) {
143 includePathArg
.append(" -i ");
144 includePathArg
.append(cleanupPathName(tmpPath
));
147 iterator
= includePathList
.iterator();
148 while (iterator
.hasNext()) {
149 IncludePath path
= (IncludePath
)iterator
.next();
150 includePathArg
.append(cleanupPathName(path
.getPath()));
152 args
.append(includePathArg
);
155 /// We don't need a real target. So just a "dummy" is given
157 args
.append(" -target dummy");
159 args
.append(cleanupPathName(depsFile
));
162 /// prepare to execute the tool
164 Commandline cmd
= new Commandline();
165 cmd
.setExecutable(toolPath
);
166 cmd
.createArgument().setLine(args
.toString());
168 LogStreamHandler streamHandler
= new LogStreamHandler(this, Project
.MSG_INFO
, Project
.MSG_WARN
);
169 Execute runner
= new Execute(streamHandler
, null);
171 runner
.setAntRun(prj
);
172 runner
.setCommandline(cmd
.getCommandline());
174 EdkLog
.log(EdkLog
.EDK_VERBOSE
, Commandline
.toString(cmd
.getCommandline()));
178 result
= runner
.execute();
179 } catch (IOException e
) {
180 throw new BuildException(e
.getMessage());
184 EdkLog
.log(EdkLog
.EDK_INFO
, "MakeDeps failed!");
188 // change the old DEP file format (makefile compatible) to just file list
190 throw new BuildException(depsFile
+ " was not generated");
195 /// Remove any duplicated path separator or inconsistent path separator
197 private String
cleanupPathName(String path
) {
198 String separator
= "\\" + File
.separator
;
199 String duplicateSeparator
= separator
+ "{2}";
200 path
= Path
.translateFile(path
);
201 path
= path
.replaceAll(duplicateSeparator
, separator
);
206 Set method for "DepsFile" attribute
208 @param name The name of dependency list file
210 public void setDepsFile(String name
) {
211 depsFile
= cleanupPathName(name
);
215 Get method for "DepsFile" attribute
217 @returns The name of dependency list file
219 public String
getDepsFile() {
224 Set method for "IgnoreError" attribute
226 @param ignore flag to control error handling (true/false)
228 public void setIgnoreError(boolean ignore
) {
229 ignoreError
= ignore
;
233 Get method for "IgnoreError" attribute
235 @returns The value of current IgnoreError flag
237 public boolean getIgnoreError() {
242 Set method for "QuietMode" attribute
244 @param quiet flag to control the output information (true/false)
246 public void setQuietMode(boolean quiet
) {
251 Get method for "QuietMode" attribute
253 @returns value of current QuietMode flag
255 public boolean getQuietMode() {
260 Set method for "SubDir" attribute
262 @param dir The name of sub-directory in which source files will be scanned
264 public void setSubDir(String dir
) {
269 Get method for "SubDir" attribute
271 @returns The name of sub-directory
273 public String
getSubDir() {
278 Set method for "IncludePath" attribute
280 @param path The name of include path
282 public void setIncludePath(String path
) {
283 includePath
= cleanupPathName(path
);
287 Get method for "IncludePath" attribute
289 @returns The name of include path
291 public String
getIncludePath() {
296 Set method for "ExtraDeps" attribute
298 @param deps The name of dependency file specified separately
300 public void setExtraDeps(String deps
) {
305 Get method for "ExtraDeps" attribute
307 @returns The name of dependency file specified separately
309 public String
getExtraDeps () {
314 Add method for "IncludePath" nested element
316 @param path The IncludePath object from nested IncludePath type of element
318 public void addIncludepath(IncludePath path
) {
319 includePathList
.add(path
);
323 Add method for "Input" nested element
325 @param input The Input object from nested Input type of element
327 public void addInput(Input inputFile
) {
328 inputFileList
.add(inputFile
);
332 The original file generated by MakeDeps.exe is for makefile uses. The target
333 part (before :) is not useful for ANT. This method will do the removal.
335 @returns true if cleaned files is saved successfully
336 @returns false if error occurs in file I/O system
338 private boolean cleanup() {
339 File df
= new File(depsFile
);
345 LineNumberReader lineReader
= null;
346 FileReader fileReader
= null;
347 Set
<String
> lineSet
= new HashSet
<String
>(100); // used to remove duplicated lines
349 fileReader
= new FileReader(df
);
350 lineReader
= new LineNumberReader(fileReader
);
353 /// clean-up each line in deps file
356 while ((line
= lineReader
.readLine()) != null) {
357 Pattern pattern
= Pattern
.compile(target
+ "[ ]*:[ ]*(.+)");
358 Matcher matcher
= pattern
.matcher(line
);
360 while (matcher
.find()) {
362 /// keep the file name after ":"
364 String filePath
= line
.substring(matcher
.start(1), matcher
.end(1));
365 filePath
= cleanupPathName(filePath
);
366 lineSet
.add(filePath
);
373 /// we may have explicitly specified dependency files
375 StringTokenizer fileTokens
= new StringTokenizer(extraDeps
, ";");
376 while (fileTokens
.hasMoreTokens()) {
377 lineSet
.add(cleanupPathName(fileTokens
.nextToken()));
381 /// compose the final file content
383 StringBuffer cleanedLines
= new StringBuffer(40960);
384 Iterator
<String
> it
= lineSet
.iterator();
385 while (it
.hasNext()) {
386 String filePath
= it
.next();
387 cleanedLines
.append(filePath
);
388 cleanedLines
.append("\n");
391 /// overwrite old dep file with new content
393 FileWriter fileWriter
= null;
394 fileWriter
= new FileWriter(df
);
395 fileWriter
.write(cleanedLines
.toString());
397 } catch (IOException e
) {
398 log (e
.getMessage());
405 Check if the dependency list file should be (re-)generated or not.
407 @returns true The dependency list file is uptodate. No re-generation is needed.
408 @returns false The dependency list file is outofdate. Re-generation is needed.
410 private boolean isUptodate() {
411 File df
= new File(depsFile
);
417 /// If the source file(s) is newer than dependency list file, we need to
418 /// re-generate the dependency list file
420 long depsFileTimeStamp
= df
.lastModified();
421 Iterator iterator
= inputFileList
.iterator();
422 while (iterator
.hasNext()) {
423 Input inputFile
= (Input
)iterator
.next();
424 File sf
= new File(inputFile
.getFile());
425 if (sf
.lastModified() > depsFileTimeStamp
) {
431 /// If the source files haven't been changed since last time the dependency
432 /// list file was generated, we need to check each file in the file list to
433 /// see if any of them is changed or not. If anyone of them is newer than
434 /// the dependency list file, MakeDeps.exe is needed to run again.
436 LineNumberReader lineReader
= null;
437 FileReader fileReader
= null;
440 fileReader
= new FileReader(df
);
441 lineReader
= new LineNumberReader(fileReader
);
444 while ((line
= lineReader
.readLine()) != null) {
445 File sourceFile
= new File(line
);
446 if (sourceFile
.lastModified() > depsFileTimeStamp
) {
453 } catch (IOException e
) {
454 log (e
.getMessage());