diff options
author | Xavier Ducrohet <xav@android.com> | 2011-10-14 11:13:58 -0700 |
---|---|---|
committer | Xavier Ducrohet <xav@android.com> | 2011-10-14 15:09:08 -0700 |
commit | e162064a7b5db1eecec34271bc7e2a4296181ea6 (patch) | |
tree | 24e0ac58aca71ad112e018a9c2b435e3a0fbb395 /anttasks | |
parent | 081eec9d6c307290535413033626c05cfc67635d (diff) | |
download | sdk-e162064a7b5db1eecec34271bc7e2a4296181ea6.zip sdk-e162064a7b5db1eecec34271bc7e2a4296181ea6.tar.gz sdk-e162064a7b5db1eecec34271bc7e2a4296181ea6.tar.bz2 |
Add BuildConfig to ant SDK project.
The BuildConfig class contains a single boolean constant
called DEBUG which is true only for debug/instrumented builds.
This allows developers to create debug only code that's automatically
stripped from release builds.
Also fixed some issues with dependency check for other tasks, notably
the aapt task that would always find new files due to not filtering
out files that are ignored by aapt itself (hidden files, version control
files, etc...)
Change-Id: I4391a87c064a185d6b337ca46e3a9f0e43c5174d
Diffstat (limited to 'anttasks')
-rw-r--r-- | anttasks/src/com/android/ant/AaptExecTask.java | 47 | ||||
-rw-r--r-- | anttasks/src/com/android/ant/BuildConfigTask.java | 68 | ||||
-rw-r--r-- | anttasks/src/com/android/ant/BuildTypedTask.java | 63 | ||||
-rw-r--r-- | anttasks/src/com/android/ant/DependencyGraph.java | 26 | ||||
-rw-r--r-- | anttasks/src/com/android/ant/DexExecTask.java | 3 | ||||
-rw-r--r-- | anttasks/src/com/android/ant/InputPath.java | 20 | ||||
-rw-r--r-- | anttasks/src/com/android/ant/SingleDependencyTask.java | 51 |
7 files changed, 248 insertions, 30 deletions
diff --git a/anttasks/src/com/android/ant/AaptExecTask.java b/anttasks/src/com/android/ant/AaptExecTask.java index 45adc7c..8731732 100644 --- a/anttasks/src/com/android/ant/AaptExecTask.java +++ b/anttasks/src/com/android/ant/AaptExecTask.java @@ -25,6 +25,7 @@ import java.io.File; import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.Set; /** * Task to execute aapt. @@ -95,6 +96,46 @@ public final class AaptExecTask extends SingleDependencyTask { private boolean mNonConstantId; /** + * Input path that ignores the same file that aapt does. + */ + private static class ResFolderInputPath extends InputPath { + public ResFolderInputPath(File file, Set<String> extensionsToCheck) { + super(file, extensionsToCheck); + } + + @Override + public boolean ignores(File file) { + String name = file.getName(); + char firstChar = name.charAt(0); + + if (firstChar == '.' || (firstChar == '_' && file.isDirectory()) || + name.charAt(name.length()-1) == '~') { + return true; + } + + if ("CVS".equals(name) || + "thumbs.db".equalsIgnoreCase(name) || + "picasa.ini".equalsIgnoreCase(name)) { + return true; + } + + String ext = getExtension(name); + if ("scc".equalsIgnoreCase(ext)) { + return true; + } + + return false; + } + } + + private final static InputPathFactory sPathFactory = new InputPathFactory() { + + public InputPath createPath(File file, Set<String> extensionsToCheck) { + return new ResFolderInputPath(file, extensionsToCheck); + } + }; + + /** * Sets the value of the "executable" attribute. * @param executable the value. */ @@ -351,7 +392,8 @@ public final class AaptExecTask extends SingleDependencyTask { 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")); + List<InputPath> inputPaths = getInputPaths(paths, Collections.singleton("xml"), + sPathFactory); // let's not forget the manifest as an input path (with no extension restrictions). if (mManifest != null) { @@ -369,7 +411,8 @@ public final class AaptExecTask extends SingleDependencyTask { } else { // 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*/); + List<InputPath> inputPaths = getInputPaths(paths, null /*extensionsToCheck*/, + sPathFactory); // let's not forget the manifest as an input path. if (mManifest != null) { diff --git a/anttasks/src/com/android/ant/BuildConfigTask.java b/anttasks/src/com/android/ant/BuildConfigTask.java new file mode 100644 index 0000000..08f91e9 --- /dev/null +++ b/anttasks/src/com/android/ant/BuildConfigTask.java @@ -0,0 +1,68 @@ +/* + * 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 com.android.sdklib.internal.build.BuildConfigGenerator; + +import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.types.Path; + +import java.io.IOException; + +public class BuildConfigTask extends BuildTypedTask { + + private String mGenFolder; + private String mAppPackage; + + public void setGenFolder(Path path) { + mGenFolder = TaskHelper.checkSinglePath("genFolder", path); + } + + public void setPackage(String appPackage) { + mAppPackage = appPackage; + } + + + @Override + public void execute() throws BuildException { + if (mGenFolder == null) { + throw new BuildException("Missing attribute genFolder"); + } + if (mAppPackage == null) { + throw new BuildException("Missing attribute package"); + } + + if (hasBuildTypeChanged()) { + if (isNewBuild()) { + System.out.println("Generating BuildConfig class."); + } else { + System.out.println("Build type changed: Generating new BuildConfig class."); + } + BuildConfigGenerator generator = new BuildConfigGenerator( + mGenFolder, mAppPackage, + Boolean.parseBoolean(getBuildType())); + + try { + generator.generate(); + } catch (IOException e) { + throw new BuildException("Failed to create BuildConfig class", e); + } + } else { + System.out.println("No need to generate new BuildConfig."); + } + } +} diff --git a/anttasks/src/com/android/ant/BuildTypedTask.java b/anttasks/src/com/android/ant/BuildTypedTask.java new file mode 100644 index 0000000..c697bac --- /dev/null +++ b/anttasks/src/com/android/ant/BuildTypedTask.java @@ -0,0 +1,63 @@ +/* + * 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 org.apache.tools.ant.Task; + +/** + * Base class for tasks that should exec when the build type change. + */ +public abstract class BuildTypedTask extends Task { + + private String mPreviousBuildType; + private String mBuildType; + + /** Sets the current build type */ + public void setBuildType(String buildType) { + mBuildType = buildType; + } + + /** Sets the previous build type */ + public void setPreviousBuildType(String previousBuildType) { + mPreviousBuildType = previousBuildType; + } + + protected String getBuildType() { + return mBuildType; + } + + /** + * Returns if it is a new build. If the built type is not input + * from the XML, this always returns true. + * A build type is defined by having an empty previousBuildType. + */ + protected boolean isNewBuild() { + return mBuildType == null || mPreviousBuildType.length() == 0; + } + + /** + * Returns true if the build type changed. + */ + protected boolean hasBuildTypeChanged() { + // no build type? return false as the feature is simply not used + if (mBuildType == null && mPreviousBuildType == null) { + return false; + } + + return mBuildType.equals(mPreviousBuildType) == false; + } +} diff --git a/anttasks/src/com/android/ant/DependencyGraph.java b/anttasks/src/com/android/ant/DependencyGraph.java index 1885c17..8671359 100644 --- a/anttasks/src/com/android/ant/DependencyGraph.java +++ b/anttasks/src/com/android/ant/DependencyGraph.java @@ -35,6 +35,8 @@ import java.util.Set; */ public class DependencyGraph { + private final static boolean DEBUG = false; + private static enum DependencyStatus { NONE, NEW_FILE, UPDATED_FILE, MISSING_FILE, ERROR; } @@ -189,6 +191,9 @@ public class DependencyGraph { mPrereqs = new HashSet<File>(prereqs.length); for (String path : prereqs) { if (path.length() > 0) { + if (DEBUG) { + System.out.println("PREREQ: " + path); + } File f = new File(path); if (mFirstPrereq == null) { mFirstPrereq = f; @@ -290,12 +295,19 @@ public class DependencyGraph { // files to go through manually if (mPrereqs.remove(file) == false) { // turns out this is a new file! + + if (DEBUG) { + System.out.println("NEW FILE: " + file.getAbsolutePath()); + } return DependencyStatus.NEW_FILE; } else { // 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) { + if (DEBUG) { + System.out.println("UPDATED FILE: " + file.getAbsolutePath()); + } return DependencyStatus.UPDATED_FILE; } } @@ -319,6 +331,9 @@ public class DependencyGraph { // Loop through our prereq files and make sure they still exist for (File prereq : mPrereqs) { if (prereq.exists() == false) { + if (DEBUG) { + System.out.println("MISSING FILE: " + prereq.getAbsolutePath()); + } return DependencyStatus.MISSING_FILE; } @@ -336,6 +351,10 @@ public class DependencyGraph { // check if we need to check this type of file, and if yes, check it. if (input.checksForModification(prereq)) { if (prereq.lastModified() > oldestTarget) { + if (DEBUG) { + System.out.println( + "UPDATED FILE: " + prereq.getAbsolutePath()); + } return DependencyStatus.UPDATED_FILE; } } @@ -345,6 +364,10 @@ public class DependencyGraph { if (prereq.equals(inputFile)) { if (input.checksForModification(prereq)) { if (prereq.lastModified() > oldestTarget) { + if (DEBUG) { + System.out.println( + "UPDATED FILE: " + prereq.getAbsolutePath()); + } return DependencyStatus.UPDATED_FILE; } } @@ -354,6 +377,9 @@ public class DependencyGraph { } else { // no input? we consider all files. if (prereq.lastModified() > oldestTarget) { + if (DEBUG) { + System.out.println("UPDATED FILE: " + prereq.getAbsolutePath()); + } return DependencyStatus.UPDATED_FILE; } } diff --git a/anttasks/src/com/android/ant/DexExecTask.java b/anttasks/src/com/android/ant/DexExecTask.java index 6be0a98..2d9479e 100644 --- a/anttasks/src/com/android/ant/DexExecTask.java +++ b/anttasks/src/com/android/ant/DexExecTask.java @@ -129,7 +129,8 @@ public class DexExecTask extends SingleDependencyTask { String depFile = mOutput + ".d"; // get InputPath with no extension restrictions - List<InputPath> inputPaths = getInputPaths(paths, null /*extensionsToCheck*/); + List<InputPath> inputPaths = getInputPaths(paths, null /*extensionsToCheck*/, + null /*factory*/); if (initDependencies(depFile, inputPaths) && dependenciesHaveChanged() == false) { System.out.println( diff --git a/anttasks/src/com/android/ant/InputPath.java b/anttasks/src/com/android/ant/InputPath.java index 3327385..b1a98b5 100644 --- a/anttasks/src/com/android/ant/InputPath.java +++ b/anttasks/src/com/android/ant/InputPath.java @@ -72,23 +72,33 @@ public class InputPath { * @return true if the file or folder are ignored. */ public boolean ignores(File file) { - return false; + // always ignore hidden files/folders. + return file.getName().startsWith(".") == false; } /** * Gets the extension (if present) on a file by looking at the filename - * @param file the file to get the extension of + * @param file the file to get the extension from * @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('.'); + return getExtension(file.getName()); + } + + /** + * Gets the extension (if present) on a file by looking at the filename + * @param fileName the filename to get the extension from + * @return the extension if present, or the empty string if the filename doesn't have + * and extension. + */ + protected static String getExtension(String fileName) { + int index = fileName.lastIndexOf('.'); if (index == -1) { return ""; } // Don't include the leading '.' in the extension - return filename.substring(index + 1); + return fileName.substring(index + 1); } } diff --git a/anttasks/src/com/android/ant/SingleDependencyTask.java b/anttasks/src/com/android/ant/SingleDependencyTask.java index dc3e15d..926e59c 100644 --- a/anttasks/src/com/android/ant/SingleDependencyTask.java +++ b/anttasks/src/com/android/ant/SingleDependencyTask.java @@ -17,7 +17,6 @@ package com.android.ant; import org.apache.tools.ant.BuildException; -import org.apache.tools.ant.Task; import java.io.File; import java.io.FileNotFoundException; @@ -29,21 +28,21 @@ import java.util.Set; /** * A base class for ant tasks that use a single dependency files to control (re)execution. */ -public abstract class SingleDependencyTask extends Task { +public abstract class SingleDependencyTask extends BuildTypedTask { private DependencyGraph mDependencies; - private String mPreviousBuildType; - private String mBuildType; - public void setPreviousBuildType(String previousBuildType) { - mPreviousBuildType = previousBuildType; - } + protected abstract String getExecTaskName(); - public void setBuildType(String buildType) { - mBuildType = buildType; + protected interface InputPathFactory { + InputPath createPath(File file, Set<String> extensionsToCheck); } - protected abstract String getExecTaskName(); + private final static InputPathFactory sDefaultFactory = new InputPathFactory() { + public InputPath createPath(File file, Set<String> extensionsToCheck) { + return new InputPath(file, extensionsToCheck); + } + }; /** * Creates a list of {@link InputPath} from a list of {@link File} and an optional list of @@ -55,11 +54,15 @@ public abstract class SingleDependencyTask extends Task { * @return a list of {@link InputPath} */ protected static List<InputPath> getInputPaths(List<File> paths, - Set<String> extensionsToCheck) { + Set<String> extensionsToCheck, InputPathFactory factory) { List<InputPath> result = new ArrayList<InputPath>(paths.size()); + if (factory == null ) { + factory = sDefaultFactory; + } + for (File f : paths) { - result.add(new InputPath(f, extensionsToCheck)); + result.add(factory.createPath(f, extensionsToCheck)); } return result; @@ -73,7 +76,7 @@ public abstract class SingleDependencyTask extends Task { * @return true if the dependency graph was successfully initialized */ protected boolean initDependencies(String dependencyFile, List<InputPath> inputPaths) { - if (mBuildType != null && mBuildType.equals(mPreviousBuildType) == false) { + if (hasBuildTypeChanged()) { // we don't care about deps, we need to execute the task no matter what. return true; } @@ -93,15 +96,19 @@ public abstract class SingleDependencyTask extends Task { * have changed since the last run */ protected boolean dependenciesHaveChanged() { - if (mBuildType != null && mBuildType.equals(mPreviousBuildType) == false) { - String execName = getExecTaskName(); - if (execName == null) { - System.out.println( - "Current build type is different than previous build: forced task run."); - } else { - System.out.println( - "Current build type is different than previous build: forced " + - execName + " run."); + if (hasBuildTypeChanged()) { + // if this is not a new build, display that build type change is forcing running + // the task. + if (isNewBuild() == false) { + String execName = getExecTaskName(); + if (execName == null) { + System.out.println( + "Current build type is different than previous build: forced task run."); + } else { + System.out.println( + "Current build type is different than previous build: forced " + + execName + " run."); + } } return true; } |