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
;
39 import org
.tianocore
.common
.logger
.EdkLog
;
42 Class MakeDeps is used to wrap MakeDeps.exe as an ANT task.
44 public class MakeDeps
extends Task
{
47 // private members, use set/get to access them
49 private static final String cmdName
= "MakeDeps";
50 private static final String target
= "dummy";
51 private String includePath
= null;
52 private String depsFile
= null;
53 private String subDir
= null;
54 private boolean quietMode
= true;
55 private boolean ignoreError
= true;
56 private String extraDeps
= "";
57 private List
<IncludePath
> includePathList
= new ArrayList
<IncludePath
>();
58 private List
<Input
> inputFileList
= new ArrayList
<Input
>();
65 The Standard execute method for ANT task. It will check if it's necessary
66 to generate the dependency list file. If no file is found or the dependency
67 is changed, it will compose the command line and call MakeDeps.exe to
68 generate the dependency list file.
70 @throws BuildException
72 public void execute() throws BuildException
{
74 /// check if the dependency list file is uptodate or not
80 Project prj
= this.getOwningTarget().getProject();
81 String toolPath
= prj
.getProperty("env.FRAMEWORK_TOOLS_PATH");
82 FrameworkLogger logger
= new FrameworkLogger(prj
, "makedeps");
83 EdkLog
.setLogLevel(prj
.getProperty("env.LOGLEVEL"));
84 EdkLog
.setLogger(logger
);
87 /// compose full tool path
89 if (toolPath
== null || toolPath
.length() == 0) {
90 toolPath
= "./" + cmdName
;
92 if (toolPath
.endsWith("/") || toolPath
.endsWith("\\")) {
93 toolPath
= toolPath
+ cmdName
;
95 toolPath
= toolPath
+ "/" + cmdName
;
100 /// compose tool arguments
102 StringBuffer args
= new StringBuffer(4096);
104 args
.append(" -ignorenotfound");
109 if (subDir
!= null && subDir
.length() > 0) {
115 /// if there's no source files, we can do nothing about dependency
117 if (inputFileList
.size() == 0) {
118 throw new BuildException("No source files specified to scan");
122 /// compose source file arguments
124 Iterator iterator
= inputFileList
.iterator();
125 while (iterator
.hasNext()) {
126 Input inputFile
= (Input
)iterator
.next();
127 String inputFileString
= cleanupPathName(inputFile
.getFile());
129 args
.append(inputFileString
);
133 /// compose search pathes argument
135 StringBuffer includePathArg
= new StringBuffer(4096);
136 if (includePath
!= null && includePath
.length() > 0) {
137 StringTokenizer pathTokens
= new StringTokenizer(includePath
, ";");
138 while (pathTokens
.hasMoreTokens()) {
139 String tmpPath
= pathTokens
.nextToken().trim();
140 if (tmpPath
.length() == 0) {
144 includePathArg
.append(" -i ");
145 includePathArg
.append(cleanupPathName(tmpPath
));
148 iterator
= includePathList
.iterator();
149 while (iterator
.hasNext()) {
150 IncludePath path
= (IncludePath
)iterator
.next();
151 includePathArg
.append(cleanupPathName(path
.getPath()));
153 args
.append(includePathArg
);
156 /// We don't need a real target. So just a "dummy" is given
158 args
.append(" -target dummy");
160 args
.append(cleanupPathName(depsFile
));
163 /// prepare to execute the tool
165 Commandline cmd
= new Commandline();
166 cmd
.setExecutable(toolPath
);
167 cmd
.createArgument().setLine(args
.toString());
169 LogStreamHandler streamHandler
= new LogStreamHandler(this, Project
.MSG_INFO
, Project
.MSG_WARN
);
170 Execute runner
= new Execute(streamHandler
, null);
172 runner
.setAntRun(prj
);
173 runner
.setCommandline(cmd
.getCommandline());
175 EdkLog
.log(EdkLog
.EDK_VERBOSE
, Commandline
.toString(cmd
.getCommandline()));
179 result
= runner
.execute();
180 } catch (IOException e
) {
181 throw new BuildException(e
.getMessage());
185 EdkLog
.log(EdkLog
.EDK_INFO
, "MakeDeps failed!");
189 // change the old DEP file format (makefile compatible) to just file list
191 throw new BuildException(depsFile
+ " was not generated!");
196 /// Remove any duplicated path separator or inconsistent path separator
198 private String
cleanupPathName(String path
) {
199 String separator
= "\\" + File
.separator
;
200 String duplicateSeparator
= separator
+ "{2}";
201 path
= Path
.translateFile(path
);
202 path
= path
.replaceAll(duplicateSeparator
, separator
);
207 Set method for "DepsFile" attribute
209 @param name The name of dependency list file
211 public void setDepsFile(String name
) {
212 depsFile
= cleanupPathName(name
);
216 Get method for "DepsFile" attribute
218 @returns The name of dependency list file
220 public String
getDepsFile() {
225 Set method for "IgnoreError" attribute
227 @param ignore flag to control error handling (true/false)
229 public void setIgnoreError(boolean ignore
) {
230 ignoreError
= ignore
;
234 Get method for "IgnoreError" attribute
236 @returns The value of current IgnoreError flag
238 public boolean getIgnoreError() {
243 Set method for "QuietMode" attribute
245 @param quiet flag to control the output information (true/false)
247 public void setQuietMode(boolean quiet
) {
252 Get method for "QuietMode" attribute
254 @returns value of current QuietMode flag
256 public boolean getQuietMode() {
261 Set method for "SubDir" attribute
263 @param dir The name of sub-directory in which source files will be scanned
265 public void setSubDir(String dir
) {
270 Get method for "SubDir" attribute
272 @returns The name of sub-directory
274 public String
getSubDir() {
279 Set method for "IncludePath" attribute
281 @param path The name of include path
283 public void setIncludePath(String path
) {
284 includePath
= cleanupPathName(path
);
288 Get method for "IncludePath" attribute
290 @returns The name of include path
292 public String
getIncludePath() {
297 Set method for "ExtraDeps" attribute
299 @param deps The name of dependency file specified separately
301 public void setExtraDeps(String deps
) {
306 Get method for "ExtraDeps" attribute
308 @returns The name of dependency file specified separately
310 public String
getExtraDeps () {
315 Add method for "IncludePath" nested element
317 @param path The IncludePath object from nested IncludePath type of element
319 public void addIncludepath(IncludePath path
) {
320 includePathList
.add(path
);
324 Add method for "Input" nested element
326 @param input The Input object from nested Input type of element
328 public void addInput(Input inputFile
) {
329 inputFileList
.add(inputFile
);
333 The original file generated by MakeDeps.exe is for makefile uses. The target
334 part (before :) is not useful for ANT. This method will do the removal.
336 @returns true if cleaned files is saved successfully
337 @returns false if error occurs in file I/O system
339 private boolean cleanup() {
340 File df
= new File(depsFile
);
346 LineNumberReader lineReader
= null;
347 FileReader fileReader
= null;
348 Set
<String
> lineSet
= new HashSet
<String
>(100); // used to remove duplicated lines
350 fileReader
= new FileReader(df
);
351 lineReader
= new LineNumberReader(fileReader
);
354 /// clean-up each line in deps file
357 while ((line
= lineReader
.readLine()) != null) {
358 String
[] filePath
= line
.split(" : ");
359 if (filePath
.length
== 2) {
361 /// keep the file name after ":"
363 lineSet
.add(cleanupPathName(filePath
[1]));
370 /// we may have explicitly specified dependency files
372 StringTokenizer fileTokens
= new StringTokenizer(extraDeps
, ";");
373 while (fileTokens
.hasMoreTokens()) {
374 lineSet
.add(cleanupPathName(fileTokens
.nextToken()));
378 /// compose the final file content
380 StringBuffer cleanedLines
= new StringBuffer(40960);
381 Iterator
<String
> it
= lineSet
.iterator();
382 while (it
.hasNext()) {
383 String filePath
= it
.next();
384 cleanedLines
.append(filePath
);
385 cleanedLines
.append("\n");
388 /// overwrite old dep file with new content
390 FileWriter fileWriter
= null;
391 fileWriter
= new FileWriter(df
);
392 fileWriter
.write(cleanedLines
.toString());
394 } catch (IOException e
) {
395 log (e
.getMessage());
402 Check if the dependency list file should be (re-)generated or not.
404 @returns true The dependency list file is uptodate. No re-generation is needed.
405 @returns false The dependency list file is outofdate. Re-generation is needed.
407 private boolean isUptodate() {
408 File df
= new File(depsFile
);
414 /// If the source file(s) is newer than dependency list file, we need to
415 /// re-generate the dependency list file
417 long depsFileTimeStamp
= df
.lastModified();
418 Iterator iterator
= inputFileList
.iterator();
419 while (iterator
.hasNext()) {
420 Input inputFile
= (Input
)iterator
.next();
421 File sf
= new File(inputFile
.getFile());
422 if (sf
.lastModified() > depsFileTimeStamp
) {
428 /// If the source files haven't been changed since last time the dependency
429 /// list file was generated, we need to check each file in the file list to
430 /// see if any of them is changed or not. If anyone of them is newer than
431 /// the dependency list file, MakeDeps.exe is needed to run again.
433 LineNumberReader lineReader
= null;
434 FileReader fileReader
= null;
437 fileReader
= new FileReader(df
);
438 lineReader
= new LineNumberReader(fileReader
);
441 while ((line
= lineReader
.readLine()) != null) {
442 File sourceFile
= new File(line
);
443 if (sourceFile
.lastModified() > depsFileTimeStamp
) {
450 } catch (IOException e
) {
451 log (e
.getMessage());