* <tr><td></td><td></td><td></td></tr>
* </table>
*/
-public final class AaptExecLoopTask extends BaseTask {
+public final class AaptExecTask extends BaseTask {
/**
* Class representing a <nocompress> node in the main task XML.
&& dependenciesHaveChanged() == false) {
System.out.println("No changed resources. R.java and Manifest.java untouched.");
return;
+ } else {
+ System.out.println("Generating resource IDs...");
}
} else {
// Find our dependency file. It should have the same name as our target .ap_ but
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.HashSet;
import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
/**
* Task to execute aidl.
}
}
- // now loop on all the source folders to find all the aidl to compile
- // and compile them
- for (String sourceFolder : sourceFolders) {
- // create a fileset to find all the aidl files in the current source folder
- FileSet fs = new FileSet();
- fs.setProject(taskProject);
- fs.setDir(new File(sourceFolder));
- NameEntry include = fs.createInclude();
- include.setName("**/*.aidl");
-
- // loop through the results of the file set
- Iterator<?> iter = fs.iterator();
- while (iter.hasNext()) {
- Object next = iter.next();
+ // gather all the aidl files from all the source folders.
+ Set<String> sourceFiles = getFileListByExtension(taskProject, sourceFolders, "**/*.aidl");
+ if (sourceFiles.size() > 0) {
+ System.out.println(String.format("Found %d aidl files.", sourceFiles.size()));
+ }
+
+ // go look for all dependency files in the gen folder.
+ Set<String> depFiles = getFileListByExtension(taskProject, mGenFolder, "**/*.d");
+
+ // parse all the dep files and keep the ones that are aidl and check if they require
+ // compilation again.
+ ArrayList<String> toCompile = new ArrayList<String>();
+ ArrayList<File> toRemove = new ArrayList<File>();
+ ArrayList<String> depsToRemove = new ArrayList<String>();
+ for (String depFile : depFiles) {
+ DependencyGraph graph = new DependencyGraph(depFile, null /*watchPaths*/);
+
+ // get the source file. it's the first item in the pre-reqs
+ List<File> preReqs = graph.getPrereqs();
+ File sourceFile = preReqs.get(0);
+ String sourceFilePath = sourceFile.getAbsolutePath();
+
+ // The gen folder may contain other dependency files not generated by aidl.
+ // We only care if the first pre-rep is an aidl file.
+ if (sourceFilePath.toLowerCase().endsWith(".aidl")) {
+ // remove from the list of sourceFiles to mark as "processed" (but not compiled
+ // yet, that'll be done by adding it to toCompile)
+ if (sourceFiles.remove(sourceFilePath) == false) {
+ // looks like the source file does not exist anymore!
+ // we'll have to remove the output!
+ List<File> outputFiles = graph.getTargets();
+ toRemove.addAll(outputFiles);
+
+ // also need to remove the dep file.
+ depsToRemove.add(depFile);
+ } else if (graph.dependenciesHaveChanged(null /*extensionsToCheck*/,
+ false /*printStatus*/)) {
+ // need to recompile!
+ toCompile.add(sourceFilePath);
+ }
+ }
+ }
+
+ // add to the list of files to compile, whatever is left in sourceFiles. Those are
+ // new files that have never been compiled.
+ toCompile.addAll(sourceFiles);
+ if (toCompile.size() > 0) {
+ System.out.println(String.format("Compiling %d aidl files.", toCompile.size()));
+
+ for (String toCompilePath : toCompile) {
ExecTask task = new ExecTask();
task.setProject(taskProject);
task.setOwningTarget(getOwningTarget());
task.createArg().setValue("-I" + importFolder);
}
- task.createArg().setValue(next.toString());
+ // set auto dependency file creation
+ task.createArg().setValue("-a");
+
+ task.createArg().setValue(toCompilePath);
// execute it.
task.execute();
}
+ } else {
+ System.out.println(String.format("No aidl files to compile."));
+ }
+
+ if (toRemove.size() > 0) {
+ System.out.println(String.format("%d obsolete output files to remove.",
+ toRemove.size()));
+ for (File toRemoveFile : toRemove) {
+ if (toRemoveFile.delete() == false) {
+ System.err.println("Failed to remove " + toRemoveFile.getAbsolutePath());
+ }
+ }
+ }
+
+ // remove the dependency files that are obsolete
+ if (depsToRemove.size() > 0) {
+ System.out.println(String.format("%d obsolete dependency files to remove.",
+ depsToRemove.size()));
+ for (String path : depsToRemove) {
+ if (new File(path).delete() == false) {
+ System.err.println("Failed to remove " + path);
+ }
+ }
+ }
+ }
+
+ private Set<String> getFileListByExtension(Project taskProject,
+ List<String> sourceFolders, String filter) {
+ HashSet<String> sourceFiles = new HashSet<String>();
+ for (String sourceFolder : sourceFolders) {
+ sourceFiles.addAll(getFileListByExtension(taskProject, sourceFolder, filter));
}
+
+ return sourceFiles;
}
+
+ private Set<String> getFileListByExtension(Project taskProject,
+ String sourceFolder, String filter) {
+ HashSet<String> sourceFiles = new HashSet<String>();
+
+ // create a fileset to find all the files in the folder
+ FileSet fs = new FileSet();
+ fs.setProject(taskProject);
+ fs.setDir(new File(sourceFolder));
+ NameEntry include = fs.createInclude();
+ include.setName(filter);
+
+ // loop through the results of the file set
+ Iterator<?> iter = fs.iterator();
+ while (iter.hasNext()) {
+ sourceFiles.add(iter.next().toString());
+ }
+
+ return sourceFiles;
+ }
+
+
}
}
assert mDependencies != null : "Dependencies have not been initialized";
- return mDependencies.dependenciesHaveChanged(mRestrictTouchedExtensionsTo);
+ return mDependencies.dependenciesHaveChanged(mRestrictTouchedExtensionsTo,
+ true /*printStatus*/);
}
}
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Collections;
-import java.util.HashSet;
+import java.util.List;
import java.util.Set;
/**
public class DependencyGraph {
// Files that we know about from the dependency file
- private Set<File> mTargets = Collections.emptySet();
- private Set<File> mPrereqs = mTargets;
+ private List<File> mTargets = Collections.emptyList();
+ private List<File> mPrereqs = mTargets;
+ private boolean mMissingDepFile = false;
+ private long mDepFileLastModified;
private final ArrayList<File> mWatchPaths;
public DependencyGraph(String dependencyFilePath, ArrayList<File> watchPaths) {
* @param extensionsToCheck a set of extensions. Only files with an extension in this set will
* be considered for a modification check. All deleted/created files will still be
* checked. If this is null, all files will be checked for modification date
+ * @param printStatus will print to {@link System#out} the dependencies status.
* @return true if new prerequisites have appeared, target files are missing or if
* prerequisite files have been modified since the last target generation.
*/
- public boolean dependenciesHaveChanged(Set<String> extensionsToCheck) {
- boolean noFile = (mTargets.size() == 0);
+ public boolean dependenciesHaveChanged(Set<String> extensionsToCheck, boolean printStatus) {
boolean missingPrereq = missingPrereqFile();
boolean newPrereq = newPrereqFile();
boolean missingTarget = missingTargetFile();
boolean modPrereq = modifiedPrereq(extensionsToCheck);
- if (noFile) {
- System.out.println("No Dependency File Found");
- }
- if (missingPrereq) {
- System.out.println("Found Deleted Prereq File");
- }
- if (newPrereq) {
- System.out.println("Found New Prereq File");
- }
- if (missingTarget) {
- System.out.println("Found Deleted Target File");
- }
- if (modPrereq) {
- System.out.println("Found Modified Prereq File");
+ if (printStatus) {
+ if (mMissingDepFile) {
+ System.out.println("No Dependency File Found");
+ }
+ if (missingPrereq) {
+ System.out.println("Found Deleted Prereq File");
+ }
+ if (newPrereq) {
+ System.out.println("Found New Prereq File");
+ }
+ if (missingTarget) {
+ System.out.println("Found Deleted Target File");
+ }
+ if (modPrereq) {
+ System.out.println("Found Modified Prereq File");
+ }
}
+
// If no dependency file has been set up, then we'll just return true
// if we have a dependency file, we'll check to see what's been changed
- return noFile || missingPrereq || newPrereq || missingTarget || modPrereq;
+ return mMissingDepFile || missingPrereq || newPrereq || missingTarget || modPrereq;
+ }
+
+ public List<File> getTargets() {
+ return mTargets;
+ }
+
+ public List<File> getPrereqs() {
+ return mPrereqs;
}
/**
* @param dependencyFilePath the dependency file
*/
private void parseDependencyFile(String dependencyFilePath) {
+ // first check if the dependency file is here.
+ File depFile = new File(dependencyFilePath);
+ if (depFile.isFile() == false) {
+ mMissingDepFile = true;
+ return;
+ }
+
+ // get the modification time of the dep file as we may need it later
+ mDepFileLastModified = depFile.lastModified();
+
// Read in our dependency file
String content = readFile(dependencyFilePath);
if (content == null) {
prereqs = files[1].trim().split(" ");
}
- mTargets = new HashSet<File>(targets.length);
+ mTargets = new ArrayList<File>(targets.length);
for (String path : targets) {
- mTargets.add(new File(path));
+ if (path.length() > 0) {
+ mTargets.add(new File(path));
+ }
}
- mPrereqs = new HashSet<File>(prereqs.length);
+ mTargets = Collections.unmodifiableList(mTargets);
+ mPrereqs = new ArrayList<File>(prereqs.length);
for (String path : prereqs) {
- mPrereqs.add(new File(path));
+ if (path.length() > 0) {
+ mPrereqs.add(new File(path));
+ }
}
+ mPrereqs = Collections.unmodifiableList(mPrereqs);
}
/**
* @return true if a new file is encountered in the dependency folders
*/
private boolean newPrereqFile() {
- for (File dir : mWatchPaths) {
- if (newFileInTree(dir)) {
- return true;
+ if (mWatchPaths != null) {
+ for (File dir : mWatchPaths) {
+ if (newFileInTree(dir)) {
+ return true;
+ }
}
}
// If we make it all the way through our directories we're good.
private boolean modifiedPrereq(Set<String> extensionsToCheck) {
// Find the oldest target
long oldestTarget = Long.MAX_VALUE;
- for (File target : mTargets) {
- if (target.lastModified() < oldestTarget) {
- oldestTarget = target.lastModified();
+ // if there's no output, then compare to the time of the dependency file.
+ if (mTargets.size() == 0) {
+ oldestTarget = mDepFileLastModified;
+ } else {
+ for (File target : mTargets) {
+ if (target.lastModified() < oldestTarget) {
+ oldestTarget = target.lastModified();
+ }
}
}
// Don't include the leading '.' in the extension
return filename.substring(filename.lastIndexOf('.') + 1);
}
+
}
File exe = new File(mExecutable);
String execTaskName = exe.getName();
+ int count = 0;
+
// now loop on all the source folders to find all the renderscript to compile
// and compile them
for (String sourceFolder : sourceFolders) {
task.execute();
}
}
+
+ if (count > 0) {
+ System.out.println(String.format("Compiled %d renderscript files.", count));
+ } else {
+ System.out.println("No renderscript files to compile.");
+ }
+
}
}
if (r == false &&
kind == IResourceDelta.REMOVED &&
AdtConstants.EXT_DEP.equalsIgnoreCase(file.getFileExtension())) {
- // This looks to be an extension file.
- // For futureproofness let's make sure this dependency file was generated by
+ // This looks to be a dependency file.
+ // For future-proofness let's make sure this dependency file was generated by
// this processor even if it's the only processor using them for now.
// look for the original file.
classpathref="android.antlibs" />
<taskdef name="aapt"
- classname="com.android.ant.AaptExecLoopTask"
+ classname="com.android.ant.AaptExecTask"
classpathref="android.antlibs" />
<taskdef name="aidl"
<target name="-code-gen">
<do-only-if-manifest-hasCode
elseText="hasCode = false. Skipping aidl/renderscript/R.java">
- <echo>Compiling aidl files into Java classes...</echo>
+ <echo>----------</echo>
+ <echo>Handling aidl files...</echo>
<aidl executable="${aidl}" framework="${android.aidl}"
genFolder="${gen.absolute.dir}">
<source path="${source.absolute.dir}"/>
</aidl>
<!-- renderscript generates resources so it must be called before aapt -->
- <echo>Compiling RenderScript files into Java classes and RenderScript bytecode...</echo>
+ <echo>----------</echo>
+ <echo>Handling RenderScript files...</echo>
<renderscript executable="${renderscript}"
framework="${android.rs}"
genFolder="${gen.absolute.dir}"
<source path="${source.absolute.dir}"/>
</renderscript>
- <echo>Generating R.java / Manifest.java from the resources...</echo>
+ <echo>----------</echo>
+ <echo>Handling Resources...</echo>
<aapt executable="${aapt}"
command="package"
verbose="${verbose}"