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
;
17 import org
.apache
.tools
.ant
.BuildException
;
18 import org
.apache
.tools
.ant
.Project
;
19 import org
.apache
.tools
.ant
.Task
;
20 import org
.apache
.tools
.ant
.taskdefs
.Execute
;
21 import org
.apache
.tools
.ant
.taskdefs
.LogStreamHandler
;
22 import org
.apache
.tools
.ant
.types
.Commandline
;
23 import org
.apache
.tools
.ant
.types
.Path
;
26 import java
.io
.FileReader
;
27 import java
.io
.FileWriter
;
28 import java
.io
.IOException
;
29 import java
.io
.LineNumberReader
;
30 import java
.util
.ArrayList
;
31 import java
.util
.Iterator
;
32 import java
.util
.List
;
33 import java
.util
.StringTokenizer
;
34 import java
.util
.regex
.Matcher
;
35 import java
.util
.regex
.Pattern
;
38 Class MakeDeps is used to wrap MakeDeps.exe as an ANT task.
40 public class MakeDeps
extends Task
{
43 // private members, use set/get to access them
45 private static final String cmdName
= "MakeDeps";
46 private static final String target
= "dummy";
47 private String includePath
= null;
48 private String depsFile
= null;
49 private String subDir
= null;
50 private boolean quietMode
= true;
51 private boolean ignoreError
= true;
52 private String extraDeps
= "";
53 private List
<IncludePath
> includePathList
= new ArrayList
<IncludePath
>();
54 private List
<Input
> inputFileList
= new ArrayList
<Input
>();
61 The Standard execute method for ANT task. It will check if it's necessary
62 to generate the dependency list file. If no file is found or the dependency
63 is changed, it will compose the command line and call MakeDeps.exe to
64 generate the dependency list file.
66 @throws BuildException
68 public void execute() throws BuildException
{
70 /// check if the dependency list file is uptodate or not
76 Project prj
= this.getOwningTarget().getProject();
77 String toolPath
= prj
.getProperty("env.FRAMEWORK_TOOLS_PATH");
79 /// compose full tool path
81 if (toolPath
== null || toolPath
.length() == 0) {
82 toolPath
= "./" + cmdName
;
84 if (toolPath
.endsWith("/") || toolPath
.endsWith("\\")) {
85 toolPath
= toolPath
+ cmdName
;
87 toolPath
= toolPath
+ "/" + cmdName
;
92 /// compose tool arguments
94 StringBuffer args
= new StringBuffer(4096);
96 args
.append(" -ignorenotfound");
101 if (subDir
!= null && subDir
.length() > 0) {
107 /// if there's no source files, we can do nothing about dependency
109 if (inputFileList
.size() == 0) {
110 throw new BuildException("No source files specified to scan");
114 /// compose source file arguments
116 Iterator iterator
= inputFileList
.iterator();
117 while (iterator
.hasNext()) {
118 Input inputFile
= (Input
)iterator
.next();
120 args
.append(cleanupPathName(inputFile
.getFile()));
124 /// compose search pathes argument
126 StringBuffer includePathArg
= new StringBuffer(4096);
127 if (includePath
!= null && includePath
.length() > 0) {
128 StringTokenizer pathTokens
= new StringTokenizer(includePath
, ";");
129 while (pathTokens
.hasMoreTokens()) {
130 String tmpPath
= pathTokens
.nextToken().trim();
131 if (tmpPath
.length() == 0) {
135 includePathArg
.append(" -i ");
136 includePathArg
.append(cleanupPathName(tmpPath
));
139 iterator
= includePathList
.iterator();
140 while (iterator
.hasNext()) {
141 IncludePath path
= (IncludePath
)iterator
.next();
142 includePathArg
.append(cleanupPathName(path
.getPath()));
144 args
.append(includePathArg
);
147 /// We don't need a real target. So just a "dummy" is given
149 args
.append(" -target dummy");
151 args
.append(cleanupPathName(depsFile
));
154 /// prepare to execute the tool
156 Commandline cmd
= new Commandline();
157 cmd
.setExecutable(toolPath
);
158 cmd
.createArgument().setLine(args
.toString());
160 LogStreamHandler streamHandler
= new LogStreamHandler(this, Project
.MSG_INFO
, Project
.MSG_WARN
);
161 Execute runner
= new Execute(streamHandler
, null);
163 runner
.setAntRun(prj
);
164 runner
.setCommandline(cmd
.getCommandline());
168 result
= runner
.execute();
169 } catch (IOException e
) {
170 throw new BuildException(e
.getMessage());
174 log ("MakeDeps failed");
178 // change the old DEP file format (makefile compatible) to just file list
180 throw new BuildException(depsFile
+ " was not generated");
185 /// Remove any duplicated path separator or inconsistent path separator
187 private String
cleanupPathName(String path
) {
188 String separator
= "\\" + File
.separator
;
189 String duplicateSeparator
= separator
+ "{2}";
190 path
= Path
.translateFile(path
);
191 path
= path
.replaceAll(duplicateSeparator
, separator
);
197 Set method for "DepsFile" attribute
199 @param name The name of dependency list file
201 public void setDepsFile(String name
) {
202 depsFile
= cleanupPathName(name
);
206 Get method for "DepsFile" attribute
208 @returns The name of dependency list file
210 public String
getDepsFile() {
215 Set method for "IgnoreError" attribute
217 @param ignore flag to control error handling (true/false)
219 public void setIgnoreError(boolean ignore
) {
220 ignoreError
= ignore
;
224 Get method for "IgnoreError" attribute
226 @returns The value of current IgnoreError flag
228 public boolean getIgnoreError() {
233 Set method for "QuietMode" attribute
235 @param quiet flag to control the output information (true/false)
237 public void setQuietMode(boolean quiet
) {
242 Get method for "QuietMode" attribute
244 @returns value of current QuietMode flag
246 public boolean getQuietMode() {
251 Set method for "SubDir" attribute
253 @param dir The name of sub-directory in which source files will be scanned
255 public void setSubDir(String dir
) {
260 Get method for "SubDir" attribute
262 @returns The name of sub-directory
264 public String
getSubDir() {
269 Set method for "IncludePath" attribute
271 @param path The name of include path
273 public void setIncludePath(String path
) {
274 includePath
= cleanupPathName(path
);
278 Get method for "IncludePath" attribute
280 @returns The name of include path
282 public String
getIncludePath() {
287 Set method for "ExtraDeps" attribute
289 @param deps The name of dependency file specified separately
291 public void setExtraDeps(String deps
) {
296 Get method for "ExtraDeps" attribute
298 @returns The name of dependency file specified separately
300 public String
getExtraDeps () {
305 Add method for "IncludePath" nested element
307 @param path The IncludePath object from nested IncludePath type of element
309 public void addIncludepath(IncludePath path
) {
310 includePathList
.add(path
);
314 Add method for "Input" nested element
316 @param input The Input object from nested Input type of element
318 public void addInput(Input inputFile
) {
319 inputFileList
.add(inputFile
);
323 The original file generated by MakeDeps.exe is for makefile uses. The target
324 part (before :) is not useful for ANT. This method will do the removal.
326 @returns true if cleaned files is saved successfully
327 @returns false if error occurs in file I/O system
329 private boolean cleanup() {
330 File df
= new File(depsFile
);
336 LineNumberReader lineReader
= null;
337 FileReader fileReader
= null;
339 fileReader
= new FileReader(df
);
340 lineReader
= new LineNumberReader(fileReader
);
343 /// clean-up each line in deps file
346 StringBuffer cleanedLines
= new StringBuffer(4096);
347 while ((line
= lineReader
.readLine()) != null) {
348 Pattern pattern
= Pattern
.compile(target
+ "[ ]*:[ ]*(.+)");
349 Matcher matcher
= pattern
.matcher(line
);
351 while (matcher
.find()) {
353 /// keep the file name after ":"
355 String filePath
= line
.substring(matcher
.start(1), matcher
.end(1));
356 filePath
= cleanupPathName(filePath
);
357 cleanedLines
.append(filePath
);
358 cleanedLines
.append("\n");
365 /// we may have explicitly specified dependency files
367 StringTokenizer fileTokens
= new StringTokenizer(extraDeps
, ";");
368 while (fileTokens
.hasMoreTokens()) {
369 cleanedLines
.append(cleanupPathName(fileTokens
.nextToken()));
370 cleanedLines
.append("\n");
374 /// overwrite old dep file with new content
376 FileWriter fileWriter
= null;
377 fileWriter
= new FileWriter(df
);
378 fileWriter
.write(cleanedLines
.toString());
380 } catch (IOException e
) {
381 log (e
.getMessage());
388 Check if the dependency list file should be (re-)generated or not.
390 @returns true The dependency list file is uptodate. No re-generation is needed.
391 @returns false The dependency list file is outofdate. Re-generation is needed.
393 private boolean isUptodate() {
394 File df
= new File(depsFile
);
400 /// If the source file(s) is newer than dependency list file, we need to
401 /// re-generate the dependency list file
403 long depsFileTimeStamp
= df
.lastModified();
404 Iterator iterator
= inputFileList
.iterator();
405 while (iterator
.hasNext()) {
406 Input inputFile
= (Input
)iterator
.next();
407 File sf
= new File(inputFile
.getFile());
408 if (sf
.lastModified() > depsFileTimeStamp
) {
414 /// If the source files haven't been changed since last time the dependency
415 /// list file was generated, we need to check each file in the file list to
416 /// see if any of them is changed or not. If anyone of them is newer than
417 /// the dependency list file, MakeDeps.exe is needed to run again.
419 LineNumberReader lineReader
= null;
420 FileReader fileReader
= null;
423 fileReader
= new FileReader(df
);
424 lineReader
= new LineNumberReader(fileReader
);
427 while ((line
= lineReader
.readLine()) != null) {
428 File sourceFile
= new File(line
);
429 if (sourceFile
.lastModified() > depsFileTimeStamp
) {
436 } catch (IOException e
) {
437 log (e
.getMessage());