159243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet/* 259243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet * Copyright (C) 2010 The Android Open Source Project 359243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet * 459243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet * Licensed under the Eclipse Public License, Version 1.0 (the "License"); 559243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet * you may not use this file except in compliance with the License. 659243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet * You may obtain a copy of the License at 759243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet * 859243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet * http://www.eclipse.org/org/documents/epl-v10.php 959243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet * 1059243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet * Unless required by applicable law or agreed to in writing, software 1159243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet * distributed under the License is distributed on an "AS IS" BASIS, 1259243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1359243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet * See the License for the specific language governing permissions and 1459243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet * limitations under the License. 1559243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet */ 1659243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet 1759243b8de886379e7154c886adbefc74dac24055Xavier Ducrohetpackage com.android.ide.eclipse.adt.internal.build; 1859243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet 1981cefe2a26dd6db8a878e30874d12cdcbff0e83bXavier Ducrohetimport com.android.SdkConstants; 207e4b8e9d595e45baa9d87cdb8282f02759e73abcTor Norbyeimport com.android.annotations.Nullable; 21c3105b949cd2a0f6cbf8a12ec4f30e49b5b5a502Xavier Ducrohetimport com.android.ide.eclipse.adt.AdtConstants; 22fd19b2c89be703549e23d501541632883819ab7bRaphael Mollimport com.android.ide.eclipse.adt.AdtPlugin; 233d3c3c3a3e4e05f7ae7a0dff440fe500f90b785cXavier Ducrohetimport com.android.ide.eclipse.adt.AndroidPrintStream; 2459243b8de886379e7154c886adbefc74dac24055Xavier Ducrohetimport com.android.ide.eclipse.adt.internal.preferences.AdtPrefs; 2559243b8de886379e7154c886adbefc74dac24055Xavier Ducrohetimport com.android.ide.eclipse.adt.internal.preferences.AdtPrefs.BuildVerbosity; 2698b631c6b3765be96b3707ba7aa54d52b10f4872Xavier Ducrohetimport com.android.ide.eclipse.adt.internal.project.BaseProjectHelper; 2759243b8de886379e7154c886adbefc74dac24055Xavier Ducrohetimport com.android.ide.eclipse.adt.internal.sdk.Sdk; 2859243b8de886379e7154c886adbefc74dac24055Xavier Ducrohetimport com.android.prefs.AndroidLocation.AndroidLocationException; 2959243b8de886379e7154c886adbefc74dac24055Xavier Ducrohetimport com.android.sdklib.IAndroidTarget; 3067000f1a4e4cc31c258afd80fe13939ae66aea2aXavier Ducrohetimport com.android.sdklib.IAndroidTarget.IOptionalLibrary; 317c19dcf5aead68f4f6675db0bac6b495396e2967Xavier Ducrohetimport com.android.sdklib.build.ApkBuilder; 32ab36f4e7488358dea4ab6b54ee2b7bef3da0232bTor Norbyeimport com.android.sdklib.build.ApkBuilder.JarStatus; 33ab36f4e7488358dea4ab6b54ee2b7bef3da0232bTor Norbyeimport com.android.sdklib.build.ApkBuilder.SigningInfo; 341fd0a0d0ad99735551876d6f7ceab7ff5d42b575Xavier Ducrohetimport com.android.sdklib.build.ApkCreationException; 351fd0a0d0ad99735551876d6f7ceab7ff5d42b575Xavier Ducrohetimport com.android.sdklib.build.DuplicateFileException; 361fd0a0d0ad99735551876d6f7ceab7ff5d42b575Xavier Ducrohetimport com.android.sdklib.build.SealedApkException; 3710e712627b86b2b0061dbd3a20f5f966b2cd7330Xavier Ducrohetimport com.android.sdklib.internal.build.DebugKeyProvider; 3867000f1a4e4cc31c258afd80fe13939ae66aea2aXavier Ducrohetimport com.android.sdklib.internal.build.DebugKeyProvider.KeytoolException; 398c578aff7c5d84bc38d5a6d391986aece3cd2e19Raphaelimport com.android.sdklib.util.GrabProcessOutput; 408c578aff7c5d84bc38d5a6d391986aece3cd2e19Raphaelimport com.android.sdklib.util.GrabProcessOutput.IProcessOutput; 41e27bbc4d1cf9c9d6b23344b977331bed0a3357a5Raphaelimport com.android.sdklib.util.GrabProcessOutput.Wait; 4259243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet 4359243b8de886379e7154c886adbefc74dac24055Xavier Ducrohetimport org.eclipse.core.resources.IFile; 4459243b8de886379e7154c886adbefc74dac24055Xavier Ducrohetimport org.eclipse.core.resources.IFolder; 4559243b8de886379e7154c886adbefc74dac24055Xavier Ducrohetimport org.eclipse.core.resources.IProject; 4659243b8de886379e7154c886adbefc74dac24055Xavier Ducrohetimport org.eclipse.core.resources.IResource; 4759243b8de886379e7154c886adbefc74dac24055Xavier Ducrohetimport org.eclipse.core.resources.IWorkspaceRoot; 4859243b8de886379e7154c886adbefc74dac24055Xavier Ducrohetimport org.eclipse.core.resources.ResourcesPlugin; 4959243b8de886379e7154c886adbefc74dac24055Xavier Ducrohetimport org.eclipse.core.runtime.CoreException; 5059243b8de886379e7154c886adbefc74dac24055Xavier Ducrohetimport org.eclipse.core.runtime.IPath; 5159243b8de886379e7154c886adbefc74dac24055Xavier Ducrohetimport org.eclipse.core.runtime.IStatus; 5259243b8de886379e7154c886adbefc74dac24055Xavier Ducrohetimport org.eclipse.core.runtime.Status; 53babf25ca7162849f0145f75be1b6c09b359b122cXavier Ducrohetimport org.eclipse.jdt.core.IClasspathContainer; 5459243b8de886379e7154c886adbefc74dac24055Xavier Ducrohetimport org.eclipse.jdt.core.IClasspathEntry; 5559243b8de886379e7154c886adbefc74dac24055Xavier Ducrohetimport org.eclipse.jdt.core.IJavaProject; 5659243b8de886379e7154c886adbefc74dac24055Xavier Ducrohetimport org.eclipse.jdt.core.JavaCore; 5759243b8de886379e7154c886adbefc74dac24055Xavier Ducrohetimport org.eclipse.jdt.core.JavaModelException; 5859243b8de886379e7154c886adbefc74dac24055Xavier Ducrohetimport org.eclipse.jface.preference.IPreferenceStore; 5959243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet 6059243b8de886379e7154c886adbefc74dac24055Xavier Ducrohetimport java.io.File; 61eca9ade6294f925e266eeece8071d5bfdede9c6aRaphael Mollimport java.io.FileWriter; 6259243b8de886379e7154c886adbefc74dac24055Xavier Ducrohetimport java.io.IOException; 6359243b8de886379e7154c886adbefc74dac24055Xavier Ducrohetimport java.io.PrintStream; 643d3c3c3a3e4e05f7ae7a0dff440fe500f90b785cXavier Ducrohetimport java.security.PrivateKey; 653d3c3c3a3e4e05f7ae7a0dff440fe500f90b785cXavier Ducrohetimport java.security.cert.X509Certificate; 6659243b8de886379e7154c886adbefc74dac24055Xavier Ducrohetimport java.util.ArrayList; 67bcf44e9429811b3e1f97d21ea92816957bce2601Xavier Ducrohetimport java.util.Collection; 68cc62a7f883c51fb8908bf936e894170d775385bcXavier Ducrohetimport java.util.Collections; 69bcf44e9429811b3e1f97d21ea92816957bce2601Xavier Ducrohetimport java.util.HashSet; 7059243b8de886379e7154c886adbefc74dac24055Xavier Ducrohetimport java.util.List; 71eca9ade6294f925e266eeece8071d5bfdede9c6aRaphael Mollimport java.util.Map; 72bcf44e9429811b3e1f97d21ea92816957bce2601Xavier Ducrohetimport java.util.Set; 73eca9ade6294f925e266eeece8071d5bfdede9c6aRaphael Mollimport java.util.TreeMap; 7459243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet 757c19dcf5aead68f4f6675db0bac6b495396e2967Xavier Ducrohet/** 767c19dcf5aead68f4f6675db0bac6b495396e2967Xavier Ducrohet * Helper with methods for the last 3 steps of the generation of an APK. 777c19dcf5aead68f4f6675db0bac6b495396e2967Xavier Ducrohet * 787c19dcf5aead68f4f6675db0bac6b495396e2967Xavier Ducrohet * {@link #packageResources(IFile, IProject[], String, int, String, String)} packages the 797c19dcf5aead68f4f6675db0bac6b495396e2967Xavier Ducrohet * application resources using aapt into a zip file that is ready to be integrated into the apk. 807c19dcf5aead68f4f6675db0bac6b495396e2967Xavier Ducrohet * 817c19dcf5aead68f4f6675db0bac6b495396e2967Xavier Ducrohet * {@link #executeDx(IJavaProject, String, String, IJavaProject[])} will convert the Java byte 827c19dcf5aead68f4f6675db0bac6b495396e2967Xavier Ducrohet * code into the Dalvik bytecode. 837c19dcf5aead68f4f6675db0bac6b495396e2967Xavier Ducrohet * 847c19dcf5aead68f4f6675db0bac6b495396e2967Xavier Ducrohet * {@link #finalPackage(String, String, String, boolean, IJavaProject, IProject[], IJavaProject[], String, boolean)} 857c19dcf5aead68f4f6675db0bac6b495396e2967Xavier Ducrohet * will make the apk from all the previous components. 867c19dcf5aead68f4f6675db0bac6b495396e2967Xavier Ducrohet * 873d3c3c3a3e4e05f7ae7a0dff440fe500f90b785cXavier Ducrohet * This class only executes the 3 above actions. It does not handle the errors, and simply sends 883d3c3c3a3e4e05f7ae7a0dff440fe500f90b785cXavier Ducrohet * them back as custom exceptions. 893d3c3c3a3e4e05f7ae7a0dff440fe500f90b785cXavier Ducrohet * 903d3c3c3a3e4e05f7ae7a0dff440fe500f90b785cXavier Ducrohet * Warnings are handled by the {@link ResourceMarker} interface. 913d3c3c3a3e4e05f7ae7a0dff440fe500f90b785cXavier Ducrohet * 923d3c3c3a3e4e05f7ae7a0dff440fe500f90b785cXavier Ducrohet * Console output (verbose and non verbose) is handled through the {@link AndroidPrintStream} passed 933d3c3c3a3e4e05f7ae7a0dff440fe500f90b785cXavier Ducrohet * to the constructor. 943d3c3c3a3e4e05f7ae7a0dff440fe500f90b785cXavier Ducrohet * 957c19dcf5aead68f4f6675db0bac6b495396e2967Xavier Ducrohet */ 9659f8d5012426884e40b77b02a7c3274eb66019a1Xavier Ducrohetpublic class BuildHelper { 9759243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet 98eca9ade6294f925e266eeece8071d5bfdede9c6aRaphael Moll private static final String CONSOLE_PREFIX_DX = "Dx"; //$NON-NLS-1$ 99eca9ade6294f925e266eeece8071d5bfdede9c6aRaphael Moll private final static String TEMP_PREFIX = "android_"; //$NON-NLS-1$ 1003d3c3c3a3e4e05f7ae7a0dff440fe500f90b785cXavier Ducrohet 101c15b4fdc76142c61db1ec29feb2afdfaea43a84bJosiah Gaskin private static final String COMMAND_CRUNCH = "crunch"; //$NON-NLS-1$ 102c15b4fdc76142c61db1ec29feb2afdfaea43a84bJosiah Gaskin private static final String COMMAND_PACKAGE = "package"; //$NON-NLS-1$ 103c15b4fdc76142c61db1ec29feb2afdfaea43a84bJosiah Gaskin 10459243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet private final IProject mProject; 1053d3c3c3a3e4e05f7ae7a0dff440fe500f90b785cXavier Ducrohet private final AndroidPrintStream mOutStream; 1063d3c3c3a3e4e05f7ae7a0dff440fe500f90b785cXavier Ducrohet private final AndroidPrintStream mErrStream; 1073d3c3c3a3e4e05f7ae7a0dff440fe500f90b785cXavier Ducrohet private final boolean mVerbose; 1083d3c3c3a3e4e05f7ae7a0dff440fe500f90b785cXavier Ducrohet private final boolean mDebugMode; 1093d3c3c3a3e4e05f7ae7a0dff440fe500f90b785cXavier Ducrohet 110bcf44e9429811b3e1f97d21ea92816957bce2601Xavier Ducrohet private final Set<String> mCompiledCodePaths = new HashSet<String>(); 111bcf44e9429811b3e1f97d21ea92816957bce2601Xavier Ducrohet 112c15b4fdc76142c61db1ec29feb2afdfaea43a84bJosiah Gaskin public static final boolean BENCHMARK_FLAG = false; 113c15b4fdc76142c61db1ec29feb2afdfaea43a84bJosiah Gaskin public static long sStartOverallTime = 0; 114c15b4fdc76142c61db1ec29feb2afdfaea43a84bJosiah Gaskin public static long sStartJavaCTime = 0; 115c15b4fdc76142c61db1ec29feb2afdfaea43a84bJosiah Gaskin 116c15b4fdc76142c61db1ec29feb2afdfaea43a84bJosiah Gaskin private final static int MILLION = 1000000; 117cc62a7f883c51fb8908bf936e894170d775385bcXavier Ducrohet private String mProguardFile; 118c15b4fdc76142c61db1ec29feb2afdfaea43a84bJosiah Gaskin 1193d3c3c3a3e4e05f7ae7a0dff440fe500f90b785cXavier Ducrohet /** 1203d3c3c3a3e4e05f7ae7a0dff440fe500f90b785cXavier Ducrohet * An object able to put a marker on a resource. 1213d3c3c3a3e4e05f7ae7a0dff440fe500f90b785cXavier Ducrohet */ 1223d3c3c3a3e4e05f7ae7a0dff440fe500f90b785cXavier Ducrohet public interface ResourceMarker { 1233d3c3c3a3e4e05f7ae7a0dff440fe500f90b785cXavier Ducrohet void setWarning(IResource resource, String message); 1243d3c3c3a3e4e05f7ae7a0dff440fe500f90b785cXavier Ducrohet } 1253d3c3c3a3e4e05f7ae7a0dff440fe500f90b785cXavier Ducrohet 1263d3c3c3a3e4e05f7ae7a0dff440fe500f90b785cXavier Ducrohet /** 1273d3c3c3a3e4e05f7ae7a0dff440fe500f90b785cXavier Ducrohet * Creates a new post-compiler helper 1283d3c3c3a3e4e05f7ae7a0dff440fe500f90b785cXavier Ducrohet * @param project 1293d3c3c3a3e4e05f7ae7a0dff440fe500f90b785cXavier Ducrohet * @param outStream 1303d3c3c3a3e4e05f7ae7a0dff440fe500f90b785cXavier Ducrohet * @param errStream 1313d3c3c3a3e4e05f7ae7a0dff440fe500f90b785cXavier Ducrohet * @param debugMode whether this is a debug build 1323d3c3c3a3e4e05f7ae7a0dff440fe500f90b785cXavier Ducrohet * @param verbose 133bcf44e9429811b3e1f97d21ea92816957bce2601Xavier Ducrohet * @throws CoreException 1343d3c3c3a3e4e05f7ae7a0dff440fe500f90b785cXavier Ducrohet */ 13559f8d5012426884e40b77b02a7c3274eb66019a1Xavier Ducrohet public BuildHelper(IProject project, AndroidPrintStream outStream, 136bcf44e9429811b3e1f97d21ea92816957bce2601Xavier Ducrohet AndroidPrintStream errStream, boolean debugMode, boolean verbose, 137bcf44e9429811b3e1f97d21ea92816957bce2601Xavier Ducrohet ResourceMarker resMarker) throws CoreException { 13859243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet mProject = project; 13959243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet mOutStream = outStream; 14059243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet mErrStream = errStream; 1413d3c3c3a3e4e05f7ae7a0dff440fe500f90b785cXavier Ducrohet mDebugMode = debugMode; 1423d3c3c3a3e4e05f7ae7a0dff440fe500f90b785cXavier Ducrohet mVerbose = verbose; 143bcf44e9429811b3e1f97d21ea92816957bce2601Xavier Ducrohet 144bcf44e9429811b3e1f97d21ea92816957bce2601Xavier Ducrohet gatherPaths(resMarker); 14559243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet } 14659243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet 147c15b4fdc76142c61db1ec29feb2afdfaea43a84bJosiah Gaskin public void updateCrunchCache() throws AaptExecException, AaptResultException { 148c15b4fdc76142c61db1ec29feb2afdfaea43a84bJosiah Gaskin // Benchmarking start 149c15b4fdc76142c61db1ec29feb2afdfaea43a84bJosiah Gaskin long startCrunchTime = 0; 150c15b4fdc76142c61db1ec29feb2afdfaea43a84bJosiah Gaskin if (BENCHMARK_FLAG) { 151c15b4fdc76142c61db1ec29feb2afdfaea43a84bJosiah Gaskin String msg = "BENCHMARK ADT: Starting Initial Packaging (.ap_)"; //$NON-NLS-1$ 152c15b4fdc76142c61db1ec29feb2afdfaea43a84bJosiah Gaskin AdtPlugin.printBuildToConsole(BuildVerbosity.ALWAYS, mProject, msg); 153c15b4fdc76142c61db1ec29feb2afdfaea43a84bJosiah Gaskin startCrunchTime = System.nanoTime(); 154c15b4fdc76142c61db1ec29feb2afdfaea43a84bJosiah Gaskin } 155c15b4fdc76142c61db1ec29feb2afdfaea43a84bJosiah Gaskin 156c15b4fdc76142c61db1ec29feb2afdfaea43a84bJosiah Gaskin // Get the resources folder to crunch from 157c15b4fdc76142c61db1ec29feb2afdfaea43a84bJosiah Gaskin IFolder resFolder = mProject.getFolder(AdtConstants.WS_RESOURCES); 158c15b4fdc76142c61db1ec29feb2afdfaea43a84bJosiah Gaskin List<String> resPaths = new ArrayList<String>(); 159c15b4fdc76142c61db1ec29feb2afdfaea43a84bJosiah Gaskin resPaths.add(resFolder.getLocation().toOSString()); 160c15b4fdc76142c61db1ec29feb2afdfaea43a84bJosiah Gaskin 161c15b4fdc76142c61db1ec29feb2afdfaea43a84bJosiah Gaskin // Get the output folder where the cache is stored. 162c15b4fdc76142c61db1ec29feb2afdfaea43a84bJosiah Gaskin IFolder cacheFolder = mProject.getFolder(AdtConstants.WS_CRUNCHCACHE); 163c15b4fdc76142c61db1ec29feb2afdfaea43a84bJosiah Gaskin String cachePath = cacheFolder.getLocation().toOSString(); 164c15b4fdc76142c61db1ec29feb2afdfaea43a84bJosiah Gaskin 165c15b4fdc76142c61db1ec29feb2afdfaea43a84bJosiah Gaskin /* For crunching, we don't need the osManifestPath, osAssetsPath, or the configFilter 166c15b4fdc76142c61db1ec29feb2afdfaea43a84bJosiah Gaskin * parameters for executeAapt 167c15b4fdc76142c61db1ec29feb2afdfaea43a84bJosiah Gaskin */ 168c15b4fdc76142c61db1ec29feb2afdfaea43a84bJosiah Gaskin executeAapt(COMMAND_CRUNCH, "", resPaths, "", cachePath, "", 0); 169c15b4fdc76142c61db1ec29feb2afdfaea43a84bJosiah Gaskin 170c15b4fdc76142c61db1ec29feb2afdfaea43a84bJosiah Gaskin // Benchmarking end 171c15b4fdc76142c61db1ec29feb2afdfaea43a84bJosiah Gaskin if (BENCHMARK_FLAG) { 172c15b4fdc76142c61db1ec29feb2afdfaea43a84bJosiah Gaskin String msg = "BENCHMARK ADT: Ending Initial Package (.ap_). \nTime Elapsed: " //$NON-NLS-1$ 173c15b4fdc76142c61db1ec29feb2afdfaea43a84bJosiah Gaskin + ((System.nanoTime() - startCrunchTime)/MILLION) + "ms"; //$NON-NLS-1$ 174c15b4fdc76142c61db1ec29feb2afdfaea43a84bJosiah Gaskin AdtPlugin.printBuildToConsole(BuildVerbosity.ALWAYS, mProject, msg); 175c15b4fdc76142c61db1ec29feb2afdfaea43a84bJosiah Gaskin } 176c15b4fdc76142c61db1ec29feb2afdfaea43a84bJosiah Gaskin } 177babf25ca7162849f0145f75be1b6c09b359b122cXavier Ducrohet 178853ab5a62d09675e0921d2eed60c02f66e3d0050Xavier Ducrohet /** 179853ab5a62d09675e0921d2eed60c02f66e3d0050Xavier Ducrohet * Packages the resources of the projet into a .ap_ file. 180853ab5a62d09675e0921d2eed60c02f66e3d0050Xavier Ducrohet * @param manifestFile the manifest of the project. 181853ab5a62d09675e0921d2eed60c02f66e3d0050Xavier Ducrohet * @param libProjects the list of library projects that this project depends on. 182853ab5a62d09675e0921d2eed60c02f66e3d0050Xavier Ducrohet * @param resFilter an optional resource filter to be used with the -c option of aapt. If null 183853ab5a62d09675e0921d2eed60c02f66e3d0050Xavier Ducrohet * no filters are used. 184853ab5a62d09675e0921d2eed60c02f66e3d0050Xavier Ducrohet * @param versionCode an optional versionCode to be inserted in the manifest during packaging. 185853ab5a62d09675e0921d2eed60c02f66e3d0050Xavier Ducrohet * If the value is <=0, no values are inserted. 186853ab5a62d09675e0921d2eed60c02f66e3d0050Xavier Ducrohet * @param outputFolder where to write the resource ap_ file. 187853ab5a62d09675e0921d2eed60c02f66e3d0050Xavier Ducrohet * @param outputFilename the name of the resource ap_ file. 1883d3c3c3a3e4e05f7ae7a0dff440fe500f90b785cXavier Ducrohet * @throws AaptExecException 1893d3c3c3a3e4e05f7ae7a0dff440fe500f90b785cXavier Ducrohet * @throws AaptResultException 190853ab5a62d09675e0921d2eed60c02f66e3d0050Xavier Ducrohet */ 191a0340fdf211a94d4d96a9e063386b0eccae9b74cXavier Ducrohet public void packageResources(IFile manifestFile, List<IProject> libProjects, String resFilter, 1923d3c3c3a3e4e05f7ae7a0dff440fe500f90b785cXavier Ducrohet int versionCode, String outputFolder, String outputFilename) 1933d3c3c3a3e4e05f7ae7a0dff440fe500f90b785cXavier Ducrohet throws AaptExecException, AaptResultException { 194c15b4fdc76142c61db1ec29feb2afdfaea43a84bJosiah Gaskin 195c15b4fdc76142c61db1ec29feb2afdfaea43a84bJosiah Gaskin // Benchmarking start 196c15b4fdc76142c61db1ec29feb2afdfaea43a84bJosiah Gaskin long startPackageTime = 0; 197c15b4fdc76142c61db1ec29feb2afdfaea43a84bJosiah Gaskin if (BENCHMARK_FLAG) { 198c15b4fdc76142c61db1ec29feb2afdfaea43a84bJosiah Gaskin String msg = "BENCHMARK ADT: Starting Initial Packaging (.ap_)"; //$NON-NLS-1$ 199c15b4fdc76142c61db1ec29feb2afdfaea43a84bJosiah Gaskin AdtPlugin.printBuildToConsole(BuildVerbosity.ALWAYS, mProject, msg); 200c15b4fdc76142c61db1ec29feb2afdfaea43a84bJosiah Gaskin startPackageTime = System.nanoTime(); 201c15b4fdc76142c61db1ec29feb2afdfaea43a84bJosiah Gaskin } 202c15b4fdc76142c61db1ec29feb2afdfaea43a84bJosiah Gaskin 20359243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet // need to figure out some path before we can execute aapt; 20459243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet 205c15b4fdc76142c61db1ec29feb2afdfaea43a84bJosiah Gaskin // get the cache folder 206c15b4fdc76142c61db1ec29feb2afdfaea43a84bJosiah Gaskin IFolder cacheFolder = mProject.getFolder(AdtConstants.WS_CRUNCHCACHE); 207c15b4fdc76142c61db1ec29feb2afdfaea43a84bJosiah Gaskin 20859243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet // get the resource folder 209c3105b949cd2a0f6cbf8a12ec4f30e49b5b5a502Xavier Ducrohet IFolder resFolder = mProject.getFolder(AdtConstants.WS_RESOURCES); 21059243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet 21159243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet // and the assets folder 212c3105b949cd2a0f6cbf8a12ec4f30e49b5b5a502Xavier Ducrohet IFolder assetsFolder = mProject.getFolder(AdtConstants.WS_ASSETS); 21359243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet 21459243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet // we need to make sure this one exists. 21559243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet if (assetsFolder.exists() == false) { 21659243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet assetsFolder = null; 21759243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet } 21859243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet 21916ed545d6175d2afde14b9585eed1feb28ce6364Xavier Ducrohet // list of res folder (main project + maybe libraries) 22016ed545d6175d2afde14b9585eed1feb28ce6364Xavier Ducrohet ArrayList<String> osResPaths = new ArrayList<String>(); 22116ed545d6175d2afde14b9585eed1feb28ce6364Xavier Ducrohet 22259243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet IPath resLocation = resFolder.getLocation(); 22359243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet IPath manifestLocation = manifestFile.getLocation(); 22459243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet 22559243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet if (resLocation != null && manifestLocation != null) { 22659243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet 22716ed545d6175d2afde14b9585eed1feb28ce6364Xavier Ducrohet // png cache folder first. 22816ed545d6175d2afde14b9585eed1feb28ce6364Xavier Ducrohet addFolderToList(osResPaths, cacheFolder); 22916ed545d6175d2afde14b9585eed1feb28ce6364Xavier Ducrohet 23016ed545d6175d2afde14b9585eed1feb28ce6364Xavier Ducrohet // regular res folder next. 23116ed545d6175d2afde14b9585eed1feb28ce6364Xavier Ducrohet osResPaths.add(resLocation.toOSString()); 23216ed545d6175d2afde14b9585eed1feb28ce6364Xavier Ducrohet 23316ed545d6175d2afde14b9585eed1feb28ce6364Xavier Ducrohet // then libraries 23459243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet if (libProjects != null) { 23559243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet for (IProject lib : libProjects) { 23616ed545d6175d2afde14b9585eed1feb28ce6364Xavier Ducrohet // png cache folder first 23778c89f931135c11c45f26590ea5ae29577bced85Xavier Ducrohet IFolder libCacheFolder = lib.getFolder(AdtConstants.WS_CRUNCHCACHE); 23816ed545d6175d2afde14b9585eed1feb28ce6364Xavier Ducrohet addFolderToList(osResPaths, libCacheFolder); 23916ed545d6175d2afde14b9585eed1feb28ce6364Xavier Ducrohet 24016ed545d6175d2afde14b9585eed1feb28ce6364Xavier Ducrohet // regular res folder next. 24178c89f931135c11c45f26590ea5ae29577bced85Xavier Ducrohet IFolder libResFolder = lib.getFolder(AdtConstants.WS_RESOURCES); 24216ed545d6175d2afde14b9585eed1feb28ce6364Xavier Ducrohet addFolderToList(osResPaths, libResFolder); 24359243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet } 24459243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet } 24559243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet 24659243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet String osManifestPath = manifestLocation.toOSString(); 24759243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet 24859243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet String osAssetsPath = null; 24959243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet if (assetsFolder != null) { 25059243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet osAssetsPath = assetsFolder.getLocation().toOSString(); 25159243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet } 25259243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet 25359243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet // build the default resource package 254c15b4fdc76142c61db1ec29feb2afdfaea43a84bJosiah Gaskin executeAapt(COMMAND_PACKAGE, osManifestPath, osResPaths, osAssetsPath, 255853ab5a62d09675e0921d2eed60c02f66e3d0050Xavier Ducrohet outputFolder + File.separator + outputFilename, resFilter, 2563d3c3c3a3e4e05f7ae7a0dff440fe500f90b785cXavier Ducrohet versionCode); 25759243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet } 258c15b4fdc76142c61db1ec29feb2afdfaea43a84bJosiah Gaskin 259c15b4fdc76142c61db1ec29feb2afdfaea43a84bJosiah Gaskin // Benchmarking end 260c15b4fdc76142c61db1ec29feb2afdfaea43a84bJosiah Gaskin if (BENCHMARK_FLAG) { 261c15b4fdc76142c61db1ec29feb2afdfaea43a84bJosiah Gaskin String msg = "BENCHMARK ADT: Ending Initial Package (.ap_). \nTime Elapsed: " //$NON-NLS-1$ 262c15b4fdc76142c61db1ec29feb2afdfaea43a84bJosiah Gaskin + ((System.nanoTime() - startPackageTime)/MILLION) + "ms"; //$NON-NLS-1$ 263c15b4fdc76142c61db1ec29feb2afdfaea43a84bJosiah Gaskin AdtPlugin.printBuildToConsole(BuildVerbosity.ALWAYS, mProject, msg); 264c15b4fdc76142c61db1ec29feb2afdfaea43a84bJosiah Gaskin } 2653d3c3c3a3e4e05f7ae7a0dff440fe500f90b785cXavier Ducrohet } 26659243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet 2673d3c3c3a3e4e05f7ae7a0dff440fe500f90b785cXavier Ducrohet /** 26816ed545d6175d2afde14b9585eed1feb28ce6364Xavier Ducrohet * Adds os path of a folder to a list only if the folder actually exists. 26916ed545d6175d2afde14b9585eed1feb28ce6364Xavier Ducrohet * @param pathList 27016ed545d6175d2afde14b9585eed1feb28ce6364Xavier Ducrohet * @param folder 27116ed545d6175d2afde14b9585eed1feb28ce6364Xavier Ducrohet */ 27216ed545d6175d2afde14b9585eed1feb28ce6364Xavier Ducrohet private void addFolderToList(List<String> pathList, IFolder folder) { 27316ed545d6175d2afde14b9585eed1feb28ce6364Xavier Ducrohet // use a File instead of the IFolder API to ignore workspace refresh issue. 27416ed545d6175d2afde14b9585eed1feb28ce6364Xavier Ducrohet File testFile = new File(folder.getLocation().toOSString()); 27516ed545d6175d2afde14b9585eed1feb28ce6364Xavier Ducrohet if (testFile.isDirectory()) { 27616ed545d6175d2afde14b9585eed1feb28ce6364Xavier Ducrohet pathList.add(testFile.getAbsolutePath()); 27716ed545d6175d2afde14b9585eed1feb28ce6364Xavier Ducrohet } 27816ed545d6175d2afde14b9585eed1feb28ce6364Xavier Ducrohet } 27916ed545d6175d2afde14b9585eed1feb28ce6364Xavier Ducrohet 28016ed545d6175d2afde14b9585eed1feb28ce6364Xavier Ducrohet /** 2813d3c3c3a3e4e05f7ae7a0dff440fe500f90b785cXavier Ducrohet * Makes a final package signed with the debug key. 2823d3c3c3a3e4e05f7ae7a0dff440fe500f90b785cXavier Ducrohet * 2833d3c3c3a3e4e05f7ae7a0dff440fe500f90b785cXavier Ducrohet * Packages the dex files, the temporary resource file into the final package file. 2843d3c3c3a3e4e05f7ae7a0dff440fe500f90b785cXavier Ducrohet * 2853d3c3c3a3e4e05f7ae7a0dff440fe500f90b785cXavier Ducrohet * Whether the package is a debug package is controlled with the <var>debugMode</var> parameter 2863d3c3c3a3e4e05f7ae7a0dff440fe500f90b785cXavier Ducrohet * in {@link #PostCompilerHelper(IProject, PrintStream, PrintStream, boolean, boolean)} 2873d3c3c3a3e4e05f7ae7a0dff440fe500f90b785cXavier Ducrohet * 2883d3c3c3a3e4e05f7ae7a0dff440fe500f90b785cXavier Ducrohet * @param intermediateApk The path to the temporary resource file. 2893d3c3c3a3e4e05f7ae7a0dff440fe500f90b785cXavier Ducrohet * @param dex The path to the dex file. 2903d3c3c3a3e4e05f7ae7a0dff440fe500f90b785cXavier Ducrohet * @param output The path to the final package file to create. 2913d3c3c3a3e4e05f7ae7a0dff440fe500f90b785cXavier Ducrohet * @param libProjects an optional list of library projects (can be null) 2923d3c3c3a3e4e05f7ae7a0dff440fe500f90b785cXavier Ducrohet * @return true if success, false otherwise. 2933d3c3c3a3e4e05f7ae7a0dff440fe500f90b785cXavier Ducrohet * @throws ApkCreationException 2943d3c3c3a3e4e05f7ae7a0dff440fe500f90b785cXavier Ducrohet * @throws AndroidLocationException 2953d3c3c3a3e4e05f7ae7a0dff440fe500f90b785cXavier Ducrohet * @throws KeytoolException 2963d3c3c3a3e4e05f7ae7a0dff440fe500f90b785cXavier Ducrohet * @throws NativeLibInJarException 2973d3c3c3a3e4e05f7ae7a0dff440fe500f90b785cXavier Ducrohet * @throws CoreException 2983d3c3c3a3e4e05f7ae7a0dff440fe500f90b785cXavier Ducrohet * @throws DuplicateFileException 2993d3c3c3a3e4e05f7ae7a0dff440fe500f90b785cXavier Ducrohet */ 3003d3c3c3a3e4e05f7ae7a0dff440fe500f90b785cXavier Ducrohet public void finalDebugPackage(String intermediateApk, String dex, String output, 301cc62a7f883c51fb8908bf936e894170d775385bcXavier Ducrohet List<IProject> libProjects, ResourceMarker resMarker) 3023d3c3c3a3e4e05f7ae7a0dff440fe500f90b785cXavier Ducrohet throws ApkCreationException, KeytoolException, AndroidLocationException, 3033d3c3c3a3e4e05f7ae7a0dff440fe500f90b785cXavier Ducrohet NativeLibInJarException, DuplicateFileException, CoreException { 3043d3c3c3a3e4e05f7ae7a0dff440fe500f90b785cXavier Ducrohet 305a19e364a559f151ca2985d348384bf0e2ef7768dRaphael Moll AdtPlugin adt = AdtPlugin.getDefault(); 306a19e364a559f151ca2985d348384bf0e2ef7768dRaphael Moll if (adt == null) { 307a19e364a559f151ca2985d348384bf0e2ef7768dRaphael Moll return; 308a19e364a559f151ca2985d348384bf0e2ef7768dRaphael Moll } 309a19e364a559f151ca2985d348384bf0e2ef7768dRaphael Moll 3103d3c3c3a3e4e05f7ae7a0dff440fe500f90b785cXavier Ducrohet // get the debug keystore to use. 311a19e364a559f151ca2985d348384bf0e2ef7768dRaphael Moll IPreferenceStore store = adt.getPreferenceStore(); 3123d3c3c3a3e4e05f7ae7a0dff440fe500f90b785cXavier Ducrohet String keystoreOsPath = store.getString(AdtPrefs.PREFS_CUSTOM_DEBUG_KEYSTORE); 3133d3c3c3a3e4e05f7ae7a0dff440fe500f90b785cXavier Ducrohet if (keystoreOsPath == null || new File(keystoreOsPath).isFile() == false) { 3143d3c3c3a3e4e05f7ae7a0dff440fe500f90b785cXavier Ducrohet keystoreOsPath = DebugKeyProvider.getDefaultKeyStoreOsPath(); 3153d3c3c3a3e4e05f7ae7a0dff440fe500f90b785cXavier Ducrohet AdtPlugin.printBuildToConsole(BuildVerbosity.VERBOSE, mProject, 3163d3c3c3a3e4e05f7ae7a0dff440fe500f90b785cXavier Ducrohet Messages.ApkBuilder_Using_Default_Key); 3173d3c3c3a3e4e05f7ae7a0dff440fe500f90b785cXavier Ducrohet } else { 3183d3c3c3a3e4e05f7ae7a0dff440fe500f90b785cXavier Ducrohet AdtPlugin.printBuildToConsole(BuildVerbosity.VERBOSE, mProject, 3193d3c3c3a3e4e05f7ae7a0dff440fe500f90b785cXavier Ducrohet String.format(Messages.ApkBuilder_Using_s_To_Sign, keystoreOsPath)); 3203d3c3c3a3e4e05f7ae7a0dff440fe500f90b785cXavier Ducrohet } 3213d3c3c3a3e4e05f7ae7a0dff440fe500f90b785cXavier Ducrohet 3223d3c3c3a3e4e05f7ae7a0dff440fe500f90b785cXavier Ducrohet // from the keystore, get the signing info 3233d3c3c3a3e4e05f7ae7a0dff440fe500f90b785cXavier Ducrohet SigningInfo info = ApkBuilder.getDebugKey(keystoreOsPath, mVerbose ? mOutStream : null); 3243d3c3c3a3e4e05f7ae7a0dff440fe500f90b785cXavier Ducrohet 325cc62a7f883c51fb8908bf936e894170d775385bcXavier Ducrohet finalPackage(intermediateApk, dex, output, libProjects, 3263d3c3c3a3e4e05f7ae7a0dff440fe500f90b785cXavier Ducrohet info != null ? info.key : null, info != null ? info.certificate : null, resMarker); 32759243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet } 32859243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet 32959243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet /** 3303d3c3c3a3e4e05f7ae7a0dff440fe500f90b785cXavier Ducrohet * Makes the final package. 3313d3c3c3a3e4e05f7ae7a0dff440fe500f90b785cXavier Ducrohet * 3323d3c3c3a3e4e05f7ae7a0dff440fe500f90b785cXavier Ducrohet * Packages the dex files, the temporary resource file into the final package file. 3333d3c3c3a3e4e05f7ae7a0dff440fe500f90b785cXavier Ducrohet * 3343d3c3c3a3e4e05f7ae7a0dff440fe500f90b785cXavier Ducrohet * Whether the package is a debug package is controlled with the <var>debugMode</var> parameter 3353d3c3c3a3e4e05f7ae7a0dff440fe500f90b785cXavier Ducrohet * in {@link #PostCompilerHelper(IProject, PrintStream, PrintStream, boolean, boolean)} 3363d3c3c3a3e4e05f7ae7a0dff440fe500f90b785cXavier Ducrohet * 33759243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet * @param intermediateApk The path to the temporary resource file. 33859243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet * @param dex The path to the dex file. 33959243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet * @param output The path to the final package file to create. 3407c19dcf5aead68f4f6675db0bac6b495396e2967Xavier Ducrohet * @param debugSign whether the apk must be signed with the debug key. 34159243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet * @param libProjects an optional list of library projects (can be null) 342853ab5a62d09675e0921d2eed60c02f66e3d0050Xavier Ducrohet * @param abiFilter an optional filter. If not null, then only the matching ABI is included in 343853ab5a62d09675e0921d2eed60c02f66e3d0050Xavier Ducrohet * the final archive 34459243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet * @return true if success, false otherwise. 3453d3c3c3a3e4e05f7ae7a0dff440fe500f90b785cXavier Ducrohet * @throws NativeLibInJarException 3463d3c3c3a3e4e05f7ae7a0dff440fe500f90b785cXavier Ducrohet * @throws ApkCreationException 3473d3c3c3a3e4e05f7ae7a0dff440fe500f90b785cXavier Ducrohet * @throws CoreException 3483d3c3c3a3e4e05f7ae7a0dff440fe500f90b785cXavier Ducrohet * @throws DuplicateFileException 34959243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet */ 3503d3c3c3a3e4e05f7ae7a0dff440fe500f90b785cXavier Ducrohet public void finalPackage(String intermediateApk, String dex, String output, 351cc62a7f883c51fb8908bf936e894170d775385bcXavier Ducrohet List<IProject> libProjects, 352cc62a7f883c51fb8908bf936e894170d775385bcXavier Ducrohet PrivateKey key, X509Certificate certificate, ResourceMarker resMarker) 3533d3c3c3a3e4e05f7ae7a0dff440fe500f90b785cXavier Ducrohet throws NativeLibInJarException, ApkCreationException, DuplicateFileException, 3543d3c3c3a3e4e05f7ae7a0dff440fe500f90b785cXavier Ducrohet CoreException { 3557c19dcf5aead68f4f6675db0bac6b495396e2967Xavier Ducrohet 3567c19dcf5aead68f4f6675db0bac6b495396e2967Xavier Ducrohet try { 3573d3c3c3a3e4e05f7ae7a0dff440fe500f90b785cXavier Ducrohet ApkBuilder apkBuilder = new ApkBuilder(output, intermediateApk, dex, 3583d3c3c3a3e4e05f7ae7a0dff440fe500f90b785cXavier Ducrohet key, certificate, 3593d3c3c3a3e4e05f7ae7a0dff440fe500f90b785cXavier Ducrohet mVerbose ? mOutStream: null); 3603d3c3c3a3e4e05f7ae7a0dff440fe500f90b785cXavier Ducrohet apkBuilder.setDebugMode(mDebugMode); 36159243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet 362cc62a7f883c51fb8908bf936e894170d775385bcXavier Ducrohet // either use the full compiled code paths or just the proguard file 363cc62a7f883c51fb8908bf936e894170d775385bcXavier Ducrohet // if present 364cc62a7f883c51fb8908bf936e894170d775385bcXavier Ducrohet Collection<String> pathsCollection = mCompiledCodePaths; 365cc62a7f883c51fb8908bf936e894170d775385bcXavier Ducrohet if (mProguardFile != null) { 366cc62a7f883c51fb8908bf936e894170d775385bcXavier Ducrohet pathsCollection = Collections.singletonList(mProguardFile); 367cc62a7f883c51fb8908bf936e894170d775385bcXavier Ducrohet mProguardFile = null; 368cc62a7f883c51fb8908bf936e894170d775385bcXavier Ducrohet } 369cc62a7f883c51fb8908bf936e894170d775385bcXavier Ducrohet 370bcf44e9429811b3e1f97d21ea92816957bce2601Xavier Ducrohet // Now we write the standard resources from all the output paths. 371cc62a7f883c51fb8908bf936e894170d775385bcXavier Ducrohet for (String path : pathsCollection) { 372bcf44e9429811b3e1f97d21ea92816957bce2601Xavier Ducrohet File file = new File(path); 373bcf44e9429811b3e1f97d21ea92816957bce2601Xavier Ducrohet if (file.isFile()) { 374bcf44e9429811b3e1f97d21ea92816957bce2601Xavier Ducrohet JarStatus jarStatus = apkBuilder.addResourcesFromJar(file); 3757c19dcf5aead68f4f6675db0bac6b495396e2967Xavier Ducrohet 376433236156debbb84b13776649e20258c1fc51491Xavier Ducrohet // check if we found native libraries in the external library. This 377433236156debbb84b13776649e20258c1fc51491Xavier Ducrohet // constitutes an error or warning depending on if they are in lib/ 378433236156debbb84b13776649e20258c1fc51491Xavier Ducrohet if (jarStatus.getNativeLibs().size() > 0) { 379bcf44e9429811b3e1f97d21ea92816957bce2601Xavier Ducrohet String libName = file.getName(); 3803d3c3c3a3e4e05f7ae7a0dff440fe500f90b785cXavier Ducrohet 381433236156debbb84b13776649e20258c1fc51491Xavier Ducrohet String msg = String.format( 382433236156debbb84b13776649e20258c1fc51491Xavier Ducrohet "Native libraries detected in '%1$s'. See console for more information.", 383433236156debbb84b13776649e20258c1fc51491Xavier Ducrohet libName); 38459243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet 385433236156debbb84b13776649e20258c1fc51491Xavier Ducrohet ArrayList<String> consoleMsgs = new ArrayList<String>(); 3863d3c3c3a3e4e05f7ae7a0dff440fe500f90b785cXavier Ducrohet 387433236156debbb84b13776649e20258c1fc51491Xavier Ducrohet consoleMsgs.add(String.format( 388433236156debbb84b13776649e20258c1fc51491Xavier Ducrohet "The library '%1$s' contains native libraries that will not run on the device.", 389433236156debbb84b13776649e20258c1fc51491Xavier Ducrohet libName)); 3903d3c3c3a3e4e05f7ae7a0dff440fe500f90b785cXavier Ducrohet 391433236156debbb84b13776649e20258c1fc51491Xavier Ducrohet if (jarStatus.hasNativeLibsConflicts()) { 392433236156debbb84b13776649e20258c1fc51491Xavier Ducrohet consoleMsgs.add("Additionally some of those libraries will interfer with the installation of the application because of their location in lib/"); 393433236156debbb84b13776649e20258c1fc51491Xavier Ducrohet consoleMsgs.add("lib/ is reserved for NDK libraries."); 394433236156debbb84b13776649e20258c1fc51491Xavier Ducrohet } 3953d3c3c3a3e4e05f7ae7a0dff440fe500f90b785cXavier Ducrohet 396433236156debbb84b13776649e20258c1fc51491Xavier Ducrohet consoleMsgs.add("The following libraries were found:"); 3973d3c3c3a3e4e05f7ae7a0dff440fe500f90b785cXavier Ducrohet 398433236156debbb84b13776649e20258c1fc51491Xavier Ducrohet for (String lib : jarStatus.getNativeLibs()) { 399433236156debbb84b13776649e20258c1fc51491Xavier Ducrohet consoleMsgs.add(" - " + lib); 400433236156debbb84b13776649e20258c1fc51491Xavier Ducrohet } 4017c19dcf5aead68f4f6675db0bac6b495396e2967Xavier Ducrohet 402433236156debbb84b13776649e20258c1fc51491Xavier Ducrohet String[] consoleStrings = consoleMsgs.toArray(new String[consoleMsgs.size()]); 4033d3c3c3a3e4e05f7ae7a0dff440fe500f90b785cXavier Ducrohet 404433236156debbb84b13776649e20258c1fc51491Xavier Ducrohet // if there's a conflict or if the prefs force error on any native code in jar 405433236156debbb84b13776649e20258c1fc51491Xavier Ducrohet // files, throw an exception 406433236156debbb84b13776649e20258c1fc51491Xavier Ducrohet if (jarStatus.hasNativeLibsConflicts() || 407433236156debbb84b13776649e20258c1fc51491Xavier Ducrohet AdtPrefs.getPrefs().getBuildForceErrorOnNativeLibInJar()) { 408433236156debbb84b13776649e20258c1fc51491Xavier Ducrohet throw new NativeLibInJarException(jarStatus, msg, libName, consoleStrings); 409433236156debbb84b13776649e20258c1fc51491Xavier Ducrohet } else { 410433236156debbb84b13776649e20258c1fc51491Xavier Ducrohet // otherwise, put a warning, and output to the console also. 411433236156debbb84b13776649e20258c1fc51491Xavier Ducrohet if (resMarker != null) { 412433236156debbb84b13776649e20258c1fc51491Xavier Ducrohet resMarker.setWarning(mProject, msg); 413433236156debbb84b13776649e20258c1fc51491Xavier Ducrohet } 4143d3c3c3a3e4e05f7ae7a0dff440fe500f90b785cXavier Ducrohet 415433236156debbb84b13776649e20258c1fc51491Xavier Ducrohet for (String string : consoleStrings) { 416433236156debbb84b13776649e20258c1fc51491Xavier Ducrohet mOutStream.println(string); 417433236156debbb84b13776649e20258c1fc51491Xavier Ducrohet } 4183d3c3c3a3e4e05f7ae7a0dff440fe500f90b785cXavier Ducrohet } 4193d3c3c3a3e4e05f7ae7a0dff440fe500f90b785cXavier Ducrohet } 420bcf44e9429811b3e1f97d21ea92816957bce2601Xavier Ducrohet } else if (file.isDirectory()) { 421433236156debbb84b13776649e20258c1fc51491Xavier Ducrohet // this is technically not a source folder (class folder instead) but since we 422433236156debbb84b13776649e20258c1fc51491Xavier Ducrohet // only care about Java resources (ie non class/java files) this will do the 423433236156debbb84b13776649e20258c1fc51491Xavier Ducrohet // same 424bcf44e9429811b3e1f97d21ea92816957bce2601Xavier Ducrohet apkBuilder.addSourceFolder(file); 42559243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet } 42659243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet } 42759243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet 42859243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet // now write the native libraries. 42959243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet // First look if the lib folder is there. 43059243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet IResource libFolder = mProject.findMember(SdkConstants.FD_NATIVE_LIBS); 43159243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet if (libFolder != null && libFolder.exists() && 43259243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet libFolder.getType() == IResource.FOLDER) { 4337c19dcf5aead68f4f6675db0bac6b495396e2967Xavier Ducrohet // get a File for the folder. 43467000f1a4e4cc31c258afd80fe13939ae66aea2aXavier Ducrohet apkBuilder.addNativeLibraries(libFolder.getLocation().toFile()); 43559243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet } 43659243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet 43759243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet // write the native libraries for the library projects. 43859243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet if (libProjects != null) { 43959243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet for (IProject lib : libProjects) { 44059243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet libFolder = lib.findMember(SdkConstants.FD_NATIVE_LIBS); 44159243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet if (libFolder != null && libFolder.exists() && 44259243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet libFolder.getType() == IResource.FOLDER) { 44367000f1a4e4cc31c258afd80fe13939ae66aea2aXavier Ducrohet apkBuilder.addNativeLibraries(libFolder.getLocation().toFile()); 44459243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet } 44559243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet } 44659243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet } 44759243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet 4487c19dcf5aead68f4f6675db0bac6b495396e2967Xavier Ducrohet // seal the APK. 4497c19dcf5aead68f4f6675db0bac6b495396e2967Xavier Ducrohet apkBuilder.sealApk(); 4507c19dcf5aead68f4f6675db0bac6b495396e2967Xavier Ducrohet } catch (SealedApkException e) { 4517c19dcf5aead68f4f6675db0bac6b495396e2967Xavier Ducrohet // this won't happen as we control when the apk is sealed. 45259243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet } 45359243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet } 45459243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet 455cc62a7f883c51fb8908bf936e894170d775385bcXavier Ducrohet public void setProguardOutput(String proguardFile) { 456cc62a7f883c51fb8908bf936e894170d775385bcXavier Ducrohet mProguardFile = proguardFile; 457cc62a7f883c51fb8908bf936e894170d775385bcXavier Ducrohet } 458cc62a7f883c51fb8908bf936e894170d775385bcXavier Ducrohet 459bcf44e9429811b3e1f97d21ea92816957bce2601Xavier Ducrohet public Collection<String> getCompiledCodePaths() { 460bcf44e9429811b3e1f97d21ea92816957bce2601Xavier Ducrohet return mCompiledCodePaths; 461edeea1c711e0fd692df97f284594b59921e35b1aXavier Ducrohet } 462edeea1c711e0fd692df97f284594b59921e35b1aXavier Ducrohet 463bcf44e9429811b3e1f97d21ea92816957bce2601Xavier Ducrohet public void runProguard(List<File> proguardConfigs, File inputJar, Collection<String> jarFiles, 464eca9ade6294f925e266eeece8071d5bfdede9c6aRaphael Moll File obfuscatedJar, File logOutput) 465eca9ade6294f925e266eeece8071d5bfdede9c6aRaphael Moll throws ProguardResultException, ProguardExecException, IOException { 466edeea1c711e0fd692df97f284594b59921e35b1aXavier Ducrohet IAndroidTarget target = Sdk.getCurrent().getTarget(mProject); 467edeea1c711e0fd692df97f284594b59921e35b1aXavier Ducrohet 468edeea1c711e0fd692df97f284594b59921e35b1aXavier Ducrohet // prepare the command line for proguard 469edeea1c711e0fd692df97f284594b59921e35b1aXavier Ducrohet List<String> command = new ArrayList<String>(); 470edeea1c711e0fd692df97f284594b59921e35b1aXavier Ducrohet command.add(AdtPlugin.getOsAbsoluteProguard()); 471edeea1c711e0fd692df97f284594b59921e35b1aXavier Ducrohet 4720bf1b2c94e8b3d829fd69d11f2efd550d6159cb9Tor Norbye for (File configFile : proguardConfigs) { 4730bf1b2c94e8b3d829fd69d11f2efd550d6159cb9Tor Norbye command.add("-include"); //$NON-NLS-1$ 4740bf1b2c94e8b3d829fd69d11f2efd550d6159cb9Tor Norbye command.add(quotePath(configFile.getAbsolutePath())); 4750bf1b2c94e8b3d829fd69d11f2efd550d6159cb9Tor Norbye } 476edeea1c711e0fd692df97f284594b59921e35b1aXavier Ducrohet 477edeea1c711e0fd692df97f284594b59921e35b1aXavier Ducrohet command.add("-injars"); //$NON-NLS-1$ 478fd19b2c89be703549e23d501541632883819ab7bRaphael Moll StringBuilder sb = new StringBuilder(quotePath(inputJar.getAbsolutePath())); 479edeea1c711e0fd692df97f284594b59921e35b1aXavier Ducrohet for (String jarFile : jarFiles) { 480edeea1c711e0fd692df97f284594b59921e35b1aXavier Ducrohet sb.append(File.pathSeparatorChar); 481fd19b2c89be703549e23d501541632883819ab7bRaphael Moll sb.append(quotePath(jarFile)); 482edeea1c711e0fd692df97f284594b59921e35b1aXavier Ducrohet } 483fd19b2c89be703549e23d501541632883819ab7bRaphael Moll command.add(quoteWinArg(sb.toString())); 484edeea1c711e0fd692df97f284594b59921e35b1aXavier Ducrohet 485edeea1c711e0fd692df97f284594b59921e35b1aXavier Ducrohet command.add("-outjars"); //$NON-NLS-1$ 486fd19b2c89be703549e23d501541632883819ab7bRaphael Moll command.add(quotePath(obfuscatedJar.getAbsolutePath())); 487edeea1c711e0fd692df97f284594b59921e35b1aXavier Ducrohet 488edeea1c711e0fd692df97f284594b59921e35b1aXavier Ducrohet command.add("-libraryjars"); //$NON-NLS-1$ 489fd19b2c89be703549e23d501541632883819ab7bRaphael Moll sb = new StringBuilder(quotePath(target.getPath(IAndroidTarget.ANDROID_JAR))); 490edeea1c711e0fd692df97f284594b59921e35b1aXavier Ducrohet IOptionalLibrary[] libraries = target.getOptionalLibraries(); 491edeea1c711e0fd692df97f284594b59921e35b1aXavier Ducrohet if (libraries != null) { 492edeea1c711e0fd692df97f284594b59921e35b1aXavier Ducrohet for (IOptionalLibrary lib : libraries) { 493edeea1c711e0fd692df97f284594b59921e35b1aXavier Ducrohet sb.append(File.pathSeparatorChar); 494fd19b2c89be703549e23d501541632883819ab7bRaphael Moll sb.append(quotePath(lib.getJarPath())); 495edeea1c711e0fd692df97f284594b59921e35b1aXavier Ducrohet } 496edeea1c711e0fd692df97f284594b59921e35b1aXavier Ducrohet } 497fd19b2c89be703549e23d501541632883819ab7bRaphael Moll command.add(quoteWinArg(sb.toString())); 498edeea1c711e0fd692df97f284594b59921e35b1aXavier Ducrohet 499edeea1c711e0fd692df97f284594b59921e35b1aXavier Ducrohet if (logOutput != null) { 500edeea1c711e0fd692df97f284594b59921e35b1aXavier Ducrohet if (logOutput.isDirectory() == false) { 501edeea1c711e0fd692df97f284594b59921e35b1aXavier Ducrohet logOutput.mkdirs(); 502edeea1c711e0fd692df97f284594b59921e35b1aXavier Ducrohet } 503edeea1c711e0fd692df97f284594b59921e35b1aXavier Ducrohet 504edeea1c711e0fd692df97f284594b59921e35b1aXavier Ducrohet command.add("-dump"); //$NON-NLS-1$ 505edeea1c711e0fd692df97f284594b59921e35b1aXavier Ducrohet command.add(new File(logOutput, "dump.txt").getAbsolutePath()); //$NON-NLS-1$ 506edeea1c711e0fd692df97f284594b59921e35b1aXavier Ducrohet 507edeea1c711e0fd692df97f284594b59921e35b1aXavier Ducrohet command.add("-printseeds"); //$NON-NLS-1$ 508edeea1c711e0fd692df97f284594b59921e35b1aXavier Ducrohet command.add(new File(logOutput, "seeds.txt").getAbsolutePath()); //$NON-NLS-1$ 509edeea1c711e0fd692df97f284594b59921e35b1aXavier Ducrohet 510edeea1c711e0fd692df97f284594b59921e35b1aXavier Ducrohet command.add("-printusage"); //$NON-NLS-1$ 511edeea1c711e0fd692df97f284594b59921e35b1aXavier Ducrohet command.add(new File(logOutput, "usage.txt").getAbsolutePath()); //$NON-NLS-1$ 512edeea1c711e0fd692df97f284594b59921e35b1aXavier Ducrohet 513edeea1c711e0fd692df97f284594b59921e35b1aXavier Ducrohet command.add("-printmapping"); //$NON-NLS-1$ 514edeea1c711e0fd692df97f284594b59921e35b1aXavier Ducrohet command.add(new File(logOutput, "mapping.txt").getAbsolutePath()); //$NON-NLS-1$ 515edeea1c711e0fd692df97f284594b59921e35b1aXavier Ducrohet } 516edeea1c711e0fd692df97f284594b59921e35b1aXavier Ducrohet 517fd19b2c89be703549e23d501541632883819ab7bRaphael Moll String commandArray[] = null; 518eca9ade6294f925e266eeece8071d5bfdede9c6aRaphael Moll 519eca9ade6294f925e266eeece8071d5bfdede9c6aRaphael Moll if (SdkConstants.currentPlatform() == SdkConstants.PLATFORM_WINDOWS) { 520fd19b2c89be703549e23d501541632883819ab7bRaphael Moll commandArray = createWindowsProguardConfig(command); 521fd19b2c89be703549e23d501541632883819ab7bRaphael Moll } 522eca9ade6294f925e266eeece8071d5bfdede9c6aRaphael Moll 523fd19b2c89be703549e23d501541632883819ab7bRaphael Moll if (commandArray == null) { 524eca9ade6294f925e266eeece8071d5bfdede9c6aRaphael Moll // For Mac & Linux, use a regular command string array. 525eca9ade6294f925e266eeece8071d5bfdede9c6aRaphael Moll commandArray = command.toArray(new String[command.size()]); 526eca9ade6294f925e266eeece8071d5bfdede9c6aRaphael Moll } 527eca9ade6294f925e266eeece8071d5bfdede9c6aRaphael Moll 528eca9ade6294f925e266eeece8071d5bfdede9c6aRaphael Moll // Define PROGUARD_HOME to point to $SDK/tools/proguard if it's not yet defined. 529eca9ade6294f925e266eeece8071d5bfdede9c6aRaphael Moll // The Mac/Linux proguard.sh can infer it correctly but not the proguard.bat one. 530eca9ade6294f925e266eeece8071d5bfdede9c6aRaphael Moll String[] envp = null; 531eca9ade6294f925e266eeece8071d5bfdede9c6aRaphael Moll Map<String, String> envMap = new TreeMap<String, String>(System.getenv()); 532eca9ade6294f925e266eeece8071d5bfdede9c6aRaphael Moll if (!envMap.containsKey("PROGUARD_HOME")) { //$NON-NLS-1$ 533eca9ade6294f925e266eeece8071d5bfdede9c6aRaphael Moll envMap.put("PROGUARD_HOME", Sdk.getCurrent().getSdkLocation() + //$NON-NLS-1$ 534eca9ade6294f925e266eeece8071d5bfdede9c6aRaphael Moll SdkConstants.FD_TOOLS + File.separator + 535eca9ade6294f925e266eeece8071d5bfdede9c6aRaphael Moll SdkConstants.FD_PROGUARD); 536eca9ade6294f925e266eeece8071d5bfdede9c6aRaphael Moll envp = new String[envMap.size()]; 537eca9ade6294f925e266eeece8071d5bfdede9c6aRaphael Moll int i = 0; 538eca9ade6294f925e266eeece8071d5bfdede9c6aRaphael Moll for (Map.Entry<String, String> entry : envMap.entrySet()) { 539eca9ade6294f925e266eeece8071d5bfdede9c6aRaphael Moll envp[i++] = String.format("%1$s=%2$s", //$NON-NLS-1$ 540eca9ade6294f925e266eeece8071d5bfdede9c6aRaphael Moll entry.getKey(), 541eca9ade6294f925e266eeece8071d5bfdede9c6aRaphael Moll entry.getValue()); 542eca9ade6294f925e266eeece8071d5bfdede9c6aRaphael Moll } 543eca9ade6294f925e266eeece8071d5bfdede9c6aRaphael Moll } 544edeea1c711e0fd692df97f284594b59921e35b1aXavier Ducrohet 545fd19b2c89be703549e23d501541632883819ab7bRaphael Moll if (AdtPrefs.getPrefs().getBuildVerbosity() == BuildVerbosity.VERBOSE) { 546fd19b2c89be703549e23d501541632883819ab7bRaphael Moll sb = new StringBuilder(); 547fd19b2c89be703549e23d501541632883819ab7bRaphael Moll for (String c : commandArray) { 548fd19b2c89be703549e23d501541632883819ab7bRaphael Moll sb.append(c).append(' '); 549fd19b2c89be703549e23d501541632883819ab7bRaphael Moll } 550fd19b2c89be703549e23d501541632883819ab7bRaphael Moll AdtPlugin.printToConsole(mProject, sb.toString()); 551fd19b2c89be703549e23d501541632883819ab7bRaphael Moll } 552fd19b2c89be703549e23d501541632883819ab7bRaphael Moll 553edeea1c711e0fd692df97f284594b59921e35b1aXavier Ducrohet // launch 554edeea1c711e0fd692df97f284594b59921e35b1aXavier Ducrohet int execError = 1; 555edeea1c711e0fd692df97f284594b59921e35b1aXavier Ducrohet try { 556edeea1c711e0fd692df97f284594b59921e35b1aXavier Ducrohet // launch the command line process 557eca9ade6294f925e266eeece8071d5bfdede9c6aRaphael Moll Process process = Runtime.getRuntime().exec(commandArray, envp); 558edeea1c711e0fd692df97f284594b59921e35b1aXavier Ducrohet 559edeea1c711e0fd692df97f284594b59921e35b1aXavier Ducrohet // list to store each line of stderr 560edeea1c711e0fd692df97f284594b59921e35b1aXavier Ducrohet ArrayList<String> results = new ArrayList<String>(); 561edeea1c711e0fd692df97f284594b59921e35b1aXavier Ducrohet 562edeea1c711e0fd692df97f284594b59921e35b1aXavier Ducrohet // get the output and return code from the process 563edeea1c711e0fd692df97f284594b59921e35b1aXavier Ducrohet execError = grabProcessOutput(mProject, process, results); 564edeea1c711e0fd692df97f284594b59921e35b1aXavier Ducrohet 5657139790c9af02de824c6f2dae7a68ff694ae1f19Xavier Ducrohet if (mVerbose) { 566edeea1c711e0fd692df97f284594b59921e35b1aXavier Ducrohet for (String resultString : results) { 567edeea1c711e0fd692df97f284594b59921e35b1aXavier Ducrohet mOutStream.println(resultString); 568edeea1c711e0fd692df97f284594b59921e35b1aXavier Ducrohet } 569edeea1c711e0fd692df97f284594b59921e35b1aXavier Ducrohet } 570edeea1c711e0fd692df97f284594b59921e35b1aXavier Ducrohet 5717139790c9af02de824c6f2dae7a68ff694ae1f19Xavier Ducrohet if (execError != 0) { 5727139790c9af02de824c6f2dae7a68ff694ae1f19Xavier Ducrohet throw new ProguardResultException(execError, 5737139790c9af02de824c6f2dae7a68ff694ae1f19Xavier Ducrohet results.toArray(new String[results.size()])); 5747139790c9af02de824c6f2dae7a68ff694ae1f19Xavier Ducrohet } 5757139790c9af02de824c6f2dae7a68ff694ae1f19Xavier Ducrohet 576edeea1c711e0fd692df97f284594b59921e35b1aXavier Ducrohet } catch (IOException e) { 577edeea1c711e0fd692df97f284594b59921e35b1aXavier Ducrohet String msg = String.format(Messages.Proguard_Exec_Error, commandArray[0]); 578edeea1c711e0fd692df97f284594b59921e35b1aXavier Ducrohet throw new ProguardExecException(msg, e); 579edeea1c711e0fd692df97f284594b59921e35b1aXavier Ducrohet } catch (InterruptedException e) { 580edeea1c711e0fd692df97f284594b59921e35b1aXavier Ducrohet String msg = String.format(Messages.Proguard_Exec_Error, commandArray[0]); 581edeea1c711e0fd692df97f284594b59921e35b1aXavier Ducrohet throw new ProguardExecException(msg, e); 582edeea1c711e0fd692df97f284594b59921e35b1aXavier Ducrohet } 583edeea1c711e0fd692df97f284594b59921e35b1aXavier Ducrohet } 584edeea1c711e0fd692df97f284594b59921e35b1aXavier Ducrohet 585fd19b2c89be703549e23d501541632883819ab7bRaphael Moll /** 586fd19b2c89be703549e23d501541632883819ab7bRaphael Moll * For tools R8 up to R11, the proguard.bat launcher on Windows only accepts 587fd19b2c89be703549e23d501541632883819ab7bRaphael Moll * arguments %1..%9. Since we generally have about 15 arguments, we were working 588fd19b2c89be703549e23d501541632883819ab7bRaphael Moll * around this by generating a temporary config file for proguard and then using 589fd19b2c89be703549e23d501541632883819ab7bRaphael Moll * that. 590fd19b2c89be703549e23d501541632883819ab7bRaphael Moll * Starting with tools R12, the proguard.bat launcher has been fixed to take 591fd19b2c89be703549e23d501541632883819ab7bRaphael Moll * all arguments using %* so we no longer need this hack. 592fd19b2c89be703549e23d501541632883819ab7bRaphael Moll * 593fd19b2c89be703549e23d501541632883819ab7bRaphael Moll * @param command 594fd19b2c89be703549e23d501541632883819ab7bRaphael Moll * @return 595fd19b2c89be703549e23d501541632883819ab7bRaphael Moll * @throws IOException 596fd19b2c89be703549e23d501541632883819ab7bRaphael Moll */ 597fd19b2c89be703549e23d501541632883819ab7bRaphael Moll private String[] createWindowsProguardConfig(List<String> command) throws IOException { 598fd19b2c89be703549e23d501541632883819ab7bRaphael Moll 599fd19b2c89be703549e23d501541632883819ab7bRaphael Moll // Arg 0 is the proguard.bat path and arg 1 is the user config file 600fd19b2c89be703549e23d501541632883819ab7bRaphael Moll String launcher = AdtPlugin.readFile(new File(command.get(0))); 601fd19b2c89be703549e23d501541632883819ab7bRaphael Moll if (launcher.contains("%*")) { //$NON-NLS-1$ 602fd19b2c89be703549e23d501541632883819ab7bRaphael Moll // This is the launcher from Tools R12. Don't work around it. 603fd19b2c89be703549e23d501541632883819ab7bRaphael Moll return null; 604fd19b2c89be703549e23d501541632883819ab7bRaphael Moll } 605fd19b2c89be703549e23d501541632883819ab7bRaphael Moll 606fd19b2c89be703549e23d501541632883819ab7bRaphael Moll // On Windows, proguard.bat can only pass %1...%9 to the java -jar proguard.jar 607fd19b2c89be703549e23d501541632883819ab7bRaphael Moll // call, but we have at least 15 arguments here so some get dropped silently 608fd19b2c89be703549e23d501541632883819ab7bRaphael Moll // and quoting is a big issue. So instead we'll work around that by writing 609fd19b2c89be703549e23d501541632883819ab7bRaphael Moll // all the arguments to a temporary config file. 610fd19b2c89be703549e23d501541632883819ab7bRaphael Moll 611fd19b2c89be703549e23d501541632883819ab7bRaphael Moll String[] commandArray = new String[3]; 612fd19b2c89be703549e23d501541632883819ab7bRaphael Moll 613fd19b2c89be703549e23d501541632883819ab7bRaphael Moll commandArray[0] = command.get(0); 614fd19b2c89be703549e23d501541632883819ab7bRaphael Moll commandArray[1] = command.get(1); 615fd19b2c89be703549e23d501541632883819ab7bRaphael Moll 616fd19b2c89be703549e23d501541632883819ab7bRaphael Moll // Write all the other arguments to a config file 617fd19b2c89be703549e23d501541632883819ab7bRaphael Moll File argsFile = File.createTempFile(TEMP_PREFIX, ".pro"); //$NON-NLS-1$ 618fd19b2c89be703549e23d501541632883819ab7bRaphael Moll // TODO FIXME this may leave a lot of temp files around on a long session. 619fd19b2c89be703549e23d501541632883819ab7bRaphael Moll // Should have a better way to clean up e.g. before each build. 620fd19b2c89be703549e23d501541632883819ab7bRaphael Moll argsFile.deleteOnExit(); 621fd19b2c89be703549e23d501541632883819ab7bRaphael Moll 622fd19b2c89be703549e23d501541632883819ab7bRaphael Moll FileWriter fw = new FileWriter(argsFile); 623fd19b2c89be703549e23d501541632883819ab7bRaphael Moll 624fd19b2c89be703549e23d501541632883819ab7bRaphael Moll for (int i = 2; i < command.size(); i++) { 625fd19b2c89be703549e23d501541632883819ab7bRaphael Moll String s = command.get(i); 626fd19b2c89be703549e23d501541632883819ab7bRaphael Moll fw.write(s); 627fd19b2c89be703549e23d501541632883819ab7bRaphael Moll fw.write(s.startsWith("-") ? ' ' : '\n'); //$NON-NLS-1$ 628fd19b2c89be703549e23d501541632883819ab7bRaphael Moll } 629fd19b2c89be703549e23d501541632883819ab7bRaphael Moll 630fd19b2c89be703549e23d501541632883819ab7bRaphael Moll fw.close(); 631fd19b2c89be703549e23d501541632883819ab7bRaphael Moll 632fd19b2c89be703549e23d501541632883819ab7bRaphael Moll commandArray[2] = "@" + argsFile.getAbsolutePath(); //$NON-NLS-1$ 633fd19b2c89be703549e23d501541632883819ab7bRaphael Moll return commandArray; 634fd19b2c89be703549e23d501541632883819ab7bRaphael Moll } 635fd19b2c89be703549e23d501541632883819ab7bRaphael Moll 636fd19b2c89be703549e23d501541632883819ab7bRaphael Moll /** 637fd19b2c89be703549e23d501541632883819ab7bRaphael Moll * Quotes a single path for proguard to deal with spaces. 638fd19b2c89be703549e23d501541632883819ab7bRaphael Moll * 639fd19b2c89be703549e23d501541632883819ab7bRaphael Moll * @param path The path to quote. 640fd19b2c89be703549e23d501541632883819ab7bRaphael Moll * @return The original path if it doesn't contain a space. 641fd19b2c89be703549e23d501541632883819ab7bRaphael Moll * Or the original path surrounded by single quotes if it contains spaces. 642fd19b2c89be703549e23d501541632883819ab7bRaphael Moll */ 643fd19b2c89be703549e23d501541632883819ab7bRaphael Moll private String quotePath(String path) { 644fd19b2c89be703549e23d501541632883819ab7bRaphael Moll if (path.indexOf(' ') != -1) { 645fd19b2c89be703549e23d501541632883819ab7bRaphael Moll path = '\'' + path + '\''; 646fd19b2c89be703549e23d501541632883819ab7bRaphael Moll } 647fd19b2c89be703549e23d501541632883819ab7bRaphael Moll return path; 648fd19b2c89be703549e23d501541632883819ab7bRaphael Moll } 649fd19b2c89be703549e23d501541632883819ab7bRaphael Moll 650fd19b2c89be703549e23d501541632883819ab7bRaphael Moll /** 651fd19b2c89be703549e23d501541632883819ab7bRaphael Moll * Quotes a compound proguard argument to deal with spaces. 652fd19b2c89be703549e23d501541632883819ab7bRaphael Moll * <p/> 653fd19b2c89be703549e23d501541632883819ab7bRaphael Moll * Proguard takes multi-path arguments such as "path1;path2" for some options. 654fd19b2c89be703549e23d501541632883819ab7bRaphael Moll * When the {@link #quotePath} methods adds quotes for such a path if it contains spaces, 655fd19b2c89be703549e23d501541632883819ab7bRaphael Moll * the proguard shell wrapper will absorb the quotes, so we need to quote around the 656fd19b2c89be703549e23d501541632883819ab7bRaphael Moll * quotes. 657fd19b2c89be703549e23d501541632883819ab7bRaphael Moll * 658fd19b2c89be703549e23d501541632883819ab7bRaphael Moll * @param path The path to quote. 659fd19b2c89be703549e23d501541632883819ab7bRaphael Moll * @return The original path if it doesn't contain a single quote. 660fd19b2c89be703549e23d501541632883819ab7bRaphael Moll * Or on Windows the original path surrounded by double quotes if it contains a quote. 661fd19b2c89be703549e23d501541632883819ab7bRaphael Moll */ 662fd19b2c89be703549e23d501541632883819ab7bRaphael Moll private String quoteWinArg(String path) { 663fd19b2c89be703549e23d501541632883819ab7bRaphael Moll if (path.indexOf('\'') != -1 && 664fd19b2c89be703549e23d501541632883819ab7bRaphael Moll SdkConstants.currentPlatform() == SdkConstants.PLATFORM_WINDOWS) { 665fd19b2c89be703549e23d501541632883819ab7bRaphael Moll path = '"' + path + '"'; 666fd19b2c89be703549e23d501541632883819ab7bRaphael Moll } 667fd19b2c89be703549e23d501541632883819ab7bRaphael Moll return path; 668fd19b2c89be703549e23d501541632883819ab7bRaphael Moll } 669fd19b2c89be703549e23d501541632883819ab7bRaphael Moll 670edeea1c711e0fd692df97f284594b59921e35b1aXavier Ducrohet 67159243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet /** 67259243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet * Execute the Dx tool for dalvik code conversion. 67359243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet * @param javaProject The java project 674bcf44e9429811b3e1f97d21ea92816957bce2601Xavier Ducrohet * @param inputPaths the input paths for DX 67559243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet * @param osOutFilePath the path of the dex file to create. 67659243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet * 67759243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet * @throws CoreException 6783d3c3c3a3e4e05f7ae7a0dff440fe500f90b785cXavier Ducrohet * @throws DexException 67959243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet */ 680bcf44e9429811b3e1f97d21ea92816957bce2601Xavier Ducrohet public void executeDx(IJavaProject javaProject, Collection<String> inputPaths, 681bcf44e9429811b3e1f97d21ea92816957bce2601Xavier Ducrohet String osOutFilePath) 682edeea1c711e0fd692df97f284594b59921e35b1aXavier Ducrohet throws CoreException, DexException { 68359243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet 68459243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet // get the dex wrapper 6857695260241c862329e63ee2fa210af5ff3c95ea7Xavier Ducrohet Sdk sdk = Sdk.getCurrent(); 6867695260241c862329e63ee2fa210af5ff3c95ea7Xavier Ducrohet DexWrapper wrapper = sdk.getDexWrapper(); 68759243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet 68859243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet if (wrapper == null) { 68959243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet throw new CoreException(new Status(IStatus.ERROR, AdtPlugin.PLUGIN_ID, 69059243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet Messages.ApkBuilder_UnableBuild_Dex_Not_loaded)); 69159243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet } 69259243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet 69359243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet try { 6943d3c3c3a3e4e05f7ae7a0dff440fe500f90b785cXavier Ducrohet // set a temporary prefix on the print streams. 6953d3c3c3a3e4e05f7ae7a0dff440fe500f90b785cXavier Ducrohet mOutStream.setPrefix(CONSOLE_PREFIX_DX); 6963d3c3c3a3e4e05f7ae7a0dff440fe500f90b785cXavier Ducrohet mErrStream.setPrefix(CONSOLE_PREFIX_DX); 6973d3c3c3a3e4e05f7ae7a0dff440fe500f90b785cXavier Ducrohet 69898b631c6b3765be96b3707ba7aa54d52b10f4872Xavier Ducrohet IFolder binFolder = BaseProjectHelper.getAndroidOutputFolder(javaProject.getProject()); 69998b631c6b3765be96b3707ba7aa54d52b10f4872Xavier Ducrohet File binFile = binFolder.getLocation().toFile(); 70098b631c6b3765be96b3707ba7aa54d52b10f4872Xavier Ducrohet File dexedLibs = new File(binFile, "dexedLibs"); 70198b631c6b3765be96b3707ba7aa54d52b10f4872Xavier Ducrohet if (dexedLibs.exists() == false) { 70298b631c6b3765be96b3707ba7aa54d52b10f4872Xavier Ducrohet dexedLibs.mkdir(); 70398b631c6b3765be96b3707ba7aa54d52b10f4872Xavier Ducrohet } 70498b631c6b3765be96b3707ba7aa54d52b10f4872Xavier Ducrohet 70598b631c6b3765be96b3707ba7aa54d52b10f4872Xavier Ducrohet // replace the libs by their dexed versions (dexing them if needed.) 70698b631c6b3765be96b3707ba7aa54d52b10f4872Xavier Ducrohet List<String> finalInputPaths = new ArrayList<String>(inputPaths.size()); 70798b631c6b3765be96b3707ba7aa54d52b10f4872Xavier Ducrohet if (inputPaths.size() == 1) { 70898b631c6b3765be96b3707ba7aa54d52b10f4872Xavier Ducrohet // only one input, no need to put a pre-dexed version, even if this path is 70998b631c6b3765be96b3707ba7aa54d52b10f4872Xavier Ducrohet // just a jar file (case for proguard'ed builds) 71098b631c6b3765be96b3707ba7aa54d52b10f4872Xavier Ducrohet finalInputPaths.addAll(inputPaths); 71198b631c6b3765be96b3707ba7aa54d52b10f4872Xavier Ducrohet } else { 712fabbec5e8c5f7a052e337972f963cb3163243c36Xavier Ducrohet for (String input : inputPaths) { 71398b631c6b3765be96b3707ba7aa54d52b10f4872Xavier Ducrohet File inputFile = new File(input); 71498b631c6b3765be96b3707ba7aa54d52b10f4872Xavier Ducrohet if (inputFile.isDirectory()) { 71598b631c6b3765be96b3707ba7aa54d52b10f4872Xavier Ducrohet finalInputPaths.add(input); 71698b631c6b3765be96b3707ba7aa54d52b10f4872Xavier Ducrohet } else if (inputFile.isFile()) { 71798b631c6b3765be96b3707ba7aa54d52b10f4872Xavier Ducrohet File dexedLib = new File(dexedLibs, inputFile.getName()); 71898b631c6b3765be96b3707ba7aa54d52b10f4872Xavier Ducrohet String dexedLibPath = dexedLib.getAbsolutePath(); 71998b631c6b3765be96b3707ba7aa54d52b10f4872Xavier Ducrohet 72098b631c6b3765be96b3707ba7aa54d52b10f4872Xavier Ducrohet if (dexedLib.isFile() == false || 72198b631c6b3765be96b3707ba7aa54d52b10f4872Xavier Ducrohet dexedLib.lastModified() < inputFile.lastModified()) { 72298b631c6b3765be96b3707ba7aa54d52b10f4872Xavier Ducrohet 72398b631c6b3765be96b3707ba7aa54d52b10f4872Xavier Ducrohet if (mVerbose) { 72498b631c6b3765be96b3707ba7aa54d52b10f4872Xavier Ducrohet mOutStream.println("Pre-Dexing " + input); 72598b631c6b3765be96b3707ba7aa54d52b10f4872Xavier Ducrohet } 72698b631c6b3765be96b3707ba7aa54d52b10f4872Xavier Ducrohet 72798b631c6b3765be96b3707ba7aa54d52b10f4872Xavier Ducrohet if (dexedLib.isFile()) { 72898b631c6b3765be96b3707ba7aa54d52b10f4872Xavier Ducrohet dexedLib.delete(); 72998b631c6b3765be96b3707ba7aa54d52b10f4872Xavier Ducrohet } 73098b631c6b3765be96b3707ba7aa54d52b10f4872Xavier Ducrohet 73198b631c6b3765be96b3707ba7aa54d52b10f4872Xavier Ducrohet int res = wrapper.run(dexedLibPath, Collections.singleton(input), 73298b631c6b3765be96b3707ba7aa54d52b10f4872Xavier Ducrohet mVerbose, mOutStream, mErrStream); 73398b631c6b3765be96b3707ba7aa54d52b10f4872Xavier Ducrohet 73498b631c6b3765be96b3707ba7aa54d52b10f4872Xavier Ducrohet if (res != 0) { 73598b631c6b3765be96b3707ba7aa54d52b10f4872Xavier Ducrohet // output error message and mark the project. 73698b631c6b3765be96b3707ba7aa54d52b10f4872Xavier Ducrohet String message = String.format(Messages.Dalvik_Error_d, res); 73798b631c6b3765be96b3707ba7aa54d52b10f4872Xavier Ducrohet throw new DexException(message); 73898b631c6b3765be96b3707ba7aa54d52b10f4872Xavier Ducrohet } 73998b631c6b3765be96b3707ba7aa54d52b10f4872Xavier Ducrohet } 74098b631c6b3765be96b3707ba7aa54d52b10f4872Xavier Ducrohet 74198b631c6b3765be96b3707ba7aa54d52b10f4872Xavier Ducrohet finalInputPaths.add(dexedLibPath); 74298b631c6b3765be96b3707ba7aa54d52b10f4872Xavier Ducrohet } 74398b631c6b3765be96b3707ba7aa54d52b10f4872Xavier Ducrohet } 74498b631c6b3765be96b3707ba7aa54d52b10f4872Xavier Ducrohet } 74598b631c6b3765be96b3707ba7aa54d52b10f4872Xavier Ducrohet 74698b631c6b3765be96b3707ba7aa54d52b10f4872Xavier Ducrohet if (mVerbose) { 74798b631c6b3765be96b3707ba7aa54d52b10f4872Xavier Ducrohet for (String input : finalInputPaths) { 748fabbec5e8c5f7a052e337972f963cb3163243c36Xavier Ducrohet mOutStream.println("Input: " + input); 749fabbec5e8c5f7a052e337972f963cb3163243c36Xavier Ducrohet } 750fabbec5e8c5f7a052e337972f963cb3163243c36Xavier Ducrohet } 751fabbec5e8c5f7a052e337972f963cb3163243c36Xavier Ducrohet 752edeea1c711e0fd692df97f284594b59921e35b1aXavier Ducrohet int res = wrapper.run(osOutFilePath, 75398b631c6b3765be96b3707ba7aa54d52b10f4872Xavier Ducrohet finalInputPaths, 7543d3c3c3a3e4e05f7ae7a0dff440fe500f90b785cXavier Ducrohet mVerbose, 75559243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet mOutStream, mErrStream); 75659243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet 7573d3c3c3a3e4e05f7ae7a0dff440fe500f90b785cXavier Ducrohet mOutStream.setPrefix(null); 7583d3c3c3a3e4e05f7ae7a0dff440fe500f90b785cXavier Ducrohet mErrStream.setPrefix(null); 7593d3c3c3a3e4e05f7ae7a0dff440fe500f90b785cXavier Ducrohet 76059243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet if (res != 0) { 76159243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet // output error message and marker the project. 7623d3c3c3a3e4e05f7ae7a0dff440fe500f90b785cXavier Ducrohet String message = String.format(Messages.Dalvik_Error_d, res); 7633d3c3c3a3e4e05f7ae7a0dff440fe500f90b785cXavier Ducrohet throw new DexException(message); 76459243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet } 7653d3c3c3a3e4e05f7ae7a0dff440fe500f90b785cXavier Ducrohet } catch (DexException e) { 7663d3c3c3a3e4e05f7ae7a0dff440fe500f90b785cXavier Ducrohet throw e; 7673d3c3c3a3e4e05f7ae7a0dff440fe500f90b785cXavier Ducrohet } catch (Throwable t) { 7683d3c3c3a3e4e05f7ae7a0dff440fe500f90b785cXavier Ducrohet String message = t.getMessage(); 76959243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet if (message == null) { 7703d3c3c3a3e4e05f7ae7a0dff440fe500f90b785cXavier Ducrohet message = t.getClass().getCanonicalName(); 77159243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet } 77259243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet message = String.format(Messages.Dalvik_Error_s, message); 77359243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet 7743d3c3c3a3e4e05f7ae7a0dff440fe500f90b785cXavier Ducrohet throw new DexException(message, t); 7753d3c3c3a3e4e05f7ae7a0dff440fe500f90b785cXavier Ducrohet } 77659243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet } 77759243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet 77859243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet /** 77959243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet * Executes aapt. If any error happen, files or the project will be marked. 780c15b4fdc76142c61db1ec29feb2afdfaea43a84bJosiah Gaskin * @param command The command for aapt to execute. Currently supported: package and crunch 78159243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet * @param osManifestPath The path to the manifest file 78259243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet * @param osResPath The path to the res folder 78359243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet * @param osAssetsPath The path to the assets folder. This can be null. 784c15b4fdc76142c61db1ec29feb2afdfaea43a84bJosiah Gaskin * @param osOutFilePath The path to the temporary resource file to create, 785c15b4fdc76142c61db1ec29feb2afdfaea43a84bJosiah Gaskin * or in the case of crunching the path to the cache to create/update. 78659243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet * @param configFilter The configuration filter for the resources to include 78759243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet * (used with -c option, for example "port,en,fr" to include portrait, English and French 78859243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet * resources.) 789853ab5a62d09675e0921d2eed60c02f66e3d0050Xavier Ducrohet * @param versionCode optional version code to insert in the manifest during packaging. If <=0 790853ab5a62d09675e0921d2eed60c02f66e3d0050Xavier Ducrohet * then no value is inserted 7913d3c3c3a3e4e05f7ae7a0dff440fe500f90b785cXavier Ducrohet * @throws AaptExecException 7923d3c3c3a3e4e05f7ae7a0dff440fe500f90b785cXavier Ducrohet * @throws AaptResultException 79359243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet */ 794c15b4fdc76142c61db1ec29feb2afdfaea43a84bJosiah Gaskin private void executeAapt(String aaptCommand, String osManifestPath, 79559243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet List<String> osResPaths, String osAssetsPath, String osOutFilePath, 7963d3c3c3a3e4e05f7ae7a0dff440fe500f90b785cXavier Ducrohet String configFilter, int versionCode) throws AaptExecException, AaptResultException { 79759243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet IAndroidTarget target = Sdk.getCurrent().getTarget(mProject); 79859243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet 79981c5fb5448a6342cb3bb29ea501fccf95573288cXavier Ducrohet @SuppressWarnings("deprecation") String aapt = target.getPath(IAndroidTarget.AAPT); 80081c5fb5448a6342cb3bb29ea501fccf95573288cXavier Ducrohet 80159243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet // Create the command line. 80259243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet ArrayList<String> commandArray = new ArrayList<String>(); 80381c5fb5448a6342cb3bb29ea501fccf95573288cXavier Ducrohet commandArray.add(aapt); 804c15b4fdc76142c61db1ec29feb2afdfaea43a84bJosiah Gaskin commandArray.add(aaptCommand); 80559243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet if (AdtPrefs.getPrefs().getBuildVerbosity() == BuildVerbosity.VERBOSE) { 80659243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet commandArray.add("-v"); //$NON-NLS-1$ 80759243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet } 80859243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet 809c15b4fdc76142c61db1ec29feb2afdfaea43a84bJosiah Gaskin // Common to all commands 810c15b4fdc76142c61db1ec29feb2afdfaea43a84bJosiah Gaskin for (String path : osResPaths) { 811c15b4fdc76142c61db1ec29feb2afdfaea43a84bJosiah Gaskin commandArray.add("-S"); //$NON-NLS-1$ 812c15b4fdc76142c61db1ec29feb2afdfaea43a84bJosiah Gaskin commandArray.add(path); 81359243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet } 81459243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet 815c15b4fdc76142c61db1ec29feb2afdfaea43a84bJosiah Gaskin if (aaptCommand.equals(COMMAND_PACKAGE)) { 816c15b4fdc76142c61db1ec29feb2afdfaea43a84bJosiah Gaskin commandArray.add("-f"); //$NON-NLS-1$ 817c15b4fdc76142c61db1ec29feb2afdfaea43a84bJosiah Gaskin commandArray.add("--no-crunch"); //$NON-NLS-1$ 8183d3c3c3a3e4e05f7ae7a0dff440fe500f90b785cXavier Ducrohet 819c15b4fdc76142c61db1ec29feb2afdfaea43a84bJosiah Gaskin // if more than one res, this means there's a library (or more) and we need 820c15b4fdc76142c61db1ec29feb2afdfaea43a84bJosiah Gaskin // to activate the auto-add-overlay 821c15b4fdc76142c61db1ec29feb2afdfaea43a84bJosiah Gaskin if (osResPaths.size() > 1) { 822c15b4fdc76142c61db1ec29feb2afdfaea43a84bJosiah Gaskin commandArray.add("--auto-add-overlay"); //$NON-NLS-1$ 823c15b4fdc76142c61db1ec29feb2afdfaea43a84bJosiah Gaskin } 824853ab5a62d09675e0921d2eed60c02f66e3d0050Xavier Ducrohet 825c15b4fdc76142c61db1ec29feb2afdfaea43a84bJosiah Gaskin if (mDebugMode) { 826c15b4fdc76142c61db1ec29feb2afdfaea43a84bJosiah Gaskin commandArray.add("--debug-mode"); //$NON-NLS-1$ 827c15b4fdc76142c61db1ec29feb2afdfaea43a84bJosiah Gaskin } 82859243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet 829c15b4fdc76142c61db1ec29feb2afdfaea43a84bJosiah Gaskin if (versionCode > 0) { 830c15b4fdc76142c61db1ec29feb2afdfaea43a84bJosiah Gaskin commandArray.add("--version-code"); //$NON-NLS-1$ 831c15b4fdc76142c61db1ec29feb2afdfaea43a84bJosiah Gaskin commandArray.add(Integer.toString(versionCode)); 832c15b4fdc76142c61db1ec29feb2afdfaea43a84bJosiah Gaskin } 83359243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet 834c15b4fdc76142c61db1ec29feb2afdfaea43a84bJosiah Gaskin if (configFilter != null) { 835c15b4fdc76142c61db1ec29feb2afdfaea43a84bJosiah Gaskin commandArray.add("-c"); //$NON-NLS-1$ 836c15b4fdc76142c61db1ec29feb2afdfaea43a84bJosiah Gaskin commandArray.add(configFilter); 837c15b4fdc76142c61db1ec29feb2afdfaea43a84bJosiah Gaskin } 83859243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet 839c15b4fdc76142c61db1ec29feb2afdfaea43a84bJosiah Gaskin commandArray.add("-M"); //$NON-NLS-1$ 840c15b4fdc76142c61db1ec29feb2afdfaea43a84bJosiah Gaskin commandArray.add(osManifestPath); 841c15b4fdc76142c61db1ec29feb2afdfaea43a84bJosiah Gaskin 842c15b4fdc76142c61db1ec29feb2afdfaea43a84bJosiah Gaskin if (osAssetsPath != null) { 843c15b4fdc76142c61db1ec29feb2afdfaea43a84bJosiah Gaskin commandArray.add("-A"); //$NON-NLS-1$ 844c15b4fdc76142c61db1ec29feb2afdfaea43a84bJosiah Gaskin commandArray.add(osAssetsPath); 845c15b4fdc76142c61db1ec29feb2afdfaea43a84bJosiah Gaskin } 84659243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet 847c15b4fdc76142c61db1ec29feb2afdfaea43a84bJosiah Gaskin commandArray.add("-I"); //$NON-NLS-1$ 848c15b4fdc76142c61db1ec29feb2afdfaea43a84bJosiah Gaskin commandArray.add(target.getPath(IAndroidTarget.ANDROID_JAR)); 84959243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet 850c15b4fdc76142c61db1ec29feb2afdfaea43a84bJosiah Gaskin commandArray.add("-F"); //$NON-NLS-1$ 851c15b4fdc76142c61db1ec29feb2afdfaea43a84bJosiah Gaskin commandArray.add(osOutFilePath); 852c15b4fdc76142c61db1ec29feb2afdfaea43a84bJosiah Gaskin } else if (aaptCommand.equals(COMMAND_CRUNCH)) { 853c15b4fdc76142c61db1ec29feb2afdfaea43a84bJosiah Gaskin commandArray.add("-C"); //$NON-NLS-1$ 854c15b4fdc76142c61db1ec29feb2afdfaea43a84bJosiah Gaskin commandArray.add(osOutFilePath); 855c15b4fdc76142c61db1ec29feb2afdfaea43a84bJosiah Gaskin } 85659243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet 85759243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet String command[] = commandArray.toArray( 85859243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet new String[commandArray.size()]); 85959243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet 86059243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet if (AdtPrefs.getPrefs().getBuildVerbosity() == BuildVerbosity.VERBOSE) { 86159243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet StringBuilder sb = new StringBuilder(); 86259243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet for (String c : command) { 86359243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet sb.append(c); 86459243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet sb.append(' '); 86559243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet } 86659243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet AdtPlugin.printToConsole(mProject, sb.toString()); 86759243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet } 86859243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet 869c15b4fdc76142c61db1ec29feb2afdfaea43a84bJosiah Gaskin // Benchmarking start 870c15b4fdc76142c61db1ec29feb2afdfaea43a84bJosiah Gaskin long startAaptTime = 0; 871c15b4fdc76142c61db1ec29feb2afdfaea43a84bJosiah Gaskin if (BENCHMARK_FLAG) { 872c15b4fdc76142c61db1ec29feb2afdfaea43a84bJosiah Gaskin String msg = "BENCHMARK ADT: Starting " + aaptCommand //$NON-NLS-1$ 873c15b4fdc76142c61db1ec29feb2afdfaea43a84bJosiah Gaskin + " call to Aapt"; //$NON-NLS-1$ 874c15b4fdc76142c61db1ec29feb2afdfaea43a84bJosiah Gaskin AdtPlugin.printBuildToConsole(BuildVerbosity.ALWAYS, mProject, msg); 875c15b4fdc76142c61db1ec29feb2afdfaea43a84bJosiah Gaskin startAaptTime = System.nanoTime(); 876c15b4fdc76142c61db1ec29feb2afdfaea43a84bJosiah Gaskin } 877c15b4fdc76142c61db1ec29feb2afdfaea43a84bJosiah Gaskin 87859243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet // launch 87959243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet try { 88059243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet // launch the command line process 88159243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet Process process = Runtime.getRuntime().exec(command); 88259243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet 88359243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet // list to store each line of stderr 8844152b691d53c5621c186bbd1a41f31024809aa7aXavier Ducrohet ArrayList<String> stdErr = new ArrayList<String>(); 88559243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet 88659243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet // get the output and return code from the process 8874152b691d53c5621c186bbd1a41f31024809aa7aXavier Ducrohet int returnCode = grabProcessOutput(mProject, process, stdErr); 88859243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet 8897139790c9af02de824c6f2dae7a68ff694ae1f19Xavier Ducrohet if (mVerbose) { 8904152b691d53c5621c186bbd1a41f31024809aa7aXavier Ducrohet for (String stdErrString : stdErr) { 8914152b691d53c5621c186bbd1a41f31024809aa7aXavier Ducrohet mOutStream.println(stdErrString); 89259243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet } 89359243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet } 8944152b691d53c5621c186bbd1a41f31024809aa7aXavier Ducrohet if (returnCode != 0) { 8954152b691d53c5621c186bbd1a41f31024809aa7aXavier Ducrohet throw new AaptResultException(returnCode, 8964152b691d53c5621c186bbd1a41f31024809aa7aXavier Ducrohet stdErr.toArray(new String[stdErr.size()])); 8977139790c9af02de824c6f2dae7a68ff694ae1f19Xavier Ducrohet } 8983d3c3c3a3e4e05f7ae7a0dff440fe500f90b785cXavier Ducrohet } catch (IOException e) { 8994152b691d53c5621c186bbd1a41f31024809aa7aXavier Ducrohet String msg = String.format(Messages.AAPT_Exec_Error_s, command[0]); 9003d3c3c3a3e4e05f7ae7a0dff440fe500f90b785cXavier Ducrohet throw new AaptExecException(msg, e); 90159243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet } catch (InterruptedException e) { 9024152b691d53c5621c186bbd1a41f31024809aa7aXavier Ducrohet String msg = String.format(Messages.AAPT_Exec_Error_s, command[0]); 9033d3c3c3a3e4e05f7ae7a0dff440fe500f90b785cXavier Ducrohet throw new AaptExecException(msg, e); 90459243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet } 905c15b4fdc76142c61db1ec29feb2afdfaea43a84bJosiah Gaskin 906c15b4fdc76142c61db1ec29feb2afdfaea43a84bJosiah Gaskin // Benchmarking end 907c15b4fdc76142c61db1ec29feb2afdfaea43a84bJosiah Gaskin if (BENCHMARK_FLAG) { 908c15b4fdc76142c61db1ec29feb2afdfaea43a84bJosiah Gaskin String msg = "BENCHMARK ADT: Ending " + aaptCommand //$NON-NLS-1$ 909c15b4fdc76142c61db1ec29feb2afdfaea43a84bJosiah Gaskin + " call to Aapt.\nBENCHMARK ADT: Time Elapsed: " //$NON-NLS-1$ 910c15b4fdc76142c61db1ec29feb2afdfaea43a84bJosiah Gaskin + ((System.nanoTime() - startAaptTime)/MILLION) + "ms"; //$NON-NLS-1$ 911c15b4fdc76142c61db1ec29feb2afdfaea43a84bJosiah Gaskin AdtPlugin.printBuildToConsole(BuildVerbosity.ALWAYS, mProject, msg); 912c15b4fdc76142c61db1ec29feb2afdfaea43a84bJosiah Gaskin } 91359243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet } 91459243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet 91559243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet /** 916bcf44e9429811b3e1f97d21ea92816957bce2601Xavier Ducrohet * Computes all the project output and dependencies that must go into building the apk. 917bcf44e9429811b3e1f97d21ea92816957bce2601Xavier Ducrohet * 918bcf44e9429811b3e1f97d21ea92816957bce2601Xavier Ducrohet * @param resMarker 91959243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet * @throws CoreException 92059243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet */ 921bcf44e9429811b3e1f97d21ea92816957bce2601Xavier Ducrohet private void gatherPaths(ResourceMarker resMarker) 922bcf44e9429811b3e1f97d21ea92816957bce2601Xavier Ducrohet throws CoreException { 923bcf44e9429811b3e1f97d21ea92816957bce2601Xavier Ducrohet IWorkspaceRoot wsRoot = ResourcesPlugin.getWorkspace().getRoot(); 92459243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet 925bcf44e9429811b3e1f97d21ea92816957bce2601Xavier Ducrohet // get a java project for the project. 926bcf44e9429811b3e1f97d21ea92816957bce2601Xavier Ducrohet IJavaProject javaProject = JavaCore.create(mProject); 927bcf44e9429811b3e1f97d21ea92816957bce2601Xavier Ducrohet 928bcf44e9429811b3e1f97d21ea92816957bce2601Xavier Ducrohet 929bcf44e9429811b3e1f97d21ea92816957bce2601Xavier Ducrohet // get the output of the main project 930bcf44e9429811b3e1f97d21ea92816957bce2601Xavier Ducrohet IPath path = javaProject.getOutputLocation(); 931bcf44e9429811b3e1f97d21ea92816957bce2601Xavier Ducrohet IResource outputResource = wsRoot.findMember(path); 932bcf44e9429811b3e1f97d21ea92816957bce2601Xavier Ducrohet if (outputResource != null && outputResource.getType() == IResource.FOLDER) { 933bcf44e9429811b3e1f97d21ea92816957bce2601Xavier Ducrohet mCompiledCodePaths.add(outputResource.getLocation().toOSString()); 934237d006af115bf2fa05058015e8a15d4487e7fe1Dominic Mitchell } 935237d006af115bf2fa05058015e8a15d4487e7fe1Dominic Mitchell 936bcf44e9429811b3e1f97d21ea92816957bce2601Xavier Ducrohet // we could use IJavaProject.getResolvedClasspath directly, but we actually 937bcf44e9429811b3e1f97d21ea92816957bce2601Xavier Ducrohet // want to see the containers themselves. 938bcf44e9429811b3e1f97d21ea92816957bce2601Xavier Ducrohet IClasspathEntry[] classpaths = javaProject.readRawClasspath(); 939bcf44e9429811b3e1f97d21ea92816957bce2601Xavier Ducrohet if (classpaths != null) { 940bcf44e9429811b3e1f97d21ea92816957bce2601Xavier Ducrohet for (IClasspathEntry e : classpaths) { 941bcf44e9429811b3e1f97d21ea92816957bce2601Xavier Ducrohet // ignore non exported entries, unless it's the LIBRARIES container, 942bcf44e9429811b3e1f97d21ea92816957bce2601Xavier Ducrohet // in which case we always want it (there may be some older projects that 943bcf44e9429811b3e1f97d21ea92816957bce2601Xavier Ducrohet // have it as non exported). 944bcf44e9429811b3e1f97d21ea92816957bce2601Xavier Ducrohet if (e.isExported() || 945bcf44e9429811b3e1f97d21ea92816957bce2601Xavier Ducrohet (e.getEntryKind() == IClasspathEntry.CPE_CONTAINER && 946bcf44e9429811b3e1f97d21ea92816957bce2601Xavier Ducrohet e.getPath().toString().equals(AdtConstants.CONTAINER_LIBRARIES))) { 947bcf44e9429811b3e1f97d21ea92816957bce2601Xavier Ducrohet handleCPE(e, javaProject, wsRoot, resMarker); 948237d006af115bf2fa05058015e8a15d4487e7fe1Dominic Mitchell } 94959243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet } 95059243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet } 95159243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet } 95259243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet 953bcf44e9429811b3e1f97d21ea92816957bce2601Xavier Ducrohet private void handleCPE(IClasspathEntry entry, IJavaProject javaProject, 954bcf44e9429811b3e1f97d21ea92816957bce2601Xavier Ducrohet IWorkspaceRoot wsRoot, ResourceMarker resMarker) { 95559243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet 956bcf44e9429811b3e1f97d21ea92816957bce2601Xavier Ducrohet // if this is a classpath variable reference, we resolve it. 957bcf44e9429811b3e1f97d21ea92816957bce2601Xavier Ducrohet if (entry.getEntryKind() == IClasspathEntry.CPE_VARIABLE) { 958bcf44e9429811b3e1f97d21ea92816957bce2601Xavier Ducrohet entry = JavaCore.getResolvedClasspathEntry(entry); 959bcf44e9429811b3e1f97d21ea92816957bce2601Xavier Ducrohet } 96059243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet 961bcf44e9429811b3e1f97d21ea92816957bce2601Xavier Ducrohet if (entry.getEntryKind() == IClasspathEntry.CPE_PROJECT) { 962bcf44e9429811b3e1f97d21ea92816957bce2601Xavier Ducrohet IProject refProject = wsRoot.getProject(entry.getPath().lastSegment()); 963bcf44e9429811b3e1f97d21ea92816957bce2601Xavier Ducrohet try { 964bcf44e9429811b3e1f97d21ea92816957bce2601Xavier Ducrohet // ignore if it's an Android project, or if it's not a Java Project 965bcf44e9429811b3e1f97d21ea92816957bce2601Xavier Ducrohet if (refProject.hasNature(JavaCore.NATURE_ID) && 966bcf44e9429811b3e1f97d21ea92816957bce2601Xavier Ducrohet refProject.hasNature(AdtConstants.NATURE_DEFAULT) == false) { 967bcf44e9429811b3e1f97d21ea92816957bce2601Xavier Ducrohet IJavaProject refJavaProject = JavaCore.create(refProject); 968babf25ca7162849f0145f75be1b6c09b359b122cXavier Ducrohet 969bcf44e9429811b3e1f97d21ea92816957bce2601Xavier Ducrohet // get the output folder 970bcf44e9429811b3e1f97d21ea92816957bce2601Xavier Ducrohet IPath path = refJavaProject.getOutputLocation(); 971bcf44e9429811b3e1f97d21ea92816957bce2601Xavier Ducrohet IResource outputResource = wsRoot.findMember(path); 972bcf44e9429811b3e1f97d21ea92816957bce2601Xavier Ducrohet if (outputResource != null && outputResource.getType() == IResource.FOLDER) { 973bcf44e9429811b3e1f97d21ea92816957bce2601Xavier Ducrohet mCompiledCodePaths.add(outputResource.getLocation().toOSString()); 974bcf44e9429811b3e1f97d21ea92816957bce2601Xavier Ducrohet } 975babf25ca7162849f0145f75be1b6c09b359b122cXavier Ducrohet } 976bcf44e9429811b3e1f97d21ea92816957bce2601Xavier Ducrohet } catch (CoreException exception) { 977bcf44e9429811b3e1f97d21ea92816957bce2601Xavier Ducrohet // can't query the project nature? ignore 978bcf44e9429811b3e1f97d21ea92816957bce2601Xavier Ducrohet } 979433236156debbb84b13776649e20258c1fc51491Xavier Ducrohet 980bcf44e9429811b3e1f97d21ea92816957bce2601Xavier Ducrohet } else if (entry.getEntryKind() == IClasspathEntry.CPE_LIBRARY) { 981bcf44e9429811b3e1f97d21ea92816957bce2601Xavier Ducrohet handleClasspathLibrary(entry, wsRoot, resMarker); 982bcf44e9429811b3e1f97d21ea92816957bce2601Xavier Ducrohet } else if (entry.getEntryKind() == IClasspathEntry.CPE_CONTAINER) { 983bcf44e9429811b3e1f97d21ea92816957bce2601Xavier Ducrohet // get the container 984bcf44e9429811b3e1f97d21ea92816957bce2601Xavier Ducrohet try { 985bcf44e9429811b3e1f97d21ea92816957bce2601Xavier Ducrohet IClasspathContainer container = JavaCore.getClasspathContainer( 986bcf44e9429811b3e1f97d21ea92816957bce2601Xavier Ducrohet entry.getPath(), javaProject); 987bcf44e9429811b3e1f97d21ea92816957bce2601Xavier Ducrohet // ignore the system and default_system types as they represent 988bcf44e9429811b3e1f97d21ea92816957bce2601Xavier Ducrohet // libraries that are part of the runtime. 989aea408b68a6f833327b6e0954a28f414f58133acXavier Ducrohet if (container != null && container.getKind() == IClasspathContainer.K_APPLICATION) { 990bcf44e9429811b3e1f97d21ea92816957bce2601Xavier Ducrohet IClasspathEntry[] entries = container.getClasspathEntries(); 991bcf44e9429811b3e1f97d21ea92816957bce2601Xavier Ducrohet for (IClasspathEntry cpe : entries) { 992bcf44e9429811b3e1f97d21ea92816957bce2601Xavier Ducrohet handleCPE(cpe, javaProject, wsRoot, resMarker); 99359243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet } 99459243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet } 995bcf44e9429811b3e1f97d21ea92816957bce2601Xavier Ducrohet } catch (JavaModelException jme) { 996bcf44e9429811b3e1f97d21ea92816957bce2601Xavier Ducrohet // can't resolve the container? ignore it. 997bcf44e9429811b3e1f97d21ea92816957bce2601Xavier Ducrohet AdtPlugin.log(jme, "Failed to resolve ClasspathContainer: %s", entry.getPath()); 99859243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet } 99959243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet } 100059243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet } 100159243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet 1002bcf44e9429811b3e1f97d21ea92816957bce2601Xavier Ducrohet private void handleClasspathLibrary(IClasspathEntry e, IWorkspaceRoot wsRoot, 1003bcf44e9429811b3e1f97d21ea92816957bce2601Xavier Ducrohet ResourceMarker resMarker) { 1004babf25ca7162849f0145f75be1b6c09b359b122cXavier Ducrohet // get the IPath 1005babf25ca7162849f0145f75be1b6c09b359b122cXavier Ducrohet IPath path = e.getPath(); 1006babf25ca7162849f0145f75be1b6c09b359b122cXavier Ducrohet 1007babf25ca7162849f0145f75be1b6c09b359b122cXavier Ducrohet IResource resource = wsRoot.findMember(path); 100881c5fb5448a6342cb3bb29ea501fccf95573288cXavier Ducrohet 100981c5fb5448a6342cb3bb29ea501fccf95573288cXavier Ducrohet if (resource != null && resource.getType() == IResource.PROJECT) { 101081c5fb5448a6342cb3bb29ea501fccf95573288cXavier Ducrohet // if it's a project we should just ignore it because it's going to be added 101181c5fb5448a6342cb3bb29ea501fccf95573288cXavier Ducrohet // later when we add all the referenced projects. 101281c5fb5448a6342cb3bb29ea501fccf95573288cXavier Ducrohet 101312d4581faa6438941e65a9dc83213be34c6ca970Tor Norbye } else if (SdkConstants.EXT_JAR.equalsIgnoreCase(path.getFileExtension())) { 101481c5fb5448a6342cb3bb29ea501fccf95573288cXavier Ducrohet // case of a jar file (which could be relative to the workspace or a full path) 1015babf25ca7162849f0145f75be1b6c09b359b122cXavier Ducrohet if (resource != null && resource.exists() && 1016babf25ca7162849f0145f75be1b6c09b359b122cXavier Ducrohet resource.getType() == IResource.FILE) { 1017bcf44e9429811b3e1f97d21ea92816957bce2601Xavier Ducrohet mCompiledCodePaths.add(resource.getLocation().toOSString()); 1018babf25ca7162849f0145f75be1b6c09b359b122cXavier Ducrohet } else { 1019babf25ca7162849f0145f75be1b6c09b359b122cXavier Ducrohet // if the jar path doesn't match a workspace resource, 1020babf25ca7162849f0145f75be1b6c09b359b122cXavier Ducrohet // then we get an OSString and check if this links to a valid file. 1021babf25ca7162849f0145f75be1b6c09b359b122cXavier Ducrohet String osFullPath = path.toOSString(); 1022babf25ca7162849f0145f75be1b6c09b359b122cXavier Ducrohet 1023babf25ca7162849f0145f75be1b6c09b359b122cXavier Ducrohet File f = new File(osFullPath); 1024babf25ca7162849f0145f75be1b6c09b359b122cXavier Ducrohet if (f.isFile()) { 1025bcf44e9429811b3e1f97d21ea92816957bce2601Xavier Ducrohet mCompiledCodePaths.add(osFullPath); 1026babf25ca7162849f0145f75be1b6c09b359b122cXavier Ducrohet } else { 1027babf25ca7162849f0145f75be1b6c09b359b122cXavier Ducrohet String message = String.format( Messages.Couldnt_Locate_s_Error, 1028babf25ca7162849f0145f75be1b6c09b359b122cXavier Ducrohet path); 1029babf25ca7162849f0145f75be1b6c09b359b122cXavier Ducrohet // always output to the console 1030babf25ca7162849f0145f75be1b6c09b359b122cXavier Ducrohet mOutStream.println(message); 1031babf25ca7162849f0145f75be1b6c09b359b122cXavier Ducrohet 1032babf25ca7162849f0145f75be1b6c09b359b122cXavier Ducrohet // put a marker 1033babf25ca7162849f0145f75be1b6c09b359b122cXavier Ducrohet if (resMarker != null) { 1034babf25ca7162849f0145f75be1b6c09b359b122cXavier Ducrohet resMarker.setWarning(mProject, message); 1035babf25ca7162849f0145f75be1b6c09b359b122cXavier Ducrohet } 1036babf25ca7162849f0145f75be1b6c09b359b122cXavier Ducrohet } 1037babf25ca7162849f0145f75be1b6c09b359b122cXavier Ducrohet } 1038babf25ca7162849f0145f75be1b6c09b359b122cXavier Ducrohet } else { 1039babf25ca7162849f0145f75be1b6c09b359b122cXavier Ducrohet // this can be the case for a class folder. 1040babf25ca7162849f0145f75be1b6c09b359b122cXavier Ducrohet if (resource != null && resource.exists() && 1041babf25ca7162849f0145f75be1b6c09b359b122cXavier Ducrohet resource.getType() == IResource.FOLDER) { 1042bcf44e9429811b3e1f97d21ea92816957bce2601Xavier Ducrohet mCompiledCodePaths.add(resource.getLocation().toOSString()); 1043babf25ca7162849f0145f75be1b6c09b359b122cXavier Ducrohet } else { 1044babf25ca7162849f0145f75be1b6c09b359b122cXavier Ducrohet // if the path doesn't match a workspace resource, 1045babf25ca7162849f0145f75be1b6c09b359b122cXavier Ducrohet // then we get an OSString and check if this links to a valid folder. 1046babf25ca7162849f0145f75be1b6c09b359b122cXavier Ducrohet String osFullPath = path.toOSString(); 1047babf25ca7162849f0145f75be1b6c09b359b122cXavier Ducrohet 1048babf25ca7162849f0145f75be1b6c09b359b122cXavier Ducrohet File f = new File(osFullPath); 1049babf25ca7162849f0145f75be1b6c09b359b122cXavier Ducrohet if (f.isDirectory()) { 1050bcf44e9429811b3e1f97d21ea92816957bce2601Xavier Ducrohet mCompiledCodePaths.add(osFullPath); 1051babf25ca7162849f0145f75be1b6c09b359b122cXavier Ducrohet } 1052babf25ca7162849f0145f75be1b6c09b359b122cXavier Ducrohet } 1053babf25ca7162849f0145f75be1b6c09b359b122cXavier Ducrohet } 1054babf25ca7162849f0145f75be1b6c09b359b122cXavier Ducrohet } 1055babf25ca7162849f0145f75be1b6c09b359b122cXavier Ducrohet 105659243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet /** 105759243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet * Checks a {@link IFile} to make sure it should be packaged as standard resources. 105859243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet * @param file the IFile representing the file. 105959243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet * @return true if the file should be packaged as standard java resources. 106059243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet */ 106159f8d5012426884e40b77b02a7c3274eb66019a1Xavier Ducrohet public static boolean checkFileForPackaging(IFile file) { 106259243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet String name = file.getName(); 106359243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet 106459243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet String ext = file.getFileExtension(); 10657c19dcf5aead68f4f6675db0bac6b495396e2967Xavier Ducrohet return ApkBuilder.checkFileForPackaging(name, ext); 106659243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet } 106759243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet 106859243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet /** 106959243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet * Checks whether an {@link IFolder} and its content is valid for packaging into the .apk as 107059243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet * standard Java resource. 107159243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet * @param folder the {@link IFolder} to check. 107259243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet */ 107359f8d5012426884e40b77b02a7c3274eb66019a1Xavier Ducrohet public static boolean checkFolderForPackaging(IFolder folder) { 107459243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet String name = folder.getName(); 10757c19dcf5aead68f4f6675db0bac6b495396e2967Xavier Ducrohet return ApkBuilder.checkFolderForPackaging(name); 107659243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet } 107759243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet 1078853ab5a62d09675e0921d2eed60c02f66e3d0050Xavier Ducrohet /** 1079a0340fdf211a94d4d96a9e063386b0eccae9b74cXavier Ducrohet * Returns a list of {@link IJavaProject} matching the provided {@link IProject} objects. 1080853ab5a62d09675e0921d2eed60c02f66e3d0050Xavier Ducrohet * @param projects the IProject objects. 1081a0340fdf211a94d4d96a9e063386b0eccae9b74cXavier Ducrohet * @return a new list object containing the IJavaProject object for the given IProject objects. 1082853ab5a62d09675e0921d2eed60c02f66e3d0050Xavier Ducrohet * @throws CoreException 1083853ab5a62d09675e0921d2eed60c02f66e3d0050Xavier Ducrohet */ 1084a0340fdf211a94d4d96a9e063386b0eccae9b74cXavier Ducrohet public static List<IJavaProject> getJavaProjects(List<IProject> projects) throws CoreException { 1085853ab5a62d09675e0921d2eed60c02f66e3d0050Xavier Ducrohet ArrayList<IJavaProject> list = new ArrayList<IJavaProject>(); 1086853ab5a62d09675e0921d2eed60c02f66e3d0050Xavier Ducrohet 1087853ab5a62d09675e0921d2eed60c02f66e3d0050Xavier Ducrohet for (IProject p : projects) { 1088853ab5a62d09675e0921d2eed60c02f66e3d0050Xavier Ducrohet if (p.isOpen() && p.hasNature(JavaCore.NATURE_ID)) { 1089853ab5a62d09675e0921d2eed60c02f66e3d0050Xavier Ducrohet 1090853ab5a62d09675e0921d2eed60c02f66e3d0050Xavier Ducrohet list.add(JavaCore.create(p)); 1091853ab5a62d09675e0921d2eed60c02f66e3d0050Xavier Ducrohet } 1092853ab5a62d09675e0921d2eed60c02f66e3d0050Xavier Ducrohet } 1093853ab5a62d09675e0921d2eed60c02f66e3d0050Xavier Ducrohet 1094a0340fdf211a94d4d96a9e063386b0eccae9b74cXavier Ducrohet return list; 1095853ab5a62d09675e0921d2eed60c02f66e3d0050Xavier Ducrohet } 1096853ab5a62d09675e0921d2eed60c02f66e3d0050Xavier Ducrohet 109759f8d5012426884e40b77b02a7c3274eb66019a1Xavier Ducrohet /** 109859f8d5012426884e40b77b02a7c3274eb66019a1Xavier Ducrohet * Get the stderr output of a process and return when the process is done. 10994152b691d53c5621c186bbd1a41f31024809aa7aXavier Ducrohet * @param process The process to get the output from 11004152b691d53c5621c186bbd1a41f31024809aa7aXavier Ducrohet * @param stderr The array to store the stderr output 110159f8d5012426884e40b77b02a7c3274eb66019a1Xavier Ducrohet * @return the process return code. 110259f8d5012426884e40b77b02a7c3274eb66019a1Xavier Ducrohet * @throws InterruptedException 110359f8d5012426884e40b77b02a7c3274eb66019a1Xavier Ducrohet */ 11048c578aff7c5d84bc38d5a6d391986aece3cd2e19Raphael public final static int grabProcessOutput( 11058c578aff7c5d84bc38d5a6d391986aece3cd2e19Raphael final IProject project, 11068c578aff7c5d84bc38d5a6d391986aece3cd2e19Raphael final Process process, 11074152b691d53c5621c186bbd1a41f31024809aa7aXavier Ducrohet final ArrayList<String> stderr) 110859f8d5012426884e40b77b02a7c3274eb66019a1Xavier Ducrohet throws InterruptedException { 110959f8d5012426884e40b77b02a7c3274eb66019a1Xavier Ducrohet 11108c578aff7c5d84bc38d5a6d391986aece3cd2e19Raphael return GrabProcessOutput.grabProcessOutput( 11118c578aff7c5d84bc38d5a6d391986aece3cd2e19Raphael process, 11124152b691d53c5621c186bbd1a41f31024809aa7aXavier Ducrohet Wait.WAIT_FOR_READERS, // we really want to make sure we get all the output! 11138c578aff7c5d84bc38d5a6d391986aece3cd2e19Raphael new IProcessOutput() { 111459f8d5012426884e40b77b02a7c3274eb66019a1Xavier Ducrohet 11158c578aff7c5d84bc38d5a6d391986aece3cd2e19Raphael @SuppressWarnings("unused") 11168c578aff7c5d84bc38d5a6d391986aece3cd2e19Raphael @Override 11177e4b8e9d595e45baa9d87cdb8282f02759e73abcTor Norbye public void out(@Nullable String line) { 111859f8d5012426884e40b77b02a7c3274eb66019a1Xavier Ducrohet if (line != null) { 1119c15b4fdc76142c61db1ec29feb2afdfaea43a84bJosiah Gaskin // If benchmarking always print the lines that 1120c15b4fdc76142c61db1ec29feb2afdfaea43a84bJosiah Gaskin // correspond to benchmarking info returned by ADT 1121c15b4fdc76142c61db1ec29feb2afdfaea43a84bJosiah Gaskin if (BENCHMARK_FLAG && line.startsWith("BENCHMARK:")) { //$NON-NLS-1$ 1122c15b4fdc76142c61db1ec29feb2afdfaea43a84bJosiah Gaskin AdtPlugin.printBuildToConsole(BuildVerbosity.ALWAYS, 1123c15b4fdc76142c61db1ec29feb2afdfaea43a84bJosiah Gaskin project, line); 1124c15b4fdc76142c61db1ec29feb2afdfaea43a84bJosiah Gaskin } else { 1125c15b4fdc76142c61db1ec29feb2afdfaea43a84bJosiah Gaskin AdtPlugin.printBuildToConsole(BuildVerbosity.VERBOSE, 1126c15b4fdc76142c61db1ec29feb2afdfaea43a84bJosiah Gaskin project, line); 1127c15b4fdc76142c61db1ec29feb2afdfaea43a84bJosiah Gaskin } 112859f8d5012426884e40b77b02a7c3274eb66019a1Xavier Ducrohet } 112959f8d5012426884e40b77b02a7c3274eb66019a1Xavier Ducrohet } 113059f8d5012426884e40b77b02a7c3274eb66019a1Xavier Ducrohet 11318c578aff7c5d84bc38d5a6d391986aece3cd2e19Raphael @Override 11327e4b8e9d595e45baa9d87cdb8282f02759e73abcTor Norbye public void err(@Nullable String line) { 11338c578aff7c5d84bc38d5a6d391986aece3cd2e19Raphael if (line != null) { 11344152b691d53c5621c186bbd1a41f31024809aa7aXavier Ducrohet stderr.add(line); 11358818ca4db2f1ae396964912bf8035ee88988f4ddXavier Ducrohet if (BuildVerbosity.VERBOSE == AdtPrefs.getPrefs().getBuildVerbosity()) { 11368818ca4db2f1ae396964912bf8035ee88988f4ddXavier Ducrohet AdtPlugin.printErrorToConsole(project, line); 11378818ca4db2f1ae396964912bf8035ee88988f4ddXavier Ducrohet } 11388c578aff7c5d84bc38d5a6d391986aece3cd2e19Raphael } 11398c578aff7c5d84bc38d5a6d391986aece3cd2e19Raphael } 11408c578aff7c5d84bc38d5a6d391986aece3cd2e19Raphael }); 114159f8d5012426884e40b77b02a7c3274eb66019a1Xavier Ducrohet } 114259243b8de886379e7154c886adbefc74dac24055Xavier Ducrohet} 1143