]> git.proxmox.com Git - mirror_edk2.git/blob - Tools/Source/FrameworkTasks/org/tianocore/framework/tasks/MakeDeps.java
1486bd384edcdf12d5add2464f5ec9f2228bdd01
[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.IOException;
20 import java.io.LineNumberReader;
21 import java.util.ArrayList;
22 import java.util.Iterator;
23 import java.util.List;
24
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;
32
33 import org.tianocore.common.logger.EdkLog;
34 import org.tianocore.common.cache.FileTimeStamp;
35
36 /**
37 Class MakeDeps is used to wrap MakeDeps.exe as an ANT task.
38 **/
39 public class MakeDeps extends Task {
40
41 //
42 // private members, use set/get to access them
43 //
44 private static final String toolName = "MakeDeps";
45 private FileArg depsFile = new FileArg();
46 private ToolArg subDir = new ToolArg();
47 private ToolArg quietMode = new ToolArg(" -", "q");
48 private ToolArg ignoreError = new ToolArg(" -", "ignorenotfound");
49 private IncludePath includePathList = new IncludePath();
50 private Input inputFileList = new Input();
51 private ToolArg target = new FileArg(" -target ", "dummy");
52
53 public MakeDeps() {
54
55 }
56
57 /**
58 The Standard execute method for ANT task. It will check if it's necessary
59 to generate the dependency list file. If no file is found or the dependency
60 is changed, it will compose the command line and call MakeDeps.exe to
61 generate the dependency list file.
62
63 @throws BuildException
64 **/
65 public void execute() throws BuildException {
66 ///
67 /// check if the dependency list file is uptodate or not
68 ///
69 if (isUptodate()) {
70 return;
71 }
72
73 Project prj = this.getOwningTarget().getProject();
74 String toolPath = prj.getProperty("env.FRAMEWORK_TOOLS_PATH");
75
76 ///
77 /// compose full tool path
78 ///
79 if (toolPath == null || toolPath.length() == 0) {
80 toolPath = toolName;
81 } else {
82 if (toolPath.endsWith("/") || toolPath.endsWith("\\")) {
83 toolPath = toolPath + toolName;
84 } else {
85 toolPath = toolPath + File.separator + toolName;
86 }
87 }
88
89 ///
90 /// compose tool arguments
91 ///
92 String argument = "" + inputFileList + includePathList + subDir
93 + quietMode + ignoreError + target + depsFile;
94
95 ///
96 /// prepare to execute the tool
97 ///
98 Commandline cmd = new Commandline();
99 cmd.setExecutable(toolPath);
100 cmd.createArgument().setLine(argument);
101
102 LogStreamHandler streamHandler = new LogStreamHandler(this, Project.MSG_INFO, Project.MSG_WARN);
103 Execute runner = new Execute(streamHandler, null);
104
105 runner.setAntRun(prj);
106 runner.setCommandline(cmd.getCommandline());
107
108 EdkLog.log(this, EdkLog.EDK_VERBOSE, Commandline.toString(cmd.getCommandline()));
109
110 int result = 0;
111 try {
112 result = runner.execute();
113 } catch (IOException e) {
114 throw new BuildException(e.getMessage());
115 }
116
117 if (result != 0) {
118 EdkLog.log(this, EdkLog.EDK_INFO, toolName + " failed!");
119 throw new BuildException(toolName + ": failed to generate dependency file!");
120 } else {
121 EdkLog.log(this, EdkLog.EDK_VERBOSE, toolName + " succeeded!");
122 }
123 }
124
125 /**
126 Set method for "DepsFile" attribute
127
128 @param name The name of dependency list file
129 **/
130 public void setDepsFile(String name) {
131 depsFile.setArg(" -o ", name);
132 }
133
134 /**
135 Get method for "DepsFile" attribute
136
137 @returns The name of dependency list file
138 **/
139 public String getDepsFile() {
140 return depsFile.getValue();
141 }
142
143 /**
144 Set method for "IgnoreError" attribute
145
146 @param ignore flag to control error handling (true/false)
147 **/
148 public void setIgnoreError(boolean ignore) {
149 if (!ignore) {
150 ignoreError.setArg(" ", " ");
151 }
152 }
153
154 /**
155 Get method for "IgnoreError" attribute
156
157 @returns The value of current IgnoreError flag
158 **/
159 public boolean getIgnoreError() {
160 return ignoreError.getValue().length() > 0;
161 }
162
163 /**
164 Set method for "QuietMode" attribute
165
166 @param quiet flag to control the output information (true/false)
167 **/
168 public void setQuietMode(boolean quiet) {
169 if (!quiet) {
170 quietMode.setArg(" ", " ");
171 }
172 }
173
174 /**
175 Get method for "QuietMode" attribute
176
177 @returns value of current QuietMode flag
178 **/
179 public boolean getQuietMode() {
180 return quietMode.getValue().length() > 0;
181 }
182
183 /**
184 Set method for "SubDir" attribute
185
186 @param dir The name of sub-directory in which source files will be scanned
187 **/
188 public void setSubDir(String dir) {
189 subDir.setArg(" -s ", dir);
190 }
191
192 /**
193 Get method for "SubDir" attribute
194
195 @returns The name of sub-directory
196 **/
197 public String getSubDir() {
198 return subDir.getValue();
199 }
200
201 /**
202 Add method for "IncludePath" nested element
203
204 @param path The IncludePath object from nested IncludePath type of element
205 **/
206 public void addConfiguredIncludepath(IncludePath path) {
207 includePathList.insert(path);
208 }
209
210 /**
211 Add method for "Input" nested element
212
213 @param input The Input object from nested Input type of element
214 **/
215 public void addConfiguredInput(Input inputFile) {
216 inputFileList.insert(inputFile);
217 }
218
219 /**
220 Check if the dependency list file should be (re-)generated or not.
221
222 @returns true The dependency list file is uptodate. No re-generation is needed.
223 @returns false The dependency list file is outofdate. Re-generation is needed.
224 **/
225 private boolean isUptodate() {
226 String dfName = depsFile.getValue();
227 File df = new File(dfName);
228 if (!df.exists()) {
229 EdkLog.log(this, EdkLog.EDK_VERBOSE, dfName + " doesn't exist!");
230 return false;
231 }
232
233 //
234 // If the source file(s) is newer than dependency list file, we need to
235 // re-generate the dependency list file
236 //
237 long depsFileTimeStamp = FileTimeStamp.get(dfName);
238 List<String> fileList = inputFileList.getNameList();
239 for (int i = 0, length = fileList.size(); i < length; ++i) {
240 String sf = fileList.get(i);
241 if (FileTimeStamp.get(sf) > depsFileTimeStamp) {
242 EdkLog.log(this, EdkLog.EDK_VERBOSE, sf + " has been changed since last build!");
243 return false;
244 }
245 }
246
247 //
248 // If the source files haven't been changed since last time the dependency
249 // list file was generated, we need to check each file in the file list to
250 // see if any of them is changed or not. If anyone of them is newer than
251 // the dependency list file, MakeDeps.exe is needed to run again.
252 //
253 LineNumberReader lineReader = null;
254 FileReader fileReader = null;
255 boolean ret = false;
256 try {
257 fileReader = new FileReader(df);
258 lineReader = new LineNumberReader(fileReader);
259
260 String line = null;
261 int lines = 0;
262 while ((line = lineReader.readLine()) != null) {
263 //
264 // check file end flag "\t" to see if the .dep was generated correctly
265 //
266 if (line.equals("\t")) {
267 ret = true;
268 continue;
269 }
270 line = line.trim();
271 //
272 // skip empty line
273 //
274 if (line.length() == 0) {
275 continue;
276 }
277 ++lines;
278
279 //
280 // If a file cannot be found (moved or removed) or newer, regenerate the dep file
281 //
282 File sourceFile = new File(line);
283 if ((!sourceFile.exists()) || (FileTimeStamp.get(line) > depsFileTimeStamp)) {
284 EdkLog.log(this, EdkLog.EDK_VERBOSE, sourceFile.getPath() + " has been (re)moved or changed since last build!");
285 ret = false;
286 break;
287 }
288 }
289
290 //
291 // check if the .dep file is empty
292 //
293 if (lines == 0) {
294 EdkLog.log(this, EdkLog.EDK_VERBOSE, dfName + " is empty!");
295 ret = false;
296 }
297
298 lineReader.close();
299 fileReader.close();
300 } catch (IOException e) {
301 throw new BuildException(e.getMessage());
302 }
303
304 return ret;
305 }
306 }
307