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
.IOException
;
20 import java
.io
.LineNumberReader
;
21 import java
.util
.ArrayList
;
22 import java
.util
.Iterator
;
23 import java
.util
.List
;
25 import org
.apache
.tools
.ant
.BuildException
;
26 import org
.apache
.tools
.ant
.Project
;
27 import org
.apache
.tools
.ant
.Task
;
28 import org
.apache
.tools
.ant
.taskdefs
.Execute
;
29 import org
.apache
.tools
.ant
.taskdefs
.LogStreamHandler
;
30 import org
.apache
.tools
.ant
.types
.Commandline
;
31 import org
.apache
.tools
.ant
.types
.Path
;
33 import org
.tianocore
.common
.logger
.EdkLog
;
36 Class MakeDeps is used to wrap MakeDeps.exe as an ANT task.
38 public class MakeDeps
extends Task
{
41 // private members, use set/get to access them
43 private static final String cmdName
= "MakeDeps";
44 private String depsFile
= null;
45 private String subDir
= null;
46 private boolean quietMode
= true;
47 private boolean ignoreError
= true;
48 private String extraDeps
= "";
49 private List
<IncludePath
> includePathList
= new ArrayList
<IncludePath
>();
50 private List
<Input
> inputFileList
= new ArrayList
<Input
>();
57 The Standard execute method for ANT task. It will check if it's necessary
58 to generate the dependency list file. If no file is found or the dependency
59 is changed, it will compose the command line and call MakeDeps.exe to
60 generate the dependency list file.
62 @throws BuildException
64 public void execute() throws BuildException
{
66 /// check if the dependency list file is uptodate or not
72 Project prj
= this.getOwningTarget().getProject();
73 String toolPath
= prj
.getProperty("env.FRAMEWORK_TOOLS_PATH");
76 /// compose full tool path
78 if (toolPath
== null || toolPath
.length() == 0) {
81 if (toolPath
.endsWith("/") || toolPath
.endsWith("\\")) {
82 toolPath
= toolPath
+ cmdName
;
84 toolPath
= toolPath
+ File
.separator
+ cmdName
;
89 /// compose tool arguments
91 StringBuffer args
= new StringBuffer(4096);
93 args
.append(" -ignorenotfound ");
98 if (subDir
!= null && subDir
.length() > 0) {
104 /// if there's no source files, we can do nothing about dependency
106 if (inputFileList
.size() == 0) {
107 throw new BuildException("No source files specified to scan");
111 /// compose source file arguments
113 for (int i
= 0, listLength
= inputFileList
.size(); i
< listLength
; ++i
) {
114 args
.append(inputFileList
.get(i
).toString());
117 for (int i
= 0, listLength
= includePathList
.size(); i
< listLength
; ++i
) {
118 args
.append(includePathList
.get(i
).toString());
122 /// We don't need a real target. So just a "dummy" is given
124 args
.append(" -target dummy");
126 args
.append(depsFile
);
129 /// prepare to execute the tool
131 Commandline cmd
= new Commandline();
132 cmd
.setExecutable(toolPath
);
133 cmd
.createArgument().setLine(args
.toString());
135 LogStreamHandler streamHandler
= new LogStreamHandler(this, Project
.MSG_INFO
, Project
.MSG_WARN
);
136 Execute runner
= new Execute(streamHandler
, null);
138 runner
.setAntRun(prj
);
139 runner
.setCommandline(cmd
.getCommandline());
141 EdkLog
.log(this, EdkLog
.EDK_VERBOSE
, Commandline
.toString(cmd
.getCommandline()));
145 result
= runner
.execute();
146 } catch (IOException e
) {
147 throw new BuildException(e
.getMessage());
151 EdkLog
.log(this, EdkLog
.EDK_INFO
, "MakeDeps failed!");
152 throw new BuildException("MakeDeps: failed to generate dependency file!");
157 /// Remove any duplicated path separator or inconsistent path separator
159 private String
cleanupPathName(String path
) {
160 String separator
= "\\" + File
.separator
;
161 String duplicateSeparator
= separator
+ "{2}";
162 path
= Path
.translateFile(path
);
163 path
= path
.replaceAll(duplicateSeparator
, separator
);
168 Set method for "DepsFile" attribute
170 @param name The name of dependency list file
172 public void setDepsFile(String name
) {
173 depsFile
= cleanupPathName(name
);
177 Get method for "DepsFile" attribute
179 @returns The name of dependency list file
181 public String
getDepsFile() {
186 Set method for "IgnoreError" attribute
188 @param ignore flag to control error handling (true/false)
190 public void setIgnoreError(boolean ignore
) {
191 ignoreError
= ignore
;
195 Get method for "IgnoreError" attribute
197 @returns The value of current IgnoreError flag
199 public boolean getIgnoreError() {
204 Set method for "QuietMode" attribute
206 @param quiet flag to control the output information (true/false)
208 public void setQuietMode(boolean quiet
) {
213 Get method for "QuietMode" attribute
215 @returns value of current QuietMode flag
217 public boolean getQuietMode() {
222 Set method for "SubDir" attribute
224 @param dir The name of sub-directory in which source files will be scanned
226 public void setSubDir(String dir
) {
227 subDir
= cleanupPathName(dir
);
231 Get method for "SubDir" attribute
233 @returns The name of sub-directory
235 public String
getSubDir() {
240 Set method for "ExtraDeps" attribute
242 @param deps The name of dependency file specified separately
244 public void setExtraDeps(String deps
) {
245 extraDeps
= cleanupPathName(deps
);
249 Get method for "ExtraDeps" attribute
251 @returns The name of dependency file specified separately
253 public String
getExtraDeps () {
258 Add method for "IncludePath" nested element
260 @param path The IncludePath object from nested IncludePath type of element
262 public void addIncludepath(IncludePath path
) {
263 includePathList
.add(path
);
267 Add method for "Input" nested element
269 @param input The Input object from nested Input type of element
271 public void addInput(Input inputFile
) {
272 inputFileList
.add(inputFile
);
276 Check if the dependency list file should be (re-)generated or not.
278 @returns true The dependency list file is uptodate. No re-generation is needed.
279 @returns false The dependency list file is outofdate. Re-generation is needed.
281 private boolean isUptodate() {
282 File df
= new File(depsFile
);
284 EdkLog
.log(this, EdkLog
.EDK_VERBOSE
, depsFile
+ " doesn't exist!");
289 // If the source file(s) is newer than dependency list file, we need to
290 // re-generate the dependency list file
292 long depsFileTimeStamp
= df
.lastModified();
293 Iterator
<Input
> iterator
= (Iterator
<Input
>)inputFileList
.iterator();
294 while (iterator
.hasNext()) {
295 Input inputFile
= iterator
.next();
296 List
<String
> fileList
= inputFile
.getNameList();
297 for (int i
= 0, length
= fileList
.size(); i
< length
; ++i
) {
298 File sf
= new File(fileList
.get(i
));
299 if (sf
.lastModified() > depsFileTimeStamp
) {
300 EdkLog
.log(this, EdkLog
.EDK_VERBOSE
, sf
.getPath() + " has been changed since last build!");
307 // If the source files haven't been changed since last time the dependency
308 // list file was generated, we need to check each file in the file list to
309 // see if any of them is changed or not. If anyone of them is newer than
310 // the dependency list file, MakeDeps.exe is needed to run again.
312 LineNumberReader lineReader
= null;
313 FileReader fileReader
= null;
316 fileReader
= new FileReader(df
);
317 lineReader
= new LineNumberReader(fileReader
);
321 while ((line
= lineReader
.readLine()) != null) {
323 // check file end flag "\t" to see if the .dep was generated correctly
325 if (line
.equals("\t")) {
333 if (line
.length() == 0) {
339 // If a file cannot be found (moved or removed) or newer, regenerate the dep file
341 File sourceFile
= new File(line
);
342 if ((!sourceFile
.exists()) || (sourceFile
.lastModified() > depsFileTimeStamp
)) {
343 EdkLog
.log(this, EdkLog
.EDK_VERBOSE
, sourceFile
.getPath() + " has been (re)moved or changed since last build!");
350 // check if the .dep file is empty
353 EdkLog
.log(this, EdkLog
.EDK_VERBOSE
, depsFile
+ " is empty!");
359 } catch (IOException e
) {
360 throw new BuildException(e
.getMessage());