aboutsummaryrefslogtreecommitdiffstats
path: root/anttasks/src
diff options
context:
space:
mode:
authorXavier Ducrohet <xav@android.com>2010-02-03 11:52:04 -0800
committerXavier Ducrohet <xav@android.com>2010-02-10 10:29:53 -0800
commit7bfc74613e9bced3f1b6291280e5cc80a5f5954a (patch)
tree7eaa9b5680deb9e39570cbe94bd5642b4dc3a64f /anttasks/src
parentb62b85a33ea02907d8929cf2d977892f61417a6a (diff)
downloadsdk-7bfc74613e9bced3f1b6291280e5cc80a5f5954a.zip
sdk-7bfc74613e9bced3f1b6291280e5cc80a5f5954a.tar.gz
sdk-7bfc74613e9bced3f1b6291280e5cc80a5f5954a.tar.bz2
Add support for library project in the Ant build system.
new build rules file for library only. Should probably extract the parts that are common to this and the default rules file. SetupTask now sets up some properties and Path reference based on the libraries. They are used by: - aapt task (now also used for the generation of R.java) which use all the res folders of the main project and the libraries, and generate an R class for the project and the libraries. - javac which compiles the src/ folders of the libraries. Bug: 2294012 Change-Id: Ie550dcf0ba8ea57696ebb1c2a61d4c6d73307bdf
Diffstat (limited to 'anttasks/src')
-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
4 files changed, 369 insertions, 100 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];
+ }
+
+}