]> git.proxmox.com Git - mirror_edk2.git/blob - Tools/Source/FrameworkTasks/org/tianocore/framework/tasks/MakeDeps.java
moved exception and logger classes to org.tianocore.common package
[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 import java.util.regex.Matcher;
29 import java.util.regex.Pattern;
30
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;
38
39 import org.tianocore.common.logger.EdkLog;
40
41 /**
42 Class MakeDeps is used to wrap MakeDeps.exe as an ANT task.
43 **/
44 public class MakeDeps extends Task {
45
46 //
47 // private members, use set/get to access them
48 //
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>();
59
60 public MakeDeps() {
61
62 }
63
64 /**
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.
69
70 @throws BuildException
71 **/
72 public void execute() throws BuildException {
73 ///
74 /// check if the dependency list file is uptodate or not
75 ///
76 if (isUptodate()) {
77 return;
78 }
79
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);
85
86 ///
87 /// compose full tool path
88 ///
89 if (toolPath == null || toolPath.length() == 0) {
90 toolPath = "./" + cmdName;
91 } else {
92 if (toolPath.endsWith("/") || toolPath.endsWith("\\")) {
93 toolPath = toolPath + cmdName;
94 } else {
95 toolPath = toolPath + "/" + cmdName;
96 }
97 }
98
99 ///
100 /// compose tool arguments
101 ///
102 StringBuffer args = new StringBuffer(4096);
103 if (ignoreError) {
104 args.append(" -ignorenotfound");
105 }
106 if (quietMode) {
107 args.append(" -q");
108 }
109 if (subDir != null && subDir.length() > 0) {
110 args.append(" -s ");
111 args.append(subDir);
112 }
113
114 ///
115 /// if there's no source files, we can do nothing about dependency
116 ///
117 if (inputFileList.size() == 0) {
118 throw new BuildException("No source files specified to scan");
119 }
120
121 ///
122 /// compose source file arguments
123 ///
124 Iterator iterator = inputFileList.iterator();
125 while (iterator.hasNext()) {
126 Input inputFile = (Input)iterator.next();
127 String inputFileString = cleanupPathName(inputFile.getFile());
128 args.append(" -f ");
129 args.append(inputFileString);
130 }
131
132 ///
133 /// compose search pathes argument
134 ///
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) {
141 continue;
142 }
143
144 includePathArg.append(" -i ");
145 includePathArg.append(cleanupPathName(tmpPath));
146 }
147 }
148 iterator = includePathList.iterator();
149 while (iterator.hasNext()) {
150 IncludePath path = (IncludePath)iterator.next();
151 includePathArg.append(cleanupPathName(path.getPath()));
152 }
153 args.append(includePathArg);
154
155 ///
156 /// We don't need a real target. So just a "dummy" is given
157 ///
158 args.append(" -target dummy");
159 args.append(" -o ");
160 args.append(cleanupPathName(depsFile));
161
162 ///
163 /// prepare to execute the tool
164 ///
165 Commandline cmd = new Commandline();
166 cmd.setExecutable(toolPath);
167 cmd.createArgument().setLine(args.toString());
168
169 LogStreamHandler streamHandler = new LogStreamHandler(this, Project.MSG_INFO, Project.MSG_WARN);
170 Execute runner = new Execute(streamHandler, null);
171
172 runner.setAntRun(prj);
173 runner.setCommandline(cmd.getCommandline());
174
175 EdkLog.log(EdkLog.EDK_VERBOSE, Commandline.toString(cmd.getCommandline()));
176
177 int result = 0;
178 try {
179 result = runner.execute();
180 } catch (IOException e) {
181 throw new BuildException(e.getMessage());
182 }
183
184 if (result != 0) {
185 EdkLog.log(EdkLog.EDK_INFO, "MakeDeps failed!");
186 return;
187 }
188
189 // change the old DEP file format (makefile compatible) to just file list
190 if (!cleanup()) {
191 throw new BuildException(depsFile + " was not generated!");
192 }
193 }
194
195 ///
196 /// Remove any duplicated path separator or inconsistent path separator
197 ///
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);
203 return path;
204 }
205
206 /**
207 Set method for "DepsFile" attribute
208
209 @param name The name of dependency list file
210 **/
211 public void setDepsFile(String name) {
212 depsFile = cleanupPathName(name);
213 }
214
215 /**
216 Get method for "DepsFile" attribute
217
218 @returns The name of dependency list file
219 **/
220 public String getDepsFile() {
221 return depsFile;
222 }
223
224 /**
225 Set method for "IgnoreError" attribute
226
227 @param ignore flag to control error handling (true/false)
228 **/
229 public void setIgnoreError(boolean ignore) {
230 ignoreError = ignore;
231 }
232
233 /**
234 Get method for "IgnoreError" attribute
235
236 @returns The value of current IgnoreError flag
237 **/
238 public boolean getIgnoreError() {
239 return ignoreError;
240 }
241
242 /**
243 Set method for "QuietMode" attribute
244
245 @param quiet flag to control the output information (true/false)
246 **/
247 public void setQuietMode(boolean quiet) {
248 quietMode = quiet;
249 }
250
251 /**
252 Get method for "QuietMode" attribute
253
254 @returns value of current QuietMode flag
255 **/
256 public boolean getQuietMode() {
257 return quietMode;
258 }
259
260 /**
261 Set method for "SubDir" attribute
262
263 @param dir The name of sub-directory in which source files will be scanned
264 **/
265 public void setSubDir(String dir) {
266 subDir = dir;
267 }
268
269 /**
270 Get method for "SubDir" attribute
271
272 @returns The name of sub-directory
273 **/
274 public String getSubDir() {
275 return subDir;
276 }
277
278 /**
279 Set method for "IncludePath" attribute
280
281 @param path The name of include path
282 **/
283 public void setIncludePath(String path) {
284 includePath = cleanupPathName(path);
285 }
286
287 /**
288 Get method for "IncludePath" attribute
289
290 @returns The name of include path
291 **/
292 public String getIncludePath() {
293 return includePath;
294 }
295
296 /**
297 Set method for "ExtraDeps" attribute
298
299 @param deps The name of dependency file specified separately
300 **/
301 public void setExtraDeps(String deps) {
302 extraDeps = deps;
303 }
304
305 /**
306 Get method for "ExtraDeps" attribute
307
308 @returns The name of dependency file specified separately
309 **/
310 public String getExtraDeps () {
311 return extraDeps;
312 }
313
314 /**
315 Add method for "IncludePath" nested element
316
317 @param path The IncludePath object from nested IncludePath type of element
318 **/
319 public void addIncludepath(IncludePath path) {
320 includePathList.add(path);
321 }
322
323 /**
324 Add method for "Input" nested element
325
326 @param input The Input object from nested Input type of element
327 **/
328 public void addInput(Input inputFile) {
329 inputFileList.add(inputFile);
330 }
331
332 /**
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.
335
336 @returns true if cleaned files is saved successfully
337 @returns false if error occurs in file I/O system
338 **/
339 private boolean cleanup() {
340 File df = new File(depsFile);
341
342 if (!df.exists()) {
343 return false;
344 }
345
346 LineNumberReader lineReader = null;
347 FileReader fileReader = null;
348 Set<String> lineSet = new HashSet<String>(100); // used to remove duplicated lines
349 try {
350 fileReader = new FileReader(df);
351 lineReader = new LineNumberReader(fileReader);
352
353 ///
354 /// clean-up each line in deps file
355 //
356 String line = null;
357 while ((line = lineReader.readLine()) != null) {
358 String[] filePath = line.split(" : ");
359 if (filePath.length == 2) {
360 ///
361 /// keep the file name after ":"
362 ///
363 lineSet.add(cleanupPathName(filePath[1]));
364 }
365 }
366 lineReader.close();
367 fileReader.close();
368
369 ///
370 /// we may have explicitly specified dependency files
371 ///
372 StringTokenizer fileTokens = new StringTokenizer(extraDeps, ";");
373 while (fileTokens.hasMoreTokens()) {
374 lineSet.add(cleanupPathName(fileTokens.nextToken()));
375 }
376
377 ///
378 /// compose the final file content
379 ///
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");
386 }
387 ///
388 /// overwrite old dep file with new content
389 ///
390 FileWriter fileWriter = null;
391 fileWriter = new FileWriter(df);
392 fileWriter.write(cleanedLines.toString());
393 fileWriter.close();
394 } catch (IOException e) {
395 log (e.getMessage());
396 }
397
398 return true;
399 }
400
401 /**
402 Check if the dependency list file should be (re-)generated or not.
403
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.
406 **/
407 private boolean isUptodate() {
408 File df = new File(depsFile);
409 if (!df.exists()) {
410 return false;
411 }
412
413 ///
414 /// If the source file(s) is newer than dependency list file, we need to
415 /// re-generate the dependency list file
416 ///
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) {
423 return false;
424 }
425 }
426
427 ///
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.
432 ///
433 LineNumberReader lineReader = null;
434 FileReader fileReader = null;
435 boolean ret = true;
436 try {
437 fileReader = new FileReader(df);
438 lineReader = new LineNumberReader(fileReader);
439
440 String line = null;
441 while ((line = lineReader.readLine()) != null) {
442 File sourceFile = new File(line);
443 if (sourceFile.lastModified() > depsFileTimeStamp) {
444 ret = false;
445 break;
446 }
447 }
448 lineReader.close();
449 fileReader.close();
450 } catch (IOException e) {
451 log (e.getMessage());
452 }
453
454 return ret;
455 }
456 }
457