aboutsummaryrefslogtreecommitdiffstats
path: root/anttasks
diff options
context:
space:
mode:
Diffstat (limited to 'anttasks')
-rw-r--r--anttasks/src/com/android/ant/AaptExecLoopTask.java30
-rw-r--r--anttasks/src/com/android/ant/AidlExecTask.java5
-rw-r--r--anttasks/src/com/android/ant/AntConstants.java63
-rw-r--r--anttasks/src/com/android/ant/BaseTask.java39
-rw-r--r--anttasks/src/com/android/ant/MultiApkExportTask.java18
-rw-r--r--anttasks/src/com/android/ant/NewSetupTask.java638
-rw-r--r--anttasks/src/com/android/ant/SetupTask.java587
7 files changed, 720 insertions, 660 deletions
diff --git a/anttasks/src/com/android/ant/AaptExecLoopTask.java b/anttasks/src/com/android/ant/AaptExecLoopTask.java
index ebefde5..6b438bb 100644
--- a/anttasks/src/com/android/ant/AaptExecLoopTask.java
+++ b/anttasks/src/com/android/ant/AaptExecLoopTask.java
@@ -88,6 +88,8 @@ public final class AaptExecLoopTask extends BaseTask {
private String mResourceFilter;
private String mRFolder;
private final ArrayList<NoCompress> mNoCompressList = new ArrayList<NoCompress>();
+ private String mProjectLibrariesResName;
+ private String mProjectLibrariesPackageName;
/**
* Sets the value of the "executable" attribute.
@@ -235,6 +237,15 @@ public final class AaptExecLoopTask extends BaseTask {
}
}
+ public void setProjectLibrariesResName(String projectLibrariesResName) {
+ mProjectLibrariesResName = projectLibrariesResName;
+ }
+
+ public void setProjectLibrariesPackageName(String projectLibrariesPackageName) {
+ mProjectLibrariesPackageName = projectLibrariesPackageName;
+ }
+
+
/**
* Returns an object representing a nested <var>nocompress</var> element.
*/
@@ -268,6 +279,13 @@ public final class AaptExecLoopTask extends BaseTask {
*/
@Override
public void execute() throws BuildException {
+ if (mProjectLibrariesResName == null) {
+ throw new BuildException("Missing attribute projectLibrariesResName");
+ }
+ if (mProjectLibrariesPackageName == null) {
+ throw new BuildException("Missing attribute projectLibrariesPackageName");
+ }
+
Project taskProject = getProject();
String libPkgProp = null;
@@ -275,7 +293,7 @@ public final class AaptExecLoopTask extends BaseTask {
// if the parameters indicate generation of the R class, check if
// more R classes need to be created for libraries.
if (mRFolder != null && new File(mRFolder).isDirectory()) {
- libPkgProp = taskProject.getProperty(AntConstants.PROP_PROJECT_LIBS_PKG);
+ libPkgProp = taskProject.getProperty(mProjectLibrariesPackageName);
if (libPkgProp != null) {
// Replace ";" with ":" since that's what aapt expects
libPkgProp = libPkgProp.replace(';', ':');
@@ -285,6 +303,11 @@ public final class AaptExecLoopTask extends BaseTask {
callAapt(libPkgProp);
}
+ @Override
+ protected String getExecTaskName() {
+ return "aapt";
+ }
+
/**
* Calls aapt with the given parameters.
* @param resourceFilter the resource configuration filter to pass to aapt (if configName is
@@ -298,7 +321,7 @@ public final class AaptExecLoopTask extends BaseTask {
final boolean generateRClass = mRFolder != null && new File(mRFolder).isDirectory();
// Get whether we have libraries
- Object libResRef = taskProject.getReference(AntConstants.PROP_PROJECT_LIBS_RES_REF);
+ Object libResRef = taskProject.getReference(mProjectLibrariesResName);
// Set up our folders to check for changed files
ArrayList<File> watchPaths = new ArrayList<File>();
@@ -358,8 +381,7 @@ public final class AaptExecLoopTask extends BaseTask {
task.setExecutable(mExecutable);
task.setFailonerror(true);
- File exe = new File(mExecutable);
- task.setTaskName(exe.getName());
+ task.setTaskName(getExecTaskName());
// aapt command. Only "package" is supported at this time really.
task.createArg().setValue(mCommand);
diff --git a/anttasks/src/com/android/ant/AidlExecTask.java b/anttasks/src/com/android/ant/AidlExecTask.java
index f2fa094..5fa1f30 100644
--- a/anttasks/src/com/android/ant/AidlExecTask.java
+++ b/anttasks/src/com/android/ant/AidlExecTask.java
@@ -93,9 +93,6 @@ public class AidlExecTask extends Task {
}
}
- File exe = new File(mExecutable);
- String execTaskName = exe.getName();
-
// now loop on all the source folders to find all the aidl to compile
// and compile them
for (String sourceFolder : sourceFolders) {
@@ -115,7 +112,7 @@ public class AidlExecTask extends Task {
task.setProject(taskProject);
task.setOwningTarget(getOwningTarget());
task.setExecutable(mExecutable);
- task.setTaskName(execTaskName);
+ task.setTaskName("aidl");
task.setFailonerror(true);
task.createArg().setValue("-p" + mFramework);
diff --git a/anttasks/src/com/android/ant/AntConstants.java b/anttasks/src/com/android/ant/AntConstants.java
deleted file mode 100644
index a87d0d5..0000000
--- a/anttasks/src/com/android/ant/AntConstants.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright (C) 2010 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;
-
-/**
- * Constants used by custom tasks and the rules files.
- */
-public interface AntConstants {
-
- /** ant property with the path to the android.jar file */
- public final static String PROP_ANDROID_JAR = "android.jar";
-
- /** ant property with the path to the framework.aidl file */
- public final static String PROP_ANDROID_AIDL = "android.aidl";
-
- /** ant property with the path to the renderscript framework include folder. */
- public final static String PROP_ANDROID_RENDERSCRIPT = "android.rs";
-
- /** ant property with the path to the aapt tool */
- public final static String PROP_AAPT = "aapt";
- /** ant property with the path to the aidl tool */
- public final static String PROP_AIDL = "aidl";
- /** ant property with the path to the dx tool */
- public final static String PROP_DX = "dx";
- /** ant property with the path to the renderscript tool */
- public final static String PROP_RENDERSCRIPT = "renderscript";
- /** ref id to the <path> object containing all the boot classpaths. */
- public final static String PROP_CLASSPATH_REF = "android.target.classpath";
-
- /** ant property ref to the list of source folder for the project libraries */
- public static final String PROP_PROJECT_LIBS_SRC_REF = "project.libraries.src";
- /** ant property ref to the list of jars for the project libraries */
- public static final String PROP_PROJECT_LIBS_JARS_REF = "project.libraries.jars";
- /** ant property ref to the list of libs folder for the project libraries */
- public static final String PROP_PROJECT_LIBS_LIBS_REF = "project.libraries.libs";
- /** ant property ref to the list of res folder for the project libraries */
- public static final String PROP_PROJECT_LIBS_RES_REF = "project.libraries.res";
- /** ant property for semi-colon separated packages for the project libraries */
- public static final String PROP_PROJECT_LIBS_PKG = "project.libraries.package";
- /** ant property for the test project directory */
- public static final String PROP_TESTED_PROJECT_DIR = "tested.project.dir";
-
- public static final String PROP_MANIFEST_PACKAGE = "manifest.package";
-
- public static final String PROP_OUT_ABS_DIR = "out.absolute.dir";
-
- public static final String PROP_KEY_STORE_PASSWORD = "key.store.password";
- public static final String PROP_KEY_ALIAS_PASSWORD = "key.alias.password";
-}
diff --git a/anttasks/src/com/android/ant/BaseTask.java b/anttasks/src/com/android/ant/BaseTask.java
index 2126d3f..00b7fcb 100644
--- a/anttasks/src/com/android/ant/BaseTask.java
+++ b/anttasks/src/com/android/ant/BaseTask.java
@@ -25,18 +25,22 @@ import java.util.ArrayList;
/**
* A base class for the ant task that contains logic for handling dependency files
*/
-public class BaseTask extends Task {
+public abstract class BaseTask extends Task {
private DependencyGraph mDependencies;
+ private String mPreviousBuildType;
+ private String mBuildType;
+
+ public void setPreviousBuildType(String previousBuildType) {
+ mPreviousBuildType = previousBuildType;
+ }
+
+ public void setBuildType(String buildType) {
+ mBuildType = buildType;
+ }
+
+ protected abstract String getExecTaskName();
- /*
- * (non-Javadoc)
- *
- * Executes the loop. Based on the values inside default.properties, this will
- * create alternate temporary ap_ files.
- *
- * @see org.apache.tools.ant.Task#execute()
- */
@Override
public void execute() throws BuildException {
@@ -46,9 +50,14 @@ public class BaseTask extends Task {
* Set up the dependency graph by passing it the location of the ".d" file
* @param dependencyFile path to the dependency file to use
* @param watchPaths a list of folders to watch for new files
- * @return true if the dependency graph was sucessfully initialized
+ * @return true if the dependency graph was successfully initialized
*/
protected boolean initDependencies(String dependencyFile, ArrayList<File> watchPaths) {
+ if (mBuildType != null && mBuildType.equals(mPreviousBuildType) == false) {
+ // we don't care about deps, we need to execute the task no matter what.
+ return true;
+ }
+
File depFile = new File(dependencyFile);
if (depFile.exists()) {
mDependencies = new DependencyGraph(dependencyFile, watchPaths);
@@ -64,6 +73,16 @@ public class BaseTask 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.");
+ }
+ return true;
+ }
+
assert mDependencies != null : "Dependencies have not been initialized";
return mDependencies.dependenciesHaveChanged();
}
diff --git a/anttasks/src/com/android/ant/MultiApkExportTask.java b/anttasks/src/com/android/ant/MultiApkExportTask.java
index a21478e..6b23162 100644
--- a/anttasks/src/com/android/ant/MultiApkExportTask.java
+++ b/anttasks/src/com/android/ant/MultiApkExportTask.java
@@ -52,6 +52,12 @@ import javax.xml.xpath.XPathFactory;
*/
public class MultiApkExportTask extends Task {
+ private static final String PROP_OUT_ABS_DIR = "out.absolute.dir";
+
+ private static final String PROP_KEY_STORE_PASSWORD = "key.store.password";
+ private static final String PROP_KEY_ALIAS_PASSWORD = "key.alias.password";
+
+
private Target mTarget;
private XPathFactory mXPathFactory;
@@ -117,7 +123,7 @@ public class MultiApkExportTask extends Task {
mXPathFactory = XPathFactory.newInstance();
File exportProjectOutput = new File(
- getValidatedProperty(antProject, AntConstants.PROP_OUT_ABS_DIR));
+ getValidatedProperty(antProject, PROP_OUT_ABS_DIR));
// if there's no error, and we can sign, prompt for the passwords.
String keyStorePassword = null;
@@ -127,23 +133,21 @@ public class MultiApkExportTask extends Task {
Input input = new Input();
input.setProject(antProject);
- input.setAddproperty(AntConstants.PROP_KEY_STORE_PASSWORD);
+ input.setAddproperty(PROP_KEY_STORE_PASSWORD);
input.setMessage(String.format("Please enter keystore password (store: %1$s):",
keyStore));
input.execute();
input = new Input();
input.setProject(antProject);
- input.setAddproperty(AntConstants.PROP_KEY_ALIAS_PASSWORD);
+ input.setAddproperty(PROP_KEY_ALIAS_PASSWORD);
input.setMessage(String.format("Please enter password for alias '%1$s':",
keyAlias));
input.execute();
// and now read the property so that they can be set into the sub ant task.
- keyStorePassword = getValidatedProperty(antProject,
- AntConstants.PROP_KEY_STORE_PASSWORD);
- keyAliasPassword = getValidatedProperty(antProject,
- AntConstants.PROP_KEY_ALIAS_PASSWORD);
+ keyStorePassword = getValidatedProperty(antProject, PROP_KEY_STORE_PASSWORD);
+ keyAliasPassword = getValidatedProperty(antProject, PROP_KEY_ALIAS_PASSWORD);
}
for (ApkData apk : apks) {
diff --git a/anttasks/src/com/android/ant/NewSetupTask.java b/anttasks/src/com/android/ant/NewSetupTask.java
new file mode 100644
index 0000000..50dcdab
--- /dev/null
+++ b/anttasks/src/com/android/ant/NewSetupTask.java
@@ -0,0 +1,638 @@
+/*
+ * Copyright (C) 2009 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.io.FileWrapper;
+import com.android.io.FolderWrapper;
+import com.android.sdklib.AndroidVersion;
+import com.android.sdklib.IAndroidTarget;
+import com.android.sdklib.ISdkLog;
+import com.android.sdklib.SdkConstants;
+import com.android.sdklib.SdkManager;
+import com.android.sdklib.IAndroidTarget.IOptionalLibrary;
+import com.android.sdklib.internal.project.ProjectProperties;
+import com.android.sdklib.internal.project.ProjectProperties.PropertyType;
+import com.android.sdklib.xml.AndroidManifest;
+import com.android.sdklib.xml.AndroidXPathFactory;
+
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.Project;
+import org.apache.tools.ant.Task;
+import org.apache.tools.ant.types.Path;
+import org.apache.tools.ant.types.Path.PathElement;
+import org.apache.tools.ant.util.DeweyDecimal;
+import org.xml.sax.InputSource;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FilenameFilter;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+
+import javax.xml.xpath.XPath;
+import javax.xml.xpath.XPathExpressionException;
+
+/**
+ * Setup Ant task. This task accomplishes:
+ * <ul>
+ * <li>Gets the project target hash string from {@link ProjectProperties#PROPERTY_TARGET},
+ * and resolves it to get the project's {@link IAndroidTarget}.</li>
+ *
+ * <li>Sets up properties so that aapt can find the android.jar and other files/folders in
+ * the resolved target.</li>
+ *
+ * <li>Sets up the boot classpath ref so that the <code>javac</code> task knows where to find
+ * the libraries. This includes the default android.jar from the resolved target but also optional
+ * libraries provided by the target (if any, when the target is an add-on).</li>
+ *
+ * <li>Resolve library dependencies and setup various Path references for them</li>
+ * </ul>
+ *
+ * This is used in the main rules file only.
+ *
+ */
+public class NewSetupTask extends Task {
+ private final static String ANT_MIN_VERSION = "1.8.0";
+
+ private String mProjectTypeOut;
+ private String mAndroidJarFileOut;
+ private String mAndroidAidlFileOut;
+ private String mRenderScriptExeOut;
+ private String mRenderScriptIncludeDirOut;
+ private String mBootclasspathrefOut;
+ private String mProjectLibrariesRootOut;
+ private String mProjectLibrariesResOut;
+ private String mProjectLibrariesPackageOut;
+ private String mProjectLibrariesJarsOut;
+ private String mProjectLibrariesLibsOut;
+
+ public void setProjectTypeOut(String projectTypeOut) {
+ mProjectTypeOut = projectTypeOut;
+ }
+
+ public void setAndroidJarFileOut(String androidJarFileOut) {
+ mAndroidJarFileOut = androidJarFileOut;
+ }
+
+ public void setAndroidAidlFileOut(String androidAidlFileOut) {
+ mAndroidAidlFileOut = androidAidlFileOut;
+ }
+
+ public void setRenderScriptExeOut(String renderScriptExeOut) {
+ mRenderScriptExeOut = renderScriptExeOut;
+ }
+
+ public void setRenderScriptIncludeDirOut(String renderScriptIncludeDirOut) {
+ mRenderScriptIncludeDirOut = renderScriptIncludeDirOut;
+ }
+
+ public void setBootclasspathrefOut(String bootclasspathrefOut) {
+ mBootclasspathrefOut = bootclasspathrefOut;
+ }
+
+ public void setProjectLibrariesRootOut(String projectLibrariesRootOut) {
+ mProjectLibrariesRootOut = projectLibrariesRootOut;
+ }
+
+ public void setProjectLibrariesResOut(String projectLibrariesResOut) {
+ mProjectLibrariesResOut = projectLibrariesResOut;
+ }
+
+ public void setProjectLibrariesPackageOut(String projectLibrariesPackageOut) {
+ mProjectLibrariesPackageOut = projectLibrariesPackageOut;
+ }
+
+ public void setProjectLibrariesJarsOut(String projectLibrariesJarsOut) {
+ mProjectLibrariesJarsOut = projectLibrariesJarsOut;
+ }
+
+ public void setProjectLibrariesLibsOut(String projectLibrariesLibsOut) {
+ mProjectLibrariesLibsOut = projectLibrariesLibsOut;
+ }
+
+ @Override
+ public void execute() throws BuildException {
+ if (mProjectTypeOut == null) {
+ throw new BuildException("Missing attribute projectTypeOut");
+ }
+ if (mAndroidJarFileOut == null) {
+ throw new BuildException("Missing attribute androidJarFileOut");
+ }
+ if (mAndroidAidlFileOut == null) {
+ throw new BuildException("Missing attribute androidAidlFileOut");
+ }
+ if (mRenderScriptExeOut == null) {
+ throw new BuildException("Missing attribute renderScriptExeOut");
+ }
+ if (mRenderScriptIncludeDirOut == null) {
+ throw new BuildException("Missing attribute renderScriptIncludeDirOut");
+ }
+ if (mBootclasspathrefOut == null) {
+ throw new BuildException("Missing attribute bootclasspathrefOut");
+ }
+ if (mProjectLibrariesRootOut == null) {
+ throw new BuildException("Missing attribute projectLibrariesRootOut");
+ }
+ if (mProjectLibrariesResOut == null) {
+ throw new BuildException("Missing attribute projectLibrariesResOut");
+ }
+ if (mProjectLibrariesPackageOut == null) {
+ throw new BuildException("Missing attribute projectLibrariesPackageOut");
+ }
+ if (mProjectLibrariesJarsOut == null) {
+ throw new BuildException("Missing attribute projectLibrariesJarsOut");
+ }
+ if (mProjectLibrariesLibsOut == null) {
+ throw new BuildException("Missing attribute projectLibrariesLibsOut");
+ }
+
+
+ Project antProject = getProject();
+
+ // check the Ant version
+ DeweyDecimal version = getVersion(antProject);
+ DeweyDecimal atLeast = new DeweyDecimal(ANT_MIN_VERSION);
+ if (atLeast.isGreaterThan(version)) {
+ throw new BuildException(
+ "The Android Ant-based build system requires Ant " +
+ ANT_MIN_VERSION +
+ " or later. Current version is " +
+ version);
+ }
+
+ // get the SDK location
+ File sdkDir = TaskHelper.getSdkLocation(antProject);
+ String sdkOsPath = sdkDir.getPath();
+
+ // Make sure the OS sdk path ends with a directory separator
+ if (sdkOsPath.length() > 0 && !sdkOsPath.endsWith(File.separator)) {
+ sdkOsPath += File.separator;
+ }
+
+ // display SDK Tools revision
+ int toolsRevison = TaskHelper.getToolsRevision(sdkDir);
+ if (toolsRevison != -1) {
+ System.out.println("Android SDK Tools Revision " + toolsRevison);
+ }
+
+ // detect that the platform tools is there.
+ File platformTools = new File(sdkDir, SdkConstants.FD_PLATFORM_TOOLS);
+ if (platformTools.isDirectory() == false) {
+ throw new BuildException(String.format(
+ "SDK Platform Tools component is missing. " +
+ "Please install it with the SDK Manager (%1$s%2$c%3$s)",
+ SdkConstants.FD_TOOLS,
+ File.separatorChar,
+ SdkConstants.androidCmdName()));
+ }
+
+ // get the target property value
+ String targetHashString = antProject.getProperty(ProjectProperties.PROPERTY_TARGET);
+
+ boolean isTestProject = false;
+
+ if (antProject.getProperty(ProjectProperties.PROPERTY_TESTED_PROJECT) != null) {
+ isTestProject = true;
+ }
+
+ if (targetHashString == null) {
+ throw new BuildException("Android Target is not set.");
+ }
+
+ // load up the sdk targets.
+ final ArrayList<String> messages = new ArrayList<String>();
+ SdkManager manager = SdkManager.createManager(sdkOsPath, new ISdkLog() {
+ public void error(Throwable t, String errorFormat, Object... args) {
+ if (errorFormat != null) {
+ messages.add(String.format("Error: " + errorFormat, args));
+ }
+ if (t != null) {
+ messages.add("Error: " + t.getMessage());
+ }
+ }
+
+ public void printf(String msgFormat, Object... args) {
+ messages.add(String.format(msgFormat, args));
+ }
+
+ public void warning(String warningFormat, Object... args) {
+ messages.add(String.format("Warning: " + warningFormat, args));
+ }
+ });
+
+ if (manager == null) {
+ // since we failed to parse the SDK, lets display the parsing output.
+ for (String msg : messages) {
+ System.out.println(msg);
+ }
+ throw new BuildException("Failed to parse SDK content.");
+ }
+
+ // resolve it
+ IAndroidTarget androidTarget = manager.getTargetFromHashString(targetHashString);
+
+ if (androidTarget == null) {
+ throw new BuildException(String.format(
+ "Unable to resolve target '%s'", targetHashString));
+ }
+
+ // display the project info
+ System.out.println("Project Target: " + androidTarget.getName());
+ if (androidTarget.isPlatform() == false) {
+ System.out.println("Vendor: " + androidTarget.getVendor());
+ System.out.println("Platform Version: " + androidTarget.getVersionName());
+ }
+ System.out.println("API level: " + androidTarget.getVersion().getApiString());
+
+ // check if the project is a library
+ boolean isLibrary = false;
+
+ String libraryProp = antProject.getProperty(ProjectProperties.PROPERTY_LIBRARY);
+ if (libraryProp != null) {
+ isLibrary = Boolean.valueOf(libraryProp).booleanValue();
+ }
+
+ if (isLibrary) {
+ System.out.println("Project Type: Android Library");
+ }
+
+ // look for referenced libraries.
+ processReferencedLibraries(antProject, androidTarget);
+
+ // always check the manifest minSdkVersion.
+ checkManifest(antProject, androidTarget.getVersion());
+
+ // sets up the properties to find android.jar/framework.aidl/target tools
+ String androidJar = androidTarget.getPath(IAndroidTarget.ANDROID_JAR);
+ antProject.setProperty(mAndroidJarFileOut, androidJar);
+
+ String androidAidl = androidTarget.getPath(IAndroidTarget.ANDROID_AIDL);
+ antProject.setProperty(mAndroidAidlFileOut, androidAidl);
+
+ Path includePath = new Path(antProject);
+ PathElement element = includePath.createPathElement();
+ element.setPath(androidTarget.getPath(IAndroidTarget.ANDROID_RS));
+ element = includePath.createPathElement();
+ element.setPath(androidTarget.getPath(IAndroidTarget.ANDROID_RS_CLANG));
+ antProject.setProperty(mRenderScriptIncludeDirOut, includePath.toString());
+
+ // TODO: figure out the actual compiler to use based on the minSdkVersion
+ antProject.setProperty(mRenderScriptExeOut,
+ sdkOsPath + SdkConstants.OS_SDK_PLATFORM_TOOLS_FOLDER +
+ SdkConstants.FN_RENDERSCRIPT);
+
+ // sets up the boot classpath
+
+ // create the Path object
+ Path bootclasspath = new Path(antProject);
+
+ // create a PathElement for the framework jar
+ element = bootclasspath.createPathElement();
+ element.setPath(androidJar);
+
+ // create PathElement for each optional library.
+ IOptionalLibrary[] libraries = androidTarget.getOptionalLibraries();
+ if (libraries != null) {
+ HashSet<String> visitedJars = new HashSet<String>();
+ for (IOptionalLibrary library : libraries) {
+ String jarPath = library.getJarPath();
+ if (visitedJars.contains(jarPath) == false) {
+ visitedJars.add(jarPath);
+
+ element = bootclasspath.createPathElement();
+ element.setPath(library.getJarPath());
+ }
+ }
+ }
+
+ // sets the path in the project with a reference
+ antProject.addReference(mBootclasspathrefOut, bootclasspath);
+
+ // finally set the project type.
+ if (isLibrary) {
+ antProject.setProperty(mProjectTypeOut, "library");
+ } else if (isTestProject) {
+ antProject.setProperty(mProjectTypeOut, "test");
+ } else {
+ antProject.setProperty(mProjectTypeOut, "project");
+ }
+ }
+
+ /**
+ * Checks the manifest <code>minSdkVersion</code> attribute.
+ * @param antProject the ant project
+ * @param androidVersion the version of the platform the project is compiling against.
+ */
+ private void checkManifest(Project antProject, AndroidVersion androidVersion) {
+ try {
+ File manifest = new File(antProject.getBaseDir(), SdkConstants.FN_ANDROID_MANIFEST_XML);
+
+ XPath xPath = AndroidXPathFactory.newXPath();
+
+ // check the package name.
+ String value = xPath.evaluate(
+ "/" + AndroidManifest.NODE_MANIFEST +
+ "/@" + AndroidManifest.ATTRIBUTE_PACKAGE,
+ new InputSource(new FileInputStream(manifest)));
+ if (value != null) { // aapt will complain if it's missing.
+ // only need to check that the package has 2 segments
+ if (value.indexOf('.') == -1) {
+ throw new BuildException(String.format(
+ "Application package '%1$s' must have a minimum of 2 segments.",
+ value));
+ }
+ }
+
+ // check the minSdkVersion value
+ value = xPath.evaluate(
+ "/" + AndroidManifest.NODE_MANIFEST +
+ "/" + AndroidManifest.NODE_USES_SDK +
+ "/@" + AndroidXPathFactory.DEFAULT_NS_PREFIX + ":" +
+ AndroidManifest.ATTRIBUTE_MIN_SDK_VERSION,
+ new InputSource(new FileInputStream(manifest)));
+
+ if (androidVersion.isPreview()) {
+ // in preview mode, the content of the minSdkVersion must match exactly the
+ // platform codename.
+ String codeName = androidVersion.getCodename();
+ if (codeName.equals(value) == false) {
+ throw new BuildException(String.format(
+ "For '%1$s' SDK Preview, attribute minSdkVersion in AndroidManifest.xml must be '%1$s'",
+ codeName));
+ }
+ } else if (value.length() > 0) {
+ // for normal platform, we'll only display warnings if the value is lower or higher
+ // than the target api level.
+ // First convert to an int.
+ int minSdkValue = -1;
+ try {
+ minSdkValue = Integer.parseInt(value);
+ } catch (NumberFormatException e) {
+ // looks like it's not a number: error!
+ throw new BuildException(String.format(
+ "Attribute %1$s in AndroidManifest.xml must be an Integer!",
+ AndroidManifest.ATTRIBUTE_MIN_SDK_VERSION));
+ }
+
+ int projectApiLevel = androidVersion.getApiLevel();
+ if (minSdkValue < projectApiLevel) {
+ System.out.println(String.format(
+ "WARNING: Attribute %1$s in AndroidManifest.xml (%2$d) is lower than the project target API level (%3$d)",
+ AndroidManifest.ATTRIBUTE_MIN_SDK_VERSION,
+ minSdkValue, projectApiLevel));
+ } else if (minSdkValue > androidVersion.getApiLevel()) {
+ System.out.println(String.format(
+ "WARNING: Attribute %1$s in AndroidManifest.xml (%2$d) is higher than the project target API level (%3$d)",
+ AndroidManifest.ATTRIBUTE_MIN_SDK_VERSION,
+ minSdkValue, projectApiLevel));
+ }
+ } else {
+ // no minSdkVersion? display a warning
+ System.out.println(
+ "WARNING: No minSdkVersion value set. Application will install on all Android versions.");
+ }
+
+ } catch (XPathExpressionException e) {
+ throw new BuildException(e);
+ } catch (FileNotFoundException e) {
+ throw new BuildException(e);
+ }
+ }
+
+ private void processReferencedLibraries(Project antProject, IAndroidTarget androidTarget) {
+ // prepare several paths for future tasks
+ Path rootPath = new Path(antProject);
+ Path resPath = new Path(antProject);
+ Path libsPath = new Path(antProject);
+ Path jarsPath = new Path(antProject);
+ StringBuilder packageStrBuilder = new StringBuilder();
+
+ FilenameFilter filter = new FilenameFilter() {
+ public boolean accept(File dir, String name) {
+ return name.toLowerCase().endsWith(".jar");
+ }
+ };
+
+ System.out.println("\n------------------\nResolving library dependencies:");
+
+ ArrayList<File> libraries = getProjectLibraries(antProject);
+
+ if (libraries.size() > 0) {
+ System.out.println("------------------\nOrdered libraries:");
+
+ for (File library : libraries) {
+ String libRootPath = library.getAbsolutePath();
+ System.out.println(libRootPath);
+
+ // get the root path.
+ PathElement element = rootPath.createPathElement();
+ element.setPath(libRootPath);
+
+ // get the res path. Always $PROJECT/res
+ element = resPath.createPathElement();
+ element.setPath(libRootPath + "/" + SdkConstants.FD_RESOURCES);
+
+ // get the libs path. Always $PROJECT/libs
+ element = libsPath.createPathElement();
+ element.setPath(libRootPath + "/" + SdkConstants.FD_NATIVE_LIBS);
+
+ // get the jars from it too.
+ // 1. the library code jar
+ element = jarsPath.createPathElement();
+ element.setPath(libRootPath + "/" + SdkConstants.FD_OUTPUT +
+ "/" + SdkConstants.FN_CLASSES_JAR);
+
+ // 2. the 3rd party jar files
+ File libsFolder = new File(library, SdkConstants.FD_NATIVE_LIBS);
+ File[] jarFiles = libsFolder.listFiles(filter);
+ if (jarFiles != null) {
+ for (File jarFile : jarFiles) {
+ element = jarsPath.createPathElement();
+ element.setPath(jarFile.getAbsolutePath());
+ }
+ }
+
+ // get the package from the manifest.
+ FileWrapper manifest = new FileWrapper(library,
+ SdkConstants.FN_ANDROID_MANIFEST_XML);
+
+ try {
+ String value = AndroidManifest.getPackage(manifest);
+ if (value != null) { // aapt will complain if it's missing.
+ packageStrBuilder.append(';');
+ packageStrBuilder.append(value);
+ }
+ } catch (Exception e) {
+ throw new BuildException(e);
+ }
+ }
+ } else {
+ System.out.println("No library dependencies.\n");
+ }
+
+ System.out.println("------------------\n");
+
+ // even with no libraries, always setup these so that various tasks in Ant don't complain
+ // (the task themselves can handle a ref to an empty Path)
+ antProject.addReference(mProjectLibrariesJarsOut, jarsPath);
+ antProject.addReference(mProjectLibrariesLibsOut, libsPath);
+
+ // the rest is done only if there's a library.
+ if (jarsPath.list().length > 0) {
+ System.out.println("DEBUG: " + rootPath.toString());
+ antProject.addReference(mProjectLibrariesRootOut, rootPath);
+ antProject.addReference(mProjectLibrariesResOut, resPath);
+ antProject.setProperty(mProjectLibrariesPackageOut, packageStrBuilder.toString());
+ }
+ }
+
+ /**
+ * Returns all the library dependencies of a given Ant project.
+ * @param antProject the Ant project
+ * @return a list of properties, sorted from highest priority to lowest.
+ */
+ private ArrayList<File> getProjectLibraries(final Project antProject) {
+ ArrayList<File> libraries = new ArrayList<File>();
+ File baseDir = antProject.getBaseDir();
+
+ // get the top level list of library dependencies.
+ List<File> topLevelLibraries = getDirectDependencies(baseDir, new IPropertySource() {
+ public String getProperty(String name) {
+ return antProject.getProperty(name);
+ }
+ });
+
+ // process the libraries in case they depend on other libraries.
+ resolveFullLibraryDependencies(topLevelLibraries, libraries);
+
+ return libraries;
+ }
+
+ /**
+ * Resolves a given list of libraries, finds out if they depend on other libraries, and
+ * returns a full list of all the direct and indirect dependencies in the proper order (first
+ * is higher priority when calling aapt).
+ * @param inLibraries the libraries to resolve
+ * @param outLibraries where to store all the libraries.
+ */
+ private void resolveFullLibraryDependencies(List<File> inLibraries, List<File> outLibraries) {
+ // loop in the inverse order to resolve dependencies on the libraries, so that if a library
+ // is required by two higher level libraries it can be inserted in the correct place
+ for (int i = inLibraries.size() - 1 ; i >= 0 ; i--) {
+ File library = inLibraries.get(i);
+
+ // get the default.property file for it
+ final ProjectProperties defaultProp = ProjectProperties.load(
+ new FolderWrapper(library), PropertyType.DEFAULT);
+
+ // get its libraries
+ List<File> dependencies = getDirectDependencies(library, new IPropertySource() {
+ public String getProperty(String name) {
+ return defaultProp.getProperty(name);
+ }
+ });
+
+ // resolve the dependencies for those libraries
+ resolveFullLibraryDependencies(dependencies, outLibraries);
+
+ // and add the current one (if needed) in front (higher priority)
+ if (outLibraries.contains(library) == false) {
+ outLibraries.add(0, library);
+ }
+ }
+ }
+
+ public interface IPropertySource {
+ String getProperty(String name);
+ }
+
+ /**
+ * Returns the top level library dependencies of a given <var>source</var> representing a
+ * project properties.
+ * @param baseFolder the base folder of the project (to resolve relative paths)
+ * @param source a source of project properties.
+ */
+ private List<File> getDirectDependencies(File baseFolder, IPropertySource source) {
+ ArrayList<File> libraries = new ArrayList<File>();
+
+ // first build the list. they are ordered highest priority first.
+ int index = 1;
+ while (true) {
+ String propName = ProjectProperties.PROPERTY_LIB_REF + Integer.toString(index++);
+ String rootPath = source.getProperty(propName);
+
+ if (rootPath == null) {
+ break;
+ }
+
+ try {
+ File library = new File(baseFolder, rootPath).getCanonicalFile();
+
+ // check for validity
+ File defaultProp = new File(library, PropertyType.DEFAULT.getFilename());
+ if (defaultProp.isFile() == false) {
+ // error!
+ throw new BuildException(String.format(
+ "%1$s resolve to a path with no %2$s file for project %3$s", rootPath,
+ PropertyType.DEFAULT.getFilename(), baseFolder.getAbsolutePath()));
+ }
+
+ if (libraries.contains(library) == false) {
+ System.out.println(String.format("%1$s: %2$s => %3$s",
+ baseFolder.getAbsolutePath(), rootPath, library.getAbsolutePath()));
+
+ libraries.add(library);
+ }
+ } catch (IOException e) {
+ throw new BuildException("Failed to resolve library path: " + rootPath, e);
+ }
+ }
+
+ return libraries;
+ }
+
+ /**
+ * Returns the Ant version as a {@link DeweyDecimal} object.
+ *
+ * This is based on the implementation of
+ * org.apache.tools.ant.taskdefs.condition.AntVersion.getVersion()
+ *
+ * @param antProject the current ant project.
+ * @return the ant version.
+ */
+ private DeweyDecimal getVersion(Project antProject) {
+ char[] versionString = antProject.getProperty("ant.version").toCharArray();
+ StringBuilder sb = new StringBuilder();
+ boolean foundFirstDigit = false;
+ for (int i = 0; i < versionString.length; i++) {
+ if (Character.isDigit(versionString[i])) {
+ sb.append(versionString[i]);
+ foundFirstDigit = true;
+ }
+ if (versionString[i] == '.' && foundFirstDigit) {
+ sb.append(versionString[i]);
+ }
+ if (Character.isLetter(versionString[i]) && foundFirstDigit) {
+ break;
+ }
+ }
+ return new DeweyDecimal(sb.toString());
+ }
+}
diff --git a/anttasks/src/com/android/ant/SetupTask.java b/anttasks/src/com/android/ant/SetupTask.java
index e15f77b..c0bc55d 100644
--- a/anttasks/src/com/android/ant/SetupTask.java
+++ b/anttasks/src/com/android/ant/SetupTask.java
@@ -16,588 +16,31 @@
package com.android.ant;
-import com.android.io.FileWrapper;
-import com.android.io.FolderWrapper;
-import com.android.sdklib.AndroidVersion;
-import com.android.sdklib.IAndroidTarget;
-import com.android.sdklib.ISdkLog;
-import com.android.sdklib.SdkConstants;
-import com.android.sdklib.SdkManager;
-import com.android.sdklib.IAndroidTarget.IOptionalLibrary;
-import com.android.sdklib.internal.project.ProjectProperties;
-import com.android.sdklib.internal.project.ProjectProperties.PropertyType;
-import com.android.sdklib.xml.AndroidManifest;
-import com.android.sdklib.xml.AndroidXPathFactory;
-
import org.apache.tools.ant.BuildException;
-import org.apache.tools.ant.Project;
+import org.apache.tools.ant.Task;
import org.apache.tools.ant.taskdefs.ImportTask;
-import org.apache.tools.ant.types.Path;
-import org.apache.tools.ant.types.Path.PathElement;
-import org.apache.tools.ant.util.DeweyDecimal;
-import org.xml.sax.InputSource;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.FilenameFilter;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.HashSet;
-
-import javax.xml.xpath.XPath;
-import javax.xml.xpath.XPathExpressionException;
/**
- * Setup/Import Ant task. This task accomplishes:
- * <ul>
- * <li>Gets the project target hash string from {@link ProjectProperties#PROPERTY_TARGET},
- * and resolves it to get the project's {@link IAndroidTarget}.</li>
- * <li>Sets up properties so that aapt can find the android.jar in the resolved target.</li>
- * <li>Sets up the boot classpath ref so that the <code>javac</code> task knows where to find
- * the libraries. This includes the default android.jar from the resolved target but also optional
- * libraries provided by the target (if any, when the target is an add-on).</li>
- * <li>Imports the build rules located in the resolved target so that the build actually does
- * something. This can be disabled with the attribute <var>import</var> set to <code>false</code>
- * </li></ul>
- *
- * This is used in build.xml/template.
+ * Legacy setupTask class used by older build system.
*
+ * If this is used it actually only display an error about the need to update the build file.
*/
-public final class SetupTask extends ImportTask {
- private final static String ANT_MIN_VERSION = "1.8.0";
- // main rules file
- private final static String RULES_MAIN = "main_rules.xml";
- // test rules file - depends on android_rules.xml
- private final static String RULES_TEST = "test_rules.xml";
- // library rules file.
- private final static String RULES_LIBRARY = "lib_rules.xml";
-
- private boolean mDoImport = true;
-
- @Override
- public void execute() throws BuildException {
- Project antProject = getProject();
-
- // check the Ant version
- DeweyDecimal version = getVersion(antProject);
- DeweyDecimal atLeast = new DeweyDecimal(ANT_MIN_VERSION);
- if (atLeast.isGreaterThan(version)) {
- throw new BuildException(
- "The Android Ant-based build system requires Ant " +
- ANT_MIN_VERSION +
- " or later. Current version is " +
- version);
- }
-
- // get the SDK location
- File sdkDir = TaskHelper.getSdkLocation(antProject);
- String sdkOsPath = sdkDir.getPath();
-
- // Make sure the OS sdk path ends with a directory separator
- if (sdkOsPath.length() > 0 && !sdkOsPath.endsWith(File.separator)) {
- sdkOsPath += File.separator;
- }
-
- // display SDK Tools revision
- int toolsRevison = TaskHelper.getToolsRevision(sdkDir);
- if (toolsRevison != -1) {
- System.out.println("Android SDK Tools Revision " + toolsRevison);
- }
-
- // detect that the platform tools is there.
- File platformTools = new File(sdkDir, SdkConstants.FD_PLATFORM_TOOLS);
- if (platformTools.isDirectory() == false) {
- throw new BuildException(String.format(
- "SDK Platform Tools component is missing. " +
- "Please install it with the SDK Manager (%1$s%2$c%3$s)",
- SdkConstants.FD_TOOLS,
- File.separatorChar,
- SdkConstants.androidCmdName()));
- }
-
- // get the target property value
- String targetHashString = antProject.getProperty(ProjectProperties.PROPERTY_TARGET);
-
- boolean isTestProject = false;
-
- if (antProject.getProperty(AntConstants.PROP_TESTED_PROJECT_DIR) != null) {
- isTestProject = true;
- }
-
- if (targetHashString == null) {
- throw new BuildException("Android Target is not set.");
- }
-
- // load up the sdk targets.
- final ArrayList<String> messages = new ArrayList<String>();
- SdkManager manager = SdkManager.createManager(sdkOsPath, new ISdkLog() {
- public void error(Throwable t, String errorFormat, Object... args) {
- if (errorFormat != null) {
- messages.add(String.format("Error: " + errorFormat, args));
- }
- if (t != null) {
- messages.add("Error: " + t.getMessage());
- }
- }
-
- public void printf(String msgFormat, Object... args) {
- messages.add(String.format(msgFormat, args));
- }
-
- public void warning(String warningFormat, Object... args) {
- messages.add(String.format("Warning: " + warningFormat, args));
- }
- });
-
- if (manager == null) {
- // since we failed to parse the SDK, lets display the parsing output.
- for (String msg : messages) {
- System.out.println(msg);
- }
- throw new BuildException("Failed to parse SDK content.");
- }
-
- // resolve it
- IAndroidTarget androidTarget = manager.getTargetFromHashString(targetHashString);
-
- if (androidTarget == null) {
- throw new BuildException(String.format(
- "Unable to resolve target '%s'", targetHashString));
- }
-
- // display the project info
- System.out.println("Project Target: " + androidTarget.getName());
- if (androidTarget.isPlatform() == false) {
- System.out.println("Vendor: " + androidTarget.getVendor());
- System.out.println("Platform Version: " + androidTarget.getVersionName());
- }
- System.out.println("API level: " + androidTarget.getVersion().getApiString());
-
- // check if the project is a library
- boolean isLibrary = false;
-
- String libraryProp = antProject.getProperty(ProjectProperties.PROPERTY_LIBRARY);
- if (libraryProp != null) {
- isLibrary = Boolean.valueOf(libraryProp).booleanValue();
- }
-
- if (isLibrary) {
- System.out.println("Project Type: Android Library");
- }
-
- // look for referenced libraries.
- processReferencedLibraries(antProject, androidTarget);
-
- // always check the manifest minSdkVersion.
- checkManifest(antProject, androidTarget.getVersion());
-
- // sets up the properties to find android.jar/framework.aidl/target tools
- String androidJar = androidTarget.getPath(IAndroidTarget.ANDROID_JAR);
- antProject.setProperty(AntConstants.PROP_ANDROID_JAR, androidJar);
-
- String androidAidl = androidTarget.getPath(IAndroidTarget.ANDROID_AIDL);
- antProject.setProperty(AntConstants.PROP_ANDROID_AIDL, androidAidl);
-
- Path includePath = new Path(antProject);
- PathElement element = includePath.createPathElement();
- element.setPath(androidTarget.getPath(IAndroidTarget.ANDROID_RS));
- element = includePath.createPathElement();
- element.setPath(androidTarget.getPath(IAndroidTarget.ANDROID_RS_CLANG));
- antProject.setProperty(AntConstants.PROP_ANDROID_RENDERSCRIPT, includePath.toString());
-
- antProject.setProperty(AntConstants.PROP_AAPT, androidTarget.getPath(IAndroidTarget.AAPT));
- antProject.setProperty(AntConstants.PROP_AIDL, androidTarget.getPath(IAndroidTarget.AIDL));
- antProject.setProperty(AntConstants.PROP_DX, androidTarget.getPath(IAndroidTarget.DX));
- antProject.setProperty(AntConstants.PROP_RENDERSCRIPT,
- sdkOsPath + SdkConstants.OS_SDK_PLATFORM_TOOLS_FOLDER +
- SdkConstants.FN_RENDERSCRIPT);
-
- // sets up the boot classpath
-
- // create the Path object
- Path bootclasspath = new Path(antProject);
-
- // create a PathElement for the framework jar
- element = bootclasspath.createPathElement();
- element.setPath(androidJar);
-
- // create PathElement for each optional library.
- IOptionalLibrary[] libraries = androidTarget.getOptionalLibraries();
- if (libraries != null) {
- HashSet<String> visitedJars = new HashSet<String>();
- for (IOptionalLibrary library : libraries) {
- String jarPath = library.getJarPath();
- if (visitedJars.contains(jarPath) == false) {
- visitedJars.add(jarPath);
-
- element = bootclasspath.createPathElement();
- element.setPath(library.getJarPath());
- }
- }
- }
-
- // finally sets the path in the project with a reference
- antProject.addReference(AntConstants.PROP_CLASSPATH_REF, bootclasspath);
-
- // Now the import section. This is only executed if the task actually has to import a file.
- if (mDoImport) {
- // check the ant folder exists in the tools folder of the SDK.
- File rulesFolder = new File(
- new File(sdkOsPath, SdkConstants.FD_TOOLS),
- SdkConstants.FD_ANT);
-
- // make sure the file exists.
- if (rulesFolder.isDirectory() == false) {
- throw new BuildException(String.format("Rules directory '%s' is missing.",
- rulesFolder.getAbsolutePath()));
- }
-
- // name of the rules files to import based on the type of project
- String importedRulesFileName =
- isLibrary ? RULES_LIBRARY : isTestProject ? RULES_TEST : RULES_MAIN;
-
- // now check the rules file exists.
- File rules = new File(rulesFolder, importedRulesFileName);
-
- if (rules.isFile() == false) {
- throw new BuildException(String.format("Build rules file '%s' is missing.",
- rules));
- }
-
- // display the file being imported.
- // figure out the path relative to the SDK
- String rulesOsPath = rules.getAbsolutePath();
- if (rulesOsPath.startsWith(sdkOsPath)) {
- rulesOsPath = rulesOsPath.substring(sdkOsPath.length());
- if (rulesOsPath.startsWith(File.separator)) {
- rulesOsPath = rulesOsPath.substring(1);
- }
- }
- System.out.println("\nImporting rules file: " + rulesOsPath);
-
- // set the file location to import
- setFile(rules.getAbsolutePath());
-
- // and import
- super.execute();
- }
- }
-
- /**
- * Sets the value of the "import" attribute.
- * @param value the value.
- */
- public void setImport(boolean value) {
- mDoImport = value;
- }
+public final class SetupTask extends Task {
/**
- * Checks the manifest <code>minSdkVersion</code> attribute.
- * @param antProject the ant project
- * @param androidVersion the version of the platform the project is compiling against.
- */
- private void checkManifest(Project antProject, AndroidVersion androidVersion) {
- try {
- File manifest = new File(antProject.getBaseDir(), SdkConstants.FN_ANDROID_MANIFEST_XML);
-
- XPath xPath = AndroidXPathFactory.newXPath();
-
- // check the package name.
- String value = xPath.evaluate(
- "/" + AndroidManifest.NODE_MANIFEST +
- "/@" + AndroidManifest.ATTRIBUTE_PACKAGE,
- new InputSource(new FileInputStream(manifest)));
- if (value != null) { // aapt will complain if it's missing.
- // only need to check that the package has 2 segments
- if (value.indexOf('.') == -1) {
- throw new BuildException(String.format(
- "Application package '%1$s' must have a minimum of 2 segments.",
- value));
- }
- }
-
- // check the minSdkVersion value
- value = xPath.evaluate(
- "/" + AndroidManifest.NODE_MANIFEST +
- "/" + AndroidManifest.NODE_USES_SDK +
- "/@" + AndroidXPathFactory.DEFAULT_NS_PREFIX + ":" +
- AndroidManifest.ATTRIBUTE_MIN_SDK_VERSION,
- new InputSource(new FileInputStream(manifest)));
-
- if (androidVersion.isPreview()) {
- // in preview mode, the content of the minSdkVersion must match exactly the
- // platform codename.
- String codeName = androidVersion.getCodename();
- if (codeName.equals(value) == false) {
- throw new BuildException(String.format(
- "For '%1$s' SDK Preview, attribute minSdkVersion in AndroidManifest.xml must be '%1$s'",
- codeName));
- }
- } else if (value.length() > 0) {
- // for normal platform, we'll only display warnings if the value is lower or higher
- // than the target api level.
- // First convert to an int.
- int minSdkValue = -1;
- try {
- minSdkValue = Integer.parseInt(value);
- } catch (NumberFormatException e) {
- // looks like it's not a number: error!
- throw new BuildException(String.format(
- "Attribute %1$s in AndroidManifest.xml must be an Integer!",
- AndroidManifest.ATTRIBUTE_MIN_SDK_VERSION));
- }
-
- int projectApiLevel = androidVersion.getApiLevel();
- if (minSdkValue < projectApiLevel) {
- System.out.println(String.format(
- "WARNING: Attribute %1$s in AndroidManifest.xml (%2$d) is lower than the project target API level (%3$d)",
- AndroidManifest.ATTRIBUTE_MIN_SDK_VERSION,
- minSdkValue, projectApiLevel));
- } else if (minSdkValue > androidVersion.getApiLevel()) {
- System.out.println(String.format(
- "WARNING: Attribute %1$s in AndroidManifest.xml (%2$d) is higher than the project target API level (%3$d)",
- AndroidManifest.ATTRIBUTE_MIN_SDK_VERSION,
- minSdkValue, projectApiLevel));
- }
- } else {
- // no minSdkVersion? display a warning
- System.out.println(
- "WARNING: No minSdkVersion value set. Application will install on all Android versions.");
- }
-
- } catch (XPathExpressionException e) {
- throw new BuildException(e);
- } catch (FileNotFoundException e) {
- throw new BuildException(e);
- }
- }
-
- private void processReferencedLibraries(Project antProject, IAndroidTarget androidTarget) {
- // prepare several paths for future tasks
- Path sourcePath = new Path(antProject);
- Path resPath = new Path(antProject);
- Path libsPath = new Path(antProject);
- Path jarsPath = new Path(antProject);
- StringBuilder sb = new StringBuilder();
-
- FilenameFilter filter = new FilenameFilter() {
- public boolean accept(File dir, String name) {
- return name.toLowerCase().endsWith(".jar");
- }
- };
-
- System.out.println("\n------------------\nResolving library dependencies:");
-
- ArrayList<File> libraries = getProjectLibraries(antProject);
-
- if (libraries.size() > 0) {
- System.out.println("------------------\nOrdered libraries:");
-
- for (File library : libraries) {
- System.out.println(library.getAbsolutePath());
-
- // get the source path. default is src but can be overriden by the property
- // "source.dir" in build.properties.
- PathElement element = sourcePath.createPathElement();
- ProjectProperties prop = ProjectProperties.load(new FolderWrapper(library),
- PropertyType.BUILD);
-
- String sourceDir = SdkConstants.FD_SOURCES;
- if (prop != null) {
- String value = prop.getProperty(ProjectProperties.PROPERTY_BUILD_SOURCE_DIR);
- if (value != null) {
- sourceDir = value;
- }
- }
-
- String path = library.getAbsolutePath();
-
- element.setPath(path + "/" + sourceDir);
-
- // get the res path. Always $PROJECT/res
- element = resPath.createPathElement();
- element.setPath(path + "/" + SdkConstants.FD_RESOURCES);
-
- // get the libs path. Always $PROJECT/libs
- element = libsPath.createPathElement();
- element.setPath(path + "/" + SdkConstants.FD_NATIVE_LIBS);
-
- // get the jars from it too
- File libsFolder = new File(library, SdkConstants.FD_NATIVE_LIBS);
- File[] jarFiles = libsFolder.listFiles(filter);
- if (jarFiles != null) {
- for (File jarFile : jarFiles) {
- element = jarsPath.createPathElement();
- element.setPath(jarFile.getAbsolutePath());
- }
- }
-
- // get the package from the manifest.
- FileWrapper manifest = new FileWrapper(library,
- SdkConstants.FN_ANDROID_MANIFEST_XML);
-
- try {
- String value = AndroidManifest.getPackage(manifest);
- if (value != null) { // aapt will complain if it's missing.
- sb.append(';');
- sb.append(value);
- }
- } catch (Exception e) {
- throw new BuildException(e);
- }
- }
- } else {
- System.out.println("No library dependencies.\n");
- }
-
- System.out.println("------------------\n");
-
- // even with no libraries, always setup these so that various tasks in Ant don't complain
- // (the task themselves can handle a ref to an empty Path)
- antProject.addReference(AntConstants.PROP_PROJECT_LIBS_SRC_REF, sourcePath);
- antProject.addReference(AntConstants.PROP_PROJECT_LIBS_JARS_REF, jarsPath);
- antProject.addReference(AntConstants.PROP_PROJECT_LIBS_LIBS_REF, libsPath);
-
- // the rest is done only if there's a library.
- if (sourcePath.list().length > 0) {
- antProject.addReference(AntConstants.PROP_PROJECT_LIBS_RES_REF, resPath);
- antProject.setProperty(AntConstants.PROP_PROJECT_LIBS_PKG, sb.toString());
- }
- }
-
- /**
- * Returns all the library dependencies of a given Ant project.
- * @param antProject the Ant project
- * @return a list of properties, sorted from highest priority to lowest.
- */
- private ArrayList<File> getProjectLibraries(final Project antProject) {
- ArrayList<File> libraries = new ArrayList<File>();
- File baseDir = antProject.getBaseDir();
-
- // get the top level list of library dependencies.
- ArrayList<File> topLevelLibraries = getDirectDependencies(baseDir, new IPropertySource() {
- public String getProperty(String name) {
- return antProject.getProperty(name);
- }
- });
-
- // process the libraries in case they depend on other libraries.
- resolveFullLibraryDependencies(topLevelLibraries, libraries);
-
- return libraries;
- }
-
- /**
- * Resolves a given list of libraries, finds out if they depend on other libraries, and
- * returns a full list of all the direct and indirect dependencies in the proper order (first
- * is higher priority when calling aapt).
- * @param inLibraries the libraries to resolve
- * @param outLibraries where to store all the libraries.
- */
- private void resolveFullLibraryDependencies(ArrayList<File> inLibraries,
- ArrayList<File> outLibraries) {
- // loop in the inverse order to resolve dependencies on the libraries, so that if a library
- // is required by two higher level libraries it can be inserted in the correct place
- for (int i = inLibraries.size() - 1 ; i >= 0 ; i--) {
- File library = inLibraries.get(i);
-
- // get the default.property file for it
- final ProjectProperties defaultProp = ProjectProperties.load(
- new FolderWrapper(library), PropertyType.DEFAULT);
-
- // get its libraries
- ArrayList<File> dependencies = getDirectDependencies(library, new IPropertySource() {
- public String getProperty(String name) {
- return defaultProp.getProperty(name);
- }
- });
-
- // resolve the dependencies for those libraries
- resolveFullLibraryDependencies(dependencies, outLibraries);
-
- // and add the current one (if needed) in front (higher priority)
- if (outLibraries.contains(library) == false) {
- outLibraries.add(0, library);
- }
- }
- }
-
- public interface IPropertySource {
- String getProperty(String name);
- }
-
- /**
- * Returns the top level library dependencies of a given <var>source</var> representing a
- * project properties.
- * @param baseFolder the base folder of the project (to resolve relative paths)
- * @param source a source of project properties.
- */
- private ArrayList<File> getDirectDependencies(File baseFolder, IPropertySource source) {
- ArrayList<File> libraries = new ArrayList<File>();
-
- // first build the list. they are ordered highest priority first.
- int index = 1;
- while (true) {
- String propName = ProjectProperties.PROPERTY_LIB_REF + Integer.toString(index++);
- String rootPath = source.getProperty(propName);
-
- if (rootPath == null) {
- break;
- }
-
- try {
- File library = new File(baseFolder, rootPath).getCanonicalFile();
-
- // check for validity
- File defaultProp = new File(library, PropertyType.DEFAULT.getFilename());
- if (defaultProp.isFile() == false) {
- // error!
- throw new BuildException(String.format(
- "%1$s resolve to a path with no %2$s file for project %3$s", rootPath,
- PropertyType.DEFAULT.getFilename(), baseFolder.getAbsolutePath()));
- }
-
- if (libraries.contains(library) == false) {
- System.out.println(String.format("%1$s: %2$s => %3$s",
- baseFolder.getAbsolutePath(), rootPath, library.getAbsolutePath()));
-
- libraries.add(library);
- }
- } catch (IOException e) {
- throw new BuildException("Failed to resolve library path: " + rootPath, e);
- }
- }
-
- return libraries;
- }
-
- /**
- * Returns the Ant version as a {@link DeweyDecimal} object.
- *
- * This is based on the implementation of
- * org.apache.tools.ant.taskdefs.condition.AntVersion.getVersion()
+ * @param b unused.
*
- * @param antProject the current ant project.
- * @return the ant version.
+ * @deprecated only present because the original {@link SetupTask} extends {@link ImportTask}.
*/
- private DeweyDecimal getVersion(Project antProject) {
- char[] versionString = antProject.getProperty("ant.version").toCharArray();
- StringBuffer sb = new StringBuffer();
- boolean foundFirstDigit = false;
- for (int i = 0; i < versionString.length; i++) {
- if (Character.isDigit(versionString[i])) {
- sb.append(versionString[i]);
- foundFirstDigit = true;
- }
- if (versionString[i] == '.' && foundFirstDigit) {
- sb.append(versionString[i]);
- }
- if (Character.isLetter(versionString[i]) && foundFirstDigit) {
- break;
- }
- }
- return new DeweyDecimal(sb.toString());
+ @Deprecated
+ public void setImport(boolean b) {
+ // do nothing
}
+ @Override
+ public void execute() throws BuildException {
+ throw new BuildException("\n\nError. You are using an obsolete build.xml\n" +
+ "You need to delete it and regenerate it using\n" +
+ "\tandroid update project\n");
+ }
}