aboutsummaryrefslogtreecommitdiff
path: root/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/builders/PreCompilerBuilder.java
diff options
context:
space:
mode:
Diffstat (limited to 'eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/builders/PreCompilerBuilder.java')
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/builders/PreCompilerBuilder.java1401
1 files changed, 0 insertions, 1401 deletions
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/builders/PreCompilerBuilder.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/builders/PreCompilerBuilder.java
deleted file mode 100644
index 0d9ee4897..000000000
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/builders/PreCompilerBuilder.java
+++ /dev/null
@@ -1,1401 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Eclipse Public License, Version 1.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.eclipse.org/org/documents/epl-v10.php
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.ide.eclipse.adt.internal.build.builders;
-
-import com.android.SdkConstants;
-import com.android.annotations.NonNull;
-import com.android.annotations.Nullable;
-import com.android.ide.common.xml.ManifestData;
-import com.android.ide.eclipse.adt.AdtConstants;
-import com.android.ide.eclipse.adt.AdtPlugin;
-import com.android.ide.eclipse.adt.internal.build.AaptParser;
-import com.android.ide.eclipse.adt.internal.build.AidlProcessor;
-import com.android.ide.eclipse.adt.internal.build.Messages;
-import com.android.ide.eclipse.adt.internal.build.RenderScriptLauncher;
-import com.android.ide.eclipse.adt.internal.build.RsSourceChangeHandler;
-import com.android.ide.eclipse.adt.internal.build.SourceProcessor;
-import com.android.ide.eclipse.adt.internal.build.builders.BaseBuilder.AbortBuildException;
-import com.android.ide.eclipse.adt.internal.lint.EclipseLintClient;
-import com.android.ide.eclipse.adt.internal.preferences.AdtPrefs;
-import com.android.ide.eclipse.adt.internal.preferences.AdtPrefs.BuildVerbosity;
-import com.android.ide.eclipse.adt.internal.project.AndroidManifestHelper;
-import com.android.ide.eclipse.adt.internal.project.BaseProjectHelper;
-import com.android.ide.eclipse.adt.internal.project.FixLaunchConfig;
-import com.android.ide.eclipse.adt.internal.project.ProjectHelper;
-import com.android.ide.eclipse.adt.internal.project.XmlErrorHandler.BasicXmlErrorListener;
-import com.android.ide.eclipse.adt.internal.resources.manager.IdeScanningContext;
-import com.android.ide.eclipse.adt.internal.resources.manager.ProjectResources;
-import com.android.ide.eclipse.adt.internal.resources.manager.ResourceManager;
-import com.android.ide.eclipse.adt.internal.sdk.AdtManifestMergeCallback;
-import com.android.ide.eclipse.adt.internal.sdk.ProjectState;
-import com.android.ide.eclipse.adt.internal.sdk.Sdk;
-import com.android.ide.eclipse.adt.io.IFileWrapper;
-import com.android.ide.eclipse.adt.io.IFolderWrapper;
-import com.android.io.StreamException;
-import com.android.manifmerger.ManifestMerger;
-import com.android.manifmerger.MergerLog;
-import com.android.sdklib.AndroidVersion;
-import com.android.sdklib.BuildToolInfo;
-import com.android.sdklib.IAndroidTarget;
-import com.android.sdklib.build.RenderScriptChecker;
-import com.android.sdklib.build.RenderScriptProcessor;
-import com.android.sdklib.internal.build.BuildConfigGenerator;
-import com.android.sdklib.internal.build.SymbolLoader;
-import com.android.sdklib.internal.build.SymbolWriter;
-import com.android.sdklib.internal.project.ProjectProperties;
-import com.android.sdklib.io.FileOp;
-import com.android.sdklib.repository.FullRevision;
-import com.android.utils.ILogger;
-import com.android.utils.Pair;
-import com.android.xml.AndroidManifest;
-import com.google.common.collect.ArrayListMultimap;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Multimap;
-
-import org.eclipse.core.resources.IFile;
-import org.eclipse.core.resources.IFolder;
-import org.eclipse.core.resources.IMarker;
-import org.eclipse.core.resources.IProject;
-import org.eclipse.core.resources.IResource;
-import org.eclipse.core.resources.IResourceDelta;
-import org.eclipse.core.resources.IWorkspaceRoot;
-import org.eclipse.core.resources.ResourcesPlugin;
-import org.eclipse.core.runtime.CoreException;
-import org.eclipse.core.runtime.IPath;
-import org.eclipse.core.runtime.IProgressMonitor;
-import org.eclipse.core.runtime.IStatus;
-import org.eclipse.core.runtime.NullProgressMonitor;
-import org.eclipse.core.runtime.Path;
-import org.eclipse.jdt.core.IJavaProject;
-import org.eclipse.jdt.core.JavaCore;
-import org.xml.sax.SAXException;
-
-import java.io.File;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-import java.util.Map;
-
-import javax.xml.parsers.ParserConfigurationException;
-
-/**
- * Pre Java Compiler.
- * This incremental builder performs 2 tasks:
- * <ul>
- * <li>compiles the resources located in the res/ folder, along with the
- * AndroidManifest.xml file into the R.java class.</li>
- * <li>compiles any .aidl files into a corresponding java file.</li>
- * </ul>
- *
- */
-public class PreCompilerBuilder extends BaseBuilder {
-
- /** This ID is used in plugin.xml and in each project's .project file.
- * It cannot be changed even if the class is renamed/moved */
- public static final String ID = "com.android.ide.eclipse.adt.PreCompilerBuilder"; //$NON-NLS-1$
-
- /** Flag to pass to PreCompiler builder that the build is a release build.
- */
- public final static String RELEASE_REQUESTED = "android.releaseBuild"; //$NON-NLS-1$
-
- private static final String PROPERTY_PACKAGE = "manifestPackage"; //$NON-NLS-1$
- private static final String PROPERTY_MERGE_MANIFEST = "mergeManifest"; //$NON-NLS-1$
- private static final String PROPERTY_COMPILE_RESOURCES = "compileResources"; //$NON-NLS-1$
- private static final String PROPERTY_COMPILE_BUILDCONFIG = "createBuildConfig"; //$NON-NLS-1$
- private static final String PROPERTY_BUILDCONFIG_MODE = "buildConfigMode"; //$NON-NLS-1$
-
- private static final boolean MANIFEST_MERGER_ENABLED_DEFAULT = false;
- private static final String MANIFEST_MERGER_PROPERTY = "manifestmerger.enabled"; //$NON-NLS-1$
-
- /** Merge Manifest Flag. Computed from resource delta, reset after action is taken.
- * Stored persistently in the project. */
- private boolean mMustMergeManifest = false;
- /** Resource compilation Flag. Computed from resource delta, reset after action is taken.
- * Stored persistently in the project. */
- private boolean mMustCompileResources = false;
- /** BuildConfig Flag. Computed from resource delta, reset after action is taken.
- * Stored persistently in the project. */
- private boolean mMustCreateBuildConfig = false;
- /** BuildConfig last more Flag. Computed from resource delta, reset after action is taken.
- * Stored persistently in the project. */
- private boolean mLastBuildConfigMode;
-
- /** cache of the java package defined in the manifest */
- private String mManifestPackage;
-
- /** Output folder for generated Java File. Created on the Builder init
- * @see #startupOnInitialize()
- */
- private IFolder mGenFolder;
-
- /**
- * Progress monitor used at the end of every build to refresh the content of the 'gen' folder
- * and set the generated files as derived.
- */
- private DerivedProgressMonitor mDerivedProgressMonitor;
-
- private AidlProcessor mAidlProcessor;
- private RsSourceChangeHandler mRenderScriptSourceChangeHandler;
-
- /**
- * Progress monitor waiting the end of the process to set a persistent value
- * in a file. This is typically used in conjunction with <code>IResource.refresh()</code>,
- * since this call is asynchronous, and we need to wait for it to finish for the file
- * to be known by eclipse, before we can call <code>resource.setPersistentProperty</code> on
- * a new file.
- */
- private static class DerivedProgressMonitor implements IProgressMonitor {
- private boolean mCancelled = false;
- private boolean mDone = false;
- private final IFolder mGenFolder;
-
- public DerivedProgressMonitor(IFolder genFolder) {
- mGenFolder = genFolder;
- }
-
- void reset() {
- mDone = false;
- }
-
- @Override
- public void beginTask(String name, int totalWork) {
- }
-
- @Override
- public void done() {
- if (mDone == false) {
- mDone = true;
- processChildrenOf(mGenFolder);
- }
- }
-
- private void processChildrenOf(IFolder folder) {
- IResource[] list;
- try {
- list = folder.members();
- } catch (CoreException e) {
- return;
- }
-
- for (IResource member : list) {
- if (member.exists()) {
- if (member.getType() == IResource.FOLDER) {
- processChildrenOf((IFolder) member);
- }
-
- try {
- member.setDerived(true, new NullProgressMonitor());
- } catch (CoreException e) {
- // This really shouldn't happen since we check that the resource
- // exist.
- // Worst case scenario, the resource isn't marked as derived.
- }
- }
- }
- }
-
- @Override
- public void internalWorked(double work) {
- }
-
- @Override
- public boolean isCanceled() {
- return mCancelled;
- }
-
- @Override
- public void setCanceled(boolean value) {
- mCancelled = value;
- }
-
- @Override
- public void setTaskName(String name) {
- }
-
- @Override
- public void subTask(String name) {
- }
-
- @Override
- public void worked(int work) {
- }
- }
-
- public PreCompilerBuilder() {
- super();
- }
-
- // build() returns a list of project from which this project depends for future compilation.
- @Override
- protected IProject[] build(
- int kind,
- @SuppressWarnings("rawtypes") Map args,
- IProgressMonitor monitor)
- throws CoreException {
- // get a project object
- IProject project = getProject();
-
- if (DEBUG_LOG) {
- AdtPlugin.log(IStatus.INFO, "%s BUILD(PRE)", project.getName());
- }
-
- // For the PreCompiler, only the library projects are considered Referenced projects,
- // as only those projects have an impact on what is generated by this builder.
- IProject[] result = null;
-
- IFolder resOutFolder = null;
-
- try {
- assert mDerivedProgressMonitor != null;
-
- mDerivedProgressMonitor.reset();
-
- // 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();
-
- IAndroidTarget projectTarget = projectState.getTarget();
-
- // get the libraries
- List<IProject> libProjects = projectState.getFullLibraryProjects();
- result = libProjects.toArray(new IProject[libProjects.size()]);
-
- IJavaProject javaProject = JavaCore.create(project);
-
- // Top level check to make sure the build can move forward.
- abortOnBadSetup(javaProject, projectState);
-
- // now we need to get the classpath list
- List<IPath> sourceFolderPathList = BaseProjectHelper.getSourceClasspaths(javaProject);
-
- IFolder androidOutputFolder = BaseProjectHelper.getAndroidOutputFolder(project);
-
- resOutFolder = getResOutFolder(androidOutputFolder);
-
- setupSourceProcessors(javaProject, projectState, sourceFolderPathList,
- androidOutputFolder);
-
- PreCompilerDeltaVisitor dv = null;
- String javaPackage = null;
- String minSdkVersion = null;
-
- if (kind == FULL_BUILD) {
- AdtPlugin.printBuildToConsole(BuildVerbosity.VERBOSE, project,
- Messages.Start_Full_Pre_Compiler);
-
- if (DEBUG_LOG) {
- AdtPlugin.log(IStatus.INFO, "%s full build!", project.getName());
- }
-
- // do some clean up.
- doClean(project, monitor);
-
- mMustMergeManifest = true;
- mMustCompileResources = true;
- mMustCreateBuildConfig = true;
-
- mAidlProcessor.prepareFullBuild(project);
- mRenderScriptSourceChangeHandler.prepareFullBuild();
- } else {
- AdtPlugin.printBuildToConsole(BuildVerbosity.VERBOSE, project,
- Messages.Start_Inc_Pre_Compiler);
-
- // Go through the resources and see if something changed.
- // Even if the mCompileResources flag is true from a previously aborted
- // build, we need to go through the Resource delta to get a possible
- // list of aidl files to compile/remove.
- IResourceDelta delta = getDelta(project);
- if (delta == null) {
- mMustCompileResources = true;
-
- mAidlProcessor.prepareFullBuild(project);
- mRenderScriptSourceChangeHandler.prepareFullBuild();
- } else {
- dv = new PreCompilerDeltaVisitor(this, sourceFolderPathList,
- mAidlProcessor.getChangeHandler(),
- mRenderScriptSourceChangeHandler);
- delta.accept(dv);
-
- // Check to see if Manifest.xml, Manifest.java, or R.java have changed:
- mMustCompileResources |= dv.getCompileResources();
- mMustMergeManifest |= dv.hasManifestChanged();
-
- // Notify the ResourceManager:
- ResourceManager resManager = ResourceManager.getInstance();
-
- if (ResourceManager.isAutoBuilding()) {
- ProjectResources projectResources = resManager.getProjectResources(project);
-
- IdeScanningContext context = new IdeScanningContext(projectResources,
- project, true);
-
- boolean wasCleared = projectResources.ensureInitialized();
-
- if (!wasCleared) {
- resManager.processDelta(delta, context);
- }
-
- // Check whether this project or its dependencies (libraries) have
- // resources that need compilation
- if (wasCleared || context.needsFullAapt()) {
- mMustCompileResources = true;
-
- // Must also call markAaptRequested on the project to not just
- // store "aapt required" on this project, but also on any projects
- // depending on this project if it's a library project
- ResourceManager.markAaptRequested(project);
- }
-
- // Update error markers in the source editor
- if (!mMustCompileResources) {
- context.updateMarkers(false /* async */);
- }
- } // else: already processed the deltas in ResourceManager's IRawDeltaListener
-
- mAidlProcessor.doneVisiting(project);
-
- // get the java package from the visitor
- javaPackage = dv.getManifestPackage();
- minSdkVersion = dv.getMinSdkVersion();
- }
- }
-
- // Has anyone marked this project as needing aapt? Typically done when
- // one of the library projects this project depends on has changed
- mMustCompileResources |= ResourceManager.isAaptRequested(project);
-
- // if the main manifest didn't change, then we check for the library
- // ones (will trigger manifest merging too)
- if (libProjects.size() > 0) {
- for (IProject libProject : libProjects) {
- IResourceDelta delta = getDelta(libProject);
- if (delta != null) {
- PatternBasedDeltaVisitor visitor = new PatternBasedDeltaVisitor(
- project, libProject,
- "PRE:LibManifest"); //$NON-NLS-1$
- visitor.addSet(ChangedFileSetHelper.MANIFEST);
-
- ChangedFileSet textSymbolCFS = null;
- if (isLibrary == false) {
- textSymbolCFS = ChangedFileSetHelper.getTextSymbols(
- libProject);
- visitor.addSet(textSymbolCFS);
- }
-
- delta.accept(visitor);
-
- mMustMergeManifest |= visitor.checkSet(ChangedFileSetHelper.MANIFEST);
-
- if (textSymbolCFS != null) {
- mMustCompileResources |= visitor.checkSet(textSymbolCFS);
- }
-
- // no need to test others if we have all flags at true.
- if (mMustMergeManifest &&
- (mMustCompileResources || textSymbolCFS == null)) {
- break;
- }
- }
- }
- }
-
- // store the build status in the persistent storage
- saveProjectBooleanProperty(PROPERTY_MERGE_MANIFEST, mMustMergeManifest);
- saveProjectBooleanProperty(PROPERTY_COMPILE_RESOURCES, mMustCompileResources);
- saveProjectBooleanProperty(PROPERTY_COMPILE_BUILDCONFIG, mMustCreateBuildConfig);
-
- // if there was some XML errors, we just return w/o doing
- // anything since we've put some markers in the files anyway.
- if (dv != null && dv.mXmlError) {
- AdtPlugin.printErrorToConsole(project, Messages.Xml_Error);
-
- return result;
- }
-
- if (projectState.getRenderScriptSupportMode()) {
- FullRevision minBuildToolsRev = new FullRevision(19,0,3);
- if (mBuildToolInfo.getRevision().compareTo(minBuildToolsRev) == -1) {
- String msg = "RenderScript support mode requires Build-Tools 19.0.3 or later.";
- AdtPlugin.printErrorToConsole(project, msg);
- markProject(AdtConstants.MARKER_ADT, msg, IMarker.SEVERITY_ERROR);
-
- return result;
- }
- }
-
- // get the manifest file
- IFile manifestFile = ProjectHelper.getManifest(project);
-
- if (manifestFile == null) {
- String msg = String.format(Messages.s_File_Missing,
- SdkConstants.FN_ANDROID_MANIFEST_XML);
- AdtPlugin.printErrorToConsole(project, msg);
- markProject(AdtConstants.MARKER_ADT, msg, IMarker.SEVERITY_ERROR);
-
- return result;
-
- // TODO: document whether code below that uses manifest (which is now guaranteed
- // to be null) will actually be executed or not.
- }
-
- // lets check the XML of the manifest first, if that hasn't been done by the
- // resource delta visitor yet.
- if (dv == null || dv.getCheckedManifestXml() == false) {
- BasicXmlErrorListener errorListener = new BasicXmlErrorListener();
- try {
- ManifestData parser = AndroidManifestHelper.parseUnchecked(
- new IFileWrapper(manifestFile),
- true /*gather data*/,
- errorListener);
-
- if (errorListener.mHasXmlError == true) {
- // There was an error in the manifest, its file has been marked
- // by the XmlErrorHandler. The stopBuild() call below will abort
- // this with an exception.
- String msg = String.format(Messages.s_Contains_Xml_Error,
- SdkConstants.FN_ANDROID_MANIFEST_XML);
- AdtPlugin.printBuildToConsole(BuildVerbosity.VERBOSE, project, msg);
- markProject(AdtConstants.MARKER_ADT, msg, IMarker.SEVERITY_ERROR);
-
- return result;
- }
-
- // Get the java package from the parser.
- // This can be null if the parsing failed because the resource is out of sync,
- // in which case the error will already have been logged anyway.
- if (parser != null) {
- javaPackage = parser.getPackage();
- minSdkVersion = parser.getMinSdkVersionString();
- }
- } catch (StreamException e) {
- handleStreamException(e);
-
- return result;
- } catch (ParserConfigurationException e) {
- String msg = String.format(
- "Bad parser configuration for %s: %s",
- manifestFile.getFullPath(),
- e.getMessage());
-
- handleException(e, msg);
- return result;
-
- } catch (SAXException e) {
- String msg = String.format(
- "Parser exception for %s: %s",
- manifestFile.getFullPath(),
- e.getMessage());
-
- handleException(e, msg);
- return result;
- } catch (IOException e) {
- String msg = String.format(
- "I/O error for %s: %s",
- manifestFile.getFullPath(),
- e.getMessage());
-
- handleException(e, msg);
- return result;
- }
- }
-
- int minSdkValue = -1;
-
- if (minSdkVersion != null) {
- try {
- minSdkValue = Integer.parseInt(minSdkVersion);
- } catch (NumberFormatException e) {
- // it's ok, it means minSdkVersion contains a (hopefully) valid codename.
- }
-
- AndroidVersion targetVersion = projectTarget.getVersion();
-
- // remove earlier marker from the manifest
- removeMarkersFromResource(manifestFile, AdtConstants.MARKER_ADT);
-
- if (minSdkValue != -1) {
- String codename = targetVersion.getCodename();
- if (codename != null) {
- // integer minSdk when the target is a preview => fatal error
- String msg = String.format(
- "Platform %1$s is a preview and requires application manifest to set %2$s to '%1$s'",
- codename, AndroidManifest.ATTRIBUTE_MIN_SDK_VERSION);
- AdtPlugin.printErrorToConsole(project, msg);
- BaseProjectHelper.markResource(manifestFile, AdtConstants.MARKER_ADT,
- msg, IMarker.SEVERITY_ERROR);
- return result;
- } else if (minSdkValue > targetVersion.getApiLevel()) {
- // integer minSdk is too high for the target => warning
- String msg = String.format(
- "Attribute %1$s (%2$d) is higher than the project target API level (%3$d)",
- AndroidManifest.ATTRIBUTE_MIN_SDK_VERSION,
- minSdkValue, targetVersion.getApiLevel());
- AdtPlugin.printBuildToConsole(BuildVerbosity.VERBOSE, project, msg);
- BaseProjectHelper.markResource(manifestFile, AdtConstants.MARKER_ADT,
- msg, IMarker.SEVERITY_WARNING);
- }
- } else {
- // looks like the min sdk is a codename, check it matches the codename
- // of the platform
- String codename = targetVersion.getCodename();
- if (codename == null) {
- // platform is not a preview => fatal error
- String msg = String.format(
- "Manifest attribute '%1$s' is set to '%2$s'. Integer is expected.",
- AndroidManifest.ATTRIBUTE_MIN_SDK_VERSION, minSdkVersion);
- AdtPlugin.printErrorToConsole(project, msg);
- BaseProjectHelper.markResource(manifestFile, AdtConstants.MARKER_ADT,
- msg, IMarker.SEVERITY_ERROR);
- return result;
- } else if (codename.equals(minSdkVersion) == false) {
- // platform and manifest codenames don't match => fatal error.
- String msg = String.format(
- "Value of manifest attribute '%1$s' does not match platform codename '%2$s'",
- AndroidManifest.ATTRIBUTE_MIN_SDK_VERSION, codename);
- AdtPlugin.printErrorToConsole(project, msg);
- BaseProjectHelper.markResource(manifestFile, AdtConstants.MARKER_ADT,
- msg, IMarker.SEVERITY_ERROR);
- return result;
- }
-
- // if we get there, the minSdkVersion is a codename matching the target
- // platform codename. In this case we set minSdkValue to the previous API
- // level, as it's used by source processors.
- minSdkValue = targetVersion.getApiLevel();
- }
- } else if (projectTarget.getVersion().isPreview()) {
- // else the minSdkVersion is not set but we are using a preview target.
- // Display an error
- String codename = projectTarget.getVersion().getCodename();
- String msg = String.format(
- "Platform %1$s is a preview and requires application manifests to set %2$s to '%1$s'",
- codename, AndroidManifest.ATTRIBUTE_MIN_SDK_VERSION);
- AdtPlugin.printErrorToConsole(project, msg);
- BaseProjectHelper.markResource(manifestFile, AdtConstants.MARKER_ADT, msg,
- IMarker.SEVERITY_ERROR);
- return result;
- }
-
- if (javaPackage == null || javaPackage.length() == 0) {
- // looks like the AndroidManifest file isn't valid.
- String msg = String.format(Messages.s_Doesnt_Declare_Package_Error,
- SdkConstants.FN_ANDROID_MANIFEST_XML);
- AdtPlugin.printErrorToConsole(project, msg);
- BaseProjectHelper.markResource(manifestFile, AdtConstants.MARKER_ADT,
- msg, IMarker.SEVERITY_ERROR);
-
- return result;
- } else if (javaPackage.indexOf('.') == -1) {
- // The application package name does not contain 2+ segments!
- String msg = String.format(
- "Application package '%1$s' must have a minimum of 2 segments.",
- SdkConstants.FN_ANDROID_MANIFEST_XML);
- AdtPlugin.printErrorToConsole(project, msg);
- BaseProjectHelper.markResource(manifestFile, AdtConstants.MARKER_ADT,
- msg, IMarker.SEVERITY_ERROR);
-
- return result;
- }
-
- // at this point we have the java package. We need to make sure it's not a different
- // package than the previous one that were built.
- if (javaPackage.equals(mManifestPackage) == false) {
- // The manifest package has changed, the user may want to update
- // the launch configuration
- if (mManifestPackage != null) {
- AdtPlugin.printBuildToConsole(BuildVerbosity.VERBOSE, project,
- Messages.Checking_Package_Change);
-
- FixLaunchConfig flc = new FixLaunchConfig(project, mManifestPackage,
- javaPackage);
- flc.start();
- }
-
- // record the new manifest package, and save it.
- mManifestPackage = javaPackage;
- saveProjectStringProperty(PROPERTY_PACKAGE, mManifestPackage);
-
- // force a clean
- doClean(project, monitor);
- mMustMergeManifest = true;
- mMustCompileResources = true;
- mMustCreateBuildConfig = true;
- mAidlProcessor.prepareFullBuild(project);
- mRenderScriptSourceChangeHandler.prepareFullBuild();
-
- saveProjectBooleanProperty(PROPERTY_MERGE_MANIFEST, mMustMergeManifest);
- saveProjectBooleanProperty(PROPERTY_COMPILE_RESOURCES, mMustCompileResources);
- saveProjectBooleanProperty(PROPERTY_COMPILE_BUILDCONFIG, mMustCreateBuildConfig);
- }
-
- try {
- handleBuildConfig(args);
- } catch (IOException e) {
- handleException(e, "Failed to create BuildConfig class");
- return result;
- }
-
- // merge the manifest
- if (mMustMergeManifest) {
- boolean enabled = MANIFEST_MERGER_ENABLED_DEFAULT;
- String propValue = projectState.getProperty(MANIFEST_MERGER_PROPERTY);
- if (propValue != null) {
- enabled = Boolean.valueOf(propValue);
- }
-
- if (mergeManifest(androidOutputFolder, libProjects, enabled) == false) {
- return result;
- }
- }
-
- List<File> libProjectsOut = new ArrayList<File>(libProjects.size());
- for (IProject libProject : libProjects) {
- libProjectsOut.add(
- BaseProjectHelper.getAndroidOutputFolder(libProject)
- .getLocation().toFile());
- }
-
- // run the source processors
- int processorStatus = SourceProcessor.COMPILE_STATUS_NONE;
-
-
- try {
- processorStatus |= mAidlProcessor.compileFiles(this,
- project, projectTarget, sourceFolderPathList,
- libProjectsOut, monitor);
- } catch (Throwable t) {
- handleException(t, "Failed to run aidl. Check workspace log for detail.");
- return result;
- }
-
- try {
- processorStatus |= compileRs(minSdkValue, projectState, androidOutputFolder,
- resOutFolder, monitor);
- } catch (Throwable t) {
- handleException(t, "Failed to run renderscript. Check workspace log for detail.");
- return result;
- }
-
- // if a processor created some resources file, force recompilation of the resources.
- if ((processorStatus & SourceProcessor.COMPILE_STATUS_RES) != 0) {
- mMustCompileResources = true;
- // save the current state before attempting the compilation
- saveProjectBooleanProperty(PROPERTY_COMPILE_RESOURCES, mMustCompileResources);
- }
-
- // handle the resources, after the processors are run since some (renderscript)
- // generate resources.
- boolean compiledTheResources = mMustCompileResources;
- if (mMustCompileResources) {
- if (DEBUG_LOG) {
- AdtPlugin.log(IStatus.INFO, "%s compiling resources!", project.getName());
- }
-
- IFile proguardFile = null;
- if (projectState.getProperty(ProjectProperties.PROPERTY_PROGUARD_CONFIG) != null) {
- proguardFile = androidOutputFolder.getFile(AdtConstants.FN_AAPT_PROGUARD);
- }
-
- handleResources(project, javaPackage, projectTarget, manifestFile, resOutFolder,
- libProjects, isLibrary, proguardFile);
- }
-
- if (processorStatus == SourceProcessor.COMPILE_STATUS_NONE &&
- compiledTheResources == false) {
- AdtPlugin.printBuildToConsole(BuildVerbosity.VERBOSE, project,
- Messages.Nothing_To_Compile);
- }
- } catch (AbortBuildException e) {
- return result;
- } finally {
- // refresh the 'gen' source folder. Once this is done with the custom progress
- // monitor to mark all new files as derived
- mGenFolder.refreshLocal(IResource.DEPTH_INFINITE, mDerivedProgressMonitor);
- if (resOutFolder != null) {
- resOutFolder.refreshLocal(IResource.DEPTH_INFINITE, mDerivedProgressMonitor);
- }
- }
-
- return result;
- }
-
- private IFolder getResOutFolder(IFolder androidOutputFolder) {
- return androidOutputFolder.getFolder(AdtConstants.WS_BIN_RELATIVE_BC);
- }
-
- @Override
- protected void clean(IProgressMonitor monitor) throws CoreException {
- super.clean(monitor);
-
- if (DEBUG_LOG) {
- AdtPlugin.log(IStatus.INFO, "%s CLEAN(PRE)", getProject().getName());
- }
-
- doClean(getProject(), monitor);
- if (mGenFolder != null) {
- mGenFolder.refreshLocal(IResource.DEPTH_INFINITE, monitor);
- }
- }
-
- private void doClean(IProject project, IProgressMonitor monitor) throws CoreException {
- AdtPlugin.printBuildToConsole(BuildVerbosity.VERBOSE, project,
- Messages.Removing_Generated_Classes);
-
- // remove all the derived resources from the 'gen' source folder.
- if (mGenFolder != null && mGenFolder.exists()) {
- // gen folder should not be derived, but previous version could set it to derived
- // so we make sure this isn't the case (or it'll get deleted by the clean)
- mGenFolder.setDerived(false, monitor);
-
- removeDerivedResources(mGenFolder, monitor);
- }
-
- // Clear the project of the generic markers
- removeMarkersFromContainer(project, AdtConstants.MARKER_AAPT_COMPILE);
- removeMarkersFromContainer(project, AdtConstants.MARKER_XML);
- removeMarkersFromContainer(project, AdtConstants.MARKER_AIDL);
- removeMarkersFromContainer(project, AdtConstants.MARKER_RENDERSCRIPT);
- removeMarkersFromContainer(project, AdtConstants.MARKER_MANIFMERGER);
- removeMarkersFromContainer(project, AdtConstants.MARKER_ANDROID);
-
- // Also clean up lint
- EclipseLintClient.clearMarkers(project);
-
- // clean the project repo
- ProjectResources res = ResourceManager.getInstance().getProjectResources(project);
- res.clear();
- }
-
- @Override
- protected void startupOnInitialize() {
- try {
- super.startupOnInitialize();
-
- IProject project = getProject();
-
- // load the previous IFolder and java package.
- mManifestPackage = loadProjectStringProperty(PROPERTY_PACKAGE);
-
- // get the source folder in which all the Java files are created
- mGenFolder = project.getFolder(SdkConstants.FD_GEN_SOURCES);
- mDerivedProgressMonitor = new DerivedProgressMonitor(mGenFolder);
-
- // Load the current compile flags. We ask for true if not found to force a recompile.
- mMustMergeManifest = loadProjectBooleanProperty(PROPERTY_MERGE_MANIFEST, true);
- mMustCompileResources = loadProjectBooleanProperty(PROPERTY_COMPILE_RESOURCES, true);
- mMustCreateBuildConfig = loadProjectBooleanProperty(PROPERTY_COMPILE_BUILDCONFIG, true);
- Boolean v = ProjectHelper.loadBooleanProperty(project, PROPERTY_BUILDCONFIG_MODE);
- if (v == null) {
- // no previous build config mode? force regenerate
- mMustCreateBuildConfig = true;
- } else {
- mLastBuildConfigMode = v;
- }
-
- } catch (Throwable throwable) {
- AdtPlugin.log(throwable, "Failed to finish PrecompilerBuilder#startupOnInitialize()");
- }
- }
-
- private void setupSourceProcessors(@NonNull IJavaProject javaProject,
- @NonNull ProjectState projectState,
- @NonNull List<IPath> sourceFolderPathList,
- @NonNull IFolder androidOutputFolder) {
- if (mAidlProcessor == null) {
- mAidlProcessor = new AidlProcessor(javaProject, mBuildToolInfo, mGenFolder);
- } else {
- mAidlProcessor.setBuildToolInfo(mBuildToolInfo);
- }
-
- List<File> sourceFolders = Lists.newArrayListWithCapacity(sourceFolderPathList.size());
- IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
-
- for (IPath path : sourceFolderPathList) {
- IResource resource = root.findMember(path);
- if (resource != null && resource.exists() && resource.getType() == IResource.FOLDER) {
- IPath fullPath = resource.getLocation();
- if (fullPath != null) {
- sourceFolders.add(fullPath.toFile());
- }
- }
- }
-
- RenderScriptChecker checker = new RenderScriptChecker(sourceFolders,
- androidOutputFolder.getLocation().toFile());
- mRenderScriptSourceChangeHandler = new RsSourceChangeHandler(checker);
- }
-
- private int compileRs(int minSdkValue,
- @NonNull ProjectState projectState,
- @NonNull IFolder androidOutputFolder,
- @NonNull IFolder resOutFolder,
- @NonNull IProgressMonitor monitor)
- throws IOException, InterruptedException {
- if (!mRenderScriptSourceChangeHandler.mustCompile()) {
- return SourceProcessor.COMPILE_STATUS_NONE;
- }
-
- RenderScriptChecker checker = mRenderScriptSourceChangeHandler.getChecker();
-
- List<File> inputs = checker.findInputFiles();
- List<File> importFolders = checker.getSourceFolders();
- File buildFolder = androidOutputFolder.getLocation().toFile();
-
-
- // get the renderscript target
- int rsTarget = minSdkValue == -1 ? 11 : minSdkValue;
- String rsTargetStr = projectState.getProperty(ProjectProperties.PROPERTY_RS_TARGET);
- if (rsTargetStr != null) {
- try {
- rsTarget = Integer.parseInt(rsTargetStr);
- } catch (NumberFormatException e) {
- handleException(e, String.format(
- "Property %s is not an integer.",
- ProjectProperties.PROPERTY_RS_TARGET));
- return SourceProcessor.COMPILE_STATUS_NONE;
- }
- }
-
- RenderScriptProcessor processor = new RenderScriptProcessor(
- inputs,
- importFolders,
- buildFolder,
- mGenFolder.getLocation().toFile(),
- resOutFolder.getLocation().toFile(),
- new File(buildFolder, SdkConstants.FD_RS_OBJ),
- new File(buildFolder, SdkConstants.FD_RS_LIBS),
- mBuildToolInfo,
- rsTarget,
- false /*debugBuild, always false for now*/,
- 3,
- projectState.getRenderScriptSupportMode());
-
- // clean old dependency files fiest
- checker.cleanDependencies();
-
- // then clean old output files
- processor.cleanOldOutput(checker.getOldOutputs());
-
- RenderScriptLauncher launcher = new RenderScriptLauncher(
- getProject(),
- mGenFolder,
- resOutFolder,
- monitor,
- AdtPrefs.getPrefs().getBuildVerbosity() == BuildVerbosity.VERBOSE /*verbose*/);
-
- // and run the build
- processor.build(launcher);
-
- return SourceProcessor.COMPILE_STATUS_CODE | SourceProcessor.COMPILE_STATUS_RES;
- }
-
- @SuppressWarnings("deprecation")
- private void handleBuildConfig(@SuppressWarnings("rawtypes") Map args)
- throws IOException, CoreException {
- boolean debugMode = !args.containsKey(RELEASE_REQUESTED);
-
- BuildConfigGenerator generator = new BuildConfigGenerator(
- mGenFolder.getLocation().toOSString(), mManifestPackage, debugMode);
-
- if (mMustCreateBuildConfig == false) {
- // check the file is present.
- IFolder folder = getGenManifestPackageFolder();
- if (folder.exists(new Path(BuildConfigGenerator.BUILD_CONFIG_NAME)) == false) {
- mMustCreateBuildConfig = true;
- AdtPlugin.printBuildToConsole(BuildVerbosity.VERBOSE, getProject(),
- String.format("Class %1$s is missing!",
- BuildConfigGenerator.BUILD_CONFIG_NAME));
- } else if (debugMode != mLastBuildConfigMode) {
- // else if the build mode changed, force creation
- mMustCreateBuildConfig = true;
- AdtPlugin.printBuildToConsole(BuildVerbosity.VERBOSE, getProject(),
- String.format("Different build mode, must update %1$s!",
- BuildConfigGenerator.BUILD_CONFIG_NAME));
- }
- }
-
- if (mMustCreateBuildConfig) {
- if (DEBUG_LOG) {
- AdtPlugin.log(IStatus.INFO, "%s generating BuilderConfig!", getProject().getName());
- }
-
- AdtPlugin.printBuildToConsole(BuildVerbosity.VERBOSE, getProject(),
- String.format("Generating %1$s...", BuildConfigGenerator.BUILD_CONFIG_NAME));
- generator.generate();
-
- mMustCreateBuildConfig = false;
- saveProjectBooleanProperty(PROPERTY_COMPILE_BUILDCONFIG, mMustCreateBuildConfig);
- saveProjectBooleanProperty(PROPERTY_BUILDCONFIG_MODE, mLastBuildConfigMode = debugMode);
- }
- }
-
- private boolean mergeManifest(IFolder androidOutFolder, List<IProject> libProjects,
- boolean enabled) throws CoreException {
- if (DEBUG_LOG) {
- AdtPlugin.log(IStatus.INFO, "%s merging manifests!", getProject().getName());
- }
-
- IFile outFile = androidOutFolder.getFile(SdkConstants.FN_ANDROID_MANIFEST_XML);
- IFile manifest = getProject().getFile(SdkConstants.FN_ANDROID_MANIFEST_XML);
-
- // remove existing markers from the manifest.
- // FIXME: only remove from manifest once the markers are put there.
- removeMarkersFromResource(getProject(), AdtConstants.MARKER_MANIFMERGER);
-
- // If the merging is not enabled or if there's no library then we simply copy the
- // manifest over.
- if (enabled == false || libProjects.size() == 0) {
- try {
- new FileOp().copyFile(manifest.getLocation().toFile(),
- outFile.getLocation().toFile());
-
- outFile.refreshLocal(IResource.DEPTH_INFINITE, mDerivedProgressMonitor);
-
- saveProjectBooleanProperty(PROPERTY_MERGE_MANIFEST, mMustMergeManifest = false);
- } catch (IOException e) {
- handleException(e, "Failed to copy Manifest");
- return false;
- }
- } else {
- final ArrayList<String> errors = new ArrayList<String>();
-
- // TODO change MergerLog.wrapSdkLog by a custom IMergerLog that will create
- // and maintain error markers.
- ManifestMerger merger = new ManifestMerger(
- MergerLog.wrapSdkLog(new ILogger() {
- @Override
- public void warning(@NonNull String warningFormat, Object... args) {
- AdtPlugin.printToConsole(getProject(), String.format(warningFormat, args));
- }
-
- @Override
- public void info(@NonNull String msgFormat, Object... args) {
- AdtPlugin.printToConsole(getProject(), String.format(msgFormat, args));
- }
-
- @Override
- public void verbose(@NonNull String msgFormat, Object... args) {
- info(msgFormat, args);
- }
-
- @Override
- public void error(@Nullable Throwable t, @Nullable String errorFormat,
- Object... args) {
- errors.add(String.format(errorFormat, args));
- }
- }),
- new AdtManifestMergeCallback());
-
- File[] libManifests = new File[libProjects.size()];
- int libIndex = 0;
- for (IProject lib : libProjects) {
- libManifests[libIndex++] = lib.getFile(SdkConstants.FN_ANDROID_MANIFEST_XML)
- .getLocation().toFile();
- }
-
- if (merger.process(
- outFile.getLocation().toFile(),
- manifest.getLocation().toFile(),
- libManifests,
- null /*injectAttributes*/, null /*packageOverride*/) == false) {
- if (errors.size() > 1) {
- StringBuilder sb = new StringBuilder();
- for (String s : errors) {
- sb.append(s).append('\n');
- }
-
- markProject(AdtConstants.MARKER_MANIFMERGER, sb.toString(),
- IMarker.SEVERITY_ERROR);
-
- } else if (errors.size() == 1) {
- markProject(AdtConstants.MARKER_MANIFMERGER, errors.get(0),
- IMarker.SEVERITY_ERROR);
- } else {
- markProject(AdtConstants.MARKER_MANIFMERGER, "Unknown error merging manifest",
- IMarker.SEVERITY_ERROR);
- }
- return false;
- }
-
- outFile.refreshLocal(IResource.DEPTH_INFINITE, mDerivedProgressMonitor);
- saveProjectBooleanProperty(PROPERTY_MERGE_MANIFEST, mMustMergeManifest = false);
- }
-
- return true;
- }
-
- /**
- * Handles resource changes and regenerate whatever files need regenerating.
- * @param project the main project
- * @param javaPackage the app package for the main project
- * @param projectTarget the target of the main project
- * @param manifest the {@link IFile} representing the project manifest
- * @param libProjects the library dependencies
- * @param isLibrary if the project is a library project
- * @throws CoreException
- * @throws AbortBuildException
- */
- private void handleResources(IProject project, String javaPackage, IAndroidTarget projectTarget,
- IFile manifest, IFolder resOutFolder, List<IProject> libProjects, boolean isLibrary,
- IFile proguardFile) throws CoreException, AbortBuildException {
- // get the resource folder
- IFolder resFolder = project.getFolder(AdtConstants.WS_RESOURCES);
-
- // get the file system path
- IPath outputLocation = mGenFolder.getLocation();
- IPath resLocation = resFolder.getLocation();
- IPath manifestLocation = manifest == null ? null : manifest.getLocation();
-
- // those locations have to exist for us to do something!
- if (outputLocation != null && resLocation != null
- && manifestLocation != null) {
- String osOutputPath = outputLocation.toOSString();
- String osResPath = resLocation.toOSString();
- String osManifestPath = manifestLocation.toOSString();
-
- // remove the aapt markers
- removeMarkersFromResource(manifest, AdtConstants.MARKER_AAPT_COMPILE);
- removeMarkersFromContainer(resFolder, AdtConstants.MARKER_AAPT_COMPILE);
-
- AdtPlugin.printBuildToConsole(BuildVerbosity.VERBOSE, project,
- Messages.Preparing_Generated_Files);
-
- // we need to figure out where to store the R class.
- // get the parent folder for R.java and update mManifestPackageSourceFolder
- IFolder mainPackageFolder = getGenManifestPackageFolder();
-
- // handle libraries
- ArrayList<IFolder> libResFolders = Lists.newArrayList();
- ArrayList<Pair<File, String>> libRFiles = Lists.newArrayList();
- if (libProjects != null) {
- for (IProject lib : libProjects) {
- IFolder libResFolder = lib.getFolder(SdkConstants.FD_RES);
- if (libResFolder.exists()) {
- libResFolders.add(libResFolder);
- }
-
- try {
- // get the package of the library, and if it's different form the
- // main project, generate the R class for it too.
- String libJavaPackage = AndroidManifest.getPackage(new IFolderWrapper(lib));
- if (libJavaPackage.equals(javaPackage) == false) {
-
- IFolder libOutput = BaseProjectHelper.getAndroidOutputFolder(lib);
- File libOutputFolder = libOutput.getLocation().toFile();
-
- libRFiles.add(Pair.of(
- new File(libOutputFolder, "R.txt"),
- libJavaPackage));
-
- }
- } catch (Exception e) {
- }
- }
- }
-
- String proguardFilePath = proguardFile != null ?
- proguardFile.getLocation().toOSString(): null;
-
- File resOutFile = resOutFolder.getLocation().toFile();
- String resOutPath = resOutFile.isDirectory() ? resOutFile.getAbsolutePath() : null;
-
- execAapt(project, projectTarget, osOutputPath, resOutPath, osResPath, osManifestPath,
- mainPackageFolder, libResFolders, libRFiles, isLibrary, proguardFilePath);
- }
- }
-
- /**
- * Executes AAPT to generate R.java/Manifest.java
- * @param project the main project
- * @param projectTarget the main project target
- * @param osOutputPath the OS output path for the generated file. This is the source folder, not
- * the package folder.
- * @param osResPath the OS path to the res folder for the main project
- * @param osManifestPath the OS path to the manifest of the main project
- * @param packageFolder the IFolder that will contain the generated file. Unlike
- * <var>osOutputPath</var> this is the direct parent of the generated files.
- * If <var>customJavaPackage</var> is not null, this must match the new destination triggered
- * by its value.
- * @param libResFolders the list of res folders for the library.
- * @param libRFiles a list of R files for the libraries.
- * @param isLibrary if the project is a library project
- * @param proguardFile an optional path to store proguard information
- * @throws AbortBuildException
- */
- @SuppressWarnings("deprecation")
- private void execAapt(IProject project, IAndroidTarget projectTarget, String osOutputPath,
- String osBcOutPath, String osResPath, String osManifestPath, IFolder packageFolder,
- ArrayList<IFolder> libResFolders, List<Pair<File, String>> libRFiles,
- boolean isLibrary, String proguardFile)
- throws AbortBuildException {
-
- // We actually need to delete the manifest.java as it may become empty and
- // in this case aapt doesn't generate an empty one, but instead doesn't
- // touch it.
- IFile manifestJavaFile = packageFolder.getFile(SdkConstants.FN_MANIFEST_CLASS);
- manifestJavaFile.getLocation().toFile().delete();
-
- // launch aapt: create the command line
- ArrayList<String> array = new ArrayList<String>();
-
- String aaptPath = mBuildToolInfo.getPath(BuildToolInfo.PathId.AAPT);
-
- array.add(aaptPath);
- array.add("package"); //$NON-NLS-1$
- array.add("-m"); //$NON-NLS-1$
- if (AdtPrefs.getPrefs().getBuildVerbosity() == BuildVerbosity.VERBOSE) {
- array.add("-v"); //$NON-NLS-1$
- }
-
- if (isLibrary) {
- array.add("--non-constant-id"); //$NON-NLS-1$
- }
-
- if (libResFolders.size() > 0) {
- array.add("--auto-add-overlay"); //$NON-NLS-1$
- }
-
- // If a library or has libraries, generate a text version of the R symbols.
- File outputFolder = BaseProjectHelper.getAndroidOutputFolder(project).getLocation()
- .toFile();
-
- if (isLibrary || !libRFiles.isEmpty()) {
- array.add("--output-text-symbols"); //$NON-NLS-1$
- array.add(outputFolder.getAbsolutePath());
- }
-
- array.add("-J"); //$NON-NLS-1$
- array.add(osOutputPath);
- array.add("-M"); //$NON-NLS-1$
- array.add(osManifestPath);
- if (osBcOutPath != null) {
- array.add("-S"); //$NON-NLS-1$
- array.add(osBcOutPath);
- }
- array.add("-S"); //$NON-NLS-1$
- array.add(osResPath);
- for (IFolder libResFolder : libResFolders) {
- array.add("-S"); //$NON-NLS-1$
- array.add(libResFolder.getLocation().toOSString());
- }
-
- array.add("-I"); //$NON-NLS-1$
- array.add(projectTarget.getPath(IAndroidTarget.ANDROID_JAR));
-
- // use the proguard file
- if (proguardFile != null && proguardFile.length() > 0) {
- array.add("-G");
- array.add(proguardFile);
- }
-
- if (AdtPrefs.getPrefs().getBuildVerbosity() == BuildVerbosity.VERBOSE) {
- StringBuilder sb = new StringBuilder();
- for (String c : array) {
- sb.append(c);
- sb.append(' ');
- }
- String cmd_line = sb.toString();
- AdtPlugin.printToConsole(project, cmd_line);
- }
-
- // launch
- try {
- // launch the command line process
- Process process = Runtime.getRuntime().exec(
- array.toArray(new String[array.size()]));
-
- // list to store each line of stderr
- ArrayList<String> stdErr = new ArrayList<String>();
-
- // get the output and return code from the process
- int returnCode = grabProcessOutput(process, stdErr);
-
- // attempt to parse the error output
- boolean parsingError = AaptParser.parseOutput(stdErr, project);
-
- // if we couldn't parse the output we display it in the console.
- if (parsingError) {
- if (returnCode != 0) {
- AdtPlugin.printErrorToConsole(project, stdErr.toArray());
- } else {
- AdtPlugin.printBuildToConsole(BuildVerbosity.NORMAL,
- project, stdErr.toArray());
- }
- }
-
- if (returnCode != 0) {
- // 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.
- if (parsingError) {
- markProject(AdtConstants.MARKER_ADT,
- Messages.Unparsed_AAPT_Errors, IMarker.SEVERITY_ERROR);
- } else if (stdErr.size() == 0) {
- // no parsing error because sdterr was empty. We still need to put
- // a marker otherwise there's no user visible feedback.
- markProject(AdtConstants.MARKER_ADT,
- String.format(Messages.AAPT_Exec_Error_d, returnCode),
- IMarker.SEVERITY_ERROR);
- }
-
- AdtPlugin.printBuildToConsole(BuildVerbosity.VERBOSE, project,
- Messages.AAPT_Error);
-
- // abort if exec failed.
- throw new AbortBuildException();
- }
-
- // now if the project has libraries, R needs to be created for each libraries
- // unless this is a library.
- if (isLibrary == false && !libRFiles.isEmpty()) {
- File rFile = new File(outputFolder, SdkConstants.FN_RESOURCE_TEXT);
- // if the project has no resources, the file could not exist.
- if (rFile.isFile()) {
- // Load the full symbols from the full R.txt file.
- SymbolLoader fullSymbolValues = new SymbolLoader(rFile);
- fullSymbolValues.load();
-
- Multimap<String, SymbolLoader> libMap = ArrayListMultimap.create();
-
- // First pass processing the libraries, collecting them by packageName,
- // and ignoring the ones that have the same package name as the application
- // (since that R class was already created).
-
- for (Pair<File, String> lib : libRFiles) {
- String libPackage = lib.getSecond();
- File rText = lib.getFirst();
-
- if (rText.isFile()) {
- // load the lib symbols
- SymbolLoader libSymbols = new SymbolLoader(rText);
- libSymbols.load();
-
- // store these symbols by associating them with the package name.
- libMap.put(libPackage, libSymbols);
- }
- }
-
- // now loop on all the package names, merge all the symbols to write,
- // and write them
- for (String packageName : libMap.keySet()) {
- Collection<SymbolLoader> symbols = libMap.get(packageName);
-
- SymbolWriter writer = new SymbolWriter(osOutputPath, packageName,
- fullSymbolValues);
- for (SymbolLoader symbolLoader : symbols) {
- writer.addSymbolsToWrite(symbolLoader);
- }
- writer.write();
- }
- }
- }
-
- } catch (IOException e1) {
- // something happen while executing the process,
- // mark the project and exit
- String msg;
- String path = array.get(0);
- if (!new File(path).exists()) {
- msg = String.format(Messages.AAPT_Exec_Error_s, path);
- } else {
- String description = e1.getLocalizedMessage();
- if (e1.getCause() != null && e1.getCause() != e1) {
- description = description + ": " + e1.getCause().getLocalizedMessage();
- }
- msg = String.format(Messages.AAPT_Exec_Error_Other_s, description);
- }
-
- markProject(AdtConstants.MARKER_ADT, msg, IMarker.SEVERITY_ERROR);
-
- // Add workaround for the Linux problem described here:
- // http://developer.android.com/sdk/installing.html#troubleshooting
- // There are various posts on StackOverflow elsewhere where people are asking
- // about aapt failing to run, so even though this is documented in the
- // Troubleshooting section add an error message to help with this
- // scenario.
- if (SdkConstants.CURRENT_PLATFORM == SdkConstants.PLATFORM_LINUX
- && System.getProperty("os.arch").endsWith("64") //$NON-NLS-1$ //$NON-NLS-2$
- && new File(aaptPath).exists()
- && new File("/usr/bin/apt-get").exists()) { //$NON-NLS-1$
- markProject(AdtConstants.MARKER_ADT,
- "Hint: On 64-bit systems, make sure the 32-bit libraries are installed: \"sudo apt-get install ia32-libs\" or on some systems, \"sudo apt-get install lib32z1\"",
- IMarker.SEVERITY_ERROR);
- // Note - this uses SEVERITY_ERROR even though it's really SEVERITY_INFO because
- // we want this error message to show up adjacent to the aapt error message
- // (and Eclipse sorts by priority)
- }
-
- // This interrupts the build.
- throw new AbortBuildException();
- } catch (InterruptedException e) {
- // we got interrupted waiting for the process to end...
- // mark the project and exit
- String msg = String.format(Messages.AAPT_Exec_Error_s, array.get(0));
- markProject(AdtConstants.MARKER_ADT, msg, IMarker.SEVERITY_ERROR);
-
- // This interrupts the build.
- throw new AbortBuildException();
- } finally {
- // we've at least attempted to run aapt, save the fact that we don't have to
- // run it again, unless there's a new resource change.
- saveProjectBooleanProperty(PROPERTY_COMPILE_RESOURCES,
- mMustCompileResources = false);
- ResourceManager.clearAaptRequest(project);
- }
- }
-
- /**
- * Creates a relative {@link IPath} from a java package.
- * @param javaPackageName the java package.
- */
- private IPath getJavaPackagePath(String javaPackageName) {
- // convert the java package into path
- String[] segments = javaPackageName.split(AdtConstants.RE_DOT);
-
- StringBuilder path = new StringBuilder();
- for (String s : segments) {
- path.append(AdtConstants.WS_SEP_CHAR);
- path.append(s);
- }
-
- return new Path(path.toString());
- }
-
- /**
- * Returns an {@link IFolder} (located inside the 'gen' source folder), that matches the
- * package defined in the manifest. This {@link IFolder} may not actually exist
- * (aapt will create it anyway).
- * @return the {@link IFolder} that will contain the R class or null if
- * the folder was not found.
- * @throws CoreException
- */
- private IFolder getGenManifestPackageFolder() throws CoreException {
- // get the path for the package
- IPath packagePath = getJavaPackagePath(mManifestPackage);
-
- // get a folder for this path under the 'gen' source folder, and return it.
- // This IFolder may not reference an actual existing folder.
- return mGenFolder.getFolder(packagePath);
- }
-}