aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--anttasks/src/com/android/ant/AaptExecLoopTask.java237
-rw-r--r--anttasks/src/com/android/ant/ApkBuilderTask.java111
-rw-r--r--anttasks/src/com/android/ant/SetupTask.java88
-rw-r--r--anttasks/src/com/android/ant/TaskHelper.java33
-rw-r--r--files/android_lib_rules.xml154
-rw-r--r--files/android_rules.xml36
-rw-r--r--sdkmanager/libs/sdklib/src/com/android/sdklib/internal/project/ProjectProperties.java5
7 files changed, 544 insertions, 120 deletions
diff --git a/anttasks/src/com/android/ant/AaptExecLoopTask.java b/anttasks/src/com/android/ant/AaptExecLoopTask.java
index 6610d23..afe4d35 100644
--- a/anttasks/src/com/android/ant/AaptExecLoopTask.java
+++ b/anttasks/src/com/android/ant/AaptExecLoopTask.java
@@ -34,9 +34,26 @@ import java.util.Map.Entry;
/**
* Task able to run an Exec task on aapt several times.
- * It does not follow the exec task format, instead it has its own parameters, which maps
- * directly to aapt.
+ * <p>It does not follow the exec task format, instead it has its own parameters, which maps
+ * directly to aapt.</p>
+ * <p>The following map shows how to use the task for each supported aapt command line
+ * parameter.</p>
*
+ * <table border="1">
+ * <tr><td><b>Aapt Option</b></td><td><b>Ant Name</b></td><td><b>Type</b></td></tr>
+ * <tr><td>path to aapt</td><td>executable</td><td>attribute (Path)</td>
+ * <tr><td>command</td><td>command</td><td>attribute (String)</td>
+ * <tr><td>-v</td><td>verbose</td><td>attribute (boolean)</td></tr>
+ * <tr><td>-f</td><td>force</td><td>attribute (boolean)</td></tr>
+ * <tr><td>-M AndroidManifest.xml</td><td>manifest</td><td>attribute (Path)</td></tr>
+ * <tr><td>-I base-package</td><td>androidjar</td><td>attribute (Path)</td></tr>
+ * <tr><td>-A asset-source-dir</td><td>assets</td><td>attribute (Path</td></tr>
+ * <tr><td>-S resource-sources</td><td>&lt;res path=""&gt;</td><td>nested element(s)<br>with attribute (Path)</td></tr>
+ * <tr><td>-0 extension</td><td>&lt;nocompress extension=""&gt;<br>&lt;nocompress&gt;</td><td>nested element(s)<br>with attribute (String)</td></tr>
+ * <tr><td>-F apk-file</td><td>apkfolder<br>outfolder<br>apkbasename<br>basename</td><td>attribute (Path)<br>attribute (Path) deprecated<br>attribute (String)<br>attribute (String) deprecated</td></tr>
+ * <tr><td>-J R-file-dir</td><td>rfolder</td><td>attribute (Path)<br>-m always enabled</td></tr>
+ * <tr><td></td><td></td><td></td></tr>
+ * </table>
*/
public final class AaptExecLoopTask extends Task {
@@ -61,20 +78,23 @@ public final class AaptExecLoopTask extends Task {
private String mExecutable;
private String mCommand;
+ private boolean mForce = true; // true due to legacy reasons
+ private boolean mVerbose = false;
private String mManifest;
- private String mResources;
+ private ArrayList<Path> mResources;
private String mAssets;
private String mAndroidJar;
- private String mOutFolder;
- private String mBaseName;
+ private String mApkFolder;
+ private String mApkBaseName;
+ private String mRFolder;
private final ArrayList<NoCompress> mNoCompressList = new ArrayList<NoCompress>();
/**
* Sets the value of the "executable" attribute.
* @param executable the value.
*/
- public void setExecutable(String executable) {
- mExecutable = executable;
+ public void setExecutable(Path executable) {
+ mExecutable = TaskHelper.checkSinglePath("executable", executable);
}
/**
@@ -86,19 +106,42 @@ public final class AaptExecLoopTask extends Task {
}
/**
+ * Sets the value of the "force" attribute.
+ * @param force the value.
+ */
+ public void setForce(boolean force) {
+ mForce = force;
+ }
+
+ /**
+ * Sets the value of the "verbose" attribute.
+ * @param verbose the value.
+ */
+ public void setVerbose(boolean verbose) {
+ mVerbose = verbose;
+ }
+
+ /**
* Sets the value of the "manifest" attribute.
* @param manifest the value.
*/
public void setManifest(Path manifest) {
- mManifest = manifest.toString();
+ mManifest = TaskHelper.checkSinglePath("manifest", manifest);
}
/**
* Sets the value of the "resources" attribute.
* @param resources the value.
+ *
+ * @deprecated Uses nested element(s) <res path="value" />
*/
+ @Deprecated
public void setResources(Path resources) {
- mResources = resources.toString();
+ if (mResources == null) {
+ mResources = new ArrayList<Path>();
+ }
+
+ mResources.add(new Path(getProject(), resources.toString()));
}
/**
@@ -106,7 +149,7 @@ public final class AaptExecLoopTask extends Task {
* @param assets the value.
*/
public void setAssets(Path assets) {
- mAssets = assets.toString();
+ mAssets = TaskHelper.checkSinglePath("assets", assets);
}
/**
@@ -114,23 +157,51 @@ public final class AaptExecLoopTask extends Task {
* @param androidJar the value.
*/
public void setAndroidjar(Path androidJar) {
- mAndroidJar = androidJar.toString();
+ mAndroidJar = TaskHelper.checkSinglePath("androidjar", androidJar);
}
/**
* Sets the value of the "outfolder" attribute.
* @param outFolder the value.
+ * @deprecated use {@link #setApkfolder(Path)}
*/
+ @Deprecated
public void setOutfolder(Path outFolder) {
- mOutFolder = outFolder.toString();
+ mApkFolder = TaskHelper.checkSinglePath("outfolder", outFolder);
+ }
+
+ /**
+ * Sets the value of the "apkfolder" attribute.
+ * @param apkFolder the value.
+ */
+ public void setApkfolder(Path apkFolder) {
+ mApkFolder = TaskHelper.checkSinglePath("apkfolder", apkFolder);
}
/**
* Sets the value of the "basename" attribute.
* @param baseName the value.
+ * @deprecated use {@link #setApkbasename(String)}
*/
+ @Deprecated
public void setBasename(String baseName) {
- mBaseName = baseName;
+ mApkBaseName = baseName;
+ }
+
+ /**
+ * Sets the value of the "apkbasename" attribute.
+ * @param apkbaseName the value.
+ */
+ public void setApkbasename(String apkbaseName) {
+ mApkBaseName = apkbaseName;
+ }
+
+ /**
+ * Sets the value of the "rfolder" attribute.
+ * @param rFolder the value.
+ */
+ public void setRfolder(Path rFolder) {
+ mRFolder = TaskHelper.checkSinglePath("rfolder", rFolder);
}
/**
@@ -142,6 +213,20 @@ public final class AaptExecLoopTask extends Task {
return nc;
}
+ /**
+ * Returns an object representing a nested <var>res</var> element.
+ */
+ public Object createRes() {
+ if (mResources == null) {
+ mResources = new ArrayList<Path>();
+ }
+
+ Path path = new Path(getProject());
+ mResources.add(path);
+
+ return path;
+ }
+
/*
* (non-Javadoc)
*
@@ -155,7 +240,25 @@ public final class AaptExecLoopTask extends Task {
Project taskProject = getProject();
// first do a full resource package
- createPackage(null /*configName*/, null /*resourceFilter*/);
+ createPackage(null /*configName*/, null /*resourceFilter*/, null /*customPackage*/);
+
+ if (mRFolder != null && new File(mRFolder).isDirectory()) {
+ String libPkgProp = taskProject.getProperty("android.libraries.package");
+ if (libPkgProp != null) {
+ // get the main package to compare in case the libraries use the same
+ String mainPackage = taskProject.getProperty("manifest.package");
+
+ String[] libPkgs = libPkgProp.split(";");
+ for (String libPkg : libPkgs) {
+ if (libPkg.length() > 0 && mainPackage.equals(libPkg) == false) {
+ // FIXME: instead of recreating R.java from scratch, maybe copy
+ // the files (R.java and manifest.java)? This would force to replace
+ // the package line on the fly.
+ createPackage(null, null, libPkg);
+ }
+ }
+ }
+ }
// now see if we need to create file with filtered resources.
// Get the project base directory.
@@ -169,7 +272,7 @@ public final class AaptExecLoopTask extends Task {
Map<String, String> apkFilters = apkSettings.getResourceFilters();
if (apkFilters.size() > 0) {
for (Entry<String, String> entry : apkFilters.entrySet()) {
- createPackage(entry.getKey(), entry.getValue());
+ createPackage(entry.getKey(), entry.getValue(), null /*custom package*/);
}
}
}
@@ -182,10 +285,13 @@ public final class AaptExecLoopTask extends Task {
* @param resourceFilter the resource configuration filter to pass to aapt (if configName is
* non null)
*/
- private void createPackage(String configName, String resourceFilter) {
+ private void createPackage(String configName, String resourceFilter, String customPackage) {
Project taskProject = getProject();
- if (configName == null || resourceFilter == null) {
+ final boolean generateRClass = mRFolder != null && new File(mRFolder).isDirectory();
+
+ if (generateRClass) {
+ } else if (configName == null || resourceFilter == null) {
System.out.println("Creating full resource package...");
} else {
System.out.println(String.format(
@@ -202,7 +308,18 @@ public final class AaptExecLoopTask extends Task {
task.createArg().setValue(mCommand);
// force flag
- task.createArg().setValue("-f");
+ if (mForce) {
+ task.createArg().setValue("-f");
+ }
+
+ // verbose flag
+ if (mVerbose) {
+ task.createArg().setValue("-v");
+ }
+
+ if (generateRClass) {
+ task.createArg().setValue("-m");
+ }
// filters if needed
if (configName != null && resourceFilter != null) {
@@ -229,39 +346,81 @@ public final class AaptExecLoopTask extends Task {
}
}
+ if (customPackage != null) {
+ task.createArg().setValue("--custom-package");
+ task.createArg().setValue(customPackage);
+ }
+
+ // if the project contains libraries, force auto-add-overlay
+ Object libSrc = taskProject.getReference("android.libraries.res");
+ if (libSrc != null) {
+ task.createArg().setValue("--auto-add-overlay");
+ }
+
// manifest location
- task.createArg().setValue("-M");
- task.createArg().setValue(mManifest);
-
- // resources location. This may not exists, and aapt doesn't like it, so we check first.
- File res = new File(mResources);
- if (res.isDirectory()) {
- task.createArg().setValue("-S");
- task.createArg().setValue(mResources);
+ if (mManifest != null) {
+ task.createArg().setValue("-M");
+ task.createArg().setValue(mManifest);
+ }
+
+ // resources locations.
+ if (mResources.size() > 0) {
+ for (Path pathList : mResources) {
+ for (String path : pathList.list()) {
+ // This may not exists, and aapt doesn't like it, so we check first.
+ File res = new File(path);
+ if (res.isDirectory()) {
+ task.createArg().setValue("-S");
+ task.createArg().setValue(path);
+ }
+ }
+ }
+ }
+
+ // add other resources coming from library project
+ Object libPath = taskProject.getReference("android.libraries.res");
+ if (libPath instanceof Path) {
+ for (String path : ((Path)libPath).list()) {
+ // This may not exists, and aapt doesn't like it, so we check first.
+ File res = new File(path);
+ if (res.isDirectory()) {
+ task.createArg().setValue("-S");
+ task.createArg().setValue(path);
+ }
+ }
}
// assets location. This may not exists, and aapt doesn't like it, so we check first.
- File assets = new File(mAssets);
- if (assets.isDirectory()) {
+ if (mAssets != null && new File(mAssets).isDirectory()) {
task.createArg().setValue("-A");
task.createArg().setValue(mAssets);
}
// android.jar
- task.createArg().setValue("-I");
- task.createArg().setValue(mAndroidJar);
+ if (mAndroidJar != null) {
+ task.createArg().setValue("-I");
+ task.createArg().setValue(mAndroidJar);
+ }
- // out file. This is based on the outFolder, baseName, and the configName (if applicable)
- String filename;
- if (configName != null && resourceFilter != null) {
- filename = mBaseName + "-" + configName + ".ap_";
- } else {
- filename = mBaseName + ".ap_";
+ // apk file. This is based on the apkFolder, apkBaseName, and the configName (if applicable)
+ if (mApkBaseName != null && mApkBaseName != null) {
+ String filename;
+ if (configName != null && resourceFilter != null) {
+ filename = mApkBaseName + "-" + configName + ".ap_";
+ } else {
+ filename = mApkBaseName + ".ap_";
+ }
+
+ File file = new File(mApkFolder, filename);
+ task.createArg().setValue("-F");
+ task.createArg().setValue(file.getAbsolutePath());
}
- File file = new File(mOutFolder, filename);
- task.createArg().setValue("-F");
- task.createArg().setValue(file.getAbsolutePath());
+ // R class generation
+ if (generateRClass) {
+ task.createArg().setValue("-J");
+ task.createArg().setValue(mRFolder);
+ }
// final setup of the task
task.setProject(taskProject);
diff --git a/anttasks/src/com/android/ant/ApkBuilderTask.java b/anttasks/src/com/android/ant/ApkBuilderTask.java
index b1e6d80..c326fa9 100644
--- a/anttasks/src/com/android/ant/ApkBuilderTask.java
+++ b/anttasks/src/com/android/ant/ApkBuilderTask.java
@@ -26,7 +26,6 @@ import com.android.sdklib.internal.project.ProjectProperties.PropertyType;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Project;
-import org.apache.tools.ant.ProjectComponent;
import org.apache.tools.ant.Task;
import org.apache.tools.ant.types.Path;
import org.apache.tools.ant.types.Path.PathElement;
@@ -43,35 +42,18 @@ public class ApkBuilderTask extends Task {
// ref id to the <path> object containing all the boot classpaths.
private final static String REF_APK_PATH = "android.apks.path";
- /**
- * Class to represent nested elements. Since they all have only one attribute ('path'), the
- * same class can be used for all the nested elements (zip, file, sourcefolder, jarfolder,
- * nativefolder).
- */
- public final static class Value extends ProjectComponent {
- String mPath;
-
- /**
- * Sets the value of the "path" attribute.
- * @param path the value.
- */
- public void setPath(Path path) {
- mPath = path.toString();
- }
- }
-
private String mOutFolder;
private String mBaseName;
private boolean mVerbose = false;
private boolean mSigned = true;
private boolean mDebug = false;
- private final ArrayList<Value> mZipList = new ArrayList<Value>();
- private final ArrayList<Value> mFileList = new ArrayList<Value>();
- private final ArrayList<Value> mSourceList = new ArrayList<Value>();
- private final ArrayList<Value> mJarfolderList = new ArrayList<Value>();
- private final ArrayList<Value> mJarfileList = new ArrayList<Value>();
- private final ArrayList<Value> mNativeList = new ArrayList<Value>();
+ 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 final ArrayList<FileInputStream> mZipArchives = new ArrayList<FileInputStream>();
private final ArrayList<File> mArchiveFiles = new ArrayList<File>();
@@ -84,7 +66,7 @@ public class ApkBuilderTask extends Task {
* @param outFolder the value.
*/
public void setOutfolder(Path outFolder) {
- mOutFolder = outFolder.toString();
+ mOutFolder = TaskHelper.checkSinglePath("outfolder", outFolder);
}
/**
@@ -123,54 +105,54 @@ public class ApkBuilderTask extends Task {
* Returns an object representing a nested <var>zip</var> element.
*/
public Object createZip() {
- Value zip = new Value();
- mZipList.add(zip);
- return zip;
+ Path path = new Path(getProject());
+ mZipList.add(path);
+ return path;
}
/**
* Returns an object representing a nested <var>file</var> element.
*/
public Object createFile() {
- Value file = new Value();
- mFileList.add(file);
- return file;
+ Path path = new Path(getProject());
+ mFileList.add(path);
+ return path;
}
/**
* Returns an object representing a nested <var>sourcefolder</var> element.
*/
public Object createSourcefolder() {
- Value file = new Value();
- mSourceList.add(file);
- return file;
+ Path path = new Path(getProject());
+ mSourceList.add(path);
+ return path;
}
/**
* Returns an object representing a nested <var>jarfolder</var> element.
*/
public Object createJarfolder() {
- Value file = new Value();
- mJarfolderList.add(file);
- return file;
+ Path path = new Path(getProject());
+ mJarfolderList.add(path);
+ return path;
}
/**
* Returns an object representing a nested <var>jarfile</var> element.
*/
public Object createJarfile() {
- Value file = new Value();
- mJarfileList.add(file);
- return file;
+ Path path = new Path(getProject());
+ mJarfileList.add(path);
+ return path;
}
/**
* Returns an object representing a nested <var>nativefolder</var> element.
*/
public Object createNativefolder() {
- Value file = new Value();
- mNativeList.add(file);
- return file;
+ Path path = new Path(getProject());
+ mNativeList.add(path);
+ return path;
}
@Override
@@ -187,37 +169,48 @@ public class ApkBuilderTask extends Task {
// go through the list of zip files to add. This will not include
// the resource package, which is handled separaly for each apk to create.
- for (Value v : mZipList) {
- FileInputStream input = new FileInputStream(v.mPath);
- mZipArchives.add(input);
+ for (Path pathList : mZipList) {
+ for (String path : pathList.list()) {
+ FileInputStream input = new FileInputStream(path);
+ mZipArchives.add(input);
+ }
}
// now go through the list of file to directly add the to the list.
- for (Value v : mFileList) {
- mArchiveFiles.add(ApkBuilderImpl.getInputFile(v.mPath));
+ for (Path pathList : mFileList) {
+ for (String path : pathList.list()) {
+ mArchiveFiles.add(ApkBuilderImpl.getInputFile(path));
+ }
}
// now go through the list of file to directly add the to the list.
- for (Value v : mSourceList) {
- ApkBuilderImpl.processSourceFolderForResource(new File(v.mPath), mJavaResources);
+ for (Path pathList : mSourceList) {
+ for (String path : pathList.list()) {
+ ApkBuilderImpl.processSourceFolderForResource(new File(path),
+ mJavaResources);
+ }
}
// now go through the list of jar folders.
- for (Value v : mJarfolderList) {
- ApkBuilderImpl.processJar(new File(v.mPath), mResourcesJars);
+ for (Path pathList : mJarfolderList) {
+ for (String path : pathList.list()) {
+ ApkBuilderImpl.processJar(new File(path), mResourcesJars);
+ }
}
// now go through the list of jar files.
- for (Value v : mJarfileList) {
- ApkBuilderImpl.processJar(new File(v.mPath), mResourcesJars);
+ for (Path pathList : mJarfileList) {
+ for (String path : pathList.list()) {
+ ApkBuilderImpl.processJar(new File(path), mResourcesJars);
+ }
}
// now the native lib folder.
- for (Value v : mNativeList) {
- String parameter = v.mPath;
- File f = new File(parameter);
-
- ApkBuilderImpl.processNativeFolder(f, mDebug, mNativeLibraries);
+ for (Path pathList : mNativeList) {
+ for (String path : pathList.list()) {
+ ApkBuilderImpl.processNativeFolder(new File(path), mDebug,
+ mNativeLibraries);
+ }
}
// create the Path item that will contain all the generated APKs
diff --git a/anttasks/src/com/android/ant/SetupTask.java b/anttasks/src/com/android/ant/SetupTask.java
index 72f5d11..6f3d0a5 100644
--- a/anttasks/src/com/android/ant/SetupTask.java
+++ b/anttasks/src/com/android/ant/SetupTask.java
@@ -22,8 +22,9 @@ import com.android.sdklib.ISdkLog;
import com.android.sdklib.SdkManager;
import com.android.sdklib.IAndroidTarget.IOptionalLibrary;
import com.android.sdklib.internal.project.ProjectProperties;
-import com.android.sdklib.xml.AndroidXPathFactory;
+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;
@@ -61,6 +62,8 @@ public final class SetupTask extends ImportTask {
private final static String ANDROID_RULES = "android_rules.xml";
// additional android rules for test project - depends on android_rules.xml
private final static String ANDROID_TEST_RULES = "android_test_rules.xml";
+ // additional android rules for test project - depends on android_rules.xml
+ private final static String ANDROID_LIBRARY_RULES = "android_lib_rules.xml";
// ant property with the path to the android.jar
private final static String PROPERTY_ANDROID_JAR = "android.jar";
// LEGACY - compatibility with 1.6 and before
@@ -153,8 +156,22 @@ public final class SetupTask extends ImportTask {
"Unable to resolve target '%s'", targetHashString));
}
+ // 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();
+ }
+
+ // look for referenced libraries.
+ processReferencedLibraries(antProject);
+
// display it
System.out.println("Project Target: " + androidTarget.getName());
+ if (isLibrary) {
+ System.out.println("Type: Android Library");
+ }
if (androidTarget.isPlatform() == false) {
System.out.println("Vendor: " + androidTarget.getVendor());
System.out.println("Platform Version: " + androidTarget.getVersionName());
@@ -227,7 +244,8 @@ public final class SetupTask extends ImportTask {
templateFolder));
}
- String importedRulesFileName = isTestProject ? ANDROID_TEST_RULES : ANDROID_RULES;
+ String importedRulesFileName = isLibrary ? ANDROID_LIBRARY_RULES :
+ isTestProject ? ANDROID_TEST_RULES : ANDROID_RULES;
// now check the rules file exists.
File rules = new File(templateFolder, importedRulesFileName);
@@ -333,4 +351,70 @@ public final class SetupTask extends ImportTask {
throw new BuildException(e);
}
}
+
+ private void processReferencedLibraries(Project antProject) {
+ // prepare several paths for future tasks
+ Path sourcePath = new Path(antProject);
+ Path resPath = new Path(antProject);
+ StringBuilder sb = new StringBuilder();
+
+ int index = 1;
+ while (true) {
+ String propName = ProjectProperties.PROPERTY_LIB_REF + Integer.toString(index++);
+ String rootPath = antProject.getProperty(propName);
+
+ if (rootPath == null) {
+ break;
+ }
+
+ // 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(rootPath, PropertyType.BUILD);
+ String sourceDir = "src";
+ if (prop != null) {
+ String value = prop.getProperty(ProjectProperties.PROPERTY_BUILD_SOURCE_DIR);
+ if (value != null) {
+ sourceDir = value;
+ }
+ }
+
+ element.setPath(rootPath + "/" + sourceDir);
+
+ // get the res path. Always $PROJECT/res
+ element = resPath.createPathElement();
+ element.setPath(rootPath + "/res");
+
+ // get the package from the manifest.
+ File manifest = new File(rootPath, "AndroidManifest.xml");
+ XPath xPath = AndroidXPathFactory.newXPath();
+
+ // check the package name.
+ try {
+ 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.
+ sb.append(';');
+ sb.append(value);
+ }
+ } catch (XPathExpressionException e) {
+ throw new BuildException(e);
+ } catch (FileNotFoundException e) {
+ throw new BuildException(e);
+ }
+
+ }
+
+ // even with no libraries, always setup android.libraries.src so that javac
+ // doesn't complain
+ antProject.addReference("android.libraries.src", sourcePath);
+
+ // the rest is done only if there's a library.
+ if (sourcePath.list().length > 0) {
+ antProject.addReference("android.libraries.res", resPath);
+ antProject.setProperty("android.libraries.package", sb.toString());
+ }
+ }
}
diff --git a/anttasks/src/com/android/ant/TaskHelper.java b/anttasks/src/com/android/ant/TaskHelper.java
new file mode 100644
index 0000000..361725a
--- /dev/null
+++ b/anttasks/src/com/android/ant/TaskHelper.java
@@ -0,0 +1,33 @@
+/*
+ * 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;
+
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.types.Path;
+
+public class TaskHelper {
+
+ public static String checkSinglePath(String attribute, Path path) {
+ String[] paths = path.list();
+ if (paths.length != 1) {
+ throw new BuildException(String.format("Path value for '%1$s' is not valid.", attribute));
+ }
+
+ return paths[0];
+ }
+
+}
diff --git a/files/android_lib_rules.xml b/files/android_lib_rules.xml
new file mode 100644
index 0000000..a6fb04d
--- /dev/null
+++ b/files/android_lib_rules.xml
@@ -0,0 +1,154 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project name="android_rules" default="debug">
+
+ <!--
+ This rules file is meant to be imported by the custom Ant task:
+ com.android.ant.SetupTask
+
+ The following properties are put in place by the importing task:
+ android.jar, android.aidl, aapt, aidl, and dx
+
+ Additionnaly, the task sets up the following classpath reference:
+ android.target.classpath
+ This is used by the compiler task as the boot classpath.
+ -->
+
+ <!-- Custom tasks -->
+ <taskdef name="aaptexec"
+ classname="com.android.ant.AaptExecLoopTask"
+ classpathref="android.antlibs" />
+
+ <taskdef name="xpath"
+ classname="com.android.ant.XPathTask"
+ classpathref="android.antlibs" />
+
+ <!-- Properties -->
+
+ <!-- Tells adb which device to target. You can change this from the command line
+ by invoking "ant -Dadb.device.arg=-d" for device "ant -Dadb.device.arg=-e" for
+ the emulator. -->
+ <property name="adb.device.arg" value="" />
+
+ <property name="android.tools.dir" location="${sdk.dir}/tools" />
+ <!-- Name of the application package extracted from manifest file -->
+ <xpath input="AndroidManifest.xml" expression="/manifest/@package"
+ output="manifest.package" />
+
+ <!-- Input directories -->
+ <property name="source.dir" value="src" />
+ <property name="source.absolute.dir" location="${source.dir}" />
+ <property name="gen.dir" value="gen" />
+ <property name="gen.absolute.dir" location="${gen.dir}" />
+ <property name="resource.dir" value="res" />
+ <property name="resource.absolute.dir" location="${resource.dir}" />
+ <property name="asset.dir" value="assets" />
+ <property name="asset.absolute.dir" location="${asset.dir}" />
+
+ <!-- Directory for the third party java libraries -->
+ <property name="external.libs.dir" value="libs" />
+ <property name="external.libs.absolute.dir" location="${external.libs.dir}" />
+
+ <!-- Directory for the native libraries -->
+ <property name="native.libs.dir" value="libs" />
+ <property name="native.libs.absolute.dir" location="${native.libs.dir}" />
+
+ <!-- Output directories -->
+ <property name="out.dir" value="bin" />
+ <property name="out.absolute.dir" location="${out.dir}" />
+ <property name="out.classes.dir" value="${out.absolute.dir}/classes" />
+ <property name="out.classes.absolute.dir" location="${out.classes.dir}" />
+
+ <!-- Verbosity -->
+ <property name="verbose" value="false" />
+ <!-- This is needed by emma as it uses multilevel verbosity instead of simple 'true' or 'false'
+ The property 'verbosity' is not user configurable and depends exclusively on 'verbose'
+ value.-->
+ <condition property="verbosity" value="verbose" else="quiet">
+ <istrue value="${verbose}" />
+ </condition>
+
+ <!-- Tools -->
+ <condition property="exe" value=".exe" else=""><os family="windows" /></condition>
+
+ <!-- Emma configuration -->
+ <property name="emma.dir" value="${sdk.dir}/tools/lib" />
+ <path id="emma.lib">
+ <pathelement location="${emma.dir}/emma.jar" />
+ <pathelement location="${emma.dir}/emma_ant.jar" />
+ </path>
+ <taskdef resource="emma_ant.properties" classpathref="emma.lib" />
+ <!-- End of emma configuration -->
+
+ <!-- Rules -->
+
+ <!-- Creates the output directories if they don't exist yet. -->
+ <target name="-dirs">
+ <echo>Creating output directories if needed...</echo>
+ <mkdir dir="${resource.absolute.dir}" />
+ <mkdir dir="${external.libs.absolute.dir}" />
+ <mkdir dir="${gen.absolute.dir}" />
+ <mkdir dir="${out.absolute.dir}" />
+ <mkdir dir="${out.classes.absolute.dir}" />
+ </target>
+
+ <!-- Generates the R.java file for this project's resources. -->
+ <target name="-resource-src" depends="-dirs">
+ <echo>Generating R.java / Manifest.java from the resources...</echo>
+ <aaptexec executable="${aapt}"
+ command="package"
+ verbose="${verbose}"
+ manifest="AndroidManifest.xml"
+ androidjar="${android.jar}"
+ rfolder="${gen.absolute.dir}">
+ <res path="${resource.absolute.dir}" />
+ </aaptexec>
+ </target>
+
+ <!-- Generates java classes from .aidl files. -->
+ <target name="-aidl" depends="-dirs">
+ <echo>Compiling aidl files into Java classes...</echo>
+ <apply executable="${aidl}" failonerror="true">
+ <arg value="-p${android.aidl}" />
+ <arg value="-I${source.absolute.dir}" />
+ <arg value="-o${gen.absolute.dir}" />
+ <fileset dir="${source.absolute.dir}">
+ <include name="**/*.aidl" />
+ </fileset>
+ </apply>
+ </target>
+
+ <!-- Compiles this project's .java files into .class files. -->
+ <target name="compile" depends="-resource-src, -aidl"
+ description="Compiles project's .java files into .class files">
+ <!-- If android rules are used for a test project, its classpath should include
+ tested project's location -->
+ <condition property="extensible.classpath"
+ value="${tested.project.absolute.dir}/bin/classes" else=".">
+ <isset property="tested.project.absolute.dir" />
+ </condition>
+ <javac encoding="ascii" target="1.5" debug="true" extdirs=""
+ destdir="${out.classes.absolute.dir}"
+ bootclasspathref="android.target.classpath"
+ verbose="${verbose}" classpath="${extensible.classpath}">
+ <src path="${source.absolute.dir}" />
+ <src path="${gen.absolute.dir}" />
+ <classpath>
+ <fileset dir="${external.libs.absolute.dir}" includes="*.jar" />
+ </classpath>
+ </javac>
+ </target>
+
+ <target name="clean" description="Removes output files created by other targets.">
+ <delete dir="${out.absolute.dir}" verbose="${verbose}" />
+ <delete dir="${gen.absolute.dir}" verbose="${verbose}" />
+ </target>
+
+ <target name="help">
+ <!-- displays starts at col 13
+ |13 80| -->
+ <echo>Android Ant Build. Available targets:</echo>
+ <echo> help: Displays this help.</echo>
+ <echo> clean: Removes output files created by other targets.</echo>
+ <echo> compile: Compiles project's .java files into .class files.</echo>
+ </target>
+</project>
diff --git a/files/android_rules.xml b/files/android_rules.xml
index a61bf16..3d9cb19 100644
--- a/files/android_rules.xml
+++ b/files/android_rules.xml
@@ -3,7 +3,7 @@
<!--
This rules file is meant to be imported by the custom Ant task:
- com.android.ant.AndroidInitTask
+ com.android.ant.SetupTask
The following properties are put in place by the importing task:
android.jar, android.aidl, aapt, aidl, and dx
@@ -86,7 +86,7 @@
<condition property="verbosity" value="verbose" else="quiet">
<istrue value="${verbose}" />
</condition>
- <!-- This is needed to switch verbosity of zipalign and aapt. Depends exclusively on 'verbose'
+ <!-- This is needed to switch verbosity of zipalign. Depends exclusively on 'verbose'
-->
<condition property="v.option" value="-v" else="">
<istrue value="${verbose}" />
@@ -118,8 +118,7 @@
<element name="external-libs" optional="yes" />
<element name="extra-parameters" optional="yes" />
<sequential>
- <echo>Converting compiled files and external libraries into ${intermediate.dex.file}...
- </echo>
+ <echo>Converting compiled files and external libraries into ${intermediate.dex.file}...</echo>
<apply executable="${dx}" failonerror="true" parallel="true">
<arg value="--dex" />
<arg value="--output=${intermediate.dex.file}" />
@@ -154,6 +153,7 @@
verbose="${verbose}">
<file path="${intermediate.dex.file}" />
<sourcefolder path="${source.absolute.dir}" />
+ <sourcefolder refid="android.libraries.src" />
<nativefolder path="${native.libs.absolute.dir}" />
<jarfolder path="${external.libs.absolute.dir}" />
<extra-jars/>
@@ -207,19 +207,14 @@
<!-- Generates the R.java file for this project's resources. -->
<target name="-resource-src" depends="-dirs">
<echo>Generating R.java / Manifest.java from the resources...</echo>
- <exec executable="${aapt}" failonerror="true">
- <arg value="package" />
- <arg line="${v.option}" />
- <arg value="-m" />
- <arg value="-J" />
- <arg path="${gen.absolute.dir}" />
- <arg value="-M" />
- <arg path="AndroidManifest.xml" />
- <arg value="-S" />
- <arg path="${resource.absolute.dir}" />
- <arg value="-I" />
- <arg path="${android.jar}" />
- </exec>
+ <aaptexec executable="${aapt}"
+ command="package"
+ verbose="${verbose}"
+ manifest="AndroidManifest.xml"
+ androidjar="${android.jar}"
+ rfolder="${gen.absolute.dir}">
+ <res path="${resource.absolute.dir}" />
+ </aaptexec>
</target>
<!-- Generates java classes from .aidl files. -->
@@ -250,6 +245,7 @@
verbose="${verbose}" classpath="${extensible.classpath}">
<src path="${source.absolute.dir}" />
<src path="${gen.absolute.dir}" />
+ <src refid="android.libraries.src" />
<classpath>
<fileset dir="${external.libs.absolute.dir}" includes="*.jar" />
</classpath>
@@ -271,11 +267,11 @@
<aaptexec executable="${aapt}"
command="package"
manifest="AndroidManifest.xml"
- resources="${resource.absolute.dir}"
assets="${asset.absolute.dir}"
androidjar="${android.jar}"
- outfolder="${out.absolute.dir}"
- basename="${ant.project.name}">
+ apkfolder="${out.absolute.dir}"
+ apkbasename="${ant.project.name}">
+ <res path="${resource.absolute.dir}" />
<!-- <nocompress /> forces no compression on any files in assets or res/raw -->
<!-- <nocompress extension="xml" /> forces no compression on specific file extensions in assets and res/raw -->
</aaptexec>
diff --git a/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/project/ProjectProperties.java b/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/project/ProjectProperties.java
index 88a06d9..e61a607 100644
--- a/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/project/ProjectProperties.java
+++ b/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/project/ProjectProperties.java
@@ -36,6 +36,9 @@ public final class ProjectProperties {
/** The property name for the project target */
public final static String PROPERTY_TARGET = "target";
+ public final static String PROPERTY_LIBRARY = "android.library";
+ public final static String PROPERTY_LIB_REF = "android.library.reference.";
+
public final static String PROPERTY_SDK = "sdk.dir";
// LEGACY - compatibility with 1.6 and before
public final static String PROPERTY_SDK_LEGACY = "sdk-location";
@@ -48,6 +51,8 @@ public final class ProjectProperties {
public final static String PROPERTY_TESTED_PROJECT = "tested.project.dir";
+ public final static String PROPERTY_BUILD_SOURCE_DIR = "source.dir";
+
public static enum PropertyType {
BUILD("build.properties", BUILD_HEADER),
DEFAULT(SdkConstants.FN_DEFAULT_PROPERTIES, DEFAULT_HEADER),