auto import from //branches/cupcake/...@132569

This commit is contained in:
The Android Open Source Project
2009-02-20 07:38:28 -08:00
parent ff4b5f241f
commit 74a996a2c7
24 changed files with 1246 additions and 318 deletions

View File

@@ -20,6 +20,7 @@ LOCAL_SRC_FILES := $(call all-subdir-java-files)
LOCAL_JAVA_LIBRARIES := \
sdklib \
apkbuilder \
ant
LOCAL_MODULE := anttasks

View File

@@ -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();
}
}

View File

@@ -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);
}
}

View File

@@ -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;
}
}