diff options
author | The Android Open Source Project <initial-contribution@android.com> | 2009-02-20 07:38:28 -0800 |
---|---|---|
committer | The Android Open Source Project <initial-contribution@android.com> | 2009-02-20 07:38:28 -0800 |
commit | 76bc028c745906e691284c685e34e72b5ccf06b5 (patch) | |
tree | c6a908295dcbece6bb31f644b3d4698f04abee20 /anttasks/src/com/android | |
parent | 4fd2474506c1ea3cb96e128d72db2a18ec1e258d (diff) | |
download | sdk-76bc028c745906e691284c685e34e72b5ccf06b5.zip sdk-76bc028c745906e691284c685e34e72b5ccf06b5.tar.gz sdk-76bc028c745906e691284c685e34e72b5ccf06b5.tar.bz2 |
auto import from //branches/cupcake/...@132569
Diffstat (limited to 'anttasks/src/com/android')
-rw-r--r-- | anttasks/src/com/android/ant/AaptExecLoopTask.java | 218 | ||||
-rw-r--r-- | anttasks/src/com/android/ant/ApkBuilderTask.java | 293 | ||||
-rw-r--r-- | anttasks/src/com/android/ant/SetupTask.java (renamed from anttasks/src/com/android/ant/AndroidInitTask.java) | 63 |
3 files changed, 549 insertions, 25 deletions
diff --git a/anttasks/src/com/android/ant/AaptExecLoopTask.java b/anttasks/src/com/android/ant/AaptExecLoopTask.java new file mode 100644 index 0000000..d2c7162 --- /dev/null +++ b/anttasks/src/com/android/ant/AaptExecLoopTask.java @@ -0,0 +1,218 @@ +/* + * 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.sdklib.project.ApkConfigurationHelper; +import com.android.sdklib.project.ProjectProperties; +import com.android.sdklib.project.ProjectProperties.PropertyType; + +import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.Project; +import org.apache.tools.ant.Task; +import org.apache.tools.ant.taskdefs.ExecTask; +import org.apache.tools.ant.types.Path; + +import java.io.File; +import java.util.Map; +import java.util.Set; +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. + * + */ +public final class AaptExecLoopTask extends Task { + + private String mExecutable; + private String mCommand; + private String mManifest; + private String mResources; + private String mAssets; + private String mAndroidJar; + private String mOutFolder; + private String mBaseName; + + /** + * Sets the value of the "executable" attribute. + * @param executable the value. + */ + public void setExecutable(String executable) { + mExecutable = executable; + } + + /** + * Sets the value of the "command" attribute. + * @param command the value. + */ + public void setCommand(String command) { + mCommand = command; + } + + /** + * Sets the value of the "manifest" attribute. + * @param manifest the value. + */ + public void setManifest(Path manifest) { + mManifest = manifest.toString(); + } + + /** + * Sets the value of the "resources" attribute. + * @param resources the value. + */ + public void setResources(Path resources) { + mResources = resources.toString(); + } + + /** + * Sets the value of the "assets" attribute. + * @param assets the value. + */ + public void setAssets(Path assets) { + mAssets = assets.toString(); + } + + /** + * Sets the value of the "androidjar" attribute. + * @param androidJar the value. + */ + public void setAndroidjar(Path androidJar) { + mAndroidJar = androidJar.toString(); + } + + /** + * Sets the value of the "outfolder" attribute. + * @param outFolder the value. + */ + public void setOutfolder(Path outFolder) { + mOutFolder = outFolder.toString(); + } + + /** + * Sets the value of the "basename" attribute. + * @param baseName the value. + */ + public void setBasename(String baseName) { + mBaseName = baseName; + } + + /* + * (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 { + Project taskProject = getProject(); + + // first do a full resource package + createPackage(null /*configName*/, null /*resourceFilter*/); + + // now see if we need to create file with filtered resources. + // Get the project base directory. + File baseDir = taskProject.getBaseDir(); + ProjectProperties properties = ProjectProperties.load(baseDir.getAbsolutePath(), + PropertyType.DEFAULT); + + Map<String, String> apkConfigs = ApkConfigurationHelper.getConfigs(properties); + if (apkConfigs.size() > 0) { + Set<Entry<String, String>> entrySet = apkConfigs.entrySet(); + for (Entry<String, String> entry : entrySet) { + createPackage(entry.getKey(), entry.getValue()); + } + } + } + + /** + * Creates a resource package. + * @param configName the name of the filter config. Can be null in which case a full resource + * package will be generated. + * @param resourceFilter the resource configuration filter to pass to aapt (if configName is + * non null) + */ + private void createPackage(String configName, String resourceFilter) { + Project taskProject = getProject(); + + if (configName == null || resourceFilter == null) { + System.out.println("Creating full resource package..."); + } else { + System.out.println(String.format( + "Creating resource package for config '%1$s' (%2$s)...", + configName, resourceFilter)); + } + + // create a task for the default apk. + ExecTask task = new ExecTask(); + task.setExecutable(mExecutable); + task.setFailonerror(true); + + // aapt command. Only "package" is supported at this time really. + task.createArg().setValue(mCommand); + + // filters if needed + if (configName != null && resourceFilter != null) { + task.createArg().setValue("-c"); + task.createArg().setValue(resourceFilter); + } + + // force flag + task.createArg().setValue("-f"); + + // manifest location + task.createArg().setValue("-M"); + task.createArg().setValue(mManifest); + + // resources location + task.createArg().setValue("-S"); + task.createArg().setValue(mResources); + + // assets location. this may not exists, and aapt doesn't like it, so we check first. + File assets = new File(mAssets); + if (assets.isDirectory()) { + task.createArg().setValue("-A"); + task.createArg().setValue(mAssets); + } + + // android.jar + 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_"; + } + + File file = new File(mOutFolder, filename); + task.createArg().setValue("-F"); + task.createArg().setValue(file.getAbsolutePath()); + + // final setup of the task + task.setProject(taskProject); + task.setOwningTarget(getOwningTarget()); + + // execute it. + task.execute(); + } +} diff --git a/anttasks/src/com/android/ant/ApkBuilderTask.java b/anttasks/src/com/android/ant/ApkBuilderTask.java new file mode 100644 index 0000000..22729ec --- /dev/null +++ b/anttasks/src/com/android/ant/ApkBuilderTask.java @@ -0,0 +1,293 @@ +/* + * 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.apkbuilder.ApkBuilder; +import com.android.apkbuilder.ApkBuilder.ApkFile; +import com.android.sdklib.project.ApkConfigurationHelper; +import com.android.sdklib.project.ProjectProperties; +import com.android.sdklib.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 java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.util.ArrayList; +import java.util.Map; +import java.util.Set; +import java.util.Map.Entry; + +public class ApkBuilderTask extends Task { + + /** + * 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 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> mJarList = new ArrayList<Value>(); + private final ArrayList<Value> mNativeList = new ArrayList<Value>(); + + private final ArrayList<FileInputStream> mZipArchives = new ArrayList<FileInputStream>(); + private final ArrayList<File> mArchiveFiles = new ArrayList<File>(); + private final ArrayList<ApkFile> mJavaResources = new ArrayList<ApkFile>(); + private final ArrayList<FileInputStream> mResourcesJars = new ArrayList<FileInputStream>(); + private final ArrayList<ApkFile> mNativeLibraries = new ArrayList<ApkFile>(); + + /** + * Sets the value of the "outfolder" attribute. + * @param outFolder the value. + */ + public void setOutfolder(Path outFolder) { + mOutFolder = outFolder.toString(); + } + + /** + * Sets the value of the "basename" attribute. + * @param baseName the value. + */ + public void setBasename(String baseName) { + mBaseName = baseName; + } + + /** + * Sets the value of the "verbose" attribute. + * @param verbose the value. + */ + public void setVerbose(boolean verbose) { + mVerbose = verbose; + } + + /** + * Sets the value of the "signed" attribute. + * @param signed the value. + */ + public void setSigned(boolean signed) { + mSigned = signed; + } + + /** + * Returns an object representing a nested <var>zip</var> element. + */ + public Object createZip() { + Value zip = new Value(); + mZipList.add(zip); + return zip; + } + + /** + * Returns an object representing a nested <var>file</var> element. + */ + public Object createFile() { + Value file = new Value(); + mFileList.add(file); + return file; + } + + /** + * Returns an object representing a nested <var>sourcefolder</var> element. + */ + public Object createSourcefolder() { + Value file = new Value(); + mSourceList.add(file); + return file; + } + + /** + * Returns an object representing a nested <var>jarfolder</var> element. + */ + public Object createJarfolder() { + Value file = new Value(); + mJarList.add(file); + return file; + } + + /** + * Returns an object representing a nested <var>nativefolder</var> element. + */ + public Object createNativefolder() { + Value file = new Value(); + mNativeList.add(file); + return file; + } + + @Override + public void execute() throws BuildException { + Project taskProject = getProject(); + + ApkBuilder apkBuilder = new ApkBuilder(); + apkBuilder.setVerbose(mVerbose); + apkBuilder.setSignedPackage(mSigned); + + try { + // setup the list of everything that needs to go in the archive. + + // 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); + } + + // now go through the list of file to directly add the to the list. + for (Value v : mFileList) { + mArchiveFiles.add(ApkBuilder.getInputFile(v.mPath)); + } + + // now go through the list of file to directly add the to the list. + for (Value v : mSourceList) { + ApkBuilder.processSourceFolderForResource(v.mPath, mJavaResources); + } + + // now go through the list of jar folders. + for (Value v : mJarList) { + ApkBuilder.processJarFolder(v.mPath, mResourcesJars); + } + + // now the native lib folder. + for (Value v : mNativeList) { + String parameter = v.mPath; + File f = new File(parameter); + + // compute the offset to get the relative path + int offset = parameter.length(); + if (parameter.endsWith(File.separator) == false) { + offset++; + } + + ApkBuilder.processNativeFolder(offset, f, mNativeLibraries); + } + + + // first do a full resource package + createApk(apkBuilder, null /*configName*/, null /*resourceFilter*/); + + // now see if we need to create file with filtered resources. + // Get the project base directory. + File baseDir = taskProject.getBaseDir(); + ProjectProperties properties = ProjectProperties.load(baseDir.getAbsolutePath(), + PropertyType.DEFAULT); + + Map<String, String> apkConfigs = ApkConfigurationHelper.getConfigs(properties); + if (apkConfigs.size() > 0) { + Set<Entry<String, String>> entrySet = apkConfigs.entrySet(); + for (Entry<String, String> entry : entrySet) { + createApk(apkBuilder, entry.getKey(), entry.getValue()); + } + } + } catch (FileNotFoundException e) { + throw new BuildException(e); + } catch (IllegalArgumentException e) { + throw new BuildException(e); + } + } + + /** + * Creates an application package. + * @param apkBuilder + * @param configName the name of the filter config. Can be null in which case a full resource + * package will be generated. + * @param resourceFilter the resource configuration filter to pass to aapt (if configName is + * non null) + * @throws FileNotFoundException + */ + private void createApk(ApkBuilder apkBuilder, String configName, String resourceFilter) + throws FileNotFoundException { + // All the files to be included in the archive have already been prep'ed up, except + // the resource package. + // figure out its name. + String filename; + if (configName != null && resourceFilter != null) { + filename = mBaseName + "-" + configName + ".ap_"; + } else { + filename = mBaseName + ".ap_"; + } + + // now we add it to the list of zip archive (it's just a zip file). + + // it's used as a zip archive input + FileInputStream resoucePackageZipFile = new FileInputStream(new File(mOutFolder, filename)); + mZipArchives.add(resoucePackageZipFile); + + // prepare the filename to generate. Same thing as the resource file. + if (configName != null && resourceFilter != null) { + filename = mBaseName + "-" + configName; + } else { + filename = mBaseName; + } + + if (mSigned) { + filename = filename + "-debug.apk"; + } else { + filename = filename + "-unsigned.apk"; + } + + if (configName == null || resourceFilter == null) { + if (mSigned) { + System.out.println(String.format( + "Creating %s and signing it with a debug key...", filename)); + } else { + System.out.println(String.format( + "Creating %s for release...", filename)); + } + } else { + if (mSigned) { + System.out.println(String.format( + "Creating %1$s (with %2$s) and signing it with a debug key...", + filename, resourceFilter)); + } else { + System.out.println(String.format( + "Creating %1$s (with %2$s) for release...", + filename, resourceFilter)); + } + } + + File f = new File(mOutFolder, filename); + + // and generate the apk + apkBuilder.createPackage(f.getAbsoluteFile(), mZipArchives, + mArchiveFiles, mJavaResources, mResourcesJars, mNativeLibraries); + + // we are done. We need to remove the resource package from the list of zip archives + // in case we have another apk to generate. + mZipArchives.remove(resoucePackageZipFile); + } +} diff --git a/anttasks/src/com/android/ant/AndroidInitTask.java b/anttasks/src/com/android/ant/SetupTask.java index d5bc55b..d425a2f 100644 --- a/anttasks/src/com/android/ant/AndroidInitTask.java +++ b/anttasks/src/com/android/ant/SetupTask.java @@ -1,11 +1,11 @@ /* - * Copyright (C) 2008 The Android Open Source Project + * Copyright (C) 2009 The Android Open Source Project * - * Licensed under the Eclipse Public License, Version 1.0 (the "License"); + * 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.eclipse.org/org/documents/epl-v10.php + * 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, @@ -33,7 +33,7 @@ import java.util.ArrayList; import java.util.HashSet; /** - * Import Target Ant task. This task accomplishes: + * 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> @@ -42,13 +42,13 @@ import java.util.HashSet; * 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.</li> - * </ul> + * 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. * */ -public class AndroidInitTask extends ImportTask { +public final class SetupTask extends ImportTask { private final static String ANDROID_RULES = "android_rules.xml"; // ant property with the path to the android.jar @@ -63,6 +63,8 @@ public class AndroidInitTask extends ImportTask { private final static String PROPERTY_DX = "dx"; // ref id to the <path> object containing all the boot classpaths. private final static String REF_CLASSPATH = "android.target.classpath"; + + private boolean mDoImport = true; @Override public void execute() throws BuildException { @@ -172,24 +174,35 @@ public class AndroidInitTask extends ImportTask { // find the file to import, and import it. String templateFolder = androidTarget.getPath(IAndroidTarget.TEMPLATES); - // make sure the file exists. - File templates = new File(templateFolder); - if (templates.isDirectory() == false) { - throw new BuildException(String.format("Template directory '%s' is missing.", - templateFolder)); + // Now the import section. This is only executed if the task actually has to import a file. + if (mDoImport) { + // make sure the file exists. + File templates = new File(templateFolder); + if (templates.isDirectory() == false) { + throw new BuildException(String.format("Template directory '%s' is missing.", + templateFolder)); + } + + // now check the rules file exists. + File rules = new File(templateFolder, ANDROID_RULES); + if (rules.isFile() == false) { + throw new BuildException(String.format("Build rules file '%s' is missing.", + templateFolder)); + } + + // set the file location to import + setFile(rules.getAbsolutePath()); + + // and import + super.execute(); } - - // now check the rules file exists. - File rules = new File(templateFolder, ANDROID_RULES); - if (rules.isFile() == false) { - throw new BuildException(String.format("Build rules file '%s' is missing.", - templateFolder)); - } - - // set the file location to import - setFile(rules.getAbsolutePath()); - - // and import it - super.execute(); + } + + /** + * Sets the value of the "import" attribute. + * @param value the value. + */ + public void setImport(boolean value) { + mDoImport = value; } } |