aboutsummaryrefslogtreecommitdiff
path: root/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/builders
diff options
context:
space:
mode:
Diffstat (limited to 'eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/builders')
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/builders/BaseBuilder.java483
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/builders/ChangedFileSet.java70
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/builders/ChangedFileSetHelper.java200
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/builders/JavaResChangedSet.java46
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/builders/PatternBasedDeltaVisitor.java139
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/builders/PostCompilerBuilder.java946
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/builders/PreCompilerBuilder.java1401
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/builders/PreCompilerDeltaVisitor.java417
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/builders/ResourceManagerBuilder.java317
9 files changed, 0 insertions, 4019 deletions
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/builders/BaseBuilder.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/builders/BaseBuilder.java
deleted file mode 100644
index 162591406..000000000
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/builders/BaseBuilder.java
+++ /dev/null
@@ -1,483 +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.annotations.NonNull;
-import com.android.annotations.Nullable;
-import com.android.ide.common.sdk.LoadStatus;
-import com.android.ide.eclipse.adt.AdtConstants;
-import com.android.ide.eclipse.adt.AdtPlugin;
-import com.android.ide.eclipse.adt.internal.build.BuildHelper;
-import com.android.ide.eclipse.adt.internal.build.Messages;
-import com.android.ide.eclipse.adt.internal.preferences.AdtPrefs.BuildVerbosity;
-import com.android.ide.eclipse.adt.internal.project.BaseProjectHelper;
-import com.android.ide.eclipse.adt.internal.project.ProjectHelper;
-import com.android.ide.eclipse.adt.internal.project.XmlErrorHandler;
-import com.android.ide.eclipse.adt.internal.project.XmlErrorHandler.XmlErrorListener;
-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.io.IAbstractFile;
-import com.android.io.StreamException;
-import com.android.sdklib.BuildToolInfo;
-import com.android.sdklib.IAndroidTarget;
-import com.android.sdklib.repository.FullRevision;
-
-import org.eclipse.core.resources.IContainer;
-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.IncrementalProjectBuilder;
-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.jobs.Job;
-import org.eclipse.jdt.core.IJavaProject;
-import org.xml.sax.SAXException;
-
-import java.util.ArrayList;
-
-import javax.xml.parsers.ParserConfigurationException;
-import javax.xml.parsers.SAXParser;
-import javax.xml.parsers.SAXParserFactory;
-
-/**
- * Base builder for XML files. This class allows for basic XML parsing with
- * error checking and marking the files for errors/warnings.
- */
-public abstract class BaseBuilder extends IncrementalProjectBuilder {
-
- protected static final boolean DEBUG_LOG = "1".equals( //$NON-NLS-1$
- System.getenv("ANDROID_BUILD_DEBUG")); //$NON-NLS-1$
-
- /** SAX Parser factory. */
- private SAXParserFactory mParserFactory;
-
- /**
- * The build tool to use to build. This is guaranteed to be non null after a call to
- * {@link #abortOnBadSetup(IJavaProject, ProjectState)} since this will throw if it can't be
- * queried.
- */
- protected BuildToolInfo mBuildToolInfo;
-
- /**
- * Base Resource Delta Visitor to handle XML error
- */
- protected static class BaseDeltaVisitor implements XmlErrorListener {
-
- /** The Xml builder used to validate XML correctness. */
- protected BaseBuilder mBuilder;
-
- /**
- * XML error flag. if true, we keep parsing the ResourceDelta but the
- * compilation will not happen (we're putting markers)
- */
- public boolean mXmlError = false;
-
- public BaseDeltaVisitor(BaseBuilder builder) {
- mBuilder = builder;
- }
-
- /**
- * Finds a matching Source folder for the current path. This checks if the current path
- * leads to, or is a source folder.
- * @param sourceFolders The list of source folders
- * @param pathSegments The segments of the current path
- * @return The segments of the source folder, or null if no match was found
- */
- protected static String[] findMatchingSourceFolder(ArrayList<IPath> sourceFolders,
- String[] pathSegments) {
-
- for (IPath p : sourceFolders) {
- // check if we are inside one of those source class path
-
- // get the segments
- String[] srcSegments = p.segments();
-
- // compare segments. We want the path of the resource
- // we're visiting to be
- boolean valid = true;
- int segmentCount = pathSegments.length;
-
- for (int i = 0 ; i < segmentCount; i++) {
- String s1 = pathSegments[i];
- String s2 = srcSegments[i];
-
- if (s1.equalsIgnoreCase(s2) == false) {
- valid = false;
- break;
- }
- }
-
- if (valid) {
- // this folder, or one of this children is a source
- // folder!
- // we return its segments
- return srcSegments;
- }
- }
-
- return null;
- }
-
- /**
- * Sent when an XML error is detected.
- * @see XmlErrorListener
- */
- @Override
- public void errorFound() {
- mXmlError = true;
- }
- }
-
- protected static class AbortBuildException extends Exception {
- private static final long serialVersionUID = 1L;
- }
-
- public BaseBuilder() {
- super();
- mParserFactory = SAXParserFactory.newInstance();
-
- // FIXME when the compiled XML support for namespace is in, set this to true.
- mParserFactory.setNamespaceAware(false);
- }
-
- /**
- * Checks an Xml file for validity. Errors/warnings will be marked on the
- * file
- * @param resource the resource to check
- * @param visitor a valid resource delta visitor
- */
- protected final void checkXML(IResource resource, BaseDeltaVisitor visitor) {
-
- // first make sure this is an xml file
- if (resource instanceof IFile) {
- IFile file = (IFile)resource;
-
- // remove previous markers
- removeMarkersFromResource(file, AdtConstants.MARKER_XML);
-
- // create the error handler
- XmlErrorHandler reporter = new XmlErrorHandler(file, visitor);
- try {
- // parse
- getParser().parse(file.getContents(), reporter);
- } catch (Exception e1) {
- }
- }
- }
-
- /**
- * Returns the SAXParserFactory, instantiating it first if it's not already
- * created.
- * @return the SAXParserFactory object
- * @throws ParserConfigurationException
- * @throws SAXException
- */
- protected final SAXParser getParser() throws ParserConfigurationException,
- SAXException {
- return mParserFactory.newSAXParser();
- }
-
- /**
- * Adds a marker to the current project. This methods catches thrown {@link CoreException},
- * and returns null instead.
- *
- * @param markerId The id of the marker to add.
- * @param message the message associated with the mark
- * @param severity the severity of the marker.
- * @return the marker that was created (or null if failure)
- * @see IMarker
- */
- protected final IMarker markProject(String markerId, String message, int severity) {
- return BaseProjectHelper.markResource(getProject(), markerId, message, severity);
- }
-
- /**
- * Removes markers from a resource and only the resource (not its children).
- * @param file The file from which to delete the markers.
- * @param markerId The id of the markers to remove. If null, all marker of
- * type <code>IMarker.PROBLEM</code> will be removed.
- */
- public final void removeMarkersFromResource(IResource resource, String markerId) {
- try {
- if (resource.exists()) {
- resource.deleteMarkers(markerId, true, IResource.DEPTH_ZERO);
- }
- } catch (CoreException ce) {
- String msg = String.format(Messages.Marker_Delete_Error, markerId, resource.toString());
- AdtPlugin.printErrorToConsole(getProject(), msg);
- }
- }
-
- /**
- * Removes markers from a container and its children.
- * @param folder The container from which to delete the markers.
- * @param markerId The id of the markers to remove. If null, all marker of
- * type <code>IMarker.PROBLEM</code> will be removed.
- */
- protected final void removeMarkersFromContainer(IContainer folder, String markerId) {
- try {
- if (folder.exists()) {
- folder.deleteMarkers(markerId, true, IResource.DEPTH_INFINITE);
- }
- } catch (CoreException ce) {
- String msg = String.format(Messages.Marker_Delete_Error, markerId, folder.toString());
- AdtPlugin.printErrorToConsole(getProject(), msg);
- }
- }
-
- /**
- * Get the stderr output of a process and return when the process is done.
- * @param process The process to get the ouput from
- * @param stdErr The array to store the stderr output
- * @return the process return code.
- * @throws InterruptedException
- */
- protected final int grabProcessOutput(final Process process,
- final ArrayList<String> stdErr) throws InterruptedException {
- return BuildHelper.grabProcessOutput(getProject(), process, stdErr);
- }
-
-
-
- /**
- * Saves a String property into the persistent storage of the project.
- * @param propertyName the name of the property. The id of the plugin is added to this string.
- * @param value the value to save
- * @return true if the save succeeded.
- */
- protected boolean saveProjectStringProperty(String propertyName, String value) {
- IProject project = getProject();
- return ProjectHelper.saveStringProperty(project, propertyName, value);
- }
-
-
- /**
- * Loads a String property from the persistent storage of the project.
- * @param propertyName the name of the property. The id of the plugin is added to this string.
- * @return the property value or null if it was not found.
- */
- protected String loadProjectStringProperty(String propertyName) {
- IProject project = getProject();
- return ProjectHelper.loadStringProperty(project, propertyName);
- }
-
- /**
- * Saves a property into the persistent storage of the project.
- * @param propertyName the name of the property. The id of the plugin is added to this string.
- * @param value the value to save
- * @return true if the save succeeded.
- */
- protected boolean saveProjectBooleanProperty(String propertyName, boolean value) {
- IProject project = getProject();
- return ProjectHelper.saveStringProperty(project, propertyName, Boolean.toString(value));
- }
-
- /**
- * Loads a boolean property from the persistent storage of the project.
- * @param propertyName the name of the property. The id of the plugin is added to this string.
- * @param defaultValue The default value to return if the property was not found.
- * @return the property value or the default value if the property was not found.
- */
- protected boolean loadProjectBooleanProperty(String propertyName, boolean defaultValue) {
- IProject project = getProject();
- return ProjectHelper.loadBooleanProperty(project, propertyName, defaultValue);
- }
-
- /**
- * Aborts the build if the SDK/project setups are broken. This does not
- * display any errors.
- *
- * @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*/);
- }
-
- protected void stopOnMarker(IProject project, String markerType, int depth,
- boolean checkSeverity)
- throws AbortBuildException {
- try {
- IMarker[] markers = project.findMarkers(markerType, false /*includeSubtypes*/, depth);
-
- if (markers.length > 0) {
- if (checkSeverity == false) {
- throw new AbortBuildException();
- } else {
- for (IMarker marker : markers) {
- int severity = marker.getAttribute(IMarker.SEVERITY, -1 /*defaultValue*/);
- if (severity == IMarker.SEVERITY_ERROR) {
- throw new AbortBuildException();
- }
- }
- }
- }
- } catch (CoreException e) {
- // don't stop, something's really screwed up and the build will break later with
- // a better error message.
- }
- }
-
- /**
- * Handles a {@link StreamException} by logging the info and marking the project.
- * This should generally be followed by exiting the build process.
- *
- * @param e the exception
- */
- protected void handleStreamException(StreamException e) {
- IAbstractFile file = e.getFile();
-
- String msg;
-
- IResource target = getProject();
- if (file instanceof IFileWrapper) {
- target = ((IFileWrapper) file).getIFile();
-
- if (e.getError() == StreamException.Error.OUTOFSYNC) {
- msg = "File is Out of sync";
- } else {
- msg = "Error reading file. Read log for details";
- }
-
- } else {
- if (e.getError() == StreamException.Error.OUTOFSYNC) {
- msg = String.format("Out of sync file: %s", file.getOsLocation());
- } else {
- msg = String.format("Error reading file %s. Read log for details",
- file.getOsLocation());
- }
- }
-
- AdtPlugin.logAndPrintError(e, getProject().getName(), msg);
- BaseProjectHelper.markResource(target, AdtConstants.MARKER_ADT, msg,
- IMarker.SEVERITY_ERROR);
- }
-
- /**
- * Handles a generic {@link Throwable} by logging the info and marking the project.
- * This should generally be followed by exiting the build process.
- *
- * @param t the {@link Throwable}.
- * @param message the message to log and to associate with the marker.
- */
- protected void handleException(Throwable t, String message) {
- AdtPlugin.logAndPrintError(t, getProject().getName(), message);
- markProject(AdtConstants.MARKER_ADT, message, IMarker.SEVERITY_ERROR);
- }
-
- /**
- * Recursively delete all the derived resources from a root resource. The root resource is not
- * deleted.
- * @param rootResource the root resource
- * @param monitor a progress monitor.
- * @throws CoreException
- *
- */
- protected void removeDerivedResources(IResource rootResource, IProgressMonitor monitor)
- throws CoreException {
- removeDerivedResources(rootResource, false, monitor);
- }
-
- /**
- * delete a resource and its children. returns true if the root resource was deleted. All
- * sub-folders *will* be deleted if they were emptied (not if they started empty).
- * @param rootResource the root resource
- * @param deleteRoot whether to delete the root folder.
- * @param monitor a progress monitor.
- * @throws CoreException
- */
- private void removeDerivedResources(IResource rootResource, boolean deleteRoot,
- IProgressMonitor monitor) throws CoreException {
- if (rootResource.exists()) {
- // if it's a folder, delete derived member.
- if (rootResource.getType() == IResource.FOLDER) {
- IFolder folder = (IFolder)rootResource;
- IResource[] members = folder.members();
- boolean wasNotEmpty = members.length > 0;
- for (IResource member : members) {
- removeDerivedResources(member, true /*deleteRoot*/, monitor);
- }
-
- // if the folder had content that is now all removed, delete the folder.
- if (deleteRoot && wasNotEmpty && folder.members().length == 0) {
- rootResource.getLocation().toFile().delete();
- }
- }
-
- // if the root resource is derived, delete it.
- if (rootResource.isDerived()) {
- rootResource.getLocation().toFile().delete();
- }
- }
- }
-
- protected void launchJob(Job newJob) {
- newJob.setPriority(Job.BUILD);
- newJob.setRule(ResourcesPlugin.getWorkspace().getRoot());
- newJob.schedule();
- }
-}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/builders/ChangedFileSet.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/builders/ChangedFileSet.java
deleted file mode 100644
index 4f5b47f6d..000000000
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/builders/ChangedFileSet.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright (C) 2012 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.annotations.NonNull;
-
-import org.apache.tools.ant.types.selectors.SelectorUtils;
-import org.eclipse.core.runtime.IPath;
-
-/**
- * Collection of file path or path patterns to be checked for changes.
- *
- * All paths should be relative to the project they belong to.
- * Patterns can use Ant-type glob patterns.
- *
- * This is an immutable class that does not store any info beyond the list of paths. This is to
- * be used in conjunction with {@link PatternBasedDeltaVisitor}.
- */
-class ChangedFileSet {
-
- private final String mLogName;
-
- private final String[] mInputs;
- private String mOutput;
-
- ChangedFileSet(String logName, String... inputs) {
- mLogName = logName;
- mInputs = inputs;
- }
-
- public void setOutput(@NonNull String output) {
- mOutput = output;
- }
-
- public boolean isInput(@NonNull String path, @NonNull IPath iPath) {
- for (String i : mInputs) {
- if (SelectorUtils.matchPath(i, path)) {
- return true;
- }
- }
-
- return false;
- }
-
- public boolean isOutput(@NonNull String path, @NonNull IPath iPath) {
- if (mOutput != null) {
- return SelectorUtils.matchPath(mOutput, path);
- }
-
- return false;
- }
-
- public String getLogName() {
- return mLogName;
- }
-}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/builders/ChangedFileSetHelper.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/builders/ChangedFileSetHelper.java
deleted file mode 100644
index 9fc19a7a6..000000000
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/builders/ChangedFileSetHelper.java
+++ /dev/null
@@ -1,200 +0,0 @@
-/*
- * Copyright (C) 2012 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.ide.eclipse.adt.AdtConstants;
-import com.android.ide.eclipse.adt.internal.project.BaseProjectHelper;
-
-import org.eclipse.core.resources.IFolder;
-import org.eclipse.core.resources.IProject;
-import org.eclipse.core.resources.IResource;
-import org.eclipse.core.runtime.IPath;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Helper class to generate {@link ChangedFileSet} for given projects.
- *
- * Also contains non project specific {@link ChangedFileSet} such as {@link #MANIFEST}
- * and {@link #NATIVE_LIBS}
- */
-class ChangedFileSetHelper {
-
- final static ChangedFileSet MANIFEST;
- final static ChangedFileSet NATIVE_LIBS;
-
- static {
- MANIFEST = new ChangedFileSet("manifest", //$NON-NLS-1$
- SdkConstants.FN_ANDROID_MANIFEST_XML);
-
- // FIXME: move compiled native libs to bin/libs/
- NATIVE_LIBS = new ChangedFileSet(
- "nativeLibs",
- SdkConstants.FD_NATIVE_LIBS + "/*/*.so", //$NON-NLS-1$
- SdkConstants.FD_NATIVE_LIBS + "/*/" + SdkConstants.FN_GDBSERVER); //$NON-NLS-1$
- }
-
- /**
- * Returns a ChangedFileSet for Java resources inside a given project's source folders.
- * @param project the project.
- * @return a ChangedFileSet
- */
- static ChangedFileSet getJavaResCfs(@NonNull IProject project) {
-
- // get the source folder for the given project.
- IPath projectPath = project.getFullPath();
-
- // get the source folders.
- List<IPath> srcPaths = BaseProjectHelper.getSourceClasspaths(project);
- List<String> paths = new ArrayList<String>(srcPaths.size());
-
- // create a pattern for each of them.
- for (IPath path : srcPaths) {
- paths.add(path.makeRelativeTo(projectPath).toString() + "/**"); //$NON-NLS-1$
- }
-
- // custom ChangedFileSet to ignore .java files.
- return new JavaResChangedSet("javaRes", //$NON-NLS-1$
- paths.toArray(new String[paths.size()]));
- }
-
- /**
- * Returns a {@link ChangedFileSet} for all the resources (included assets), and the output
- * file (compiled resources
- * @param project the project
- * @return a ChangeFileSet
- */
- static ChangedFileSet getResCfs(@NonNull IProject project) {
- // generated res is inside the project's android output folder
- String path = getRelativeAndroidOut(project);
-
- ChangedFileSet set = new ChangedFileSet(
- "resources", //$NON-NLS-1$
- SdkConstants.FD_RES + "/**", //$NON-NLS-1$
- SdkConstants.FD_ASSETS + "/**", //$NON-NLS-1$
- path + '/' + AdtConstants.WS_BIN_RELATIVE_BC + "/**"); //$NON-NLS-1$
-
- // output file is based on the project's android output folder
- set.setOutput(path + '/' + AdtConstants.FN_RESOURCES_AP_);
-
- return set;
- }
-
- /**
- * Returns a {@link ChangedFileSet} for all the resources (included assets), and the output
- * file (compiled resources
- * @param project the project
- * @return a ChangeFileSet
- */
- static ChangedFileSet getMergedManifestCfs(@NonNull IProject project) {
- // input path is inside the project's android output folder
- String path = getRelativeAndroidOut(project);
-
- ChangedFileSet set = new ChangedFileSet(
- "mergedManifest", //$NON-NLS-1$
- path + '/' + SdkConstants.FN_ANDROID_MANIFEST_XML);
-
- return set;
- }
-
- /**
- * Returns a {@link ChangedFileSet} for the generated R.txt file
- * @param project the project
- * @return a ChangeFileSet
- */
- static ChangedFileSet getTextSymbols(@NonNull IProject project) {
- // input path is inside the project's android output folder
- String path = getRelativeAndroidOut(project);
-
- ChangedFileSet set = new ChangedFileSet(
- "textSymbols", //$NON-NLS-1$
- path + '/' + SdkConstants.FN_RESOURCE_TEXT);
-
- return set;
- }
-
- /**
- * Returns a {@link ChangedFileSet} for a project's javac output.
- * @param project the project
- * @return a ChangedFileSet
- */
- static ChangedFileSet getByteCodeCfs(@NonNull IProject project) {
- // input pattern is based on the project's Java compiler's output folder
- String path = getRelativeJavaCOut(project);
-
- ChangedFileSet set = new ChangedFileSet("compiledCode", //$NON-NLS-1$
- path + "/**/*" + SdkConstants.DOT_CLASS); //$NON-NLS-1$
-
- return set;
- }
-
- /**
- * Returns a {@link ChangedFileSet} for a project's complete resources, including
- * generated resources and crunch cache.
- * @param project the project
- * @return a ChangeFileSet
- */
- static ChangedFileSet getFullResCfs(@NonNull IProject project) {
- // generated res are in the project's android output folder
- String path = getRelativeAndroidOut(project);
-
- ChangedFileSet set = new ChangedFileSet("libResources", //$NON-NLS-1$
- SdkConstants.FD_RES + "/**", //$NON-NLS-1$
- path + '/' + SdkConstants.FD_RES + "/**"); //$NON-NLS-1$
-
- return set;
- }
-
- /**
- * Returns a {@link ChangedFileSet} for a project's whole code, including
- * compiled bytecode, 3rd party libs, and the output file containing the Dalvik
- * bytecode file.
- * @param project the project
- * @return a ChangeFileSet
- */
- static ChangedFileSet getCodeCfs(@NonNull IProject project) {
- // input pattern is based on the project's Java compiler's output folder
- String path = getRelativeJavaCOut(project);
-
- ChangedFileSet set = new ChangedFileSet("classAndJars", //$NON-NLS-1$
- path + "/**/*" + SdkConstants.DOT_CLASS, //$NON-NLS-1$
- SdkConstants.FD_NATIVE_LIBS + "/*" + SdkConstants.DOT_JAR); //$NON-NLS-1$
-
- // output file is based on the project's android output folder
- path = getRelativeAndroidOut(project);
- set.setOutput(path + '/' + SdkConstants.FN_APK_CLASSES_DEX);
-
- return set;
- }
-
- private static String getRelativePath(@NonNull IProject project, @NonNull IResource resource) {
- return resource.getFullPath().makeRelativeTo(project.getFullPath()).toString();
- }
-
- private static String getRelativeAndroidOut(@NonNull IProject project) {
- IFolder folder = BaseProjectHelper.getAndroidOutputFolder(project);
- return getRelativePath(project, folder);
- }
-
- private static String getRelativeJavaCOut(@NonNull IProject project) {
- IFolder folder = BaseProjectHelper.getJavaOutputFolder(project);
- return getRelativePath(project, folder);
- }
-}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/builders/JavaResChangedSet.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/builders/JavaResChangedSet.java
deleted file mode 100644
index 6b257efbf..000000000
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/builders/JavaResChangedSet.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright (C) 2012 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.annotations.NonNull;
-import com.android.sdklib.build.ApkBuilder;
-
-import org.eclipse.core.runtime.IPath;
-
-/**
- * Custom {@link ChangedFileSet} for java resources.
- *
- * This builds the set of inputs to be all the source folders of the given project,
- * and excludes files that won't be packaged.
- * This exclusion can't be easily described as a glob-pattern so it's overriding the default
- * behavior instead.
- *
- */
-class JavaResChangedSet extends ChangedFileSet {
-
- JavaResChangedSet(String logName, String... inputs) {
- super(logName, inputs);
- }
-
- @Override
- public boolean isInput(@NonNull String path, @NonNull IPath iPath) {
- if (!ApkBuilder.checkFileForPackaging(iPath.lastSegment(), iPath.getFileExtension())) {
- return false;
- }
- return super.isInput(path, iPath);
- }
-}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/builders/PatternBasedDeltaVisitor.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/builders/PatternBasedDeltaVisitor.java
deleted file mode 100644
index b52ede90c..000000000
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/builders/PatternBasedDeltaVisitor.java
+++ /dev/null
@@ -1,139 +0,0 @@
-/*
- * Copyright (C) 2012 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.ide.eclipse.adt.AdtPlugin;
-import com.android.ide.eclipse.adt.internal.build.BuildHelper;
-
-import org.eclipse.core.resources.IFolder;
-import org.eclipse.core.resources.IProject;
-import org.eclipse.core.resources.IResource;
-import org.eclipse.core.resources.IResourceDelta;
-import org.eclipse.core.resources.IResourceDeltaVisitor;
-import org.eclipse.core.runtime.CoreException;
-import org.eclipse.core.runtime.IPath;
-import org.eclipse.core.runtime.IStatus;
-
-import java.util.ArrayList;
-import java.util.IdentityHashMap;
-import java.util.List;
-import java.util.Map;
-
-/**
- * Delta visitor checking changed files against given glob-patterns.
- *
- * The visitor is given {@link ChangedFileSet} objects which contains patterns to detect change
- * in input and output files. (Output files are only tested if the delta indicate the file
- * was removed).
- *
- * After the visitor has visited the whole delta, it can be queried to see which ChangedFileSet
- * recognized a file change. (ChangedFileSet are immutable and do not record this info).
- */
-class PatternBasedDeltaVisitor implements IResourceDeltaVisitor {
-
- private final static boolean DEBUG_LOG = "1".equals( //$NON-NLS-1$
- System.getenv("ANDROID_VISITOR_DEBUG")); //$NON-NLS-1$
-
- private final IProject mMainProject;
- private final IProject mDeltaProject;
-
- private final List<ChangedFileSet> mSets = new ArrayList<ChangedFileSet>();
- private final Map<ChangedFileSet, Boolean> mResults =
- new IdentityHashMap<ChangedFileSet, Boolean>();
-
- private final String mLogName;
-
- PatternBasedDeltaVisitor(IProject mainProject, IProject deltaProject, String logName) {
- mMainProject = mainProject;
- mDeltaProject = deltaProject;
- mLogName = logName;
- if (DEBUG_LOG) {
- AdtPlugin.log(IStatus.INFO, "%s (%s): Delta for %s", //$NON-NLS-1$
- mMainProject.getName(), mLogName, mDeltaProject.getName());
- }
- }
-
- void addSet(ChangedFileSet bundle) {
- mSets.add(bundle);
- }
-
- boolean checkSet(ChangedFileSet bundle) {
- Boolean r = mResults.get(bundle);
- if (r != null) {
- return r.booleanValue();
- }
-
- return false;
- }
-
- @Override
- public boolean visit(IResourceDelta delta) throws CoreException {
- IResource resource = delta.getResource();
-
- if (resource.getType() == IResource.FOLDER) {
- // always visit the subfolders, unless the folder is not to be included
- return BuildHelper.checkFolderForPackaging((IFolder)resource);
-
- } else if (resource.getType() == IResource.FILE) {
- IPath path = resource.getFullPath().makeRelativeTo(mDeltaProject.getFullPath());
- String pathStr = path.toString();
-
- // FIXME: no need to loop through all the sets once they have all said they need something (return false below and above)
- for (ChangedFileSet set : mSets) {
- // FIXME: should ignore sets that have already returned true.
-
- if (set.isInput(pathStr, path)) {
- mResults.put(set, Boolean.TRUE);
-
- if (DEBUG_LOG) {
- String cfs_logName = set.getLogName();
-
- if (cfs_logName != null) {
- AdtPlugin.log(IStatus.INFO, "%s (%s:%s): %s", //$NON-NLS-1$
- mMainProject.getName(), mLogName, cfs_logName,
- resource.getFullPath().toString());
- } else {
- AdtPlugin.log(IStatus.INFO, "%s (%s): %s", //$NON-NLS-1$
- mMainProject.getName(), mLogName,
- resource.getFullPath().toString());
- }
- }
-
- } else if (delta.getKind() == IResourceDelta.REMOVED &&
- set.isOutput(pathStr, path)) {
- mResults.put(set, Boolean.TRUE);
-
- if (DEBUG_LOG) {
- String cfs_logName = set.getLogName();
-
- if (cfs_logName != null) {
- AdtPlugin.log(IStatus.INFO, "%s (%s:%s): %s", //$NON-NLS-1$
- mMainProject.getName(), mLogName, cfs_logName,
- resource.getFullPath().toString());
- } else {
- AdtPlugin.log(IStatus.INFO, "%s (%s): %s", //$NON-NLS-1$
- mMainProject.getName(), mLogName,
- resource.getFullPath().toString());
- }
- }
- }
- }
- }
-
- return true;
- }
-}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/builders/PostCompilerBuilder.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/builders/PostCompilerBuilder.java
deleted file mode 100644
index 8aacb44ef..000000000
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/builders/PostCompilerBuilder.java
+++ /dev/null
@@ -1,946 +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.eclipse.adt.AdtConstants;
-import com.android.ide.eclipse.adt.AdtPlugin;
-import com.android.ide.eclipse.adt.AndroidPrintStream;
-import com.android.ide.eclipse.adt.internal.build.AaptExecException;
-import com.android.ide.eclipse.adt.internal.build.AaptParser;
-import com.android.ide.eclipse.adt.internal.build.AaptResultException;
-import com.android.ide.eclipse.adt.internal.build.BuildHelper;
-import com.android.ide.eclipse.adt.internal.build.BuildHelper.ResourceMarker;
-import com.android.ide.eclipse.adt.internal.build.DexException;
-import com.android.ide.eclipse.adt.internal.build.Messages;
-import com.android.ide.eclipse.adt.internal.build.NativeLibInJarException;
-import com.android.ide.eclipse.adt.internal.lint.LintDeltaProcessor;
-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.ApkInstallManager;
-import com.android.ide.eclipse.adt.internal.project.BaseProjectHelper;
-import com.android.ide.eclipse.adt.internal.project.LibraryClasspathContainerInitializer;
-import com.android.ide.eclipse.adt.internal.project.ProjectHelper;
-import com.android.ide.eclipse.adt.internal.resources.manager.ResourceManager;
-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.prefs.AndroidLocation.AndroidLocationException;
-import com.android.sdklib.build.ApkBuilder;
-import com.android.sdklib.build.ApkCreationException;
-import com.android.sdklib.build.DuplicateFileException;
-import com.android.sdklib.build.IArchiveBuilder;
-import com.android.sdklib.build.SealedApkException;
-import com.android.sdklib.internal.build.DebugKeyProvider.KeytoolException;
-import com.android.xml.AndroidManifest;
-
-import org.eclipse.core.resources.IContainer;
-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.runtime.CoreException;
-import org.eclipse.core.runtime.IPath;
-import org.eclipse.core.runtime.IProgressMonitor;
-import org.eclipse.core.runtime.IStatus;
-import org.eclipse.jdt.core.IJavaModelMarker;
-import org.eclipse.jdt.core.IJavaProject;
-import org.eclipse.jdt.core.JavaCore;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-import java.util.Map;
-import java.util.jar.Attributes;
-import java.util.jar.JarEntry;
-import java.util.jar.JarOutputStream;
-import java.util.jar.Manifest;
-import java.util.regex.Pattern;
-
-public class PostCompilerBuilder 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.ApkBuilder"; //$NON-NLS-1$
-
- private static final String PROPERTY_CONVERT_TO_DEX = "convertToDex"; //$NON-NLS-1$
- private static final String PROPERTY_PACKAGE_RESOURCES = "packageResources"; //$NON-NLS-1$
- private static final String PROPERTY_BUILD_APK = "buildApk"; //$NON-NLS-1$
-
- /** Flag to pass to PostCompiler builder that sets if it runs or not.
- * Set this flag whenever calling build if PostCompiler is to run
- */
- public final static String POST_C_REQUESTED = "RunPostCompiler"; //$NON-NLS-1$
-
- /**
- * Dex conversion flag. This is set to true if one of the changed/added/removed
- * file is a .class file. Upon visiting all the delta resource, if this
- * flag is true, then we know we'll have to make the "classes.dex" file.
- */
- private boolean mConvertToDex = false;
-
- /**
- * Package resources flag. This is set to true if one of the changed/added/removed
- * file is a resource file. Upon visiting all the delta resource, if
- * this flag is true, then we know we'll have to repackage the resources.
- */
- private boolean mPackageResources = false;
-
- /**
- * Final package build flag.
- */
- private boolean mBuildFinalPackage = false;
-
- private AndroidPrintStream mOutStream = null;
- private AndroidPrintStream mErrStream = null;
-
-
- private ResourceMarker mResourceMarker = new ResourceMarker() {
- @Override
- public void setWarning(IResource resource, String message) {
- BaseProjectHelper.markResource(resource, AdtConstants.MARKER_PACKAGING,
- message, IMarker.SEVERITY_WARNING);
- }
- };
-
-
- public PostCompilerBuilder() {
- super();
- }
-
- @Override
- protected void clean(IProgressMonitor monitor) throws CoreException {
- super.clean(monitor);
-
- // Get the project.
- IProject project = getProject();
-
- if (DEBUG_LOG) {
- AdtPlugin.log(IStatus.INFO, "%s CLEAN(POST)", project.getName());
- }
-
- // Clear the project of the generic markers
- removeMarkersFromContainer(project, AdtConstants.MARKER_AAPT_PACKAGE);
- removeMarkersFromContainer(project, AdtConstants.MARKER_PACKAGING);
-
- // also remove the files in the output folder (but not the Eclipse output folder).
- IFolder javaOutput = BaseProjectHelper.getJavaOutputFolder(project);
- IFolder androidOutput = BaseProjectHelper.getAndroidOutputFolder(project);
-
- if (javaOutput.equals(androidOutput) == false) {
- // get the content
- IResource[] members = androidOutput.members();
- for (IResource member : members) {
- if (member.equals(javaOutput) == false) {
- member.delete(true /*force*/, monitor);
- }
- }
- }
- }
-
- // 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(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;
- }
-
- private static class JarBuilder implements IArchiveBuilder {
-
- private static Pattern R_PATTERN = Pattern.compile("R(\\$.*)?\\.class"); //$NON-NLS-1$
- private static String BUILD_CONFIG_CLASS = "BuildConfig.class"; //$NON-NLS-1$
-
- private final byte[] buffer = new byte[1024];
- private final JarOutputStream mOutputStream;
- private final String mAppPackage;
-
- JarBuilder(JarOutputStream outputStream, String appPackage) {
- mOutputStream = outputStream;
- mAppPackage = appPackage.replace('.', '/');
- }
-
- public void addFile(IFile file, IFolder rootFolder) throws ApkCreationException {
- // we only package class file from the output folder
- if (SdkConstants.EXT_CLASS.equals(file.getFileExtension()) == false) {
- return;
- }
-
- IPath packageApp = file.getParent().getFullPath().makeRelativeTo(
- rootFolder.getFullPath());
-
- String name = file.getName();
- // Ignore the library's R/Manifest/BuildConfig classes.
- if (mAppPackage.equals(packageApp.toString()) &&
- (BUILD_CONFIG_CLASS.equals(name) ||
- R_PATTERN.matcher(name).matches())) {
- return;
- }
-
- IPath path = file.getFullPath().makeRelativeTo(rootFolder.getFullPath());
- try {
- addFile(file.getContents(), file.getLocalTimeStamp(), path.toString());
- } catch (ApkCreationException e) {
- throw e;
- } catch (Exception e) {
- throw new ApkCreationException(e, "Failed to add %s", file);
- }
- }
-
- @Override
- public void addFile(File file, String archivePath) throws ApkCreationException,
- SealedApkException, DuplicateFileException {
- try {
- FileInputStream inputStream = new FileInputStream(file);
- long lastModified = file.lastModified();
- addFile(inputStream, lastModified, archivePath);
- } catch (ApkCreationException e) {
- throw e;
- } catch (Exception e) {
- throw new ApkCreationException(e, "Failed to add %s", file);
- }
- }
-
- private void addFile(InputStream content, long lastModified, String archivePath)
- throws IOException, ApkCreationException {
- // create the jar entry
- JarEntry entry = new JarEntry(archivePath);
- entry.setTime(lastModified);
-
- try {
- // add the entry to the jar archive
- mOutputStream.putNextEntry(entry);
-
- // read the content of the entry from the input stream, and write
- // it into the archive.
- int count;
- while ((count = content.read(buffer)) != -1) {
- mOutputStream.write(buffer, 0, count);
- }
- } finally {
- try {
- if (content != null) {
- content.close();
- }
- } catch (Exception e) {
- throw new ApkCreationException(e, "Failed to close stream");
- }
- }
- }
- }
-
- /**
- * Updates the crunch cache if needed and return true if the build must continue.
- */
- private boolean updateCrunchCache(IProject project, BuildHelper helper) {
- try {
- helper.updateCrunchCache();
- } catch (AaptExecException e) {
- BaseProjectHelper.markResource(project, AdtConstants.MARKER_PACKAGING,
- e.getMessage(), IMarker.SEVERITY_ERROR);
- return false;
- } 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);
- }
- }
-
- return true;
- }
-
- /**
- * Writes the library jar file.
- * @param jarIFile the destination file
- * @param project the library project
- * @param appPackage the library android package
- * @param javaOutputFolder the JDT output folder.
- */
- private void writeLibraryPackage(IFile jarIFile, IProject project, String appPackage,
- IFolder javaOutputFolder) {
-
- JarOutputStream jos = null;
- try {
- Manifest manifest = new Manifest();
- Attributes mainAttributes = manifest.getMainAttributes();
- mainAttributes.put(Attributes.Name.CLASS_PATH, "Android ADT"); //$NON-NLS-1$
- mainAttributes.putValue("Created-By", "1.0 (Android)"); //$NON-NLS-1$ //$NON-NLS-2$
- jos = new JarOutputStream(
- new FileOutputStream(jarIFile.getLocation().toFile()), manifest);
-
- JarBuilder jarBuilder = new JarBuilder(jos, appPackage);
-
- // write the class files
- writeClassFilesIntoJar(jarBuilder, javaOutputFolder, javaOutputFolder);
-
- // now write the standard Java resources from the output folder
- ApkBuilder.addSourceFolder(jarBuilder, javaOutputFolder.getLocation().toFile());
-
- saveProjectBooleanProperty(PROPERTY_CONVERT_TO_DEX, mConvertToDex);
- } catch (Exception e) {
- AdtPlugin.log(e, "Failed to write jar file %s", jarIFile.getLocation().toOSString());
- } finally {
- if (jos != null) {
- try {
- jos.close();
- } catch (IOException e) {
- // pass
- }
- }
- }
- }
-
- private void writeClassFilesIntoJar(JarBuilder builder, IFolder folder, IFolder rootFolder)
- throws CoreException, IOException, ApkCreationException {
- IResource[] members = folder.members();
- for (IResource member : members) {
- if (member.getType() == IResource.FOLDER) {
- writeClassFilesIntoJar(builder, (IFolder) member, rootFolder);
- } else if (member.getType() == IResource.FILE) {
- IFile file = (IFile) member;
- builder.addFile(file, rootFolder);
- }
- }
- }
-
- @Override
- protected void startupOnInitialize() {
- super.startupOnInitialize();
-
- // load the build status. We pass true as the default value to
- // force a recompile in case the property was not found
- mConvertToDex = loadProjectBooleanProperty(PROPERTY_CONVERT_TO_DEX, true);
- mPackageResources = loadProjectBooleanProperty(PROPERTY_PACKAGE_RESOURCES, true);
- mBuildFinalPackage = loadProjectBooleanProperty(PROPERTY_BUILD_APK, true);
- }
-
- @Override
- protected void abortOnBadSetup(
- @NonNull IJavaProject javaProject,
- @Nullable ProjectState projectState) throws AbortBuildException, CoreException {
- super.abortOnBadSetup(javaProject, projectState);
-
- IProject iProject = getProject();
-
- // do a (hopefully quick) search for Precompiler type markers. Those are always only
- // errors.
- stopOnMarker(iProject, AdtConstants.MARKER_AAPT_COMPILE, IResource.DEPTH_INFINITE,
- false /*checkSeverity*/);
- stopOnMarker(iProject, AdtConstants.MARKER_AIDL, IResource.DEPTH_INFINITE,
- false /*checkSeverity*/);
- stopOnMarker(iProject, AdtConstants.MARKER_RENDERSCRIPT, IResource.DEPTH_INFINITE,
- false /*checkSeverity*/);
- stopOnMarker(iProject, AdtConstants.MARKER_ANDROID, IResource.DEPTH_ZERO,
- false /*checkSeverity*/);
-
- // do a search for JDT markers. Those can be errors or warnings
- stopOnMarker(iProject, IJavaModelMarker.JAVA_MODEL_PROBLEM_MARKER,
- IResource.DEPTH_INFINITE, true /*checkSeverity*/);
- stopOnMarker(iProject, IJavaModelMarker.BUILDPATH_PROBLEM_MARKER,
- IResource.DEPTH_INFINITE, true /*checkSeverity*/);
- }
-}
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);
- }
-}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/builders/PreCompilerDeltaVisitor.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/builders/PreCompilerDeltaVisitor.java
deleted file mode 100644
index 57316f568..000000000
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/builders/PreCompilerDeltaVisitor.java
+++ /dev/null
@@ -1,417 +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.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.Messages;
-import com.android.ide.eclipse.adt.internal.build.SourceChangeHandler;
-import com.android.ide.eclipse.adt.internal.build.builders.BaseBuilder.BaseDeltaVisitor;
-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.io.IFileWrapper;
-import com.google.common.collect.Lists;
-
-import org.eclipse.core.resources.IContainer;
-import org.eclipse.core.resources.IFile;
-import org.eclipse.core.resources.IFolder;
-import org.eclipse.core.resources.IResource;
-import org.eclipse.core.resources.IResourceDelta;
-import org.eclipse.core.resources.IResourceDeltaVisitor;
-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 java.util.Arrays;
-import java.util.List;
-
-/**
- * Resource Delta visitor for the pre-compiler.
- * <p/>This delta visitor only cares about files that are the source or the result of actions of the
- * {@link PreCompilerBuilder}:
- * <ul><li>R.java/Manifest.java generated by compiling the resources</li>
- * <li>Any Java files generated by <code>aidl</code></li></ul>.
- *
- * Therefore it looks for the following:
- * <ul><li>Any modification in the resource folder</li>
- * <li>Removed files from the source folder receiving generated Java files</li>
- * <li>Any modification to aidl files.</li>
- *
- */
-class PreCompilerDeltaVisitor extends BaseDeltaVisitor implements IResourceDeltaVisitor {
-
- // Result fields.
- private boolean mChangedManifest = false;
-
- /**
- * Compile flag. This is set to true if one of the changed/added/removed
- * files is Manifest.java, or R.java. All other file changes
- * will be taken care of by ResourceManager.
- */
- private boolean mCompileResources = false;
-
- /** Manifest check/parsing flag. */
- private boolean mCheckedManifestXml = false;
-
- /** Application Package, gathered from the parsing of the manifest */
- private String mJavaPackage = null;
- /** minSDKVersion attribute value, gathered from the parsing of the manifest */
- private String mMinSdkVersion = null;
-
- // Internal usage fields.
- /**
- * In Resource folder flag. This allows us to know if we're in the
- * resource folder.
- */
- private boolean mInRes = false;
-
- /**
- * Current Source folder. This allows us to know if we're in a source
- * folder, and which folder.
- */
- private IFolder mSourceFolder = null;
-
- /** List of source folders. */
- private final List<IPath> mSourceFolders;
- private boolean mIsGenSourceFolder = false;
-
- private final List<SourceChangeHandler> mSourceChangeHandlers = Lists.newArrayList();
- private final IWorkspaceRoot mRoot;
-
- private IFolder mAndroidOutputFolder;
-
- public PreCompilerDeltaVisitor(BaseBuilder builder, List<IPath> sourceFolders,
- SourceChangeHandler... handlers) {
- super(builder);
- mSourceFolders = sourceFolders;
- mRoot = ResourcesPlugin.getWorkspace().getRoot();
-
- mSourceChangeHandlers.addAll(Arrays.asList(handlers));
-
- mAndroidOutputFolder = BaseProjectHelper.getAndroidOutputFolder(builder.getProject());
- }
-
- /**
- * Get whether Manifest.java, Manifest.xml, or R.java have changed
- * @return true if any of Manifest.xml, Manifest.java, or R.java have been modified
- */
- public boolean getCompileResources() {
- return mCompileResources || mChangedManifest;
- }
-
- public boolean hasManifestChanged() {
- return mChangedManifest;
- }
-
- /**
- * Returns whether the manifest file was parsed/checked for error during the resource delta
- * visiting.
- */
- public boolean getCheckedManifestXml() {
- return mCheckedManifestXml;
- }
-
- /**
- * Returns the manifest package if the manifest was checked/parsed.
- * <p/>
- * This can return null in two cases:
- * <ul>
- * <li>The manifest was not part of the resource change delta, and the manifest was
- * not checked/parsed ({@link #getCheckedManifestXml()} returns <code>false</code>)</li>
- * <li>The manifest was parsed ({@link #getCheckedManifestXml()} returns <code>true</code>),
- * but the package declaration is missing</li>
- * </ul>
- * @return the manifest package or null.
- */
- public String getManifestPackage() {
- return mJavaPackage;
- }
-
- /**
- * Returns the minSDkVersion attribute from the manifest if it was checked/parsed.
- * <p/>
- * This can return null in two cases:
- * <ul>
- * <li>The manifest was not part of the resource change delta, and the manifest was
- * not checked/parsed ({@link #getCheckedManifestXml()} returns <code>false</code>)</li>
- * <li>The manifest was parsed ({@link #getCheckedManifestXml()} returns <code>true</code>),
- * but the package declaration is missing</li>
- * </ul>
- * @return the minSdkVersion or null.
- */
- public String getMinSdkVersion() {
- return mMinSdkVersion;
- }
-
- /*
- * (non-Javadoc)
- *
- * @see org.eclipse.core.resources.IResourceDeltaVisitor
- * #visit(org.eclipse.core.resources.IResourceDelta)
- */
- @Override
- public boolean visit(IResourceDelta delta) throws CoreException {
- // we are only going to look for changes in res/, source folders and in
- // AndroidManifest.xml since the delta visitor goes through the main
- // folder before its children we can check when the path segment
- // count is 2 (format will be /$Project/folder) and make sure we are
- // processing res/, source folders or AndroidManifest.xml
-
- IResource resource = delta.getResource();
- IPath path = resource.getFullPath();
- String[] segments = path.segments();
-
- // since the delta visitor also visits the root we return true if
- // segments.length = 1
- if (segments.length == 1) {
- // this is always the Android project since we call
- // Builder#getDelta(IProject) on the project itself.
- return true;
- } else if (segments.length == 2) {
- // if we are at an item directly under the root directory,
- // then we are not yet in a source or resource folder
- mInRes = false;
- mSourceFolder = null;
-
- if (SdkConstants.FD_RESOURCES.equalsIgnoreCase(segments[1])) {
- // this is the resource folder that was modified. we want to
- // see its content.
-
- // since we're going to visit its children next, we set the
- // flag
- mInRes = true;
- mSourceFolder = null;
- return true;
- } else if (SdkConstants.FN_ANDROID_MANIFEST_XML.equalsIgnoreCase(segments[1])) {
- // any change in the manifest could trigger a new R.java
- // class, so we don't need to check the delta kind
- if (delta.getKind() != IResourceDelta.REMOVED) {
- // clean the error markers on the file.
- IFile manifestFile = (IFile)resource;
-
- if (manifestFile.exists()) {
- manifestFile.deleteMarkers(AdtConstants.MARKER_XML, true,
- IResource.DEPTH_ZERO);
- manifestFile.deleteMarkers(AdtConstants.MARKER_ANDROID, true,
- IResource.DEPTH_ZERO);
- }
-
- // parse the manifest for data and error
- ManifestData manifestData = AndroidManifestHelper.parse(
- new IFileWrapper(manifestFile), true /*gatherData*/, this);
-
- if (manifestData != null) {
- mJavaPackage = manifestData.getPackage();
- mMinSdkVersion = manifestData.getMinSdkVersionString();
- }
-
- mCheckedManifestXml = true;
- }
- mChangedManifest = true;
-
- // we don't want to go to the children, not like they are
- // any for this resource anyway.
- return false;
- }
- }
-
- // at this point we can either be in the source folder or in the
- // resource folder or in a different folder that contains a source
- // folder.
- // This is due to not all source folder being src/. Some could be
- // something/somethingelse/src/
-
- // so first we test if we already know we are in a source or
- // resource folder.
-
- if (mSourceFolder != null) {
- // if we are in the res folder, we are looking for the following changes:
- // - added/removed/modified aidl files.
- // - missing R.java file
-
- // if the resource is a folder, we just go straight to the children
- if (resource.getType() == IResource.FOLDER) {
- return true;
- }
-
- if (resource.getType() != IResource.FILE) {
- return false;
- }
- IFile file = (IFile)resource;
-
- // get the modification kind
- int kind = delta.getKind();
-
- // we process normal source folder and the 'gen' source folder differently.
- if (mIsGenSourceFolder) {
- // this is the generated java file source folder.
- // - if R.java/Manifest.java are removed/modified, we recompile the resources
- // - if aidl files are removed/modified, we recompile them.
-
- boolean outputWarning = false;
-
- String fileName = resource.getName();
-
- // Special case of R.java/Manifest.java.
- if (SdkConstants.FN_RESOURCE_CLASS.equals(fileName) ||
- SdkConstants.FN_MANIFEST_CLASS.equals(fileName)) {
- // if it was removed, there's a possibility that it was removed due to a
- // package change, or an aidl that was removed, but the only thing
- // that will happen is that we'll have an extra build. Not much of a problem.
- mCompileResources = true;
-
- // we want a warning
- outputWarning = true;
- } else {
- // look to see if this file was generated by a processor.
- for (SourceChangeHandler handler : mSourceChangeHandlers) {
- if (handler.handleGeneratedFile(file, kind)) {
- outputWarning = true;
- break; // there shouldn't be 2 processors that handle the same file.
- }
- }
- }
-
- if (outputWarning) {
- if (kind == IResourceDelta.REMOVED) {
- // We print an error just so that it's red, but it's just a warning really.
- String msg = String.format(Messages.s_Removed_Recreating_s, fileName);
- AdtPlugin.printErrorToConsole(mBuilder.getProject(), msg);
- } else if (kind == IResourceDelta.CHANGED) {
- // the file was modified manually! we can't allow it.
- String msg = String.format(Messages.s_Modified_Manually_Recreating_s,
- fileName);
- AdtPlugin.printErrorToConsole(mBuilder.getProject(), msg);
- }
- }
- } else {
- // this is another source folder.
- for (SourceChangeHandler handler : mSourceChangeHandlers) {
- handler.handleSourceFile(file, kind);
- }
- }
-
- // no children.
- return false;
- } else if (mInRes) {
- // if we are in the res folder, we are looking for the following
- // changes:
- // - added/removed/modified xml files.
- // - added/removed files of any other type
-
- // if the resource is a folder, we just go straight to the
- // children
- if (resource.getType() == IResource.FOLDER) {
- return true;
- }
-
- // get the extension of the resource
- String ext = resource.getFileExtension();
- int kind = delta.getKind();
-
- String p = resource.getProjectRelativePath().toString();
- String message = null;
- switch (kind) {
- case IResourceDelta.CHANGED:
- // display verbose message
- message = String.format(Messages.s_Modified_Recreating_s, p);
- break;
- case IResourceDelta.ADDED:
- // display verbose message
- message = String.format(Messages.Added_s_s_Needs_Updating, p,
- SdkConstants.FN_RESOURCE_CLASS);
- break;
- case IResourceDelta.REMOVED:
- // display verbose message
- message = String.format(Messages.s_Removed_s_Needs_Updating, p,
- SdkConstants.FN_RESOURCE_CLASS);
- break;
- }
- if (message != null) {
- AdtPlugin.printBuildToConsole(BuildVerbosity.VERBOSE,
- mBuilder.getProject(), message);
- }
-
- // If it's an XML resource, check the syntax
- if (SdkConstants.EXT_XML.equalsIgnoreCase(ext) && kind != IResourceDelta.REMOVED) {
- // check xml Validity
- mBuilder.checkXML(resource, this);
- }
- // Whether or not to generate R.java for a changed resource is taken care of by the
- // Resource Manager.
- } else if (resource instanceof IFolder) {
- // first check if we are in the android output folder.
- if (resource.equals(mAndroidOutputFolder)) {
- // we want to visit the merged manifest.
- return true;
- }
-
- // in this case we may be inside a folder that contains a source
- // folder, go through the list of known source folders
-
- for (IPath sourceFolderPath : mSourceFolders) {
- // first check if they match exactly.
- if (sourceFolderPath.equals(path)) {
- // this is a source folder!
- mInRes = false;
- mSourceFolder = getFolder(sourceFolderPath); // all non null due to test above
- mIsGenSourceFolder = path.segmentCount() == 2 &&
- path.segment(1).equals(SdkConstants.FD_GEN_SOURCES);
- return true;
- }
-
- // check if we are on the way to a source folder.
- int count = sourceFolderPath.matchingFirstSegments(path);
- if (count == path.segmentCount()) {
- mInRes = false;
- return true;
- }
- }
-
- // if we're here, we are visiting another folder
- // like /$Project/bin/ for instance (we get notified for changes
- // in .class!)
- // This could also be another source folder and we have found
- // R.java in a previous source folder
- // We don't want to visit its children
- return false;
- }
-
- return false;
- }
-
- /**
- * Returns a handle to the folder identified by the given path in this container.
- * <p/>The different with {@link IContainer#getFolder(IPath)} is that this returns a non
- * null object only if the resource actually exists and is a folder (and not a file)
- * @param path the path of the folder to return.
- * @return a handle to the folder if it exists, or null otherwise.
- */
- private IFolder getFolder(IPath path) {
- IResource resource = mRoot.findMember(path);
- if (resource != null && resource.exists() && resource.getType() == IResource.FOLDER) {
- return (IFolder)resource;
- }
-
- return null;
- }
-
-}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/builders/ResourceManagerBuilder.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/builders/ResourceManagerBuilder.java
deleted file mode 100644
index 8e01cca29..000000000
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/builders/ResourceManagerBuilder.java
+++ /dev/null
@@ -1,317 +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.ide.eclipse.adt.AdtConstants;
-import com.android.ide.eclipse.adt.AdtPlugin;
-import com.android.ide.eclipse.adt.internal.build.Messages;
-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.BaseProjectHelper;
-import com.android.ide.eclipse.adt.internal.project.ProjectHelper;
-import com.android.ide.eclipse.adt.internal.sdk.ProjectState;
-import com.android.ide.eclipse.adt.internal.sdk.Sdk;
-import com.android.sdklib.BuildToolInfo;
-import com.android.sdklib.IAndroidTarget;
-import com.android.utils.Pair;
-
-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.IWorkspaceRoot;
-import org.eclipse.core.resources.IncrementalProjectBuilder;
-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.Status;
-import org.eclipse.core.runtime.SubProgressMonitor;
-import org.eclipse.core.runtime.jobs.Job;
-import org.eclipse.jdt.core.IClasspathEntry;
-import org.eclipse.jdt.core.IJavaProject;
-import org.eclipse.jdt.core.JavaCore;
-
-import java.util.List;
-import java.util.Map;
-
-/**
- * Resource manager builder whose only purpose is to refresh the resource folder
- * so that the other builder use an up to date version.
- */
-public class ResourceManagerBuilder extends BaseBuilder {
-
- public static final String ID = "com.android.ide.eclipse.adt.ResourceManagerBuilder"; //$NON-NLS-1$
-
- public ResourceManagerBuilder() {
- super();
- }
-
- @Override
- protected void clean(IProgressMonitor monitor) throws CoreException {
- super.clean(monitor);
-
- // Get the project.
- IProject project = getProject();
-
- // Clear the project of the generic markers
- removeMarkersFromContainer(project, AdtConstants.MARKER_ADT);
- }
-
- // build() returns a list of project from which this project depends for future compilation.
- @SuppressWarnings("unchecked")
- @Override
- protected IProject[] build(int kind, Map args, IProgressMonitor monitor)
- throws CoreException {
- // Get the project.
- final IProject project = getProject();
- IJavaProject javaProject = JavaCore.create(project);
-
- // Clear the project of the generic markers
- removeMarkersFromContainer(project, AdtConstants.MARKER_ADT);
-
- // check for existing target marker, in which case we abort.
- // (this means: no SDK, no target, or unresolvable target.)
- try {
- abortOnBadSetup(javaProject, null);
- } catch (AbortBuildException e) {
- return null;
- }
-
- // Check the compiler compliance level, displaying the error message
- // since this is the first builder.
- Pair<Integer, String> result = ProjectHelper.checkCompilerCompliance(project);
- String errorMessage = null;
- switch (result.getFirst().intValue()) {
- case ProjectHelper.COMPILER_COMPLIANCE_LEVEL:
- errorMessage = Messages.Requires_Compiler_Compliance_s;
- break;
- case ProjectHelper.COMPILER_COMPLIANCE_SOURCE:
- errorMessage = Messages.Requires_Source_Compatibility_s;
- break;
- case ProjectHelper.COMPILER_COMPLIANCE_CODEGEN_TARGET:
- errorMessage = Messages.Requires_Class_Compatibility_s;
- break;
- }
-
- if (errorMessage != null) {
- errorMessage = String.format(errorMessage,
- result.getSecond() == null ? "(no value)" : result.getSecond());
-
- if (JavaCore.VERSION_1_7.equals(result.getSecond())) {
- // If the user is trying to target 1.7 but compiling with something older,
- // the error message can be a bit misleading; instead point them in the
- // direction of updating the project's build target.
- Sdk currentSdk = Sdk.getCurrent();
- if (currentSdk != null) {
- IAndroidTarget target = currentSdk.getTarget(project.getProject());
- if (target != null && target.getVersion().getApiLevel() < 19) {
- errorMessage = "Using 1.7 requires compiling with Android 4.4 " +
- "(KitKat); currently using " + target.getVersion();
- }
-
- ProjectState projectState = Sdk.getProjectState(project);
- if (projectState != null) {
- BuildToolInfo buildToolInfo = projectState.getBuildToolInfo();
- if (buildToolInfo == null) {
- buildToolInfo = currentSdk.getLatestBuildTool();
- }
- if (buildToolInfo != null && buildToolInfo.getRevision().getMajor() < 19) {
- errorMessage = "Using 1.7 requires using Android Build Tools " +
- "version 19 or later; currently using " +
- buildToolInfo.getRevision();
- }
- }
- }
- }
-
- markProject(AdtConstants.MARKER_ADT, errorMessage, IMarker.SEVERITY_ERROR);
- AdtPlugin.printErrorToConsole(project, errorMessage);
-
- return null;
- }
-
- // Check that the SDK directory has been setup.
- String osSdkFolder = AdtPlugin.getOsSdkFolder();
-
- if (osSdkFolder == null || osSdkFolder.length() == 0) {
- AdtPlugin.printErrorToConsole(project, Messages.No_SDK_Setup_Error);
- markProject(AdtConstants.MARKER_ADT, Messages.No_SDK_Setup_Error,
- IMarker.SEVERITY_ERROR);
-
- return null;
- }
-
- // check the 'gen' source folder is present
- boolean hasGenSrcFolder = false; // whether the project has a 'gen' source folder setup
-
- IClasspathEntry[] classpaths = javaProject.readRawClasspath();
- if (classpaths != null) {
- for (IClasspathEntry e : classpaths) {
- if (e.getEntryKind() == IClasspathEntry.CPE_SOURCE) {
- IPath path = e.getPath();
- if (path.segmentCount() == 2 &&
- path.segment(1).equals(SdkConstants.FD_GEN_SOURCES)) {
- hasGenSrcFolder = true;
- break;
- }
- }
- }
- }
-
- boolean genFolderPresent = false; // whether the gen folder actually exists
- IResource resource = project.findMember(SdkConstants.FD_GEN_SOURCES);
- genFolderPresent = resource != null && resource.exists();
-
- if (hasGenSrcFolder == false && genFolderPresent) {
- // No source folder setup for 'gen' in the project, but there's already a
- // 'gen' resource (file or folder).
- String message;
- if (resource.getType() == IResource.FOLDER) {
- // folder exists already! This is an error. If the folder had been created
- // by the NewProjectWizard, it'd be a source folder.
- message = String.format("%1$s already exists but is not a source folder. Convert to a source folder or rename it.",
- resource.getFullPath().toString());
- } else {
- // resource exists but is not a folder.
- message = String.format(
- "Resource %1$s is in the way. ADT needs a source folder called 'gen' to work. Rename or delete resource.",
- resource.getFullPath().toString());
- }
-
- AdtPlugin.printErrorToConsole(project, message);
- markProject(AdtConstants.MARKER_ADT, message, IMarker.SEVERITY_ERROR);
-
- return null;
- } else if (hasGenSrcFolder == false || genFolderPresent == false) {
- // either there is no 'gen' source folder in the project (older SDK),
- // or the folder does not exist (was deleted, or was a fresh svn checkout maybe.)
-
- // In case we are migrating from an older SDK, we go through the current source
- // folders and delete the generated Java files.
- List<IPath> sourceFolders = BaseProjectHelper.getSourceClasspaths(javaProject);
- IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
- for (IPath path : sourceFolders) {
- IResource member = root.findMember(path);
- if (member != null) {
- removeDerivedResources(member, monitor);
- }
- }
-
- // create the new source folder, if needed
- IFolder genFolder = project.getFolder(SdkConstants.FD_GEN_SOURCES);
- if (genFolderPresent == false) {
- AdtPlugin.printBuildToConsole(BuildVerbosity.VERBOSE, project,
- "Creating 'gen' source folder for generated Java files");
- genFolder.create(true /* force */, true /* local */,
- new SubProgressMonitor(monitor, 10));
- }
-
- // add it to the source folder list, if needed only (or it will throw)
- if (hasGenSrcFolder == false) {
- IClasspathEntry[] entries = javaProject.getRawClasspath();
- entries = ProjectHelper.addEntryToClasspath(entries,
- JavaCore.newSourceEntry(genFolder.getFullPath()));
- javaProject.setRawClasspath(entries, new SubProgressMonitor(monitor, 10));
- }
-
- // refresh specifically the gen folder first, as it may break the build
- // if it doesn't arrive in time then refresh the whole project as usual.
- genFolder.refreshLocal(IResource.DEPTH_ZERO, new SubProgressMonitor(monitor, 10));
- project.refreshLocal(IResource.DEPTH_INFINITE, new SubProgressMonitor(monitor, 10));
-
- // it seems like doing this fails to properly rebuild the project. the Java builder
- // running right after this builder will not see the gen folder, and will not be
- // restarted after this build. Therefore in this particular case, we start another
- // build asynchronously so that it's rebuilt after this build.
- launchJob(new Job("rebuild") {
- @Override
- protected IStatus run(IProgressMonitor m) {
- try {
- project.build(IncrementalProjectBuilder.INCREMENTAL_BUILD, m);
- return Status.OK_STATUS;
- } catch (CoreException e) {
- return e.getStatus();
- }
- }
- });
-
- }
-
- // convert older projects which use bin as the eclipse output folder into projects
- // using bin/classes
- IFolder androidOutput = BaseProjectHelper.getAndroidOutputFolder(project);
- IFolder javaOutput = BaseProjectHelper.getJavaOutputFolder(project);
- if (androidOutput.exists() == false || javaOutput == null ||
- javaOutput.getParent().equals(androidOutput) == false) {
- // get what we want as the new java output.
- IFolder newJavaOutput = androidOutput.getFolder(SdkConstants.FD_CLASSES_OUTPUT);
-
- if (androidOutput.exists() == false) {
- androidOutput.create(true /*force*/, true /*local*/, monitor);
- }
-
- if (newJavaOutput.exists() == false) {
- newJavaOutput.create(true /*force*/, true /*local*/, monitor);
- }
-
- // set the java output to this project.
- javaProject.setOutputLocation(newJavaOutput.getFullPath(), monitor);
-
- // need to do a full build. Can't build while we're already building, so launch a
- // job to build it right after this build
- launchJob(new Job("rebuild") {
- @Override
- protected IStatus run(IProgressMonitor jobMonitor) {
- try {
- project.build(IncrementalProjectBuilder.CLEAN_BUILD, jobMonitor);
- return Status.OK_STATUS;
- } catch (CoreException e) {
- return e.getStatus();
- }
- }
- });
- }
-
- // check that we have bin/res/
- IFolder binResFolder = androidOutput.getFolder(SdkConstants.FD_RESOURCES);
- if (binResFolder.exists() == false) {
- binResFolder.create(true /* force */, true /* local */,
- new SubProgressMonitor(monitor, 10));
- project.refreshLocal(IResource.DEPTH_ONE, new SubProgressMonitor(monitor, 10));
- }
-
- // Check the preference to be sure we are supposed to refresh
- // the folders.
- if (AdtPrefs.getPrefs().getBuildForceResResfresh()) {
- AdtPlugin.printBuildToConsole(BuildVerbosity.VERBOSE, project, Messages.Refreshing_Res);
-
- // refresh the res folder.
- IFolder resFolder = project.getFolder(AdtConstants.WS_RESOURCES);
- resFolder.refreshLocal(IResource.DEPTH_INFINITE, monitor);
-
- // Also refresh the assets folder to make sure the ApkBuilder
- // will now it's changed and will force a new resource packaging.
- IFolder assetsFolder = project.getFolder(AdtConstants.WS_ASSETS);
- assetsFolder.refreshLocal(IResource.DEPTH_INFINITE, monitor);
- }
-
- return null;
- }
-}