aboutsummaryrefslogtreecommitdiffstats
path: root/anttasks
diff options
context:
space:
mode:
authorXavier Ducrohet <xav@android.com>2011-09-01 18:27:32 -0700
committerXavier Ducrohet <xav@android.com>2011-09-23 09:37:08 -0700
commita9a28238f7b20d7c0a05c95afad02fcdb34e0d0e (patch)
tree5c3416656d6affb7f3f3bacb556a05805ff35e2e /anttasks
parente85fc5515d4507eb96c74f0d5c0969a09a7b4779 (diff)
downloadsdk-a9a28238f7b20d7c0a05c95afad02fcdb34e0d0e.zip
sdk-a9a28238f7b20d7c0a05c95afad02fcdb34e0d0e.tar.gz
sdk-a9a28238f7b20d7c0a05c95afad02fcdb34e0d0e.tar.bz2
Add dependency support for ApkBuilder ant step.
Change-Id: I7230a2aa3df5fab8b420f1ed2f359621fbda7f5a
Diffstat (limited to 'anttasks')
-rw-r--r--anttasks/src/com/android/ant/AaptExecTask.java37
-rw-r--r--anttasks/src/com/android/ant/ApkBuilderTask.java184
-rw-r--r--anttasks/src/com/android/ant/BaseTask.java29
-rw-r--r--anttasks/src/com/android/ant/DependencyGraph.java116
-rw-r--r--anttasks/src/com/android/ant/DexExecTask.java6
-rw-r--r--anttasks/src/com/android/ant/InputPath.java94
6 files changed, 309 insertions, 157 deletions
diff --git a/anttasks/src/com/android/ant/AaptExecTask.java b/anttasks/src/com/android/ant/AaptExecTask.java
index 4d16d1f..fc0de71 100644
--- a/anttasks/src/com/android/ant/AaptExecTask.java
+++ b/anttasks/src/com/android/ant/AaptExecTask.java
@@ -16,8 +16,6 @@
package com.android.ant;
-import com.android.ant.DependencyGraph.InputPath;
-
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.taskdefs.ExecTask;
@@ -337,11 +335,6 @@ public final class AaptExecTask extends BaseTask {
}
}
- // as is its AndroidManifest.xml
- if (mManifest != null) {
- paths.add(new File(mManifest));
- }
-
// and if libraries exist, their res folders folders too.
if (libResRef instanceof Path) {
for (String path : ((Path)libResRef).list()) {
@@ -349,20 +342,17 @@ public final class AaptExecTask extends BaseTask {
}
}
- // If we're here to generate a .ap_ file we need to use assets as an input path as well.
- if (!generateRClass) {
- File assetsDir = new File(mAssets);
- if (mAssets != null && assetsDir.isDirectory()) {
- paths.add(assetsDir);
- }
- }
-
// Now we figure out what we need to do
if (generateRClass) {
// in this case we only want to run aapt if an XML file was touched, or if any
// file is added/removed
List<InputPath> inputPaths = getInputPaths(paths, Collections.singleton("xml"));
+ // let's not forget the manifest as an input path (with no extension restrictions).
+ if (mManifest != null) {
+ inputPaths.add(new InputPath(new File(mManifest)));
+ }
+
// Check to see if our dependencies have changed. If not, then skip
if (initDependencies(mRFolder + File.separator + "R.java.d", inputPaths)
&& dependenciesHaveChanged() == false) {
@@ -372,10 +362,23 @@ public final class AaptExecTask extends BaseTask {
System.out.println("Generating resource IDs...");
}
} else {
- // in this case we want to run aapt if any file updated/removed/added in any of the
- // input path
+ // in this case we want to run aapt if any file was updated/removed/added in any of the
+ // input paths
List<InputPath> inputPaths = getInputPaths(paths, null /*extensionsToCheck*/);
+ // let's not forget the manifest as an input path.
+ if (mManifest != null) {
+ inputPaths.add(new InputPath(new File(mManifest)));
+ }
+
+ // If we're here to generate a .ap_ file we need to use assets as an input path as well.
+ if (mAssets != null) {
+ File assetsDir = new File(mAssets);
+ if (assetsDir.isDirectory()) {
+ inputPaths.add(new InputPath(assetsDir));
+ }
+ }
+
// Find our dependency file. It should have the same name as our target .ap_ but
// with a .d extension
String dependencyFilePath = mApkFolder + File.separator + mApkName;
diff --git a/anttasks/src/com/android/ant/ApkBuilderTask.java b/anttasks/src/com/android/ant/ApkBuilderTask.java
index 3f8dec1..88bd59c 100644
--- a/anttasks/src/com/android/ant/ApkBuilderTask.java
+++ b/anttasks/src/com/android/ant/ApkBuilderTask.java
@@ -20,17 +20,18 @@ import com.android.sdklib.build.ApkBuilder;
import com.android.sdklib.build.ApkCreationException;
import com.android.sdklib.build.DuplicateFileException;
import com.android.sdklib.build.SealedApkException;
+import com.android.sdklib.build.ApkBuilder.FileEntry;
import org.apache.tools.ant.BuildException;
-import org.apache.tools.ant.Task;
import org.apache.tools.ant.types.Path;
import java.io.File;
import java.io.FilenameFilter;
import java.util.ArrayList;
+import java.util.List;
import java.util.regex.Pattern;
-public class ApkBuilderTask extends Task {
+public class ApkBuilderTask extends BaseTask {
private final static Pattern PATTERN_JAR_EXT = Pattern.compile("^.+\\.jar$",
Pattern.CASE_INSENSITIVE);
@@ -42,17 +43,30 @@ public class ApkBuilderTask extends Task {
private boolean mDebugPackaging = false;
private boolean mDebugSigning = false;
private boolean mHasCode = true;
- private String mAbiFilter = null;
private Path mDexPath;
private final ArrayList<Path> mZipList = new ArrayList<Path>();
- private final ArrayList<Path> mFileList = new ArrayList<Path>();
private final ArrayList<Path> mSourceList = new ArrayList<Path>();
private final ArrayList<Path> mJarfolderList = new ArrayList<Path>();
private final ArrayList<Path> mJarfileList = new ArrayList<Path>();
private final ArrayList<Path> mNativeList = new ArrayList<Path>();
+ private static class SourceFolderInputPath extends InputPath {
+ public SourceFolderInputPath(File file) {
+ super(file);
+ }
+
+ @Override
+ public boolean ignores(File file) {
+ if (file.isDirectory()) {
+ return !ApkBuilder.checkFolderForPackaging(file.getName());
+ } else {
+ return !ApkBuilder.checkFileForPackaging(file.getName());
+ }
+ }
+ }
+
/**
* Sets the value of the "outfolder" attribute.
* @param outFolder the value.
@@ -113,21 +127,6 @@ public class ApkBuilderTask extends Task {
}
/**
- * Sets an ABI filter. If non <code>null</code>, then only native libraries matching the given
- * ABI will be packaged with the APK.
- * @param abiFilter the ABI to accept (and reject all other). If null or empty string, no ABIs
- * are rejected. This must be a single ABI name as defined by the Android NDK. For a list
- * of valid ABI names, see $NDK/docs/CPU-ARCH-ABIS.TXT
- */
- public void setAbifilter(String abiFilter) {
- if (abiFilter != null && abiFilter.length() > 0) {
- mAbiFilter = abiFilter.trim();
- } else {
- mAbiFilter = null;
- }
- }
-
- /**
* Sets the hascode attribute. Default is true.
* If set to false, then <dex> and <sourcefolder> nodes are ignored and not processed.
* @param hasCode the value of the attribute.
@@ -159,17 +158,6 @@ public class ApkBuilderTask extends Task {
}
/**
- * Returns an object representing a nested <var>file</var> element.
- */
- public Object createFile() {
- System.out.println("WARNING: Using deprecated <file> inner element in ApkBuilderTask." +
- "Use <dex path=...> instead.");
- Path path = new Path(getProject());
- mFileList.add(path);
- return path;
- }
-
- /**
* Returns an object representing a nested <var>sourcefolder</var> element.
*/
public Object createSourcefolder() {
@@ -236,48 +224,43 @@ public class ApkBuilderTask extends Task {
}
try {
- if (mDebugSigning) {
- System.out.println(String.format(
- "Creating %s and signing it with a debug key...", outputFile.getName()));
- } else {
- System.out.println(String.format(
- "Creating %s for release...", outputFile.getName()));
- }
+ // build list of input files/folders to compute dependencies
+ // add the content of the zip files.
+ List<InputPath> inputPaths = new ArrayList<InputPath>();
- ApkBuilder apkBuilder = new ApkBuilder(
- outputFile,
- new File(mOutFolder, mResourceFile),
- dexFile,
- mDebugSigning ? ApkBuilder.getDebugKeystore() : null,
- mVerbose ? System.out : null);
- apkBuilder.setDebugMode(mDebugPackaging);
+ // resource file
+ InputPath resourceInputPath = new InputPath(new File(mOutFolder, mResourceFile));
+ inputPaths.add(resourceInputPath);
+ // dex file
+ inputPaths.add(new InputPath(dexFile));
- // add the content of the zip files.
+ // zip input files
+ List<File> zipFiles = new ArrayList<File>();
for (Path pathList : mZipList) {
for (String path : pathList.list()) {
- apkBuilder.addZipFile(new File(path));
+ File f = new File(path);
+ zipFiles.add(f);
+ inputPaths.add(new InputPath(f));
}
}
- // add the files that go to the root of the archive (this is deprecated)
- for (Path pathList : mFileList) {
- for (String path : pathList.list()) {
- File f = new File(path);
- apkBuilder.addFile(f, f.getName());
- }
- }
-
- // now go through the list of file to directly add the to the list.
+ // now go through the list of source folders used to add non java files.
+ List<File> sourceFolderList = new ArrayList<File>();
if (mHasCode) {
for (Path pathList : mSourceList) {
for (String path : pathList.list()) {
- apkBuilder.addSourceFolder(new File(path));
+ File f = new File(path);
+ sourceFolderList.add(f);
+ // because this is a source folder but we only care about non
+ // java files.
+ inputPaths.add(new SourceFolderInputPath(f));
}
}
}
// now go through the list of jar folders.
+ List<File> jarFileList = new ArrayList<File>();
for (Path pathList : mJarfolderList) {
for (String path : pathList.list()) {
// it's ok if top level folders are missing
@@ -290,7 +273,9 @@ public class ApkBuilderTask extends Task {
});
for (String filename : filenames) {
- apkBuilder.addResourcesFromJar(new File(folder, filename));
+ File f = new File(folder, filename);
+ jarFileList.add(f);
+ inputPaths.add(new InputPath(f));
}
}
}
@@ -299,25 +284,101 @@ public class ApkBuilderTask extends Task {
// now go through the list of jar files.
for (Path pathList : mJarfileList) {
for (String path : pathList.list()) {
- apkBuilder.addResourcesFromJar(new File(path));
+ File f = new File(path);
+ jarFileList.add(f);
+ inputPaths.add(new InputPath(f));
}
}
// now the native lib folder.
+ List<FileEntry> nativeFileList = new ArrayList<FileEntry>();
for (Path pathList : mNativeList) {
for (String path : pathList.list()) {
// it's ok if top level folders are missing
File folder = new File(path);
if (folder.isDirectory()) {
- apkBuilder.addNativeLibraries(folder, mAbiFilter);
+ List<FileEntry> entries = ApkBuilder.getNativeFiles(folder,
+ mDebugPackaging);
+ // add the list to the list of native files and then create an input
+ // path for each file
+ nativeFileList.addAll(entries);
+
+ for (FileEntry entry : entries) {
+ inputPaths.add(new InputPath(entry.mFile));
+ }
}
}
}
+ // Finally figure out the path to the dependency file.
+ String depFile = outputFile.getAbsolutePath() + ".d";
+
+ // check dependencies
+ if (initDependencies(depFile, inputPaths) && dependenciesHaveChanged() == false) {
+ System.out.println(
+ "No changes. No need to create apk.");
+ return;
+ }
+
+ if (mDebugSigning) {
+ System.out.println(String.format(
+ "Creating %s and signing it with a debug key...", outputFile.getName()));
+ } else {
+ System.out.println(String.format(
+ "Creating %s for release...", outputFile.getName()));
+ }
+
+ ApkBuilder apkBuilder = new ApkBuilder(
+ outputFile,
+ resourceInputPath.getFile(),
+ dexFile,
+ mDebugSigning ? ApkBuilder.getDebugKeystore() : null,
+ mVerbose ? System.out : null);
+ apkBuilder.setDebugMode(mDebugPackaging);
+
+
+ // add the content of the zip files.
+ for (File f : zipFiles) {
+ apkBuilder.addZipFile(f);
+ }
+
+ // now go through the list of file to directly add the to the list.
+ for (File f : sourceFolderList) {
+ apkBuilder.addSourceFolder(f);
+ }
+
+ // now go through the list of jar folders.
+ for (Path pathList : mJarfolderList) {
+ for (String path : pathList.list()) {
+ // it's ok if top level folders are missing
+ File folder = new File(path);
+ if (folder.isDirectory()) {
+ String[] filenames = folder.list(new FilenameFilter() {
+ public boolean accept(File dir, String name) {
+ return PATTERN_JAR_EXT.matcher(name).matches();
+ }
+ });
+
+ for (String filename : filenames) {
+ apkBuilder.addResourcesFromJar(new File(folder, filename));
+ }
+ }
+ }
+ }
+
+ // now go through the list of jar files.
+ for (File f : jarFileList) {
+ apkBuilder.addResourcesFromJar(f);
+ }
+
+ // and finally the native files
+ apkBuilder.addNativeLibraries(nativeFileList);
// close the archive
apkBuilder.sealApk();
+ // and generate the dependency file
+ generateDependencyFile(depFile, inputPaths, outputFile.getAbsolutePath());
} catch (DuplicateFileException e) {
System.err.println(String.format(
"Found duplicate file for APK: %1$s\nOrigin 1: %2$s\nOrigin 2: %3$s",
@@ -331,4 +392,9 @@ public class ApkBuilderTask extends Task {
throw new BuildException(e);
}
}
+
+ @Override
+ protected String getExecTaskName() {
+ return "apkbuilder";
+ }
}
diff --git a/anttasks/src/com/android/ant/BaseTask.java b/anttasks/src/com/android/ant/BaseTask.java
index 8a82fe9..b1c37b8 100644
--- a/anttasks/src/com/android/ant/BaseTask.java
+++ b/anttasks/src/com/android/ant/BaseTask.java
@@ -16,8 +16,6 @@
package com.android.ant;
-import com.android.ant.DependencyGraph.InputPath;
-
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Task;
@@ -113,11 +111,11 @@ public abstract class BaseTask extends Task {
}
protected void generateDependencyFile(String depFilePath,
- List<File> inputs, String outputFile) {
- File file = new File(depFilePath);
+ List<InputPath> inputs, String outputFile) {
+ File depFile = new File(depFilePath);
try {
- PrintStream ps = new PrintStream(file);
+ PrintStream ps = new PrintStream(depFile);
// write the output file.
ps.print(outputFile);
@@ -126,11 +124,12 @@ public abstract class BaseTask extends Task {
//write the input files
int count = inputs.size();
for (int i = 0 ; i < count ; i++) {
- File input = inputs.get(i);
- if (input.isDirectory()) {
- writeContent(ps, input);
+ InputPath input = inputs.get(i);
+ File file = input.getFile();
+ if (file.isDirectory()) {
+ writeContent(ps, file, input);
} else {
- ps.print(input.getAbsolutePath());
+ ps.print(file.getAbsolutePath());
ps.println(" \\");
}
}
@@ -141,13 +140,17 @@ public abstract class BaseTask extends Task {
}
}
- private void writeContent(PrintStream ps, File input) {
- File[] files = input.listFiles();
+ private void writeContent(PrintStream ps, File file, InputPath input) {
+ if (input.ignores(file)) {
+ return;
+ }
+
+ File[] files = file.listFiles();
if (files != null) {
for (File f : files) {
if (f.isDirectory()) {
- writeContent(ps, f);
- } else {
+ writeContent(ps, f, input);
+ } else if (input.ignores(f) == false) {
ps.print(f.getAbsolutePath());
ps.println(" \\");
}
diff --git a/anttasks/src/com/android/ant/DependencyGraph.java b/anttasks/src/com/android/ant/DependencyGraph.java
index b51965d..9c5e8ad 100644
--- a/anttasks/src/com/android/ant/DependencyGraph.java
+++ b/anttasks/src/com/android/ant/DependencyGraph.java
@@ -47,22 +47,6 @@ public class DependencyGraph {
private long mDepFileLastModified;
private final List<InputPath> mNewInputs;
- public static class InputPath {
- File mFile;
- /**
- * 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
- */
- Set<String> mExtensionsToCheck;
-
- public InputPath(File file, Set<String> extensions) {
- mFile = file;
- mExtensionsToCheck = extensions;
- }
- }
-
-
public DependencyGraph(String dependencyFilePath, List<InputPath> newInputPaths) {
mNewInputs = newInputPaths;
parseDependencyFile(dependencyFilePath);
@@ -225,7 +209,7 @@ public class DependencyGraph {
* This should be followed by a call to {@link #checkPrereqFiles(long)} which
* will process the remaining files in the prereq list.
*
- * If a change is found, this will return immediatly with either
+ * If a change is found, this will return immediately with either
* {@link DependencyStatus#NEW_FILE} or {@link DependencyStatus#UPDATED_FILE}.
*
* @param oldestTarget the timestamp of the oldest output file to compare against.
@@ -236,15 +220,14 @@ public class DependencyGraph {
private DependencyStatus checkInputs(long oldestTarget) {
if (mNewInputs != null) {
for (InputPath input : mNewInputs) {
- if (input.mFile.isDirectory()) {
- DependencyStatus status = checkInputFolder(input.mFile,
- input.mExtensionsToCheck, oldestTarget);
+ File file = input.getFile();
+ if (file.isDirectory()) {
+ DependencyStatus status = checkInputFolder(file, input, oldestTarget);
if (status != DependencyStatus.NONE) {
return status;
}
- } else if (input.mFile.isFile()) {
- DependencyStatus status = checkInputFile(input.mFile,
- input.mExtensionsToCheck, oldestTarget);
+ } else if (file.isFile()) {
+ DependencyStatus status = checkInputFile(file, input, oldestTarget);
if (status != DependencyStatus.NONE) {
return status;
}
@@ -260,31 +243,33 @@ public class DependencyGraph {
* Check all the files in the tree under root and check to see if the files are
* listed under the dependencies, or if they have been modified. Recurses into subdirs.
*
- * @param rootFolder the folder to search through.
- * @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 folder the folder to search through.
+ * @param inputFolder the root level inputFolder
* @param oldestTarget the time stamp of the oldest output file to compare against.
*
* @return the status of the file in the folder.
*/
- private DependencyStatus checkInputFolder(File rootFolder, Set<String> extensionsToCheck,
+ private DependencyStatus checkInputFolder(File folder, InputPath inputFolder,
long oldestTarget) {
- File[] files = rootFolder.listFiles();
+ if (inputFolder.ignores(folder)) {
+ return DependencyStatus.NONE;
+ }
+
+ File[] files = folder.listFiles();
if (files == null) {
- System.err.println("ERROR " + rootFolder.toString() + " is not a dir or can't be read");
+ System.err.println("ERROR " + folder.toString() + " is not a dir or can't be read");
return DependencyStatus.ERROR;
}
// Loop through files in this folder
for (File file : files) {
// If this is a directory, recurse into it
if (file.isDirectory()) {
- DependencyStatus status = checkInputFolder(file, extensionsToCheck, oldestTarget);
+ DependencyStatus status = checkInputFolder(file, inputFolder, oldestTarget);
if (status != DependencyStatus.NONE) {
return status;
}
} else if (file.isFile()) {
- DependencyStatus status = checkInputFile(file, extensionsToCheck, oldestTarget);
+ DependencyStatus status = checkInputFile(file, inputFolder, oldestTarget);
if (status != DependencyStatus.NONE) {
return status;
}
@@ -294,8 +279,12 @@ public class DependencyGraph {
return DependencyStatus.NONE;
}
- private DependencyStatus checkInputFile(File file, Set<String> extensionsToCheck,
+ private DependencyStatus checkInputFile(File file, InputPath inputFolder,
long oldestTarget) {
+ if (inputFolder.ignores(file)) {
+ return DependencyStatus.NONE;
+ }
+
// if it's a file, remove it from the list of prereqs.
// This way if files in this folder don't trigger a build we'll have less
// files to go through manually
@@ -303,9 +292,9 @@ public class DependencyGraph {
// turns out this is a new file!
return DependencyStatus.NEW_FILE;
} else {
- // check the time stamp on this file if it's a file we care about based on the
- // list of extensions to check.
- if (extensionsToCheck == null || extensionsToCheck.contains(getExtension(file))) {
+ // check the time stamp on this file if it's a file we care about based what the
+ // input folder decides.
+ if (inputFolder.checksForModification(file)) {
if (file.lastModified() > oldestTarget) {
return DependencyStatus.UPDATED_FILE;
}
@@ -324,31 +313,45 @@ public class DependencyGraph {
* @return the status of the files
*/
private DependencyStatus checkPrereqFiles(long oldestTarget) {
+ // TODO: Optimize for the case of a specific file as inputPath.
+ // We should have a map of filepath to inputpath to quickly search through them?
+
// Loop through our prereq files and make sure they still exist
for (File prereq : mPrereqs) {
if (prereq.exists() == false) {
return DependencyStatus.MISSING_FILE;
}
- // check the time stamp on this file if it's a file we care about based on the
- // list of extensions to check.
- // to get the extensions to check, we look in which input folder this file is.
- Set<String> extensionsToCheck = null;
+ // check the time stamp on this file if it's a file we care about.
+ // To know if we care about the file we have to find the matching input.
if (mNewInputs != null) {
String filePath = prereq.getAbsolutePath();
for (InputPath input : mNewInputs) {
- if (filePath.startsWith(input.mFile.getAbsolutePath())) {
- extensionsToCheck = input.mExtensionsToCheck;
- break;
+ File inputFile = input.getFile();
+ // if the input path is a directory, check if the prereq file is in it,
+ // otherwise check if the prereq file match exactly the input path.
+ if (inputFile.isDirectory()) {
+ if (filePath.startsWith(inputFile.getAbsolutePath())) {
+ // ok file is inside a directory type input folder.
+ // check if we need to check this type of file, and if yes, check it.
+ if (input.checksForModification(prereq)) {
+ if (prereq.lastModified() > oldestTarget) {
+ return DependencyStatus.UPDATED_FILE;
+ }
+ }
+ }
+ } else {
+ // this is a file input path, we must check if the match is exact.
+ if (prereq.equals(inputFile)) {
+ if (input.checksForModification(prereq)) {
+ if (prereq.lastModified() > oldestTarget) {
+ return DependencyStatus.UPDATED_FILE;
+ }
+ }
+ }
}
}
}
-
- if (extensionsToCheck == null || extensionsToCheck.contains(getExtension(prereq))) {
- if (prereq.lastModified() > oldestTarget) {
- return DependencyStatus.UPDATED_FILE;
- }
- }
}
// If we get this far, then all our prereq are okay
@@ -415,19 +418,4 @@ public class DependencyGraph {
}
return null;
}
-
- /**
- * Gets the extension (if present) on a file by looking at the filename
- * @param file the file to get the extension of
- * @return the extension if present, or the empty string if the filename doesn't have
- * and extension.
- */
- private static String getExtension(File file) {
- String filename = file.getName();
- if (filename.lastIndexOf('.') == -1) {
- return "";
- }
- // Don't include the leading '.' in the extension
- return filename.substring(filename.lastIndexOf('.') + 1);
- }
}
diff --git a/anttasks/src/com/android/ant/DexExecTask.java b/anttasks/src/com/android/ant/DexExecTask.java
index e4296b2..4016417 100644
--- a/anttasks/src/com/android/ant/DexExecTask.java
+++ b/anttasks/src/com/android/ant/DexExecTask.java
@@ -16,8 +16,6 @@
package com.android.ant;
-import com.android.ant.DependencyGraph.InputPath;
-
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.taskdefs.ExecTask;
import org.apache.tools.ant.types.FileSet;
@@ -163,7 +161,7 @@ public class DexExecTask extends BaseTask {
task.createArg().setValue(mOutput);
- for (File f :paths) {
+ for (File f : paths) {
task.createArg().setValue(f.getAbsolutePath());
}
@@ -171,7 +169,7 @@ public class DexExecTask extends BaseTask {
task.execute();
// generate the dependency file.
- generateDependencyFile(depFile, paths, mOutput);
+ generateDependencyFile(depFile, inputPaths, mOutput);
}
@Override
diff --git a/anttasks/src/com/android/ant/InputPath.java b/anttasks/src/com/android/ant/InputPath.java
new file mode 100644
index 0000000..3327385
--- /dev/null
+++ b/anttasks/src/com/android/ant/InputPath.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.ant;
+
+import java.io.File;
+import java.util.Set;
+
+public class InputPath {
+
+ private final File mFile;
+ /**
+ * 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.
+ */
+ private final Set<String> mTouchedExtensions;
+
+ public InputPath(File file) {
+ this(file, null);
+ }
+
+ public InputPath(File file, Set<String> extensionsToCheck) {
+ mFile = file;
+ mTouchedExtensions = extensionsToCheck;
+ }
+
+ public File getFile() {
+ return mFile;
+ }
+
+ /**
+ * Returns whether this input path (likely actually a folder) must check this files for
+ * modification (all files are checked for add/delete).
+ *
+ * This is configured by constructing the {@link InputPath} with additional restriction
+ * parameters such as specific extensions.
+ * @param file the file to check
+ * @return true if the file must be checked for modification.
+ */
+ public boolean checksForModification(File file) {
+ if (ignores(file)) {
+ return false;
+ }
+
+ if (mTouchedExtensions != null &&
+ mTouchedExtensions.contains(getExtension(file)) == false) {
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Returns whether the InputPath ignores a given file or folder. If it is ignored then
+ * the file (or folder) is not checked for any event (modification/add/delete).
+ * If it's a folder, then it and its content are completely ignored.
+ * @param file the file or folder to check
+ * @return true if the file or folder are ignored.
+ */
+ public boolean ignores(File file) {
+ return false;
+ }
+
+ /**
+ * Gets the extension (if present) on a file by looking at the filename
+ * @param file the file to get the extension of
+ * @return the extension if present, or the empty string if the filename doesn't have
+ * and extension.
+ */
+ protected static String getExtension(File file) {
+ String filename = file.getName();
+ int index = filename.lastIndexOf('.');
+ if (index == -1) {
+ return "";
+ }
+ // Don't include the leading '.' in the extension
+ return filename.substring(index + 1);
+ }
+
+}