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
;
40 Class MakeDeps is used to wrap MakeDeps.exe as an ANT task.
42 public class MakeDeps
extends Task
{
45 // private members, use set/get to access them
47 private static final String cmdName
= "MakeDeps";
48 private static final String target
= "dummy";
49 private String includePath
= null;
50 private String depsFile
= null;
51 private String subDir
= null;
52 private boolean quietMode
= true;
53 private boolean ignoreError
= true;
54 private String extraDeps
= "";
55 private List
<IncludePath
> includePathList
= new ArrayList
<IncludePath
>();
56 private List
<Input
> inputFileList
= new ArrayList
<Input
>();
63 The Standard execute method for ANT task. It will check if it's necessary
64 to generate the dependency list file. If no file is found or the dependency
65 is changed, it will compose the command line and call MakeDeps.exe to
66 generate the dependency list file.
68 @throws BuildException
70 public void execute() throws BuildException
{
72 /// check if the dependency list file is uptodate or not
78 Project prj
= this.getOwningTarget().getProject();
79 String toolPath
= prj
.getProperty("env.FRAMEWORK_TOOLS_PATH");
81 /// compose full tool path
83 if (toolPath
== null || toolPath
.length() == 0) {
84 toolPath
= "./" + cmdName
;
86 if (toolPath
.endsWith("/") || toolPath
.endsWith("\\")) {
87 toolPath
= toolPath
+ cmdName
;
89 toolPath
= toolPath
+ "/" + cmdName
;
94 /// compose tool arguments
96 StringBuffer args
= new StringBuffer(4096);
98 args
.append(" -ignorenotfound");
103 if (subDir
!= null && subDir
.length() > 0) {
109 /// if there's no source files, we can do nothing about dependency
111 if (inputFileList
.size() == 0) {
112 throw new BuildException("No source files specified to scan");
116 /// compose source file arguments
118 Iterator iterator
= inputFileList
.iterator();
119 while (iterator
.hasNext()) {
120 Input inputFile
= (Input
)iterator
.next();
122 args
.append(cleanupPathName(inputFile
.getFile()));
126 /// compose search pathes argument
128 StringBuffer includePathArg
= new StringBuffer(4096);
129 if (includePath
!= null && includePath
.length() > 0) {
130 StringTokenizer pathTokens
= new StringTokenizer(includePath
, ";");
131 while (pathTokens
.hasMoreTokens()) {
132 String tmpPath
= pathTokens
.nextToken().trim();
133 if (tmpPath
.length() == 0) {
137 includePathArg
.append(" -i ");
138 includePathArg
.append(cleanupPathName(tmpPath
));
141 iterator
= includePathList
.iterator();
142 while (iterator
.hasNext()) {
143 IncludePath path
= (IncludePath
)iterator
.next();
144 includePathArg
.append(cleanupPathName(path
.getPath()));
146 args
.append(includePathArg
);
149 /// We don't need a real target. So just a "dummy" is given
151 args
.append(" -target dummy");
153 args
.append(cleanupPathName(depsFile
));
156 /// prepare to execute the tool
158 Commandline cmd
= new Commandline();
159 cmd
.setExecutable(toolPath
);
160 cmd
.createArgument().setLine(args
.toString());
162 LogStreamHandler streamHandler
= new LogStreamHandler(this, Project
.MSG_INFO
, Project
.MSG_WARN
);
163 Execute runner
= new Execute(streamHandler
, null);
165 runner
.setAntRun(prj
);
166 runner
.setCommandline(cmd
.getCommandline());
170 result
= runner
.execute();
171 } catch (IOException e
) {
172 throw new BuildException(e
.getMessage());
176 log ("MakeDeps failed");
180 // change the old DEP file format (makefile compatible) to just file list
182 throw new BuildException(depsFile
+ " was not generated");
187 /// Remove any duplicated path separator or inconsistent path separator
189 private String
cleanupPathName(String path
) {
191 path
= (new File(path
)).getCanonicalPath();
192 } catch (IOException e
) {
193 String separator
= "\\" + File
.separator
;
194 String duplicateSeparator
= separator
+ "{2}";
195 path
= Path
.translateFile(path
);
196 path
= path
.replaceAll(duplicateSeparator
, separator
);
204 Set method for "DepsFile" attribute
206 @param name The name of dependency list file
208 public void setDepsFile(String name
) {
209 depsFile
= cleanupPathName(name
);
213 Get method for "DepsFile" attribute
215 @returns The name of dependency list file
217 public String
getDepsFile() {
222 Set method for "IgnoreError" attribute
224 @param ignore flag to control error handling (true/false)
226 public void setIgnoreError(boolean ignore
) {
227 ignoreError
= ignore
;
231 Get method for "IgnoreError" attribute
233 @returns The value of current IgnoreError flag
235 public boolean getIgnoreError() {
240 Set method for "QuietMode" attribute
242 @param quiet flag to control the output information (true/false)
244 public void setQuietMode(boolean quiet
) {
249 Get method for "QuietMode" attribute
251 @returns value of current QuietMode flag
253 public boolean getQuietMode() {
258 Set method for "SubDir" attribute
260 @param dir The name of sub-directory in which source files will be scanned
262 public void setSubDir(String dir
) {
267 Get method for "SubDir" attribute
269 @returns The name of sub-directory
271 public String
getSubDir() {
276 Set method for "IncludePath" attribute
278 @param path The name of include path
280 public void setIncludePath(String path
) {
281 includePath
= cleanupPathName(path
);
285 Get method for "IncludePath" attribute
287 @returns The name of include path
289 public String
getIncludePath() {
294 Set method for "ExtraDeps" attribute
296 @param deps The name of dependency file specified separately
298 public void setExtraDeps(String deps
) {
303 Get method for "ExtraDeps" attribute
305 @returns The name of dependency file specified separately
307 public String
getExtraDeps () {
312 Add method for "IncludePath" nested element
314 @param path The IncludePath object from nested IncludePath type of element
316 public void addIncludepath(IncludePath path
) {
317 includePathList
.add(path
);
321 Add method for "Input" nested element
323 @param input The Input object from nested Input type of element
325 public void addInput(Input inputFile
) {
326 inputFileList
.add(inputFile
);
330 The original file generated by MakeDeps.exe is for makefile uses. The target
331 part (before :) is not useful for ANT. This method will do the removal.
333 @returns true if cleaned files is saved successfully
334 @returns false if error occurs in file I/O system
336 private boolean cleanup() {
337 File df
= new File(depsFile
);
343 LineNumberReader lineReader
= null;
344 FileReader fileReader
= null;
345 Set
<String
> lineSet
= new HashSet
<String
>(100); // used to remove duplicated lines
347 fileReader
= new FileReader(df
);
348 lineReader
= new LineNumberReader(fileReader
);
351 /// clean-up each line in deps file
354 while ((line
= lineReader
.readLine()) != null) {
355 Pattern pattern
= Pattern
.compile(target
+ "[ ]*:[ ]*(.+)");
356 Matcher matcher
= pattern
.matcher(line
);
358 while (matcher
.find()) {
360 /// keep the file name after ":"
362 String filePath
= line
.substring(matcher
.start(1), matcher
.end(1));
363 filePath
= cleanupPathName(filePath
);
364 lineSet
.add(filePath
);
371 /// we may have explicitly specified dependency files
373 StringTokenizer fileTokens
= new StringTokenizer(extraDeps
, ";");
374 while (fileTokens
.hasMoreTokens()) {
375 lineSet
.add(cleanupPathName(fileTokens
.nextToken()));
379 /// compose the final file content
381 StringBuffer cleanedLines
= new StringBuffer(40960);
382 Iterator
<String
> it
= lineSet
.iterator();
383 while (it
.hasNext()) {
384 String filePath
= it
.next();
385 cleanedLines
.append(filePath
);
386 cleanedLines
.append("\n");
389 /// overwrite old dep file with new content
391 FileWriter fileWriter
= null;
392 fileWriter
= new FileWriter(df
);
393 fileWriter
.write(cleanedLines
.toString());
395 } catch (IOException e
) {
396 log (e
.getMessage());
403 Check if the dependency list file should be (re-)generated or not.
405 @returns true The dependency list file is uptodate. No re-generation is needed.
406 @returns false The dependency list file is outofdate. Re-generation is needed.
408 private boolean isUptodate() {
409 File df
= new File(depsFile
);
415 /// If the source file(s) is newer than dependency list file, we need to
416 /// re-generate the dependency list file
418 long depsFileTimeStamp
= df
.lastModified();
419 Iterator iterator
= inputFileList
.iterator();
420 while (iterator
.hasNext()) {
421 Input inputFile
= (Input
)iterator
.next();
422 File sf
= new File(inputFile
.getFile());
423 if (sf
.lastModified() > depsFileTimeStamp
) {
429 /// If the source files haven't been changed since last time the dependency
430 /// list file was generated, we need to check each file in the file list to
431 /// see if any of them is changed or not. If anyone of them is newer than
432 /// the dependency list file, MakeDeps.exe is needed to run again.
434 LineNumberReader lineReader
= null;
435 FileReader fileReader
= null;
438 fileReader
= new FileReader(df
);
439 lineReader
= new LineNumberReader(fileReader
);
442 while ((line
= lineReader
.readLine()) != null) {
443 File sourceFile
= new File(line
);
444 if (sourceFile
.lastModified() > depsFileTimeStamp
) {
451 } catch (IOException e
) {
452 log (e
.getMessage());