]> git.proxmox.com Git - mirror_edk2.git/blob - Tools/Source/FrameworkTasks/org/tianocore/framework/tasks/MakeDeps.java
Fixed the issue caused by introducing INCLUDE_PATH property;
[mirror_edk2.git] / Tools / Source / FrameworkTasks / org / tianocore / framework / tasks / MakeDeps.java
1 /** @file
2 This file is to wrap MakeDeps.exe tool as ANT task, which is used to generate
3 dependency files for source code.
4
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
10
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.
13
14 **/
15 package org.tianocore.framework.tasks;
16
17 import java.io.File;
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;
26 import java.util.Set;
27 import java.util.StringTokenizer;
28
29 import org.apache.tools.ant.BuildException;
30 import org.apache.tools.ant.Project;
31 import org.apache.tools.ant.Task;
32 import org.apache.tools.ant.taskdefs.Execute;
33 import org.apache.tools.ant.taskdefs.LogStreamHandler;
34 import org.apache.tools.ant.types.Commandline;
35 import org.apache.tools.ant.types.Path;
36
37 import org.tianocore.common.logger.EdkLog;
38
39 /**
40 Class MakeDeps is used to wrap MakeDeps.exe as an ANT task.
41 **/
42 public class MakeDeps extends Task {
43
44 //
45 // private members, use set/get to access them
46 //
47 private static final String cmdName = "MakeDeps";
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>();
55
56 public MakeDeps() {
57
58 }
59
60 /**
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.
65
66 @throws BuildException
67 **/
68 public void execute() throws BuildException {
69 ///
70 /// check if the dependency list file is uptodate or not
71 ///
72 if (isUptodate()) {
73 return;
74 }
75
76 Project prj = this.getOwningTarget().getProject();
77 String toolPath = prj.getProperty("env.FRAMEWORK_TOOLS_PATH");
78 FrameworkLogger logger = new FrameworkLogger(prj, "makedeps");
79 EdkLog.setLogLevel(prj.getProperty("env.LOGLEVEL"));
80 EdkLog.setLogger(logger);
81
82 ///
83 /// compose full tool path
84 ///
85 if (toolPath == null || toolPath.length() == 0) {
86 toolPath = cmdName;
87 } else {
88 if (toolPath.endsWith("/") || toolPath.endsWith("\\")) {
89 toolPath = toolPath + cmdName;
90 } else {
91 toolPath = toolPath + File.separator + cmdName;
92 }
93 }
94
95 ///
96 /// compose tool arguments
97 ///
98 StringBuffer args = new StringBuffer(4096);
99 if (ignoreError) {
100 args.append(" -ignorenotfound ");
101 }
102 if (quietMode) {
103 args.append(" -q ");
104 }
105 if (subDir != null && subDir.length() > 0) {
106 args.append(" -s ");
107 args.append(subDir);
108 }
109
110 ///
111 /// if there's no source files, we can do nothing about dependency
112 ///
113 if (inputFileList.size() == 0) {
114 throw new BuildException("No source files specified to scan");
115 }
116
117 ///
118 /// compose source file arguments
119 ///
120 for (int i = 0, listLength = inputFileList.size(); i < listLength; ++i) {
121 args.append(inputFileList.get(i).toString());
122 }
123
124 for (int i = 0, listLength = includePathList.size(); i < listLength; ++i) {
125 args.append(includePathList.get(i).toString());
126 }
127
128 ///
129 /// We don't need a real target. So just a "dummy" is given
130 ///
131 args.append(" -target dummy");
132 args.append(" -o ");
133 args.append(depsFile);
134
135 ///
136 /// prepare to execute the tool
137 ///
138 Commandline cmd = new Commandline();
139 cmd.setExecutable(toolPath);
140 cmd.createArgument().setLine(args.toString());
141
142 LogStreamHandler streamHandler = new LogStreamHandler(this, Project.MSG_INFO, Project.MSG_WARN);
143 Execute runner = new Execute(streamHandler, null);
144
145 runner.setAntRun(prj);
146 runner.setCommandline(cmd.getCommandline());
147
148 EdkLog.log(EdkLog.EDK_VERBOSE, Commandline.toString(cmd.getCommandline()));
149
150 int result = 0;
151 try {
152 result = runner.execute();
153 } catch (IOException e) {
154 throw new BuildException(e.getMessage());
155 }
156
157 if (result != 0) {
158 EdkLog.log(EdkLog.EDK_INFO, "MakeDeps failed!");
159 throw new BuildException("MakeDeps: failed to generate dependency file!");
160 }
161 }
162
163 ///
164 /// Remove any duplicated path separator or inconsistent path separator
165 ///
166 private String cleanupPathName(String path) {
167 String separator = "\\" + File.separator;
168 String duplicateSeparator = separator + "{2}";
169 path = Path.translateFile(path);
170 path = path.replaceAll(duplicateSeparator, separator);
171 return path;
172 }
173
174 /**
175 Set method for "DepsFile" attribute
176
177 @param name The name of dependency list file
178 **/
179 public void setDepsFile(String name) {
180 depsFile = cleanupPathName(name);
181 }
182
183 /**
184 Get method for "DepsFile" attribute
185
186 @returns The name of dependency list file
187 **/
188 public String getDepsFile() {
189 return depsFile;
190 }
191
192 /**
193 Set method for "IgnoreError" attribute
194
195 @param ignore flag to control error handling (true/false)
196 **/
197 public void setIgnoreError(boolean ignore) {
198 ignoreError = ignore;
199 }
200
201 /**
202 Get method for "IgnoreError" attribute
203
204 @returns The value of current IgnoreError flag
205 **/
206 public boolean getIgnoreError() {
207 return ignoreError;
208 }
209
210 /**
211 Set method for "QuietMode" attribute
212
213 @param quiet flag to control the output information (true/false)
214 **/
215 public void setQuietMode(boolean quiet) {
216 quietMode = quiet;
217 }
218
219 /**
220 Get method for "QuietMode" attribute
221
222 @returns value of current QuietMode flag
223 **/
224 public boolean getQuietMode() {
225 return quietMode;
226 }
227
228 /**
229 Set method for "SubDir" attribute
230
231 @param dir The name of sub-directory in which source files will be scanned
232 **/
233 public void setSubDir(String dir) {
234 subDir = cleanupPathName(dir);
235 }
236
237 /**
238 Get method for "SubDir" attribute
239
240 @returns The name of sub-directory
241 **/
242 public String getSubDir() {
243 return subDir;
244 }
245
246 /**
247 Set method for "ExtraDeps" attribute
248
249 @param deps The name of dependency file specified separately
250 **/
251 public void setExtraDeps(String deps) {
252 extraDeps = cleanupPathName(deps);
253 }
254
255 /**
256 Get method for "ExtraDeps" attribute
257
258 @returns The name of dependency file specified separately
259 **/
260 public String getExtraDeps () {
261 return extraDeps;
262 }
263
264 /**
265 Add method for "IncludePath" nested element
266
267 @param path The IncludePath object from nested IncludePath type of element
268 **/
269 public void addIncludepath(IncludePath path) {
270 includePathList.add(path);
271 }
272
273 /**
274 Add method for "Input" nested element
275
276 @param input The Input object from nested Input type of element
277 **/
278 public void addInput(Input inputFile) {
279 inputFileList.add(inputFile);
280 }
281
282 /**
283 Check if the dependency list file should be (re-)generated or not.
284
285 @returns true The dependency list file is uptodate. No re-generation is needed.
286 @returns false The dependency list file is outofdate. Re-generation is needed.
287 **/
288 private boolean isUptodate() {
289 File df = new File(depsFile);
290 if (!df.exists()) {
291 return false;
292 }
293
294 //
295 // If the source file(s) is newer than dependency list file, we need to
296 // re-generate the dependency list file
297 //
298 long depsFileTimeStamp = df.lastModified();
299 Iterator<Input> iterator = (Iterator<Input>)inputFileList.iterator();
300 while (iterator.hasNext()) {
301 Input inputFile = iterator.next();
302 List<String> fileList = inputFile.getNameList();
303 for (int i = 0, length = fileList.size(); i < length; ++i) {
304 File sf = new File(fileList.get(i));
305 if (sf.lastModified() > depsFileTimeStamp) {
306 return false;
307 }
308 }
309 }
310
311 //
312 // If the source files haven't been changed since last time the dependency
313 // list file was generated, we need to check each file in the file list to
314 // see if any of them is changed or not. If anyone of them is newer than
315 // the dependency list file, MakeDeps.exe is needed to run again.
316 //
317 LineNumberReader lineReader = null;
318 FileReader fileReader = null;
319 boolean ret = true;
320 try {
321 fileReader = new FileReader(df);
322 lineReader = new LineNumberReader(fileReader);
323
324 String line = null;
325 while ((line = lineReader.readLine()) != null) {
326 File sourceFile = new File(line);
327 //
328 // If a file cannot be found (moved or removed) or newer, regenerate the dep file
329 //
330 if ((!sourceFile.exists()) || (sourceFile.lastModified() > depsFileTimeStamp)) {
331 ret = false;
332 break;
333 }
334 }
335 lineReader.close();
336 fileReader.close();
337 } catch (IOException e) {
338 log (e.getMessage());
339 }
340
341 return ret;
342 }
343 }
344