diff options
author | Xavier Ducrohet <xav@android.com> | 2010-06-03 19:50:37 -0700 |
---|---|---|
committer | Xavier Ducrohet <xav@android.com> | 2010-06-04 10:53:28 -0700 |
commit | 9b2c8551d6cd9eadd3934a3511eadd68b1076024 (patch) | |
tree | 9914a0c8a09f0d8d0b465b5a58289874c2059f7e /anttasks/src | |
parent | 2e623920849ce79ad293557d21758add4aea95d8 (diff) | |
download | sdk-9b2c8551d6cd9eadd3934a3511eadd68b1076024.zip sdk-9b2c8551d6cd9eadd3934a3511eadd68b1076024.tar.gz sdk-9b2c8551d6cd9eadd3934a3511eadd68b1076024.tar.bz2 |
Rework the multi-apk log file(s).
Move away from a single log file used for:
- tell the dev what file was created with that properties
- used to increment minor versionCode for specific apks
- used to detect config change from what export to another.
There are now three files for each case, with the last two
using a never changing filename. Only a new build log file
is created at each export.
Change-Id: Ia9b464e6ffefe24463a537ee48d0a20a7a004af7
Diffstat (limited to 'anttasks/src')
-rw-r--r-- | anttasks/src/com/android/ant/MultiApkExportTask.java | 356 |
1 files changed, 193 insertions, 163 deletions
diff --git a/anttasks/src/com/android/ant/MultiApkExportTask.java b/anttasks/src/com/android/ant/MultiApkExportTask.java index d22b1e1..7666fbc 100644 --- a/anttasks/src/com/android/ant/MultiApkExportTask.java +++ b/anttasks/src/com/android/ant/MultiApkExportTask.java @@ -18,10 +18,9 @@ package com.android.ant; import com.android.sdklib.internal.export.ApkData; import com.android.sdklib.internal.export.MultiApkExportHelper; +import com.android.sdklib.internal.export.ProjectConfig; import com.android.sdklib.internal.export.MultiApkExportHelper.ExportException; import com.android.sdklib.internal.export.MultiApkExportHelper.Target; -import com.android.sdklib.io.FileWrapper; -import com.android.sdklib.io.IAbstractFile; import org.apache.tools.ant.BuildException; import org.apache.tools.ant.Project; @@ -36,6 +35,7 @@ import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.util.HashSet; +import java.util.List; import java.util.Map; import java.util.Set; import java.util.Map.Entry; @@ -86,79 +86,84 @@ public class MultiApkExportTask extends Task { } System.out.println("versionCode: " + version); - // checks whether the projects can be signed. - boolean canSign = false; - String keyStore = null, keyAlias = null; - if (mTarget == Target.RELEASE) { - String value = antProject.getProperty("key.store"); - keyStore = value != null && value.length() > 0 ? value : null; - value = antProject.getProperty("key.alias"); - keyAlias = value != null && value.length() > 0 ? value : null; - canSign = keyStore != null && keyAlias != null; - } - // get the list of projects - String projects = getValidatedProperty(antProject, "projects"); + String projectList = getValidatedProperty(antProject, "projects"); - // look to see if there's an export log from a previous export - IAbstractFile log = getBuildLog(appPackage, versionCode); + File rootFolder = antProject.getBaseDir(); + MultiApkExportHelper helper = new MultiApkExportHelper(rootFolder.getAbsolutePath(), + appPackage, versionCode, mTarget); - MultiApkExportHelper helper = new MultiApkExportHelper(appPackage, versionCode, mTarget); try { - ApkData[] apks = helper.getProjects(projects, log); - - // some temp var used by the project loop - HashSet<String> compiledProject = new HashSet<String>(); - mXPathFactory = XPathFactory.newInstance(); - - File exportProjectOutput = new File(getValidatedProperty(antProject, - "out.absolute.dir")); - - // if there's no error, and we can sign, prompt for the passwords. - String keyStorePassword = null; - String keyAliasPassword = null; - if (canSign) { - System.out.println("Found signing keystore and key alias. Need passwords."); - - Input input = new Input(); - input.setProject(antProject); - input.setAddproperty("key.store.password"); - input.setMessage(String.format("Please enter keystore password (store: %1$s):", - keyStore)); - input.execute(); - - input = new Input(); - input.setProject(antProject); - input.setAddproperty("key.alias.password"); - input.setMessage(String.format("Please enter password for alias '%1$s':", - keyAlias)); - input.execute(); - - // and now read the property so that they can be set into the sub ant task. - keyStorePassword = getValidatedProperty(antProject, "key.store.password"); - keyAliasPassword = getValidatedProperty(antProject, "key.alias.password"); - } + if (mTarget == Target.CLEAN) { + // for a clean, we don't need the list of ApkData, we only need the list of + // projects + List<ProjectConfig> projects = helper.getProjects(projectList); + for (ProjectConfig projectConfig : projects) { + executeCleanSubAnt(antProject, projectConfig); + } + } else { + // checks whether the projects can be signed. + String value = antProject.getProperty("key.store"); + String keyStore = value != null && value.length() > 0 ? value : null; + value = antProject.getProperty("key.alias"); + String keyAlias = value != null && value.length() > 0 ? value : null; + boolean canSign = keyStore != null && keyAlias != null; + + List<ApkData> apks = helper.getApkData(projectList); + + // some temp var used by the project loop + HashSet<String> compiledProject = new HashSet<String>(); + mXPathFactory = XPathFactory.newInstance(); + + File exportProjectOutput = new File(getValidatedProperty(antProject, + "out.absolute.dir")); + + // if there's no error, and we can sign, prompt for the passwords. + String keyStorePassword = null; + String keyAliasPassword = null; + if (canSign) { + System.out.println("Found signing keystore and key alias. Need passwords."); + + Input input = new Input(); + input.setProject(antProject); + input.setAddproperty("key.store.password"); + input.setMessage(String.format("Please enter keystore password (store: %1$s):", + keyStore)); + input.execute(); + + input = new Input(); + input.setProject(antProject); + input.setAddproperty("key.alias.password"); + input.setMessage(String.format("Please enter password for alias '%1$s':", + keyAlias)); + input.execute(); + + // and now read the property so that they can be set into the sub ant task. + keyStorePassword = getValidatedProperty(antProject, "key.store.password"); + keyAliasPassword = getValidatedProperty(antProject, "key.alias.password"); + } - for (ApkData apk : apks) { + for (ApkData apk : apks) { - Map<String, String> variantMap = apk.getSoftVariantMap(); + Map<String, String> variantMap = apk.getSoftVariantMap(); - // first, do the full export. - makeSubAnt(antProject, appPackage, versionCode, apk, null, - exportProjectOutput, canSign, keyStore, keyAlias, - keyStorePassword, keyAliasPassword, compiledProject); + if (variantMap.size() > 0) { + // if there are soft variants, only export those. + for (Entry<String, String> entry : variantMap.entrySet()) { + executeReleaseSubAnt(antProject, appPackage, versionCode, apk, entry, + exportProjectOutput, canSign, keyStore, keyAlias, + keyStorePassword, keyAliasPassword, compiledProject); + } + } else { + // do the full export. + executeReleaseSubAnt(antProject, appPackage, versionCode, apk, null, + exportProjectOutput, canSign, keyStore, keyAlias, + keyStorePassword, keyAliasPassword, compiledProject); - // then do the soft variants. - for (Entry<String, String> entry : variantMap.entrySet()) { - makeSubAnt(antProject, appPackage, versionCode, apk, entry, - exportProjectOutput, canSign, keyStore, keyAlias, - keyStorePassword, keyAliasPassword, compiledProject); + } } - } - - if (mTarget == Target.RELEASE) { - helper.makeBuildLog(log, apks); + helper.writeLogs(); } } catch (ExportException e) { // we only want to have Ant display the message, not the stack trace, since @@ -169,7 +174,43 @@ public class MultiApkExportTask extends Task { } /** - * Creates and executes a sub ant task. + * Creates and execute a clean sub ant task. + * @param antProject the current Ant project + * @param projectConfig the project to clean. + */ + private void executeCleanSubAnt(Project antProject, ProjectConfig projectConfig) { + + String relativePath = projectConfig.getRelativePath(); + + // this output is prepended by "[android-export] " (17 chars), so we put 61 stars + System.out.println("\n*************************************************************"); + System.out.println("Cleaning project: " + relativePath); + + SubAnt subAnt = new SubAnt(); + subAnt.setTarget(mTarget.getTarget()); + subAnt.setProject(antProject); + + File subProjectFolder = projectConfig.getProjectFolder(); + + FileSet fileSet = new FileSet(); + fileSet.setProject(antProject); + fileSet.setDir(subProjectFolder); + fileSet.setIncludes("build.xml"); + subAnt.addFileset(fileSet); + + // TODO: send the verbose flag from the main build.xml to the subAnt project. + //subAnt.setVerbose(true); + + // end of the output by this task. Everything that follows will be output + // by the subant. + System.out.println("Calling to project's Ant file..."); + System.out.println("----------\n"); + + subAnt.execute(); + } + + /** + * Creates and executes a release sub ant task. * @param antProject the current Ant project * @param appPackage the application package string. * @param versionCode the current version of the application @@ -184,20 +225,22 @@ public class MultiApkExportTask extends Task { * @param keyAliasPassword the password of the key alias for signing * @param compiledProject a list of projects that have already been compiled. */ - private void makeSubAnt(Project antProject, String appPackage, int versionCode, + private void executeReleaseSubAnt(Project antProject, String appPackage, int versionCode, ApkData apk, Entry<String, String> softVariant, File exportProjectOutput, boolean canSign, String keyStore, String keyAlias, String keyStorePassword, String keyAliasPassword, Set<String> compiledProject) { + String relativePath = apk.getProjectConfig().getRelativePath(); + // this output is prepended by "[android-export] " (17 chars), so we put 61 stars System.out.println("\n*************************************************************"); - System.out.println("Exporting project: " + apk.getRelativePath()); + System.out.println("Exporting project: " + relativePath); SubAnt subAnt = new SubAnt(); subAnt.setTarget(mTarget.getTarget()); subAnt.setProject(antProject); - File subProjectFolder = new File(antProject.getBaseDir(), apk.getRelativePath()); + File subProjectFolder = apk.getProjectConfig().getProjectFolder(); FileSet fileSet = new FileSet(); fileSet.setProject(antProject); @@ -208,94 +251,92 @@ public class MultiApkExportTask extends Task { // TODO: send the verbose flag from the main build.xml to the subAnt project. //subAnt.setVerbose(true); - if (mTarget == Target.RELEASE) { - // only do the compilation part if it's the first time we export - // this project. - // (projects can be export multiple time if some properties are set up to - // generate more than one APK (for instance ABI split). - if (compiledProject.contains(apk.getRelativePath()) == false) { - compiledProject.add(apk.getRelativePath()); - } else { - addProp(subAnt, "do.not.compile", "true"); - } - - // set the version code, and filtering - int compositeVersionCode = apk.getCompositeVersionCode(versionCode); - addProp(subAnt, "version.code", Integer.toString(compositeVersionCode)); - System.out.println("Composite versionCode: " + compositeVersionCode); - String abi = apk.getAbi(); - if (abi != null) { - addProp(subAnt, "filter.abi", abi); - System.out.println("ABI Filter: " + abi); - } - - // set the output file names/paths. Keep all the temporary files in the project - // folder, and only put the final file (which is different depending on whether - // the file can be signed) locally. - - // read the base name from the build.xml file. - String name = null; - try { - File buildFile = new File(subProjectFolder, "build.xml"); - XPath xPath = mXPathFactory.newXPath(); - name = xPath.evaluate("/project/@name", - new InputSource(new FileInputStream(buildFile))); - } catch (XPathExpressionException e) { - throw new BuildException("Failed to read build.xml", e); - } catch (FileNotFoundException e) { - throw new BuildException("build.xml is missing.", e); - } - - // override the resource pack file as well as the final name - String pkgName = name + "-" + apk.getBuildInfo(); - String finalNameRoot = appPackage + "-" + compositeVersionCode; - if (softVariant != null) { - String tmp = "-" + softVariant.getKey(); - pkgName += tmp; - finalNameRoot += tmp; - - // set the resource filter. - addProp(subAnt, "aapt.resource.filter", softVariant.getValue()); - System.out.println("res Filter: " + softVariant.getValue()); - } - - // set the resource pack file name. - addProp(subAnt, "resource.package.file.name", pkgName + ".ap_"); + // only do the compilation part if it's the first time we export + // this project. + // (projects can be export multiple time if some properties are set up to + // generate more than one APK (for instance ABI split). + if (compiledProject.contains(relativePath) == false) { + compiledProject.add(relativePath); + } else { + addProp(subAnt, "do.not.compile", "true"); + } + // set the version code, and filtering + int compositeVersionCode = apk.getCompositeVersionCode(versionCode); + addProp(subAnt, "version.code", Integer.toString(compositeVersionCode)); + System.out.println("Composite versionCode: " + compositeVersionCode); + String abi = apk.getAbi(); + if (abi != null) { + addProp(subAnt, "filter.abi", abi); + System.out.println("ABI Filter: " + abi); + } - if (canSign) { - // set the properties for the password. - addProp(subAnt, "key.store", keyStore); - addProp(subAnt, "key.alias", keyAlias); - addProp(subAnt, "key.store.password", keyStorePassword); - addProp(subAnt, "key.alias.password", keyAliasPassword); + // set the output file names/paths. Keep all the temporary files in the project + // folder, and only put the final file (which is different depending on whether + // the file can be signed) locally. - // temporary file only get a filename change (still stored in the project - // bin folder). - addProp(subAnt, "out.unsigned.file.name", - name + "-" + apk.getBuildInfo() + "-unsigned.apk"); - addProp(subAnt, "out.unaligned.file", - name + "-" + apk.getBuildInfo() + "-unaligned.apk"); + // read the base name from the build.xml file. + String name = null; + try { + File buildFile = new File(subProjectFolder, "build.xml"); + XPath xPath = mXPathFactory.newXPath(); + name = xPath.evaluate("/project/@name", + new InputSource(new FileInputStream(buildFile))); + } catch (XPathExpressionException e) { + throw new BuildException("Failed to read build.xml", e); + } catch (FileNotFoundException e) { + throw new BuildException("build.xml is missing.", e); + } - // final file is stored locally with a name based on the package - String outputName = finalNameRoot + "-release.apk"; - apk.setOutputName(softVariant != null ? softVariant.getKey() : null, outputName); - addProp(subAnt, "out.release.file", - new File(exportProjectOutput, outputName).getAbsolutePath()); + // override the resource pack file as well as the final name + String pkgName = name + "-" + apk.getBuildInfo(); + String finalNameRoot = appPackage + "-" + compositeVersionCode; + if (softVariant != null) { + String tmp = "-" + softVariant.getKey(); + pkgName += tmp; + finalNameRoot += tmp; + + // set the resource filter. + addProp(subAnt, "aapt.resource.filter", softVariant.getValue()); + System.out.println("res Filter: " + softVariant.getValue()); + } - } else { - // put some empty prop. This is to override possible ones defined in the - // project. The reason is that if there's more than one project, we don't - // want some to signed and some not to be (and we don't want each project - // to prompt for password.) - addProp(subAnt, "key.store", ""); - addProp(subAnt, "key.alias", ""); - // final file is the unsigned version. It gets stored locally. - String outputName = finalNameRoot + "-unsigned.apk"; - apk.setOutputName(softVariant != null ? softVariant.getKey() : null, outputName); - addProp(subAnt, "out.unsigned.file", - new File(exportProjectOutput, outputName).getAbsolutePath()); - } + // set the resource pack file name. + addProp(subAnt, "resource.package.file.name", pkgName + ".ap_"); + + + if (canSign) { + // set the properties for the password. + addProp(subAnt, "key.store", keyStore); + addProp(subAnt, "key.alias", keyAlias); + addProp(subAnt, "key.store.password", keyStorePassword); + addProp(subAnt, "key.alias.password", keyAliasPassword); + + // temporary file only get a filename change (still stored in the project + // bin folder). + addProp(subAnt, "out.unsigned.file.name", + name + "-" + apk.getBuildInfo() + "-unsigned.apk"); + addProp(subAnt, "out.unaligned.file", + name + "-" + apk.getBuildInfo() + "-unaligned.apk"); + + // final file is stored locally with a name based on the package + String outputName = finalNameRoot + "-release.apk"; + apk.setOutputName(softVariant != null ? softVariant.getKey() : null, outputName); + addProp(subAnt, "out.release.file", + new File(exportProjectOutput, outputName).getAbsolutePath()); + + } else { + // put some empty prop. This is to override possible ones defined in the + // project. The reason is that if there's more than one project, we don't + // want some to signed and some not to be (and we don't want each project + // to prompt for password.) + addProp(subAnt, "key.store", ""); + addProp(subAnt, "key.alias", ""); + // final file is the unsigned version. It gets stored locally. + String outputName = finalNameRoot + "-unsigned.apk"; + apk.setOutputName(softVariant != null ? softVariant.getKey() : null, outputName); + addProp(subAnt, "out.unsigned.file", + new File(exportProjectOutput, outputName).getAbsolutePath()); } // end of the output by this task. Everything that follows will be output @@ -323,7 +364,6 @@ public class MultiApkExportTask extends Task { return value; } - /** * Adds a property to a {@link SubAnt} task. * @param task the task. @@ -336,14 +376,4 @@ public class MultiApkExportTask extends Task { prop.setValue(value); task.addProperty(prop); } - - /** - * Returns the {@link File} for the build log. - * @param appPackage - * @param versionCode - * @return A new non-null {@link IAbstractFile} mapping to the build log. - */ - private IAbstractFile getBuildLog(String appPackage, int versionCode) { - return new FileWrapper(appPackage + "." + versionCode + ".log"); - } } |