aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorXavier Ducrohet <xav@android.com>2012-05-08 18:23:25 -0700
committerXavier Ducrohet <xav@android.com>2012-05-21 15:55:04 -0700
commitd542e65fe2c7fc968c646f43c2d99d52ca3f380a (patch)
tree9c774d03d2c609495d567a0fa0fc787bbd323a83
parenta84497267ef0f8280fcd33f9fb5c848a34f6a609 (diff)
downloadsdk-d542e65fe2c7fc968c646f43c2d99d52ca3f380a.tar.gz
Manifest merge for ADT.
Change-Id: I635098594605af497a8b7d244e502385b8f34d1e
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/.classpath3
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/META-INF/MANIFEST.MF3
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/plugin.xml8
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/AdtConstants.java4
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/builders/BaseBuilder.java3
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/builders/ChangedFileSetHelper.java23
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/builders/PatternBasedDeltaVisitor.java41
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/builders/PostCompilerBuilder.java108
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/builders/PreCompilerBuilder.java176
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/builders/PreCompilerDeltaVisitor.java23
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk/ProjectState.java10
-rwxr-xr-xeclipse/scripts/create_all_symlinks.sh2
12 files changed, 310 insertions, 94 deletions
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/.classpath b/eclipse/plugins/com.android.ide.eclipse.adt/.classpath
index 3a203c471..4c132edb6 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/.classpath
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/.classpath
@@ -1,7 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry excluding="Makefile|resources/" kind="src" path="src"/>
- <classpathentry exported="true" kind="lib" path="libs/ant-glob.jar"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
<classpathentry kind="lib" path="libs/kxml2-2.3.0.jar"/>
@@ -15,6 +14,8 @@
<classpathentry kind="lib" path="libs/assetstudio.jar" sourcepath="/assetstudio"/>
<classpathentry combineaccessrules="false" kind="src" path="/ddmlib"/>
<classpathentry combineaccessrules="false" kind="src" path="/ddmuilib"/>
+ <classpathentry exported="true" kind="lib" path="libs/ant-glob.jar"/>
+ <classpathentry exported="true" kind="lib" path="libs/manifmerger.jar" sourcepath="/ManifestMerger"/>
<classpathentry kind="var" path="ANDROID_SRC/sdk/eclipse/plugins/com.android.ide.eclipse.adt/libs/propertysheet.jar" sourcepath="/ANDROID_SRC/external/eclipse-windowbuilder/propertysheet/src"/>
<classpathentry kind="var" path="ANDROID_SRC/prebuilts/tools/common/asm-tools/asm-4.0.jar" sourcepath="/ANDROID_SRC/prebuilts/tools/common/asm-tools/src.zip"/>
<classpathentry kind="var" path="ANDROID_SRC/prebuilts/tools/common/asm-tools/asm-tree-4.0.jar" sourcepath="/ANDROID_SRC/prebuilts/tools/common/asm-tools/src.zip"/>
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/META-INF/MANIFEST.MF b/eclipse/plugins/com.android.ide.eclipse.adt/META-INF/MANIFEST.MF
index 427b1762a..38d2885d1 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/META-INF/MANIFEST.MF
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/META-INF/MANIFEST.MF
@@ -18,7 +18,8 @@ Bundle-ClassPath: .,
libs/asm-tree-4.0.jar,
libs/propertysheet.jar,
libs/ant-glob.jar,
- libs/swtmenubar.jar
+ libs/swtmenubar.jar,
+ libs/manifmerger.jar
Bundle-Activator: com.android.ide.eclipse.adt.AdtPlugin
Bundle-Vendor: The Android Open Source Project
Require-Bundle: com.android.ide.eclipse.base,
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/plugin.xml b/eclipse/plugins/com.android.ide.eclipse.adt/plugin.xml
index 6d609367f..5c3e9a0ea 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/plugin.xml
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/plugin.xml
@@ -58,6 +58,14 @@
<persistent value="true" />
</extension>
<extension
+ id="com.android.ide.eclipse.adt.manifMergerProblem"
+ name="Android Manifest Merger Problem"
+ point="org.eclipse.core.resources.markers">
+ <super type="org.eclipse.core.resources.problemmarker" />
+ <super type="org.eclipse.core.resources.textmarker" />
+ <persistent value="true" />
+ </extension>
+ <extension
id="com.android.ide.eclipse.adt.adtProblem"
name="Android ADT Problem"
point="org.eclipse.core.resources.markers">
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/AdtConstants.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/AdtConstants.java
index 904c4e6da..e5e84d90b 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/AdtConstants.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/AdtConstants.java
@@ -237,6 +237,7 @@ public class AdtConstants {
* from the {@link PreCompilerBuilder} */
public final static String MARKER_ANDROID = LEGACY_PLUGIN_ID + ".androidProblem"; //$NON-NLS-1$
+
/** aapt marker error when running the package command, only to be used in
* {@link PostCompilerBuilder} */
public final static String MARKER_AAPT_PACKAGE = LEGACY_PLUGIN_ID + ".aapt2Problem"; //$NON-NLS-1$
@@ -244,6 +245,9 @@ public class AdtConstants {
/** final packaging error marker, only to be used in {@link PostCompilerBuilder} */
public final static String MARKER_PACKAGING = AdtPlugin.PLUGIN_ID + ".packagingProblem"; //$NON-NLS-1$
+ /** manifest merger error, only to be used in {@link PreCompilerBuilder} */
+ public final static String MARKER_MANIFMERGER = AdtPlugin.PLUGIN_ID + ".manifMergerProblem"; //$NON-NLS-1$
+
/** Marker for lint errors */
public final static String MARKER_LINT = AdtPlugin.PLUGIN_ID + ".lintProblem"; //$NON-NLS-1$
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
index 8b9492d02..1444f76a4 100644
--- 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
@@ -57,7 +57,8 @@ import javax.xml.parsers.SAXParserFactory;
*/
public abstract class BaseBuilder extends IncrementalProjectBuilder {
- protected final static boolean DEBUG = false;
+ 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;
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
index 36d739746..fd963c02f 100644
--- 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
@@ -94,6 +94,23 @@ class ChangedFileSetHelper {
}
/**
+ * 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 a project's javac output.
* @param project the project
* @return a ChangedFileSet
@@ -102,7 +119,7 @@ class ChangedFileSetHelper {
// input pattern is based on the project's Java compiler's output folder
String path = getRelativeJavaCOut(project);
- ChangedFileSet set = new ChangedFileSet("bytecode", //$NON-NLS-1$
+ ChangedFileSet set = new ChangedFileSet("compiledCode", //$NON-NLS-1$
path + "/**/*" + AdtConstants.DOT_CLASS); //$NON-NLS-1$
return set;
@@ -136,9 +153,9 @@ class ChangedFileSetHelper {
// input pattern is based on the project's Java compiler's output folder
String path = getRelativeJavaCOut(project);
- ChangedFileSet set = new ChangedFileSet("libResources", //$NON-NLS-1$
+ ChangedFileSet set = new ChangedFileSet("classAndJars", //$NON-NLS-1$
path + "/**/*" + AdtConstants.DOT_CLASS, //$NON-NLS-1$
- SdkConstants.FD_NATIVE_LIBS + "*" + AdtConstants.DOT_JAR); //$NON-NLS-1$
+ SdkConstants.FD_NATIVE_LIBS + "/*" + AdtConstants.DOT_JAR); //$NON-NLS-1$
// output file is based on the project's android output folder
path = getRelativeAndroidOut(project);
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
index 7109eb85c..81fceb164 100644
--- 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
@@ -29,7 +29,7 @@ import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IStatus;
import java.util.ArrayList;
-import java.util.HashMap;
+import java.util.IdentityHashMap;
import java.util.List;
import java.util.Map;
@@ -45,18 +45,26 @@ import java.util.Map;
*/
class PatternBasedDeltaVisitor implements IResourceDeltaVisitor {
- private final boolean DEBUG_LOG = "1".equals( //$NON-NLS-1$
- System.getenv("ANDROID_VISITOR_DEBUG")); //$NON-NLS-1$
+ 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 IProject mProject;
+ private final Map<ChangedFileSet, Boolean> mResults =
+ new IdentityHashMap<ChangedFileSet, Boolean>();
- private final Map<ChangedFileSet, Boolean> mResults = new HashMap<ChangedFileSet, Boolean>();
private final String mLogName;
- PatternBasedDeltaVisitor(IProject project, String logName) {
- mProject = project;
+ 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) {
@@ -81,7 +89,7 @@ class PatternBasedDeltaVisitor implements IResourceDeltaVisitor {
return BuildHelper.checkFolderForPackaging((IFolder)resource);
} else if (resource.getType() == IResource.FILE) {
- IPath path = resource.getFullPath().makeRelativeTo(mProject.getFullPath());
+ IPath path = resource.getFullPath().makeRelativeTo(mDeltaProject.getFullPath());
// 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) {
@@ -95,12 +103,13 @@ class PatternBasedDeltaVisitor implements IResourceDeltaVisitor {
String cfs_logName = set.getLogName();
if (cfs_logName != null) {
- AdtPlugin.log(IStatus.INFO, "%s (%s): %s", //$NON-NLS-1$
- mLogName, cfs_logName,
+ 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", //$NON-NLS-1$
- mLogName, resource.getFullPath().toString());
+ AdtPlugin.log(IStatus.INFO, "%s (%s): %s", //$NON-NLS-1$
+ mMainProject.getName(), mLogName,
+ resource.getFullPath().toString());
}
}
@@ -112,12 +121,12 @@ class PatternBasedDeltaVisitor implements IResourceDeltaVisitor {
String cfs_logName = set.getLogName();
if (cfs_logName != null) {
- AdtPlugin.log(IStatus.INFO, "%s (%s): REMOVED: %s", //$NON-NLS-1$
- mLogName, cfs_logName,
+ 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: REMOVED: %s", //$NON-NLS-1$
- mLogName,
+ AdtPlugin.log(IStatus.INFO, "%s (%s): %s", //$NON-NLS-1$
+ mMainProject.getName(), mLogName,
resource.getFullPath().toString());
}
}
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
index 99f37ad4e..ea3a32515 100644
--- 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
@@ -134,8 +134,8 @@ public class PostCompilerBuilder extends BaseBuilder {
// Get the project.
IProject project = getProject();
- if (DEBUG) {
- System.out.println("CLEAN(POST) " + project.getName());
+ if (DEBUG_LOG) {
+ AdtPlugin.log(IStatus.INFO, "%s CLEAN(POST)", project.getName());
}
// Clear the project of the generic markers
@@ -167,8 +167,8 @@ public class PostCompilerBuilder extends BaseBuilder {
// get a project object
IProject project = getProject();
- if (DEBUG) {
- System.out.println("BUILD(POST) " + project.getName());
+ if (DEBUG_LOG) {
+ AdtPlugin.log(IStatus.INFO, "%s BUILD(POST)", project.getName());
}
// Benchmarking start
@@ -228,8 +228,8 @@ public class PostCompilerBuilder extends BaseBuilder {
AdtPlugin.printBuildToConsole(BuildVerbosity.VERBOSE, project,
Messages.Start_Full_Apk_Build);
- if (DEBUG) {
- System.out.println("\tfull build!");
+ if (DEBUG_LOG) {
+ AdtPlugin.log(IStatus.INFO, "%s full build!", project.getName());
}
// Full build: we do all the steps.
@@ -248,28 +248,31 @@ public class PostCompilerBuilder extends BaseBuilder {
mConvertToDex = true;
mBuildFinalPackage = true;
} else {
- PatternBasedDeltaVisitor dv = new PatternBasedDeltaVisitor(project,
- project.getName());
- dv.addSet(ChangedFileSetHelper.MANIFEST);
- ChangedFileSet resCFS = ChangedFileSetHelper.getResCfs(project);
- dv.addSet(resCFS);
+ PatternBasedDeltaVisitor dv = new PatternBasedDeltaVisitor(
+ project, project,
+ "POST:Main");
- ChangedFileSet androidCodeCFS = ChangedFileSetHelper.getCodeCfs(project);
- dv.addSet(androidCodeCFS);
+ ChangedFileSet manifestCfs = ChangedFileSetHelper.getMergedManifestCfs(project);
+ dv.addSet(manifestCfs);
- ChangedFileSet javaResCFS = ChangedFileSetHelper.getJavaResCfs(project);
- dv.addSet(javaResCFS);
+ 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(ChangedFileSetHelper.MANIFEST) ||
- dv.checkSet(resCFS);
+ mPackageResources |= dv.checkSet(manifestCfs) || dv.checkSet(resCfs);
- mConvertToDex |= dv.checkSet(androidCodeCFS);
+ mConvertToDex |= dv.checkSet(androidCodeCfs);
- mBuildFinalPackage |= dv.checkSet(javaResCFS) ||
+ mBuildFinalPackage |= dv.checkSet(javaResCfs) ||
dv.checkSet(ChangedFileSetHelper.NATIVE_LIBS);
}
@@ -279,17 +282,18 @@ public class PostCompilerBuilder extends BaseBuilder {
delta = getDelta(libProject);
if (delta != null) {
PatternBasedDeltaVisitor visitor = new PatternBasedDeltaVisitor(
- libProject, project.getName());
+ project, libProject,
+ "POST:Lib");
- ChangedFileSet libResCFS = ChangedFileSetHelper.getFullResCfs(
+ ChangedFileSet libResCfs = ChangedFileSetHelper.getFullResCfs(
libProject);
- visitor.addSet(libResCFS);
+ visitor.addSet(libResCfs);
visitor.addSet(ChangedFileSetHelper.NATIVE_LIBS);
// FIXME: add check on the library.jar?
delta.accept(visitor);
- mPackageResources |= visitor.checkSet(libResCFS);
+ mPackageResources |= visitor.checkSet(libResCfs);
mBuildFinalPackage |= visitor.checkSet(
ChangedFileSetHelper.NATIVE_LIBS);
}
@@ -303,19 +307,20 @@ public class PostCompilerBuilder extends BaseBuilder {
delta = getDelta(referencedJavaProject.getProject());
if (delta != null) {
PatternBasedDeltaVisitor visitor = new PatternBasedDeltaVisitor(
- referencedJavaProject.getProject(), project.getName());
+ project, referencedJavaProject.getProject(),
+ "POST:RefedProject");
- ChangedFileSet javaResCFS = ChangedFileSetHelper.getJavaResCfs(project);
- visitor.addSet(javaResCFS);
+ ChangedFileSet javaResCfs = ChangedFileSetHelper.getJavaResCfs(project);
+ visitor.addSet(javaResCfs);
- ChangedFileSet bytecodeCFS = ChangedFileSetHelper.getByteCodeCfs(project);
- visitor.addSet(bytecodeCFS);
+ ChangedFileSet bytecodeCfs = ChangedFileSetHelper.getByteCodeCfs(project);
+ visitor.addSet(bytecodeCfs);
delta.accept(visitor);
// save the state
- mConvertToDex |= visitor.checkSet(bytecodeCFS);
- mBuildFinalPackage |= visitor.checkSet(javaResCFS);
+ mConvertToDex |= visitor.checkSet(bytecodeCfs);
+ mBuildFinalPackage |= visitor.checkSet(javaResCfs);
}
}
}
@@ -350,8 +355,8 @@ public class PostCompilerBuilder extends BaseBuilder {
// also update the crunch cache always since aapt does it smartly only
// on the files that need it.
- if (DEBUG) {
- System.out.println("\trunning crunch!");
+ if (DEBUG_LOG) {
+ AdtPlugin.log(IStatus.INFO, "%s running crunch!", project.getName());
}
BuildHelper helper = new BuildHelper(project,
mOutStream, mErrStream,
@@ -365,8 +370,8 @@ public class PostCompilerBuilder extends BaseBuilder {
if (mConvertToDex) { // in this case this means some class files changed and
// we need to update the jar file.
- if (DEBUG) {
- System.out.println("\tupdating jar!");
+ if (DEBUG_LOG) {
+ AdtPlugin.log(IStatus.INFO, "%s updating jar!", project.getName());
}
// resource to the AndroidManifest.xml file
@@ -473,8 +478,17 @@ public class PostCompilerBuilder extends BaseBuilder {
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 = project.getFile(SdkConstants.FN_ANDROID_MANIFEST_XML);
+ IFile manifestFile = androidOutputFolder.getFile(
+ SdkConstants.FN_ANDROID_MANIFEST_XML);
if (manifestFile == null || manifestFile.exists() == false) {
// mark project and exit
@@ -484,14 +498,6 @@ public class PostCompilerBuilder extends BaseBuilder {
return allRefProjects;
}
- IPath androidBinLocation = androidOutputFolder.getLocation();
- if (androidBinLocation == null) {
- markProject(AdtConstants.MARKER_PACKAGING, Messages.Output_Missing,
- IMarker.SEVERITY_ERROR);
- return allRefProjects;
- }
- String osAndroidBinPath = androidBinLocation.toOSString();
-
// Remove the old .apk.
// This make sure that if the apk is corrupted, then dx (which would attempt
// to open it), will not fail.
@@ -507,8 +513,8 @@ public class PostCompilerBuilder extends BaseBuilder {
if (mPackageResources) {
// also update the crunch cache always since aapt does it smartly only
// on the files that need it.
- if (DEBUG) {
- System.out.println("\trunning crunch!");
+ if (DEBUG_LOG) {
+ AdtPlugin.log(IStatus.INFO, "%s running crunch!", project.getName());
}
if (updateCrunchCache(project, helper) == false) {
return allRefProjects;
@@ -517,8 +523,8 @@ public class PostCompilerBuilder extends BaseBuilder {
// refresh recursively bin/res folder
resOutputFolder.refreshLocal(IResource.DEPTH_INFINITE, monitor);
- if (DEBUG) {
- System.out.println("\tpackaging resources!");
+ if (DEBUG_LOG) {
+ AdtPlugin.log(IStatus.INFO, "%s packaging resources!", project.getName());
}
// remove some aapt_package only markers.
removeMarkersFromContainer(project, AdtConstants.MARKER_AAPT_PACKAGE);
@@ -562,8 +568,8 @@ public class PostCompilerBuilder extends BaseBuilder {
// then we check if we need to package the .class into classes.dex
if (mConvertToDex) {
- if (DEBUG) {
- System.out.println("\trunning dex!");
+ if (DEBUG_LOG) {
+ AdtPlugin.log(IStatus.INFO, "%s running dex!", project.getName());
}
try {
Collection<String> dxInputPaths = helper.getCompiledCodePaths();
@@ -600,8 +606,8 @@ public class PostCompilerBuilder extends BaseBuilder {
// This is the default package with all the resources.
try {
- if (DEBUG) {
- System.out.println("\tmaking final package!");
+ if (DEBUG_LOG) {
+ AdtPlugin.log(IStatus.INFO, "%s making final package!", project.getName());
}
helper.finalDebugPackage(
osAndroidBinPath + File.separator + AdtConstants.FN_RESOURCES_AP_,
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
index 232f40f52..0347af66e 100644
--- 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
@@ -40,10 +40,13 @@ 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.sdklib.AndroidVersion;
import com.android.sdklib.IAndroidTarget;
+import com.android.sdklib.ISdkLog;
import com.android.sdklib.SdkConstants;
import com.android.sdklib.internal.build.BuildConfigGenerator;
+import com.android.sdklib.io.FileOp;
import com.android.sdklib.xml.AndroidManifest;
import com.android.sdklib.xml.ManifestData;
@@ -56,6 +59,7 @@ 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.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Path;
import org.eclipse.jdt.core.IJavaProject;
@@ -90,19 +94,26 @@ public class PreCompilerBuilder extends BaseBuilder {
*/
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$
- /**
- * Resource Compile flag. This flag is reset to false after each successful compilation, and
- * stored in the project persistent properties. This allows the builder to remember its state
- * when the project is closed/opened.
- */
+ 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;
private final List<SourceProcessor> mProcessors = new ArrayList<SourceProcessor>(2);
@@ -219,8 +230,8 @@ public class PreCompilerBuilder extends BaseBuilder {
// get a project object
IProject project = getProject();
- if (DEBUG) {
- System.out.println("BUILD(PRE) " + project.getName());
+ if (DEBUG_LOG) {
+ AdtPlugin.log(IStatus.INFO, "%s BUILD(PRE)", project.getName());
}
// For the PreCompiler, only the library projects are considered Referenced projects,
@@ -254,6 +265,8 @@ public class PreCompilerBuilder extends BaseBuilder {
// now we need to get the classpath list
List<IPath> sourceFolderPathList = BaseProjectHelper.getSourceClasspaths(javaProject);
+ IFolder androidOutputFolder = BaseProjectHelper.getAndroidOutputFolder(project);
+
PreCompilerDeltaVisitor dv = null;
String javaPackage = null;
String minSdkVersion = null;
@@ -262,13 +275,14 @@ public class PreCompilerBuilder extends BaseBuilder {
AdtPlugin.printBuildToConsole(BuildVerbosity.VERBOSE, project,
Messages.Start_Full_Pre_Compiler);
- if (DEBUG) {
- System.out.println("\tfull build!");
+ 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;
@@ -301,13 +315,15 @@ public class PreCompilerBuilder extends BaseBuilder {
// 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();
ProjectResources projectResources = resManager.getProjectResources(project);
if (ResourceManager.isAutoBuilding()) {
- IdeScanningContext context = new IdeScanningContext(projectResources, project);
+ IdeScanningContext context = new IdeScanningContext(projectResources,
+ project);
resManager.processDelta(delta, context);
@@ -342,7 +358,31 @@ public class PreCompilerBuilder extends BaseBuilder {
// 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 (mMustMergeManifest == false && 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);
+
+ delta.accept(visitor);
+
+ mMustMergeManifest |= visitor.checkSet(ChangedFileSetHelper.MANIFEST);
+
+ // no need to test others.
+ if (mMustMergeManifest) {
+ break;
+ }
+ }
+ }
+ }
+
// store the build status in the persistent storage
+ saveProjectBooleanProperty(PROPERTY_MERGE_MANIFEST, mMustMergeManifest);
saveProjectBooleanProperty(PROPERTY_COMPILE_RESOURCES, mMustCompileResources);
saveProjectBooleanProperty(PROPERTY_COMPILE_BUILDCONFIG, mMustCreateBuildConfig);
@@ -354,7 +394,6 @@ public class PreCompilerBuilder extends BaseBuilder {
return result;
}
-
// get the manifest file
IFile manifestFile = ProjectHelper.getManifest(project);
@@ -549,12 +588,14 @@ public class PreCompilerBuilder extends BaseBuilder {
// force a clean
doClean(project, monitor);
+ mMustMergeManifest = true;
mMustCompileResources = true;
mMustCreateBuildConfig = true;
for (SourceProcessor processor : mProcessors) {
processor.prepareFullBuild(project);
}
+ saveProjectBooleanProperty(PROPERTY_MERGE_MANIFEST, mMustMergeManifest);
saveProjectBooleanProperty(PROPERTY_COMPILE_RESOURCES, mMustCompileResources);
saveProjectBooleanProperty(PROPERTY_COMPILE_BUILDCONFIG, mMustCreateBuildConfig);
}
@@ -566,6 +607,19 @@ public class PreCompilerBuilder extends BaseBuilder {
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;
+ }
+ }
+
// run the source processors
int processorStatus = SourceProcessor.COMPILE_STATUS_NONE;
for (SourceProcessor processor : mProcessors) {
@@ -591,8 +645,8 @@ public class PreCompilerBuilder extends BaseBuilder {
// generate resources.
boolean compiledTheResources = mMustCompileResources;
if (mMustCompileResources) {
- if (DEBUG) {
- System.out.println("\tcompiling resources!");
+ if (DEBUG_LOG) {
+ AdtPlugin.log(IStatus.INFO, "%s compiling resources!", project.getName());
}
handleResources(project, javaPackage, projectTarget, manifestFile, libProjects,
projectState.isLibrary());
@@ -618,8 +672,8 @@ public class PreCompilerBuilder extends BaseBuilder {
protected void clean(IProgressMonitor monitor) throws CoreException {
super.clean(monitor);
- if (DEBUG) {
- System.out.println("CLEAN(PRE) " + getProject().getName());
+ if (DEBUG_LOG) {
+ AdtPlugin.log(IStatus.INFO, "%s CLEAN(PRE)", getProject().getName());
}
doClean(getProject(), monitor);
@@ -646,6 +700,7 @@ public class PreCompilerBuilder extends BaseBuilder {
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
@@ -667,6 +722,7 @@ public class PreCompilerBuilder extends BaseBuilder {
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);
@@ -715,6 +771,10 @@ public class PreCompilerBuilder extends BaseBuilder {
}
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();
@@ -725,6 +785,90 @@ public class PreCompilerBuilder extends BaseBuilder {
}
}
+ 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>();
+
+ ManifestMerger merger = new ManifestMerger(new ISdkLog() {
+
+ @Override
+ public void warning(String warningFormat, Object... args) {
+ AdtPlugin.printToConsole(getProject(), String.format(warningFormat, args));
+ }
+
+ @Override
+ public void printf(String msgFormat, Object... args) {
+ AdtPlugin.printToConsole(getProject(), String.format(msgFormat, args));
+ }
+
+ @Override
+ public void error(Throwable t, String errorFormat, Object... args) {
+ errors.add(String.format(errorFormat, args));
+ }
+ });
+
+ 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) == 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.
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
index 1c9692433..c8f448cc5 100644
--- 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
@@ -24,6 +24,7 @@ import com.android.ide.eclipse.adt.internal.build.SourceProcessor;
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.android.sdklib.SdkConstants;
import com.android.sdklib.xml.ManifestData;
@@ -58,9 +59,11 @@ import java.util.List;
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.xml, Manifest.java, or R.java. All other file changes
+ * files is Manifest.java, or R.java. All other file changes
* will be taken care of by ResourceManager.
*/
private boolean mCompileResources = false;
@@ -94,7 +97,7 @@ class PreCompilerDeltaVisitor extends BaseDeltaVisitor implements IResourceDelta
new ArrayList<SourceChangeHandler>();
private final IWorkspaceRoot mRoot;
-
+ private IFolder mAndroidOutputFolder;
public PreCompilerDeltaVisitor(BaseBuilder builder, List<IPath> sourceFolders,
List<SourceProcessor> processors) {
@@ -106,6 +109,8 @@ class PreCompilerDeltaVisitor extends BaseDeltaVisitor implements IResourceDelta
SourceChangeHandler handler = processor.getChangeHandler();
mSourceChangeHandlers.add(handler);
}
+
+ mAndroidOutputFolder = BaseProjectHelper.getAndroidOutputFolder(builder.getProject());
}
/**
@@ -113,7 +118,11 @@ class PreCompilerDeltaVisitor extends BaseDeltaVisitor implements IResourceDelta
* @return true if any of Manifest.xml, Manifest.java, or R.java have been modified
*/
public boolean getCompileResources() {
- return mCompileResources;
+ return mCompileResources || mChangedManifest;
+ }
+
+ public boolean hasManifestChanged() {
+ return mChangedManifest;
}
/**
@@ -220,7 +229,7 @@ class PreCompilerDeltaVisitor extends BaseDeltaVisitor implements IResourceDelta
mCheckedManifestXml = true;
}
- mCompileResources = true;
+ mChangedManifest = true;
// we don't want to go to the children, not like they are
// any for this resource anyway.
@@ -356,6 +365,12 @@ class PreCompilerDeltaVisitor extends BaseDeltaVisitor implements IResourceDelta
// 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
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk/ProjectState.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk/ProjectState.java
index 84ee34169..64053adcf 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk/ProjectState.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk/ProjectState.java
@@ -16,6 +16,8 @@
package com.android.ide.eclipse.adt.internal.sdk;
+import com.android.annotations.NonNull;
+import com.android.annotations.Nullable;
import com.android.ide.eclipse.adt.AdtPlugin;
import com.android.sdklib.IAndroidTarget;
import com.android.sdklib.internal.project.ProjectProperties;
@@ -206,6 +208,14 @@ public final class ProjectState {
return mProperties;
}
+ public @Nullable String getProperty(@NonNull String name) {
+ if (mProperties != null) {
+ return mProperties.getProperty(name);
+ }
+
+ return null;
+ }
+
public void setTarget(IAndroidTarget target) {
mTarget = target;
}
diff --git a/eclipse/scripts/create_all_symlinks.sh b/eclipse/scripts/create_all_symlinks.sh
index 68481c1b4..2ec32ebab 100755
--- a/eclipse/scripts/create_all_symlinks.sh
+++ b/eclipse/scripts/create_all_symlinks.sh
@@ -124,7 +124,7 @@ CP_FILES="$CP_FILES @:$BASE_PLUGIN_DEST $BASE_PLUGIN_LIBS $BASE_PLUGIN_PREBUILTS
### ADT ###
ADT_DEST="sdk/eclipse/plugins/com.android.ide.eclipse.adt/libs"
-ADT_LIBS="ant-glob assetstudio ide_common layoutlib_api lint_api lint_checks ninepatch propertysheet rule_api sdkuilib swtmenubar"
+ADT_LIBS="ant-glob assetstudio ide_common layoutlib_api lint_api lint_checks ninepatch propertysheet rule_api sdkuilib swtmenubar manifmerger"
ADT_PREBUILTS="\
prebuilts/misc/common/kxml2/kxml2-2.3.0.jar \
prebuilts/tools/common/asm-tools/asm-4.0.jar \