List of usage examples for org.eclipse.jdt.core IJavaProject getProject
IProject getProject();
IProject
on which this IJavaProject
was created. From source file:com.android.ide.eclipse.adt.internal.build.ApkBuilder.java
License:Open Source License
@SuppressWarnings("unchecked") @Override/*from w w w . j a v a2 s . com*/ protected IProject[] build(int kind, Map args, IProgressMonitor monitor) throws CoreException { // get a project object IProject project = getProject(); // list of referenced projects. IProject[] referencedProjects = null; try { // Top level check to make sure the build can move forward. abortOnBadSetup(project); // get the list of referenced projects. referencedProjects = ProjectHelper.getReferencedProjects(project); IJavaProject[] referencedJavaProjects = getJavaProjects(referencedProjects); // get the output folder, this method returns the path with a trailing // separator IJavaProject javaProject = JavaCore.create(project); IFolder outputFolder = BaseProjectHelper.getOutputFolder(project); // now we need to get the classpath list ArrayList<IPath> sourceList = BaseProjectHelper.getSourceClasspaths(javaProject); // First thing we do is go through the resource delta to not // lose it if we have to abort the build for any reason. ApkDeltaVisitor dv = null; if (kind == FULL_BUILD) { AdtPlugin.printBuildToConsole(AdtConstants.BUILD_VERBOSE, project, Messages.Start_Full_Apk_Build); mPackageResources = true; mConvertToDex = true; mBuildFinalPackage = true; } else { AdtPlugin.printBuildToConsole(AdtConstants.BUILD_VERBOSE, project, Messages.Start_Inc_Apk_Build); // go through the resources and see if something changed. IResourceDelta delta = getDelta(project); if (delta == null) { mPackageResources = true; mConvertToDex = true; mBuildFinalPackage = true; } else { dv = new ApkDeltaVisitor(this, sourceList, outputFolder); delta.accept(dv); // save the state mPackageResources |= dv.getPackageResources(); mConvertToDex |= dv.getConvertToDex(); mBuildFinalPackage |= dv.getMakeFinalPackage(); } // also go through the delta for all the referenced projects, until we are forced to // compile anyway for (int i = 0; i < referencedJavaProjects.length && (mBuildFinalPackage == false || mConvertToDex == false); i++) { IJavaProject referencedJavaProject = referencedJavaProjects[i]; delta = getDelta(referencedJavaProject.getProject()); if (delta != null) { ReferencedProjectDeltaVisitor refProjectDv = new ReferencedProjectDeltaVisitor( referencedJavaProject); delta.accept(refProjectDv); // save the state mConvertToDex |= refProjectDv.needDexConvertion(); mBuildFinalPackage |= refProjectDv.needMakeFinalPackage(); } } } // store the build status in the persistent storage saveProjectBooleanProperty(PROPERTY_CONVERT_TO_DEX, mConvertToDex); saveProjectBooleanProperty(PROPERTY_PACKAGE_RESOURCES, mPackageResources); saveProjectBooleanProperty(PROPERTY_BUILD_APK, mBuildFinalPackage); if (dv != null && dv.mXmlError) { AdtPlugin.printBuildToConsole(AdtConstants.BUILD_VERBOSE, project, Messages.Xml_Error); // if there was some XML errors, we just return w/o doing // anything since we've put some markers in the files anyway return referencedProjects; } if (outputFolder == null) { // mark project and exit markProject(AdtConstants.MARKER_ADT, Messages.Failed_To_Get_Output, IMarker.SEVERITY_ERROR); return referencedProjects; } // first thing we do is check that the SDK directory has been setup. String osSdkFolder = AdtPlugin.getOsSdkFolder(); if (osSdkFolder.length() == 0) { // this has already been checked in the precompiler. Therefore, // while we do have to cancel the build, we don't have to return // any error or throw anything. return referencedProjects; } // get the extra configs for the project. // The map contains (name, filter) where 'name' is a name to be used in the apk filename, // and filter is the resource filter to be used in the aapt -c parameters to restrict // which resource configurations to package in the apk. Map<String, String> configs = Sdk.getCurrent().getProjectApkConfigs(project); // do some extra check, in case the output files are not present. This // will force to recreate them. IResource tmp = null; if (mPackageResources == false) { // check the full resource package tmp = outputFolder.findMember(AndroidConstants.FN_RESOURCES_AP_); if (tmp == null || tmp.exists() == false) { mPackageResources = true; mBuildFinalPackage = true; } else { // if the full package is present, we check the filtered resource packages as well if (configs != null) { Set<Entry<String, String>> entrySet = configs.entrySet(); for (Entry<String, String> entry : entrySet) { String filename = String.format(AndroidConstants.FN_RESOURCES_S_AP_, entry.getKey()); tmp = outputFolder.findMember(filename); if (tmp == null || (tmp instanceof IFile && tmp.exists() == false)) { String msg = String.format(Messages.s_Missing_Repackaging, filename); AdtPlugin.printBuildToConsole(AdtConstants.BUILD_VERBOSE, project, msg); mPackageResources = true; mBuildFinalPackage = true; break; } } } } } // check classes.dex is present. If not we force to recreate it. if (mConvertToDex == false) { tmp = outputFolder.findMember(AndroidConstants.FN_CLASSES_DEX); if (tmp == null || tmp.exists() == false) { mConvertToDex = true; mBuildFinalPackage = true; } } // also check the final file(s)! String finalPackageName = ProjectHelper.getApkFilename(project, null /*config*/); if (mBuildFinalPackage == false) { tmp = outputFolder.findMember(finalPackageName); if (tmp == null || (tmp instanceof IFile && tmp.exists() == false)) { String msg = String.format(Messages.s_Missing_Repackaging, finalPackageName); AdtPlugin.printBuildToConsole(AdtConstants.BUILD_VERBOSE, project, msg); mBuildFinalPackage = true; } else if (configs != null) { // if the full apk is present, we check the filtered apk as well Set<Entry<String, String>> entrySet = configs.entrySet(); for (Entry<String, String> entry : entrySet) { String filename = ProjectHelper.getApkFilename(project, entry.getKey()); tmp = outputFolder.findMember(filename); if (tmp == null || (tmp instanceof IFile && tmp.exists() == false)) { String msg = String.format(Messages.s_Missing_Repackaging, filename); AdtPlugin.printBuildToConsole(AdtConstants.BUILD_VERBOSE, project, msg); mBuildFinalPackage = true; break; } } } } // at this point we know if we need to recreate the temporary apk // or the dex file, but we don't know if we simply need to recreate them // because they are missing // refresh the output directory first IContainer ic = outputFolder.getParent(); if (ic != null) { ic.refreshLocal(IResource.DEPTH_ONE, monitor); } // we need to test all three, as we may need to make the final package // but not the intermediary ones. if (mPackageResources || mConvertToDex || mBuildFinalPackage) { IPath binLocation = outputFolder.getLocation(); if (binLocation == null) { markProject(AdtConstants.MARKER_ADT, Messages.Output_Missing, IMarker.SEVERITY_ERROR); return referencedProjects; } String osBinPath = binLocation.toOSString(); // Remove the old .apk. // This make sure that if the apk is corrupted, then dx (which would attempt // to open it), will not fail. String osFinalPackagePath = osBinPath + File.separator + finalPackageName; File finalPackage = new File(osFinalPackagePath); // if delete failed, this is not really a problem, as the final package generation // handle already present .apk, and if that one failed as well, the user will be // notified. finalPackage.delete(); if (configs != null) { Set<Entry<String, String>> entrySet = configs.entrySet(); for (Entry<String, String> entry : entrySet) { String packageFilepath = osBinPath + File.separator + ProjectHelper.getApkFilename(project, entry.getKey()); finalPackage = new File(packageFilepath); finalPackage.delete(); } } // first we check if we need to package the resources. if (mPackageResources) { // remove some aapt_package only markers. removeMarkersFromContainer(project, AndroidConstants.MARKER_AAPT_PACKAGE); // need to figure out some path before we can execute aapt; // resource to the AndroidManifest.xml file IResource manifestResource = project .findMember(AndroidConstants.WS_SEP + AndroidConstants.FN_ANDROID_MANIFEST); if (manifestResource == null || manifestResource.exists() == false) { // mark project and exit String msg = String.format(Messages.s_File_Missing, AndroidConstants.FN_ANDROID_MANIFEST); markProject(AdtConstants.MARKER_ADT, msg, IMarker.SEVERITY_ERROR); return referencedProjects; } // get the resource folder IFolder resFolder = project.getFolder(AndroidConstants.WS_RESOURCES); // and the assets folder IFolder assetsFolder = project.getFolder(AndroidConstants.WS_ASSETS); // we need to make sure this one exists. if (assetsFolder.exists() == false) { assetsFolder = null; } IPath resLocation = resFolder.getLocation(); IPath manifestLocation = manifestResource.getLocation(); if (resLocation != null && manifestLocation != null) { String osResPath = resLocation.toOSString(); String osManifestPath = manifestLocation.toOSString(); String osAssetsPath = null; if (assetsFolder != null) { osAssetsPath = assetsFolder.getLocation().toOSString(); } // build the default resource package if (executeAapt(project, osManifestPath, osResPath, osAssetsPath, osBinPath + File.separator + AndroidConstants.FN_RESOURCES_AP_, null /*configFilter*/) == false) { // aapt failed. Whatever files that needed to be marked // have already been marked. We just return. return referencedProjects; } // now do the same thing for all the configured resource packages. if (configs != null) { Set<Entry<String, String>> entrySet = configs.entrySet(); for (Entry<String, String> entry : entrySet) { String outPathFormat = osBinPath + File.separator + AndroidConstants.FN_RESOURCES_S_AP_; String outPath = String.format(outPathFormat, entry.getKey()); if (executeAapt(project, osManifestPath, osResPath, osAssetsPath, outPath, entry.getValue()) == false) { // aapt failed. Whatever files that needed to be marked // have already been marked. We just return. return referencedProjects; } } } // build has been done. reset the state of the builder mPackageResources = false; // and store it saveProjectBooleanProperty(PROPERTY_PACKAGE_RESOURCES, mPackageResources); } } // then we check if we need to package the .class into classes.dex if (mConvertToDex) { if (executeDx(javaProject, osBinPath, osBinPath + File.separator + AndroidConstants.FN_CLASSES_DEX, referencedJavaProjects) == false) { // dx failed, we return return referencedProjects; } // build has been done. reset the state of the builder mConvertToDex = false; // and store it saveProjectBooleanProperty(PROPERTY_CONVERT_TO_DEX, mConvertToDex); } // now we need to make the final package from the intermediary apk // and classes.dex. // This is the default package with all the resources. String classesDexPath = osBinPath + File.separator + AndroidConstants.FN_CLASSES_DEX; if (finalPackage(osBinPath + File.separator + AndroidConstants.FN_RESOURCES_AP_, classesDexPath, osFinalPackagePath, javaProject, referencedJavaProjects) == false) { return referencedProjects; } // now do the same thing for all the configured resource packages. if (configs != null) { String resPathFormat = osBinPath + File.separator + AndroidConstants.FN_RESOURCES_S_AP_; Set<Entry<String, String>> entrySet = configs.entrySet(); for (Entry<String, String> entry : entrySet) { // make the filename for the resource package. String resPath = String.format(resPathFormat, entry.getKey()); // make the filename for the apk to generate String apkOsFilePath = osBinPath + File.separator + ProjectHelper.getApkFilename(project, entry.getKey()); if (finalPackage(resPath, classesDexPath, apkOsFilePath, javaProject, referencedJavaProjects) == false) { return referencedProjects; } } } // we are done. // get the resource to bin outputFolder.refreshLocal(IResource.DEPTH_ONE, monitor); // build has been done. reset the state of the builder mBuildFinalPackage = false; // and store it saveProjectBooleanProperty(PROPERTY_BUILD_APK, mBuildFinalPackage); // reset the installation manager to force new installs of this project ApkInstallManager.getInstance().resetInstallationFor(project); AdtPlugin.printBuildToConsole(AdtConstants.BUILD_VERBOSE, getProject(), "Build Success!"); } } catch (Exception exception) { // try to catch other exception to actually display an error. This will be useful // if we get an NPE or something so that we can at least notify the user that something // went wrong. // first check if this is a CoreException we threw to cancel the build. if (exception instanceof CoreException) { if (((CoreException) exception).getStatus().getSeverity() == IStatus.CANCEL) { // Project is already marked with an error. Nothing to do return referencedProjects; } } String msg = exception.getMessage(); if (msg == null) { msg = exception.getClass().getCanonicalName(); } msg = String.format("Unknown error: %1$s", msg); AdtPlugin.printErrorToConsole(project, msg); markProject(AdtConstants.MARKER_ADT, msg, IMarker.SEVERITY_ERROR); } return referencedProjects; }
From source file:com.android.ide.eclipse.adt.internal.build.ApkBuilder.java
License:Open Source License
/** * Makes the final package. Package the dex files, the temporary resource file into the final * package file.//w ww .j av a2 s . c o m * @param intermediateApk The path to the temporary resource file. * @param dex The path to the dex file. * @param output The path to the final package file to create. * @param javaProject * @param referencedJavaProjects * @return true if success, false otherwise. */ private boolean finalPackage(String intermediateApk, String dex, String output, final IJavaProject javaProject, IJavaProject[] referencedJavaProjects) { FileOutputStream fos = null; try { IPreferenceStore store = AdtPlugin.getDefault().getPreferenceStore(); String osKeyPath = store.getString(AdtPlugin.PREFS_CUSTOM_DEBUG_KEYSTORE); if (osKeyPath == null || new File(osKeyPath).exists() == false) { osKeyPath = DebugKeyProvider.getDefaultKeyStoreOsPath(); AdtPlugin.printBuildToConsole(AdtConstants.BUILD_VERBOSE, getProject(), Messages.ApkBuilder_Using_Default_Key); } else { AdtPlugin.printBuildToConsole(AdtConstants.BUILD_VERBOSE, getProject(), String.format(Messages.ApkBuilder_Using_s_To_Sign, osKeyPath)); } // TODO: get the store type from somewhere else. DebugKeyProvider provider = new DebugKeyProvider(osKeyPath, null /* storeType */, new IKeyGenOutput() { public void err(String message) { AdtPlugin.printErrorToConsole(javaProject.getProject(), Messages.ApkBuilder_Signing_Key_Creation_s + message); } public void out(String message) { AdtPlugin.printBuildToConsole(AdtConstants.BUILD_VERBOSE, javaProject.getProject(), Messages.ApkBuilder_Signing_Key_Creation_s + message); } }); PrivateKey key = provider.getDebugKey(); X509Certificate certificate = (X509Certificate) provider.getCertificate(); if (key == null) { String msg = String.format(Messages.Final_Archive_Error_s, Messages.ApkBuilder_Unable_To_Gey_Key); AdtPlugin.printErrorToConsole(javaProject.getProject(), msg); markProject(AdtConstants.MARKER_ADT, msg, IMarker.SEVERITY_ERROR); return false; } // compare the certificate expiration date if (certificate != null && certificate.getNotAfter().compareTo(new Date()) < 0) { // TODO, regenerate a new one. String msg = String.format(Messages.Final_Archive_Error_s, String.format(Messages.ApkBuilder_Certificate_Expired_on_s, DateFormat.getInstance().format(certificate.getNotAfter()))); AdtPlugin.printErrorToConsole(javaProject.getProject(), msg); markProject(AdtConstants.MARKER_ADT, msg, IMarker.SEVERITY_ERROR); return false; } // create the jar builder. fos = new FileOutputStream(output); SignedJarBuilder builder = new SignedJarBuilder(fos, key, certificate); // add the intermediate file containing the compiled resources. AdtPlugin.printBuildToConsole(AdtConstants.BUILD_VERBOSE, getProject(), String.format(Messages.ApkBuilder_Packaging_s, intermediateApk)); FileInputStream fis = new FileInputStream(intermediateApk); try { builder.writeZip(fis, null /* filter */); } finally { fis.close(); } // Now we add the new file to the zip archive for the classes.dex file. AdtPlugin.printBuildToConsole(AdtConstants.BUILD_VERBOSE, getProject(), String.format(Messages.ApkBuilder_Packaging_s, AndroidConstants.FN_CLASSES_DEX)); File entryFile = new File(dex); builder.writeFile(entryFile, AndroidConstants.FN_CLASSES_DEX); // Now we write the standard resources from the project and the referenced projects. writeStandardResources(builder, javaProject, referencedJavaProjects); // Now we write the standard resources from the external libraries for (String libraryOsPath : getExternalJars()) { AdtPlugin.printBuildToConsole(AdtConstants.BUILD_VERBOSE, getProject(), String.format(Messages.ApkBuilder_Packaging_s, libraryOsPath)); try { fis = new FileInputStream(libraryOsPath); builder.writeZip(fis, mJavaResourcesFilter); } finally { fis.close(); } } // now write the native libraries. // First look if the lib folder is there. IResource libFolder = javaProject.getProject().findMember(SdkConstants.FD_NATIVE_LIBS); if (libFolder != null && libFolder.exists() && libFolder.getType() == IResource.FOLDER) { // look inside and put .so in lib/* by keeping the relative folder path. writeNativeLibraries(libFolder.getFullPath().segmentCount(), builder, libFolder); } // close the jar file and write the manifest and sign it. builder.close(); } catch (GeneralSecurityException e1) { // mark project and return String msg = String.format(Messages.Final_Archive_Error_s, e1.getMessage()); AdtPlugin.printErrorToConsole(javaProject.getProject(), msg); markProject(AdtConstants.MARKER_ADT, msg, IMarker.SEVERITY_ERROR); return false; } catch (IOException e1) { // mark project and return String msg = String.format(Messages.Final_Archive_Error_s, e1.getMessage()); AdtPlugin.printErrorToConsole(javaProject.getProject(), msg); markProject(AdtConstants.MARKER_ADT, msg, IMarker.SEVERITY_ERROR); return false; } catch (KeytoolException e) { String eMessage = e.getMessage(); // mark the project with the standard message String msg = String.format(Messages.Final_Archive_Error_s, eMessage); markProject(AdtConstants.MARKER_ADT, msg, IMarker.SEVERITY_ERROR); // output more info in the console AdtPlugin.printErrorToConsole(javaProject.getProject(), msg, String.format(Messages.ApkBuilder_JAVA_HOME_is_s, e.getJavaHome()), Messages.ApkBuilder_Update_or_Execute_manually_s, e.getCommandLine()); } catch (AndroidLocationException e) { String eMessage = e.getMessage(); // mark the project with the standard message String msg = String.format(Messages.Final_Archive_Error_s, eMessage); markProject(AdtConstants.MARKER_ADT, msg, IMarker.SEVERITY_ERROR); // and also output it in the console AdtPlugin.printErrorToConsole(javaProject.getProject(), msg); } catch (CoreException e) { // mark project and return String msg = String.format(Messages.Final_Archive_Error_s, e.getMessage()); AdtPlugin.printErrorToConsole(javaProject.getProject(), msg); markProject(AdtConstants.MARKER_ADT, msg, IMarker.SEVERITY_ERROR); return false; } catch (Exception e) { // try to catch other exception to actually display an error. This will be useful // if we get an NPE or something so that we can at least notify the user that something // went wrong (otherwise the build appears to succeed but the zip archive is not closed // and therefore invalid. String msg = e.getMessage(); if (msg == null) { msg = e.getClass().getCanonicalName(); } msg = String.format("Unknown error: %1$s", msg); AdtPlugin.printErrorToConsole(javaProject.getProject(), msg); markProject(AdtConstants.MARKER_ADT, msg, IMarker.SEVERITY_ERROR); return false; } finally { if (fos != null) { try { fos.close(); } catch (IOException e) { // pass. } } } return true; }
From source file:com.android.ide.eclipse.adt.internal.build.ApkBuilder.java
License:Open Source License
/** * Writes the standard resources of a project and its referenced projects * into a {@link SignedJarBuilder}.//from w w w.ja v a 2s . c om * Standard resources are non java/aidl files placed in the java package folders. * @param jarBuilder the {@link SignedJarBuilder}. * @param javaProject the javaProject object. * @param referencedJavaProjects the java projects that this project references. * @throws IOException * @throws CoreException */ private void writeStandardResources(SignedJarBuilder jarBuilder, IJavaProject javaProject, IJavaProject[] referencedJavaProjects) throws IOException, CoreException { IWorkspace ws = ResourcesPlugin.getWorkspace(); IWorkspaceRoot wsRoot = ws.getRoot(); // create a list of path already put into the archive, in order to detect conflict ArrayList<String> list = new ArrayList<String>(); writeStandardProjectResources(jarBuilder, javaProject, wsRoot, list); for (IJavaProject referencedJavaProject : referencedJavaProjects) { // only include output from non android referenced project // (This is to handle the case of reference Android projects in the context of // instrumentation projects that need to reference the projects to be tested). if (referencedJavaProject.getProject().hasNature(AndroidConstants.NATURE) == false) { writeStandardProjectResources(jarBuilder, referencedJavaProject, wsRoot, list); } } }
From source file:com.android.ide.eclipse.adt.internal.build.ApkBuilder.java
License:Open Source License
/** * Returns the list of the output folders for the specified {@link IJavaProject} objects, if * they are Android projects.// w ww. j ava 2 s . c om * * @param referencedJavaProjects the java projects. * @return an array, always. Can be empty. * @throws CoreException */ private String[] getProjectOutputs(IJavaProject[] referencedJavaProjects) throws CoreException { ArrayList<String> list = new ArrayList<String>(); IWorkspace ws = ResourcesPlugin.getWorkspace(); IWorkspaceRoot wsRoot = ws.getRoot(); for (IJavaProject javaProject : referencedJavaProjects) { // only include output from non android referenced project // (This is to handle the case of reference Android projects in the context of // instrumentation projects that need to reference the projects to be tested). if (javaProject.getProject().hasNature(AndroidConstants.NATURE) == false) { // get the output folder IPath path = null; try { path = javaProject.getOutputLocation(); } catch (JavaModelException e) { continue; } IResource outputResource = wsRoot.findMember(path); if (outputResource != null && outputResource.getType() == IResource.FOLDER) { String outputOsPath = outputResource.getLocation().toOSString(); list.add(outputOsPath); } } } return list.toArray(new String[list.size()]); }
From source file:com.android.ide.eclipse.adt.internal.build.builders.BaseBuilder.java
License:Open Source License
/** * Aborts the build if the SDK/project setups are broken. This does not * display any errors.// ww w .j av a2s . c om * * @param javaProject The {@link IJavaProject} being compiled. * @param projectState the project state, optional. will be queried if null. * @throws CoreException */ protected void abortOnBadSetup(@NonNull IJavaProject javaProject, @Nullable ProjectState projectState) throws AbortBuildException, CoreException { IProject iProject = javaProject.getProject(); // check if we have finished loading the project target. Sdk sdk = Sdk.getCurrent(); if (sdk == null) { throw new AbortBuildException(); } if (projectState == null) { projectState = Sdk.getProjectState(javaProject.getProject()); } // get the target for the project IAndroidTarget target = projectState.getTarget(); if (target == null) { throw new AbortBuildException(); } // check on the target data. if (sdk.checkAndLoadTargetData(target, javaProject) != LoadStatus.LOADED) { throw new AbortBuildException(); } mBuildToolInfo = projectState.getBuildToolInfo(); if (mBuildToolInfo == null) { mBuildToolInfo = sdk.getLatestBuildTool(); if (mBuildToolInfo == null) { AdtPlugin.printBuildToConsole(BuildVerbosity.VERBOSE, iProject, "No \"Build Tools\" package available; use SDK Manager to install one."); throw new AbortBuildException(); } else { AdtPlugin.printBuildToConsole(BuildVerbosity.VERBOSE, iProject, String.format("Using default Build Tools revision %s", mBuildToolInfo.getRevision())); } } // abort if there are TARGET or ADT type markers stopOnMarker(iProject, AdtConstants.MARKER_TARGET, IResource.DEPTH_ZERO, false /*checkSeverity*/); stopOnMarker(iProject, AdtConstants.MARKER_ADT, IResource.DEPTH_ZERO, false /*checkSeverity*/); }
From source file:com.android.ide.eclipse.adt.internal.build.builders.PostCompilerBuilder.java
License:Open Source License
@Override protected IProject[] build(int kind, @SuppressWarnings("rawtypes") Map args, IProgressMonitor monitor) throws CoreException { // get a project object IProject project = getProject();//from ww w . jav a 2 s. c om if (DEBUG_LOG) { AdtPlugin.log(IStatus.INFO, "%s BUILD(POST)", project.getName()); } // Benchmarking start long startBuildTime = 0; if (BuildHelper.BENCHMARK_FLAG) { // End JavaC Timer String msg = "BENCHMARK ADT: Ending Compilation \n BENCHMARK ADT: Time Elapsed: " + //$NON-NLS-1$ (System.nanoTime() - BuildHelper.sStartJavaCTime) / Math.pow(10, 6) + "ms"; //$NON-NLS-1$ AdtPlugin.printBuildToConsole(BuildVerbosity.ALWAYS, project, msg); msg = "BENCHMARK ADT: Starting PostCompilation"; //$NON-NLS-1$ AdtPlugin.printBuildToConsole(BuildVerbosity.ALWAYS, project, msg); startBuildTime = System.nanoTime(); } // list of referenced projects. This is a mix of java projects and library projects // and is computed below. IProject[] allRefProjects = null; try { // get the project info ProjectState projectState = Sdk.getProjectState(project); // this can happen if the project has no project.properties. if (projectState == null) { return null; } boolean isLibrary = projectState.isLibrary(); // get the libraries List<IProject> libProjects = projectState.getFullLibraryProjects(); IJavaProject javaProject = JavaCore.create(project); // get the list of referenced projects. List<IProject> javaProjects = ProjectHelper.getReferencedProjects(project); List<IJavaProject> referencedJavaProjects = BuildHelper.getJavaProjects(javaProjects); // mix the java project and the library projects final int size = libProjects.size() + javaProjects.size(); ArrayList<IProject> refList = new ArrayList<IProject>(size); refList.addAll(libProjects); refList.addAll(javaProjects); allRefProjects = refList.toArray(new IProject[size]); // get the android output folder IFolder androidOutputFolder = BaseProjectHelper.getAndroidOutputFolder(project); IFolder resOutputFolder = androidOutputFolder.getFolder(SdkConstants.FD_RES); // First thing we do is go through the resource delta to not // lose it if we have to abort the build for any reason. if (args.containsKey(POST_C_REQUESTED) && AdtPrefs.getPrefs().getBuildSkipPostCompileOnFileSave()) { // Skip over flag setting } else if (kind == FULL_BUILD) { AdtPlugin.printBuildToConsole(BuildVerbosity.VERBOSE, project, Messages.Start_Full_Apk_Build); if (DEBUG_LOG) { AdtPlugin.log(IStatus.INFO, "%s full build!", project.getName()); } // Full build: we do all the steps. mPackageResources = true; mConvertToDex = true; mBuildFinalPackage = true; } else { AdtPlugin.printBuildToConsole(BuildVerbosity.VERBOSE, project, Messages.Start_Inc_Apk_Build); // go through the resources and see if something changed. IResourceDelta delta = getDelta(project); if (delta == null) { // no delta? Same as full build: we do all the steps. mPackageResources = true; mConvertToDex = true; mBuildFinalPackage = true; } else { if (ResourceManager.isAutoBuilding() && AdtPrefs.getPrefs().isLintOnSave()) { // Check for errors on save/build, if enabled LintDeltaProcessor.create().process(delta); } PatternBasedDeltaVisitor dv = new PatternBasedDeltaVisitor(project, project, "POST:Main"); ChangedFileSet manifestCfs = ChangedFileSetHelper.getMergedManifestCfs(project); dv.addSet(manifestCfs); ChangedFileSet resCfs = ChangedFileSetHelper.getResCfs(project); dv.addSet(resCfs); ChangedFileSet androidCodeCfs = ChangedFileSetHelper.getCodeCfs(project); dv.addSet(androidCodeCfs); ChangedFileSet javaResCfs = ChangedFileSetHelper.getJavaResCfs(project); dv.addSet(javaResCfs); dv.addSet(ChangedFileSetHelper.NATIVE_LIBS); delta.accept(dv); // save the state mPackageResources |= dv.checkSet(manifestCfs) || dv.checkSet(resCfs); mConvertToDex |= dv.checkSet(androidCodeCfs); mBuildFinalPackage |= dv.checkSet(javaResCfs) || dv.checkSet(ChangedFileSetHelper.NATIVE_LIBS); } // check the libraries if (libProjects.size() > 0) { for (IProject libProject : libProjects) { delta = getDelta(libProject); if (delta != null) { PatternBasedDeltaVisitor visitor = new PatternBasedDeltaVisitor(project, libProject, "POST:Lib"); ChangedFileSet libResCfs = ChangedFileSetHelper.getFullResCfs(libProject); visitor.addSet(libResCfs); visitor.addSet(ChangedFileSetHelper.NATIVE_LIBS); // FIXME: add check on the library.jar? delta.accept(visitor); mPackageResources |= visitor.checkSet(libResCfs); mBuildFinalPackage |= visitor.checkSet(ChangedFileSetHelper.NATIVE_LIBS); } } } // also go through the delta for all the referenced projects final int referencedCount = referencedJavaProjects.size(); for (int i = 0; i < referencedCount; i++) { IJavaProject referencedJavaProject = referencedJavaProjects.get(i); delta = getDelta(referencedJavaProject.getProject()); if (delta != null) { IProject referencedProject = referencedJavaProject.getProject(); PatternBasedDeltaVisitor visitor = new PatternBasedDeltaVisitor(project, referencedProject, "POST:RefedProject"); ChangedFileSet javaResCfs = ChangedFileSetHelper.getJavaResCfs(referencedProject); visitor.addSet(javaResCfs); ChangedFileSet bytecodeCfs = ChangedFileSetHelper.getByteCodeCfs(referencedProject); visitor.addSet(bytecodeCfs); delta.accept(visitor); // save the state mConvertToDex |= visitor.checkSet(bytecodeCfs); mBuildFinalPackage |= visitor.checkSet(javaResCfs); } } } // store the build status in the persistent storage saveProjectBooleanProperty(PROPERTY_CONVERT_TO_DEX, mConvertToDex); saveProjectBooleanProperty(PROPERTY_PACKAGE_RESOURCES, mPackageResources); saveProjectBooleanProperty(PROPERTY_BUILD_APK, mBuildFinalPackage); // Top level check to make sure the build can move forward. Only do this after recording // delta changes. abortOnBadSetup(javaProject, projectState); // Get the output stream. Since the builder is created for the life of the // project, they can be kept around. if (mOutStream == null) { mOutStream = new AndroidPrintStream(project, null /*prefix*/, AdtPlugin.getOutStream()); mErrStream = new AndroidPrintStream(project, null /*prefix*/, AdtPlugin.getOutStream()); } // remove older packaging markers. removeMarkersFromContainer(javaProject.getProject(), AdtConstants.MARKER_PACKAGING); // finished with the common init and tests. Special case of the library. if (isLibrary) { // check the jar output file is present, if not create it. IFile jarIFile = androidOutputFolder .getFile(project.getName().toLowerCase() + SdkConstants.DOT_JAR); if (mConvertToDex == false && jarIFile.exists() == false) { mConvertToDex = true; } // also update the crunch cache always since aapt does it smartly only // on the files that need it. if (DEBUG_LOG) { AdtPlugin.log(IStatus.INFO, "%s running crunch!", project.getName()); } BuildHelper helper = new BuildHelper(projectState, mBuildToolInfo, mOutStream, mErrStream, false /*jumbo mode doesn't matter here*/, false /*dex merger doesn't matter here*/, true /*debugMode*/, AdtPrefs.getPrefs().getBuildVerbosity() == BuildVerbosity.VERBOSE, mResourceMarker); updateCrunchCache(project, helper); // refresh recursively bin/res folder resOutputFolder.refreshLocal(IResource.DEPTH_INFINITE, monitor); if (mConvertToDex) { // in this case this means some class files changed and // we need to update the jar file. if (DEBUG_LOG) { AdtPlugin.log(IStatus.INFO, "%s updating jar!", project.getName()); } // resource to the AndroidManifest.xml file IFile manifestFile = project.getFile(SdkConstants.FN_ANDROID_MANIFEST_XML); String appPackage = AndroidManifest.getPackage(new IFileWrapper(manifestFile)); IFolder javaOutputFolder = BaseProjectHelper.getJavaOutputFolder(project); writeLibraryPackage(jarIFile, project, appPackage, javaOutputFolder); saveProjectBooleanProperty(PROPERTY_CONVERT_TO_DEX, mConvertToDex = false); // refresh the bin folder content with no recursion to update the library // jar file. androidOutputFolder.refreshLocal(IResource.DEPTH_ONE, monitor); // Also update the projects. The only way to force recompile them is to // reset the library container. List<ProjectState> parentProjects = projectState.getParentProjects(); LibraryClasspathContainerInitializer.updateProject(parentProjects); } return allRefProjects; } // Check to see if we're going to launch or export. If not, we can skip // the packaging and dexing process. if (!args.containsKey(POST_C_REQUESTED) && AdtPrefs.getPrefs().getBuildSkipPostCompileOnFileSave()) { AdtPlugin.printBuildToConsole(BuildVerbosity.VERBOSE, project, Messages.Skip_Post_Compiler); return allRefProjects; } else { AdtPlugin.printBuildToConsole(BuildVerbosity.VERBOSE, project, Messages.Start_Full_Post_Compiler); } // first thing we do is check that the SDK directory has been setup. String osSdkFolder = AdtPlugin.getOsSdkFolder(); if (osSdkFolder.length() == 0) { // this has already been checked in the precompiler. Therefore, // while we do have to cancel the build, we don't have to return // any error or throw anything. return allRefProjects; } // do some extra check, in case the output files are not present. This // will force to recreate them. IResource tmp = null; if (mPackageResources == false) { // check the full resource package tmp = androidOutputFolder.findMember(AdtConstants.FN_RESOURCES_AP_); if (tmp == null || tmp.exists() == false) { mPackageResources = true; } } // check classes.dex is present. If not we force to recreate it. if (mConvertToDex == false) { tmp = androidOutputFolder.findMember(SdkConstants.FN_APK_CLASSES_DEX); if (tmp == null || tmp.exists() == false) { mConvertToDex = true; } } // also check the final file(s)! String finalPackageName = ProjectHelper.getApkFilename(project, null /*config*/); if (mBuildFinalPackage == false) { tmp = androidOutputFolder.findMember(finalPackageName); if (tmp == null || (tmp instanceof IFile && tmp.exists() == false)) { String msg = String.format(Messages.s_Missing_Repackaging, finalPackageName); AdtPlugin.printBuildToConsole(BuildVerbosity.VERBOSE, project, msg); mBuildFinalPackage = true; } } // at this point we know if we need to recreate the temporary apk // or the dex file, but we don't know if we simply need to recreate them // because they are missing // refresh the output directory first IContainer ic = androidOutputFolder.getParent(); if (ic != null) { ic.refreshLocal(IResource.DEPTH_ONE, monitor); } // we need to test all three, as we may need to make the final package // but not the intermediary ones. if (mPackageResources || mConvertToDex || mBuildFinalPackage) { String forceJumboStr = projectState.getProperty(AdtConstants.DEX_OPTIONS_FORCEJUMBO); Boolean jumbo = Boolean.valueOf(forceJumboStr); String dexMergerStr = projectState.getProperty(AdtConstants.DEX_OPTIONS_DISABLE_MERGER); Boolean dexMerger = Boolean.valueOf(dexMergerStr); BuildHelper helper = new BuildHelper(projectState, mBuildToolInfo, mOutStream, mErrStream, jumbo.booleanValue(), dexMerger.booleanValue(), true /*debugMode*/, AdtPrefs.getPrefs().getBuildVerbosity() == BuildVerbosity.VERBOSE, mResourceMarker); IPath androidBinLocation = androidOutputFolder.getLocation(); if (androidBinLocation == null) { markProject(AdtConstants.MARKER_PACKAGING, Messages.Output_Missing, IMarker.SEVERITY_ERROR); return allRefProjects; } String osAndroidBinPath = androidBinLocation.toOSString(); // resource to the AndroidManifest.xml file IFile manifestFile = androidOutputFolder.getFile(SdkConstants.FN_ANDROID_MANIFEST_XML); if (manifestFile == null || manifestFile.exists() == false) { // mark project and exit String msg = String.format(Messages.s_File_Missing, SdkConstants.FN_ANDROID_MANIFEST_XML); markProject(AdtConstants.MARKER_PACKAGING, msg, IMarker.SEVERITY_ERROR); return allRefProjects; } // Remove the old .apk. // This make sure that if the apk is corrupted, then dx (which would attempt // to open it), will not fail. String osFinalPackagePath = osAndroidBinPath + File.separator + finalPackageName; File finalPackage = new File(osFinalPackagePath); // if delete failed, this is not really a problem, as the final package generation // handle already present .apk, and if that one failed as well, the user will be // notified. finalPackage.delete(); // Check if we need to package the resources. if (mPackageResources) { // also update the crunch cache always since aapt does it smartly only // on the files that need it. if (DEBUG_LOG) { AdtPlugin.log(IStatus.INFO, "%s running crunch!", project.getName()); } if (updateCrunchCache(project, helper) == false) { return allRefProjects; } // refresh recursively bin/res folder resOutputFolder.refreshLocal(IResource.DEPTH_INFINITE, monitor); if (DEBUG_LOG) { AdtPlugin.log(IStatus.INFO, "%s packaging resources!", project.getName()); } // remove some aapt_package only markers. removeMarkersFromContainer(project, AdtConstants.MARKER_AAPT_PACKAGE); try { helper.packageResources(manifestFile, libProjects, null /*resfilter*/, 0 /*versionCode */, osAndroidBinPath, AdtConstants.FN_RESOURCES_AP_); } catch (AaptExecException e) { BaseProjectHelper.markResource(project, AdtConstants.MARKER_PACKAGING, e.getMessage(), IMarker.SEVERITY_ERROR); return allRefProjects; } catch (AaptResultException e) { // attempt to parse the error output String[] aaptOutput = e.getOutput(); boolean parsingError = AaptParser.parseOutput(aaptOutput, project); // if we couldn't parse the output we display it in the console. if (parsingError) { AdtPlugin.printErrorToConsole(project, (Object[]) aaptOutput); // if the exec failed, and we couldn't parse the error output (and // therefore not all files that should have been marked, were marked), // we put a generic marker on the project and abort. BaseProjectHelper.markResource(project, AdtConstants.MARKER_PACKAGING, Messages.Unparsed_AAPT_Errors, IMarker.SEVERITY_ERROR); } } // build has been done. reset the state of the builder mPackageResources = false; // and store it saveProjectBooleanProperty(PROPERTY_PACKAGE_RESOURCES, mPackageResources); } String classesDexPath = osAndroidBinPath + File.separator + SdkConstants.FN_APK_CLASSES_DEX; // then we check if we need to package the .class into classes.dex if (mConvertToDex) { if (DEBUG_LOG) { AdtPlugin.log(IStatus.INFO, "%s running dex!", project.getName()); } try { Collection<String> dxInputPaths = helper.getCompiledCodePaths(); helper.executeDx(javaProject, dxInputPaths, classesDexPath); } catch (DexException e) { String message = e.getMessage(); AdtPlugin.printErrorToConsole(project, message); BaseProjectHelper.markResource(project, AdtConstants.MARKER_PACKAGING, message, IMarker.SEVERITY_ERROR); Throwable cause = e.getCause(); if (cause instanceof NoClassDefFoundError || cause instanceof NoSuchMethodError) { AdtPlugin.printErrorToConsole(project, Messages.Incompatible_VM_Warning, Messages.Requires_1_5_Error); } // dx failed, we return return allRefProjects; } // build has been done. reset the state of the builder mConvertToDex = false; // and store it saveProjectBooleanProperty(PROPERTY_CONVERT_TO_DEX, mConvertToDex); } // now we need to make the final package from the intermediary apk // and classes.dex. // This is the default package with all the resources. try { if (DEBUG_LOG) { AdtPlugin.log(IStatus.INFO, "%s making final package!", project.getName()); } helper.finalDebugPackage(osAndroidBinPath + File.separator + AdtConstants.FN_RESOURCES_AP_, classesDexPath, osFinalPackagePath, libProjects, mResourceMarker); } catch (KeytoolException e) { String eMessage = e.getMessage(); // mark the project with the standard message String msg = String.format(Messages.Final_Archive_Error_s, eMessage); BaseProjectHelper.markResource(project, AdtConstants.MARKER_PACKAGING, msg, IMarker.SEVERITY_ERROR); // output more info in the console AdtPlugin.printErrorToConsole(project, msg, String.format(Messages.ApkBuilder_JAVA_HOME_is_s, e.getJavaHome()), Messages.ApkBuilder_Update_or_Execute_manually_s, e.getCommandLine()); AdtPlugin.log(e, msg); return allRefProjects; } catch (ApkCreationException e) { String eMessage = e.getMessage(); // mark the project with the standard message String msg = String.format(Messages.Final_Archive_Error_s, eMessage); BaseProjectHelper.markResource(project, AdtConstants.MARKER_PACKAGING, msg, IMarker.SEVERITY_ERROR); AdtPlugin.log(e, msg); } catch (AndroidLocationException e) { String eMessage = e.getMessage(); // mark the project with the standard message String msg = String.format(Messages.Final_Archive_Error_s, eMessage); BaseProjectHelper.markResource(project, AdtConstants.MARKER_PACKAGING, msg, IMarker.SEVERITY_ERROR); AdtPlugin.log(e, msg); } catch (NativeLibInJarException e) { String msg = e.getMessage(); BaseProjectHelper.markResource(project, AdtConstants.MARKER_PACKAGING, msg, IMarker.SEVERITY_ERROR); AdtPlugin.printErrorToConsole(project, (Object[]) e.getAdditionalInfo()); } catch (CoreException e) { // mark project and return String msg = String.format(Messages.Final_Archive_Error_s, e.getMessage()); AdtPlugin.printErrorToConsole(project, msg); BaseProjectHelper.markResource(project, AdtConstants.MARKER_PACKAGING, msg, IMarker.SEVERITY_ERROR); AdtPlugin.log(e, msg); } catch (DuplicateFileException e) { String msg1 = String.format( "Found duplicate file for APK: %1$s\nOrigin 1: %2$s\nOrigin 2: %3$s", e.getArchivePath(), e.getFile1(), e.getFile2()); String msg2 = String.format(Messages.Final_Archive_Error_s, msg1); AdtPlugin.printErrorToConsole(project, msg2); BaseProjectHelper.markResource(project, AdtConstants.MARKER_PACKAGING, msg2, IMarker.SEVERITY_ERROR); } // we are done. // refresh the bin folder content with no recursion. androidOutputFolder.refreshLocal(IResource.DEPTH_ONE, monitor); // build has been done. reset the state of the builder mBuildFinalPackage = false; // and store it saveProjectBooleanProperty(PROPERTY_BUILD_APK, mBuildFinalPackage); // reset the installation manager to force new installs of this project ApkInstallManager.getInstance().resetInstallationFor(project); AdtPlugin.printBuildToConsole(BuildVerbosity.VERBOSE, getProject(), "Build Success!"); } } catch (AbortBuildException e) { return allRefProjects; } catch (Exception exception) { // try to catch other exception to actually display an error. This will be useful // if we get an NPE or something so that we can at least notify the user that something // went wrong. // first check if this is a CoreException we threw to cancel the build. if (exception instanceof CoreException) { if (((CoreException) exception).getStatus().getSeverity() == IStatus.CANCEL) { // Project is already marked with an error. Nothing to do return allRefProjects; } } String msg = exception.getMessage(); if (msg == null) { msg = exception.getClass().getCanonicalName(); } msg = String.format("Unknown error: %1$s", msg); AdtPlugin.logAndPrintError(exception, project.getName(), msg); markProject(AdtConstants.MARKER_PACKAGING, msg, IMarker.SEVERITY_ERROR); } // Benchmarking end if (BuildHelper.BENCHMARK_FLAG) { String msg = "BENCHMARK ADT: Ending PostCompilation. \n BENCHMARK ADT: Time Elapsed: " + //$NON-NLS-1$ ((System.nanoTime() - startBuildTime) / Math.pow(10, 6)) + "ms"; //$NON-NLS-1$ AdtPlugin.printBuildToConsole(BuildVerbosity.ALWAYS, project, msg); // End Overall Timer msg = "BENCHMARK ADT: Done with everything! \n BENCHMARK ADT: Time Elapsed: " + //$NON-NLS-1$ (System.nanoTime() - BuildHelper.sStartOverallTime) / Math.pow(10, 6) + "ms"; //$NON-NLS-1$ AdtPlugin.printBuildToConsole(BuildVerbosity.ALWAYS, project, msg); } return allRefProjects; }
From source file:com.android.ide.eclipse.adt.internal.build.BuildHelper.java
License:Open Source License
/** * Execute the Dx tool for dalvik code conversion. * @param javaProject The java project/*from www . ja v a2 s . c o m*/ * @param inputPaths the input paths for DX * @param osOutFilePath the path of the dex file to create. * * @throws CoreException * @throws DexException */ public void executeDx(IJavaProject javaProject, Collection<String> inputPaths, String osOutFilePath) throws CoreException, DexException { // get the dex wrapper Sdk sdk = Sdk.getCurrent(); DexWrapper wrapper = sdk.getDexWrapper(mBuildToolInfo); if (wrapper == null) { throw new CoreException( new Status(IStatus.ERROR, AdtPlugin.PLUGIN_ID, Messages.ApkBuilder_UnableBuild_Dex_Not_loaded)); } try { // set a temporary prefix on the print streams. mOutStream.setPrefix(CONSOLE_PREFIX_DX); mErrStream.setPrefix(CONSOLE_PREFIX_DX); IFolder binFolder = BaseProjectHelper.getAndroidOutputFolder(javaProject.getProject()); File binFile = binFolder.getLocation().toFile(); File dexedLibs = new File(binFile, "dexedLibs"); if (dexedLibs.exists() == false) { dexedLibs.mkdir(); } // replace the libs by their dexed versions (dexing them if needed.) List<String> finalInputPaths = new ArrayList<String>(inputPaths.size()); if (mDisableDexMerger || inputPaths.size() == 1) { // only one input, no need to put a pre-dexed version, even if this path is // just a jar file (case for proguard'ed builds) finalInputPaths.addAll(inputPaths); } else { for (String input : inputPaths) { File inputFile = new File(input); if (inputFile.isDirectory()) { finalInputPaths.add(input); } else if (inputFile.isFile()) { String fileName = getDexFileName(inputFile); File dexedLib = new File(dexedLibs, fileName); String dexedLibPath = dexedLib.getAbsolutePath(); if (dexedLib.isFile() == false || dexedLib.lastModified() < inputFile.lastModified()) { if (mVerbose) { mOutStream.println(String.format("Pre-Dexing %1$s -> %2$s", input, fileName)); } if (dexedLib.isFile()) { dexedLib.delete(); } int res = wrapper.run(dexedLibPath, Collections.singleton(input), mForceJumbo, mVerbose, mOutStream, mErrStream); if (res != 0) { // output error message and mark the project. String message = String.format(Messages.Dalvik_Error_d, res); throw new DexException(message); } } else { if (mVerbose) { mOutStream.println(String.format("Using Pre-Dexed %1$s <- %2$s", fileName, input)); } } finalInputPaths.add(dexedLibPath); } } } if (mVerbose) { for (String input : finalInputPaths) { mOutStream.println("Input: " + input); } } int res = wrapper.run(osOutFilePath, finalInputPaths, mForceJumbo, mVerbose, mOutStream, mErrStream); mOutStream.setPrefix(null); mErrStream.setPrefix(null); if (res != 0) { // output error message and marker the project. String message = String.format(Messages.Dalvik_Error_d, res); throw new DexException(message); } } catch (DexException e) { throw e; } catch (Throwable t) { String message = t.getMessage(); if (message == null) { message = t.getClass().getCanonicalName(); } message = String.format(Messages.Dalvik_Error_s, message); throw new DexException(message, t); } }
From source file:com.android.ide.eclipse.adt.internal.build.PostCompilerBuilder.java
License:Open Source License
@SuppressWarnings({ "unchecked" }) @Override//w w w . java2 s . c om protected IProject[] build(int kind, Map args, IProgressMonitor monitor) throws CoreException { // get a project object IProject project = getProject(); // list of referenced projects. IProject[] libProjects = null; IProject[] javaProjects = null; IProject[] allRefProjects = null; try { // get the project info ProjectState projectState = Sdk.getProjectState(project); if (projectState == null || projectState.isLibrary()) { // library project do not need to be dexified or packaged. return null; } // get the libraries libProjects = projectState.getFullLibraryProjects(); IJavaProject javaProject = JavaCore.create(project); // Top level check to make sure the build can move forward. abortOnBadSetup(javaProject); // get the list of referenced projects. javaProjects = ProjectHelper.getReferencedProjects(project); IJavaProject[] referencedJavaProjects = PostCompilerHelper.getJavaProjects(javaProjects); // mix the java project and the library projects final int libCount = libProjects.length; final int javaCount = javaProjects != null ? javaProjects.length : 0; allRefProjects = new IProject[libCount + javaCount]; if (libCount > 0) { System.arraycopy(libProjects, 0, allRefProjects, 0, libCount); } if (javaCount > 0) { System.arraycopy(javaProjects, 0, allRefProjects, libCount, javaCount); } // get the output folder, this method returns the path with a trailing // separator IFolder outputFolder = BaseProjectHelper.getOutputFolder(project); // now we need to get the classpath list ArrayList<IPath> sourceList = BaseProjectHelper.getSourceClasspaths(javaProject); // First thing we do is go through the resource delta to not // lose it if we have to abort the build for any reason. PostCompilerDeltaVisitor dv = null; if (kind == FULL_BUILD) { AdtPlugin.printBuildToConsole(BuildVerbosity.VERBOSE, project, Messages.Start_Full_Apk_Build); mPackageResources = true; mConvertToDex = true; mBuildFinalPackage = true; } else { AdtPlugin.printBuildToConsole(BuildVerbosity.VERBOSE, project, Messages.Start_Inc_Apk_Build); // go through the resources and see if something changed. IResourceDelta delta = getDelta(project); if (delta == null) { mPackageResources = true; mConvertToDex = true; mBuildFinalPackage = true; } else { dv = new PostCompilerDeltaVisitor(this, sourceList, outputFolder); delta.accept(dv); // save the state mPackageResources |= dv.getPackageResources(); mConvertToDex |= dv.getConvertToDex(); mBuildFinalPackage |= dv.getMakeFinalPackage(); } // if the main resources didn't change, then we check for the library // ones (will trigger resource repackaging too) if ((mPackageResources == false || mBuildFinalPackage == false) && libProjects.length > 0) { for (IProject libProject : libProjects) { delta = getDelta(libProject); if (delta != null) { LibraryDeltaVisitor visitor = new LibraryDeltaVisitor(); delta.accept(visitor); mPackageResources |= visitor.getResChange(); mBuildFinalPackage |= visitor.getLibChange(); if (mPackageResources && mBuildFinalPackage) { break; } } } } // also go through the delta for all the referenced projects, until we are forced to // compile anyway for (int i = 0; i < referencedJavaProjects.length && (mBuildFinalPackage == false || mConvertToDex == false); i++) { IJavaProject referencedJavaProject = referencedJavaProjects[i]; delta = getDelta(referencedJavaProject.getProject()); if (delta != null) { ReferencedProjectDeltaVisitor refProjectDv = new ReferencedProjectDeltaVisitor( referencedJavaProject); delta.accept(refProjectDv); // save the state mConvertToDex |= refProjectDv.needDexConvertion(); mBuildFinalPackage |= refProjectDv.needMakeFinalPackage(); } } } // store the build status in the persistent storage saveProjectBooleanProperty(PROPERTY_CONVERT_TO_DEX, mConvertToDex); saveProjectBooleanProperty(PROPERTY_PACKAGE_RESOURCES, mPackageResources); saveProjectBooleanProperty(PROPERTY_BUILD_APK, mBuildFinalPackage); if (dv != null && dv.mXmlError) { AdtPlugin.printBuildToConsole(BuildVerbosity.VERBOSE, project, Messages.Xml_Error); // if there was some XML errors, we just return w/o doing // anything since we've put some markers in the files anyway return allRefProjects; } // remove older packaging markers. removeMarkersFromProject(javaProject.getProject(), AndroidConstants.MARKER_PACKAGING); if (outputFolder == null) { // mark project and exit markProject(AndroidConstants.MARKER_PACKAGING, Messages.Failed_To_Get_Output, IMarker.SEVERITY_ERROR); return allRefProjects; } // first thing we do is check that the SDK directory has been setup. String osSdkFolder = AdtPlugin.getOsSdkFolder(); if (osSdkFolder.length() == 0) { // this has already been checked in the precompiler. Therefore, // while we do have to cancel the build, we don't have to return // any error or throw anything. return allRefProjects; } // do some extra check, in case the output files are not present. This // will force to recreate them. IResource tmp = null; if (mPackageResources == false) { // check the full resource package tmp = outputFolder.findMember(AndroidConstants.FN_RESOURCES_AP_); if (tmp == null || tmp.exists() == false) { mPackageResources = true; mBuildFinalPackage = true; } } // check classes.dex is present. If not we force to recreate it. if (mConvertToDex == false) { tmp = outputFolder.findMember(SdkConstants.FN_APK_CLASSES_DEX); if (tmp == null || tmp.exists() == false) { mConvertToDex = true; mBuildFinalPackage = true; } } // also check the final file(s)! String finalPackageName = ProjectHelper.getApkFilename(project, null /*config*/); if (mBuildFinalPackage == false) { tmp = outputFolder.findMember(finalPackageName); if (tmp == null || (tmp instanceof IFile && tmp.exists() == false)) { String msg = String.format(Messages.s_Missing_Repackaging, finalPackageName); AdtPlugin.printBuildToConsole(BuildVerbosity.VERBOSE, project, msg); mBuildFinalPackage = true; } } // at this point we know if we need to recreate the temporary apk // or the dex file, but we don't know if we simply need to recreate them // because they are missing // refresh the output directory first IContainer ic = outputFolder.getParent(); if (ic != null) { ic.refreshLocal(IResource.DEPTH_ONE, monitor); } // Get the DX output stream. Since the builder is created for the life of the // project, they can be kept around. if (mDxOutStream == null) { mDxOutStream = AdtPlugin.getOutPrintStream(project, CONSOLE_PREFIX_DX); mDxErrStream = AdtPlugin.getErrPrintStream(project, CONSOLE_PREFIX_DX); } // we need to test all three, as we may need to make the final package // but not the intermediary ones. if (mPackageResources || mConvertToDex || mBuildFinalPackage) { PostCompilerHelper helper = new PostCompilerHelper(project, mDxOutStream, mDxErrStream); // resource to the AndroidManifest.xml file IFile manifestFile = project.getFile(SdkConstants.FN_ANDROID_MANIFEST_XML); if (manifestFile == null || manifestFile.exists() == false) { // mark project and exit String msg = String.format(Messages.s_File_Missing, SdkConstants.FN_ANDROID_MANIFEST_XML); markProject(AndroidConstants.MARKER_PACKAGING, msg, IMarker.SEVERITY_ERROR); return allRefProjects; } IPath binLocation = outputFolder.getLocation(); if (binLocation == null) { markProject(AndroidConstants.MARKER_PACKAGING, Messages.Output_Missing, IMarker.SEVERITY_ERROR); return allRefProjects; } String osBinPath = binLocation.toOSString(); // Remove the old .apk. // This make sure that if the apk is corrupted, then dx (which would attempt // to open it), will not fail. String osFinalPackagePath = osBinPath + File.separator + finalPackageName; File finalPackage = new File(osFinalPackagePath); // if delete failed, this is not really a problem, as the final package generation // handle already present .apk, and if that one failed as well, the user will be // notified. finalPackage.delete(); // first we check if we need to package the resources. if (mPackageResources) { // remove some aapt_package only markers. removeMarkersFromContainer(project, AndroidConstants.MARKER_AAPT_PACKAGE); // need to figure out some path before we can execute aapt; if (helper.packageResources(manifestFile, libProjects, null /*resfilter*/, 0 /*versionCode */, osBinPath, AndroidConstants.FN_RESOURCES_AP_) == false) { // aapt failed. Whatever files that needed to be marked // have already been marked. We just return. return allRefProjects; } // build has been done. reset the state of the builder mPackageResources = false; // and store it saveProjectBooleanProperty(PROPERTY_PACKAGE_RESOURCES, mPackageResources); } // then we check if we need to package the .class into classes.dex if (mConvertToDex) { if (helper.executeDx(javaProject, osBinPath, osBinPath + File.separator + SdkConstants.FN_APK_CLASSES_DEX, referencedJavaProjects) == false) { // dx failed, we return return allRefProjects; } // build has been done. reset the state of the builder mConvertToDex = false; // and store it saveProjectBooleanProperty(PROPERTY_CONVERT_TO_DEX, mConvertToDex); } // figure out whether the application is debuggable. // It is considered debuggable if the attribute debuggable is set to true // in the manifest boolean debuggable = false; XPath xpath = AndroidXPathFactory.newXPath(); String result = xpath.evaluate("/" + AndroidManifest.NODE_MANIFEST + //$NON-NLS-1$ "/" + AndroidManifest.NODE_APPLICATION + //$NON-NLS-1$ "/@" + AndroidXPathFactory.DEFAULT_NS_PREFIX + //$NON-NLS-1$ ":" + AndroidManifest.ATTRIBUTE_DEBUGGABLE, //$NON-NLS-1$ new InputSource(manifestFile.getContents())); if (result.length() > 0) { debuggable = Boolean.valueOf(result); } // now we need to make the final package from the intermediary apk // and classes.dex. // This is the default package with all the resources. String classesDexPath = osBinPath + File.separator + SdkConstants.FN_APK_CLASSES_DEX; if (helper.finalPackage(osBinPath + File.separator + AndroidConstants.FN_RESOURCES_AP_, classesDexPath, osFinalPackagePath, true /*debugSign*/, javaProject, libProjects, referencedJavaProjects, null /*abiFilter*/, debuggable) == false) { return allRefProjects; } // we are done. // get the resource to bin outputFolder.refreshLocal(IResource.DEPTH_ONE, monitor); // build has been done. reset the state of the builder mBuildFinalPackage = false; // and store it saveProjectBooleanProperty(PROPERTY_BUILD_APK, mBuildFinalPackage); // reset the installation manager to force new installs of this project ApkInstallManager.getInstance().resetInstallationFor(project); AdtPlugin.printBuildToConsole(BuildVerbosity.VERBOSE, getProject(), "Build Success!"); } } catch (Exception exception) { // try to catch other exception to actually display an error. This will be useful // if we get an NPE or something so that we can at least notify the user that something // went wrong. // first check if this is a CoreException we threw to cancel the build. if (exception instanceof CoreException) { if (((CoreException) exception).getStatus().getSeverity() == IStatus.CANCEL) { // Project is already marked with an error. Nothing to do return allRefProjects; } } String msg = exception.getMessage(); if (msg == null) { msg = exception.getClass().getCanonicalName(); } msg = String.format("Unknown error: %1$s", msg); AdtPlugin.logAndPrintError(exception, project.getName(), msg); markProject(AndroidConstants.MARKER_PACKAGING, msg, IMarker.SEVERITY_ERROR); } return allRefProjects; }
From source file:com.android.ide.eclipse.adt.internal.build.PostCompilerBuilder.java
License:Open Source License
@Override protected void abortOnBadSetup(IJavaProject javaProject) throws CoreException { super.abortOnBadSetup(javaProject); // for this version, we stop on any marker (ie also markers coming from JDT). // The depth is set to ZERO to make sure we don't stop on warning on resources. // Only markers set directly on the project are considered. IMarker[] markers = javaProject.getProject().findMarkers(null /*type*/, false /*includeSubtypes*/, IResource.DEPTH_ZERO);//from w w w. j av a 2 s. co m if (markers.length > 0) { stopBuild(""); } }
From source file:com.android.ide.eclipse.adt.internal.build.PostCompilerHelper.java
License:Open Source License
/** * Makes the final package. Package the dex files, the temporary resource file into the final * package file.// w w w .j a v a2 s.c o m * @param intermediateApk The path to the temporary resource file. * @param dex The path to the dex file. * @param output The path to the final package file to create. * @param debugSign whether the apk must be signed with the debug key. * @param javaProject the java project being compiled * @param libProjects an optional list of library projects (can be null) * @param referencedJavaProjects referenced projects. * @param abiFilter an optional filter. If not null, then only the matching ABI is included in * the final archive * @param debuggable whether the project manifest has debuggable==true. If true, any gdbserver * executables will be packaged with the native libraries. * @return true if success, false otherwise. */ public boolean finalPackage(String intermediateApk, String dex, String output, boolean debugSign, final IJavaProject javaProject, IProject[] libProjects, IJavaProject[] referencedJavaProjects, String abiFilter, boolean debuggable) { IProject project = javaProject.getProject(); String keystoreOsPath = null; if (debugSign) { IPreferenceStore store = AdtPlugin.getDefault().getPreferenceStore(); keystoreOsPath = store.getString(AdtPrefs.PREFS_CUSTOM_DEBUG_KEYSTORE); if (keystoreOsPath == null || new File(keystoreOsPath).isFile() == false) { try { keystoreOsPath = DebugKeyProvider.getDefaultKeyStoreOsPath(); AdtPlugin.printBuildToConsole(BuildVerbosity.VERBOSE, mProject, Messages.ApkBuilder_Using_Default_Key); } catch (KeytoolException e) { String eMessage = e.getMessage(); // mark the project with the standard message String msg = String.format(Messages.Final_Archive_Error_s, eMessage); BaseProjectHelper.markResource(mProject, AndroidConstants.MARKER_PACKAGING, msg, IMarker.SEVERITY_ERROR); // output more info in the console AdtPlugin.printErrorToConsole(mProject, msg, String.format(Messages.ApkBuilder_JAVA_HOME_is_s, e.getJavaHome()), Messages.ApkBuilder_Update_or_Execute_manually_s, e.getCommandLine()); return false; } catch (AndroidLocationException e) { String eMessage = e.getMessage(); // mark the project with the standard message String msg = String.format(Messages.Final_Archive_Error_s, eMessage); BaseProjectHelper.markResource(mProject, AndroidConstants.MARKER_PACKAGING, msg, IMarker.SEVERITY_ERROR); return false; } } else { AdtPlugin.printBuildToConsole(BuildVerbosity.VERBOSE, mProject, String.format(Messages.ApkBuilder_Using_s_To_Sign, keystoreOsPath)); } } try { ApkBuilder apkBuilder = new ApkBuilder(output, intermediateApk, dex, keystoreOsPath, AdtPrefs.getPrefs().getBuildVerbosity() == BuildVerbosity.VERBOSE ? AdtPlugin.getOutPrintStream(project, null) : null); apkBuilder.setDebugMode(debuggable); // Now we write the standard resources from the project and the referenced projects. writeStandardResources(apkBuilder, javaProject, referencedJavaProjects); // Now we write the standard resources from the external jars for (String libraryOsPath : getExternalJars()) { JarStatus status = apkBuilder.addResourcesFromJar(new File(libraryOsPath)); // check if we found native libraries in the external library. This // constitutes an error or warning depending on if they are in lib/ if (status.getNativeLibs().size() > 0) { String libName = new File(libraryOsPath).getName(); String msg = String.format( "Native libraries detected in '%1$s'. See console for more information.", libName); BaseProjectHelper.markResource(mProject, AndroidConstants.MARKER_PACKAGING, msg, status.hasNativeLibsConflicts() || AdtPrefs.getPrefs().getBuildForceErrorOnNativeLibInJar() ? IMarker.SEVERITY_ERROR : IMarker.SEVERITY_WARNING); ArrayList<String> consoleMsgs = new ArrayList<String>(); consoleMsgs.add(String.format( "The library '%1$s' contains native libraries that will not run on the device.", libName)); if (status.hasNativeLibsConflicts()) { consoleMsgs.add( "Additionally some of those libraries will interfer with the installation of the application because of their location in lib/"); consoleMsgs.add("lib/ is reserved for NDK libraries."); } consoleMsgs.add("The following libraries were found:"); for (String lib : status.getNativeLibs()) { consoleMsgs.add(" - " + lib); } AdtPlugin.printErrorToConsole(mProject, consoleMsgs.toArray()); return false; } } // now write the native libraries. // First look if the lib folder is there. IResource libFolder = mProject.findMember(SdkConstants.FD_NATIVE_LIBS); if (libFolder != null && libFolder.exists() && libFolder.getType() == IResource.FOLDER) { // get a File for the folder. apkBuilder.addNativeLibraries(libFolder.getLocation().toFile(), abiFilter); } // write the native libraries for the library projects. if (libProjects != null) { for (IProject lib : libProjects) { libFolder = lib.findMember(SdkConstants.FD_NATIVE_LIBS); if (libFolder != null && libFolder.exists() && libFolder.getType() == IResource.FOLDER) { apkBuilder.addNativeLibraries(libFolder.getLocation().toFile(), abiFilter); } } } // seal the APK. apkBuilder.sealApk(); return true; } catch (CoreException e) { // mark project and return String msg = String.format(Messages.Final_Archive_Error_s, e.getMessage()); AdtPlugin.printErrorToConsole(mProject, msg); BaseProjectHelper.markResource(mProject, AndroidConstants.MARKER_PACKAGING, msg, IMarker.SEVERITY_ERROR); } catch (ApkCreationException e) { // mark project and return String msg = String.format(Messages.Final_Archive_Error_s, e.getMessage()); AdtPlugin.printErrorToConsole(mProject, msg); BaseProjectHelper.markResource(mProject, AndroidConstants.MARKER_PACKAGING, msg, IMarker.SEVERITY_ERROR); } catch (DuplicateFileException e) { String msg1 = String.format("Found duplicate file for APK: %1$s\nOrigin 1: %2$s\nOrigin 2: %3$s", e.getArchivePath(), e.getFile1(), e.getFile2()); String msg2 = String.format(Messages.Final_Archive_Error_s, msg1); AdtPlugin.printErrorToConsole(mProject, msg2); BaseProjectHelper.markResource(mProject, AndroidConstants.MARKER_PACKAGING, msg2, IMarker.SEVERITY_ERROR); } catch (SealedApkException e) { // this won't happen as we control when the apk is sealed. } catch (Exception e) { // try to catch other exception to actually display an error. This will be useful // if we get an NPE or something so that we can at least notify the user that something // went wrong (otherwise the build appears to succeed but the zip archive is not closed // and therefore invalid. String msg = e.getMessage(); if (msg == null) { msg = e.getClass().getCanonicalName(); } msg = String.format("Unknown error: %1$s", msg); AdtPlugin.printErrorToConsole(mProject, msg); BaseProjectHelper.markResource(mProject, AndroidConstants.MARKER_PACKAGING, msg, IMarker.SEVERITY_ERROR); } return false; }