aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/BuildHelper.java351
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/DexWrapper.java5
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/builders/PostCompilerBuilder.java15
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/project/ExportHelper.java39
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/project/LibraryClasspathContainerInitializer.java54
-rw-r--r--sdkmanager/libs/sdklib/src/com/android/sdklib/build/ApkBuilder.java25
6 files changed, 186 insertions, 303 deletions
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/BuildHelper.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/BuildHelper.java
index e915544..ad4b787 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/BuildHelper.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/BuildHelper.java
@@ -21,8 +21,6 @@ import com.android.ide.eclipse.adt.AdtPlugin;
import com.android.ide.eclipse.adt.AndroidPrintStream;
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.Sdk;
import com.android.prefs.AndroidLocation.AndroidLocationException;
import com.android.sdklib.IAndroidTarget;
@@ -33,11 +31,9 @@ import com.android.sdklib.build.ApkBuilder.JarStatus;
import com.android.sdklib.build.ApkBuilder.SigningInfo;
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;
import com.android.sdklib.internal.build.DebugKeyProvider.KeytoolException;
-import com.android.sdklib.internal.build.SignedJarBuilder;
import com.android.sdklib.util.GrabProcessOutput;
import com.android.sdklib.util.GrabProcessOutput.IProcessOutput;
import com.android.sdklib.util.GrabProcessOutput.Wait;
@@ -46,9 +42,6 @@ import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
-import org.eclipse.core.resources.IResourceProxy;
-import org.eclipse.core.resources.IResourceProxyVisitor;
-import org.eclipse.core.resources.IWorkspace;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
@@ -69,8 +62,11 @@ import java.io.PrintStream;
import java.security.PrivateKey;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashSet;
import java.util.List;
import java.util.Map;
+import java.util.Set;
import java.util.TreeMap;
/**
@@ -108,6 +104,8 @@ public class BuildHelper {
private final boolean mVerbose;
private final boolean mDebugMode;
+ private final Set<String> mCompiledCodePaths = new HashSet<String>();
+
public static final boolean BENCHMARK_FLAG = false;
public static long sStartOverallTime = 0;
public static long sStartJavaCTime = 0;
@@ -128,14 +126,18 @@ public class BuildHelper {
* @param errStream
* @param debugMode whether this is a debug build
* @param verbose
+ * @throws CoreException
*/
public BuildHelper(IProject project, AndroidPrintStream outStream,
- AndroidPrintStream errStream, boolean debugMode, boolean verbose) {
+ AndroidPrintStream errStream, boolean debugMode, boolean verbose,
+ ResourceMarker resMarker) throws CoreException {
mProject = project;
mOutStream = outStream;
mErrStream = errStream;
mDebugMode = debugMode;
mVerbose = verbose;
+
+ gatherPaths(resMarker);
}
public void updateCrunchCache() throws AaptExecException, AaptResultException {
@@ -169,11 +171,6 @@ public class BuildHelper {
}
}
- public static void writeResources(IArchiveBuilder builder, IJavaProject javaProject)
- throws DuplicateFileException, ApkCreationException, SealedApkException, CoreException {
- writeStandardResources(builder, javaProject, null);
- }
-
/**
* Packages the resources of the projet into a .ap_ file.
* @param manifestFile the manifest of the project.
@@ -365,19 +362,16 @@ public class BuildHelper {
mVerbose ? mOutStream: null);
apkBuilder.setDebugMode(mDebugMode);
- // Now we write the standard resources from the project and the referenced projects.
- writeStandardResources(apkBuilder, javaProject, referencedJavaProjects);
-
- // Now we write the standard resources from the external jars
- for (String libraryOsPath : getExternalDependencies(resMarker)) {
- File libFile = new File(libraryOsPath);
- if (libFile.isFile()) {
- JarStatus jarStatus = apkBuilder.addResourcesFromJar(new File(libraryOsPath));
+ // Now we write the standard resources from all the output paths.
+ for (String path : mCompiledCodePaths) {
+ File file = new File(path);
+ if (file.isFile()) {
+ JarStatus jarStatus = apkBuilder.addResourcesFromJar(file);
// check if we found native libraries in the external library. This
// constitutes an error or warning depending on if they are in lib/
if (jarStatus.getNativeLibs().size() > 0) {
- String libName = new File(libraryOsPath).getName();
+ String libName = file.getName();
String msg = String.format(
"Native libraries detected in '%1$s'. See console for more information.",
@@ -418,11 +412,11 @@ public class BuildHelper {
}
}
}
- } else if (libFile.isDirectory()) {
+ } else if (file.isDirectory()) {
// this is technically not a source folder (class folder instead) but since we
// only care about Java resources (ie non class/java files) this will do the
// same
- apkBuilder.addSourceFolder(libFile);
+ apkBuilder.addSourceFolder(file);
}
}
@@ -453,66 +447,11 @@ public class BuildHelper {
}
}
- /**
- * Return a list of the project output for compiled Java code.
- * @return
- * @throws CoreException
- */
- public String[] getProjectJavaOutputs() throws CoreException {
- IFolder outputFolder = BaseProjectHelper.getJavaOutputFolder(mProject);
-
- // get the list of referenced projects output to add
- List<IProject> javaProjects = ProjectHelper.getReferencedProjects(mProject);
- List<IJavaProject> referencedJavaProjects = BuildHelper.getJavaProjects(javaProjects);
-
- // get the project output, and since it's a new list object, just add the outputFolder
- // of the project directly to it.
- List<String> projectOutputs = getProjectJavaOutputs(referencedJavaProjects);
-
- projectOutputs.add(0, outputFolder.getLocation().toOSString());
-
- return projectOutputs.toArray(new String[projectOutputs.size()]);
- }
-
- /**
- * Returns an array for all the compiled code for the project. This can include the
- * code compiled by Eclipse for the main project and dependencies (Java only projects), as well
- * as external jars used by the project or its library.
- *
- * This array of paths is compatible with the input for dx and can be passed as is to
- * {@link #executeDx(IJavaProject, String[], String)}.
- *
- * @param resMarker
- * @return a array (never empty) containing paths to compiled code.
- * @throws CoreException
- */
- public String[] getCompiledCodePaths(boolean includeProjectOutputs, ResourceMarker resMarker)
- throws CoreException {
-
- // get the list of libraries to include with the source code
- String[] libraries = getExternalDependencies(resMarker);
-
- int startIndex = 0;
-
- String[] compiledPaths;
-
- if (includeProjectOutputs) {
- String[] projectOutputs = getProjectJavaOutputs();
-
- compiledPaths = new String[libraries.length + projectOutputs.length];
-
- System.arraycopy(projectOutputs, 0, compiledPaths, 0, projectOutputs.length);
- startIndex = projectOutputs.length;
- } else {
- compiledPaths = new String[libraries.length];
- }
-
- System.arraycopy(libraries, 0, compiledPaths, startIndex, libraries.length);
-
- return compiledPaths;
+ public Collection<String> getCompiledCodePaths() {
+ return mCompiledCodePaths;
}
- public void runProguard(List<File> proguardConfigs, File inputJar, String[] jarFiles,
+ public void runProguard(List<File> proguardConfigs, File inputJar, Collection<String> jarFiles,
File obfuscatedJar, File logOutput)
throws ProguardResultException, ProguardExecException, IOException {
IAndroidTarget target = Sdk.getCurrent().getTarget(mProject);
@@ -723,13 +662,14 @@ public class BuildHelper {
/**
* Execute the Dx tool for dalvik code conversion.
* @param javaProject The java project
- * @param inputPath the path to the main input of dex
+ * @param inputPaths the input paths for DX
* @param osOutFilePath the path of the dex file to create.
*
* @throws CoreException
* @throws DexException
*/
- public void executeDx(IJavaProject javaProject, String[] inputPaths, String osOutFilePath)
+ public void executeDx(IJavaProject javaProject, Collection<String> inputPaths,
+ String osOutFilePath)
throws CoreException, DexException {
// get the dex wrapper
@@ -917,153 +857,94 @@ public class BuildHelper {
}
/**
- * Writes the standard resources of a project and its referenced projects
- * into a {@link SignedJarBuilder}.
- * Standard resources are non java/aidl files placed in the java package folders.
- * @param builder the archive builder.
- * @param javaProject the javaProject object.
- * @param referencedJavaProjects the java projects that this project references.
- * @throws ApkCreationException if an error occurred
- * @throws SealedApkException if the APK is already sealed.
- * @throws DuplicateFileException if a file conflicts with another already added to the APK
- * at the same location inside the APK archive.
- * @throws CoreException
- */
- private static void writeStandardResources(IArchiveBuilder builder, IJavaProject javaProject,
- List<IJavaProject> referencedJavaProjects)
- throws DuplicateFileException, ApkCreationException, SealedApkException,
- CoreException {
- IWorkspace ws = ResourcesPlugin.getWorkspace();
- IWorkspaceRoot wsRoot = ws.getRoot();
-
- writeStandardProjectResources(builder, javaProject, wsRoot);
-
- if (referencedJavaProjects != null) {
- for (IJavaProject referencedJavaProject : referencedJavaProjects) {
- // only include output from non android referenced project
- // (This is to handle the case of reference Android projects in the context of
- // instrumentation projects that need to reference the projects to be tested).
- if (referencedJavaProject.getProject().hasNature(
- AdtConstants.NATURE_DEFAULT) == false) {
- writeStandardProjectResources(builder, referencedJavaProject, wsRoot);
- }
- }
- }
- }
-
- /**
- * Writes the standard resources of a {@link IJavaProject} into a {@link SignedJarBuilder}.
- * Standard resources are non java/aidl files placed in the java package folders.
- * @param jarBuilder the {@link ApkBuilder}.
- * @param javaProject the javaProject object.
- * @param wsRoot the {@link IWorkspaceRoot}.
- * @throws ApkCreationException if an error occurred
- * @throws SealedApkException if the APK is already sealed.
- * @throws DuplicateFileException if a file conflicts with another already added to the APK
- * at the same location inside the APK archive.
+ * Computes all the project output and dependencies that must go into building the apk.
+ *
+ * @param resMarker
* @throws CoreException
*/
- private static void writeStandardProjectResources(IArchiveBuilder builder,
- IJavaProject javaProject, IWorkspaceRoot wsRoot)
- throws DuplicateFileException, ApkCreationException, SealedApkException, CoreException {
- // get the source pathes
- List<IPath> sourceFolders = BaseProjectHelper.getSourceClasspaths(javaProject);
-
- // loop on them and then recursively go through the content looking for matching files.
- for (IPath sourcePath : sourceFolders) {
- IResource sourceResource = wsRoot.findMember(sourcePath);
- if (sourceResource != null && sourceResource.getType() == IResource.FOLDER) {
- writeFolderResources(builder, javaProject, (IFolder) sourceResource);
- }
- }
- }
-
- private static void writeFolderResources(IArchiveBuilder builder,
- final IJavaProject javaProject, IFolder root) throws CoreException,
- ApkCreationException, SealedApkException, DuplicateFileException {
- final List<IPath> pathsToPackage = new ArrayList<IPath>();
- root.accept(new IResourceProxyVisitor() {
- @Override
- public boolean visit(IResourceProxy proxy) throws CoreException {
- if (proxy.getType() == IResource.FOLDER) {
- // If this folder isn't wanted, don't traverse into it.
- return ApkBuilder.checkFolderForPackaging(proxy.getName());
- }
- // If it's not a folder, it must be a file. We won't see any other resource type.
- if (!ApkBuilder.checkFileForPackaging(proxy.getName())) {
- return true;
- }
- IResource res = proxy.requestResource();
- if (!javaProject.isOnClasspath(res)) {
- return true;
- }
- // Just record that we need to package this. Packaging here throws
- // inappropriate checked exceptions.
- IPath location = res.getLocation();
- pathsToPackage.add(location);
- return true;
- }
- }, 0);
- IPath rootLocation = root.getLocation();
- for (IPath path : pathsToPackage) {
- IPath archivePath = path.makeRelativeTo(rootLocation);
- builder.addFile(path.toFile(), archivePath.toString());
- }
- }
+ private void gatherPaths(ResourceMarker resMarker)
+ throws CoreException {
+ IWorkspaceRoot wsRoot = ResourcesPlugin.getWorkspace().getRoot();
- /**
- * Returns an array of external dependencies used the project. This can be paths to jar files
- * or to source folders.
- *
- * @param resMarker if non null, used to put Resource marker on problem files.
- * @return an array of OS-specific absolute file paths
- */
- private final String[] getExternalDependencies(ResourceMarker resMarker) {
- // get a java project from it
+ // get a java project for the project.
IJavaProject javaProject = JavaCore.create(mProject);
- IWorkspaceRoot wsRoot = ResourcesPlugin.getWorkspace().getRoot();
- ArrayList<String> oslibraryList = new ArrayList<String>();
+ // get the output of the main project
+ IPath path = javaProject.getOutputLocation();
+ IResource outputResource = wsRoot.findMember(path);
+ if (outputResource != null && outputResource.getType() == IResource.FOLDER) {
+ mCompiledCodePaths.add(outputResource.getLocation().toOSString());
+ }
// we could use IJavaProject.getResolvedClasspath directly, but we actually
// want to see the containers themselves.
IClasspathEntry[] classpaths = javaProject.readRawClasspath();
if (classpaths != null) {
for (IClasspathEntry e : classpaths) {
- // if this is a classpath variable reference, we resolve it.
- if (e.getEntryKind() == IClasspathEntry.CPE_VARIABLE) {
- e = JavaCore.getResolvedClasspathEntry(e);
+ // ignore non exported entries, unless it's the LIBRARIES container,
+ // in which case we always want it (there may be some older projects that
+ // have it as non exported).
+ if (e.isExported() ||
+ (e.getEntryKind() == IClasspathEntry.CPE_CONTAINER &&
+ e.getPath().toString().equals(AdtConstants.CONTAINER_LIBRARIES))) {
+ handleCPE(e, javaProject, wsRoot, resMarker);
}
+ }
+ }
+ }
- if (e.getEntryKind() == IClasspathEntry.CPE_LIBRARY) {
- handleClasspathEntry(e, wsRoot, oslibraryList, resMarker);
- } else if (e.getEntryKind() == IClasspathEntry.CPE_CONTAINER) {
- // get the container
- try {
- IClasspathContainer container = JavaCore.getClasspathContainer(
- e.getPath(), javaProject);
- // ignore the system and default_system types as they represent
- // libraries that are part of the runtime.
- if (container.getKind() == IClasspathContainer.K_APPLICATION) {
- IClasspathEntry[] entries = container.getClasspathEntries();
- for (IClasspathEntry entry : entries) {
- handleClasspathEntry(entry, wsRoot, oslibraryList, resMarker);
- }
- }
- } catch (JavaModelException jme) {
- // can't resolve the container? ignore it.
- AdtPlugin.log(jme, "Failed to resolve ClasspathContainer: %s", e.getPath());
+ private void handleCPE(IClasspathEntry entry, IJavaProject javaProject,
+ IWorkspaceRoot wsRoot, ResourceMarker resMarker) {
+
+ // if this is a classpath variable reference, we resolve it.
+ if (entry.getEntryKind() == IClasspathEntry.CPE_VARIABLE) {
+ entry = JavaCore.getResolvedClasspathEntry(entry);
+ }
+
+ if (entry.getEntryKind() == IClasspathEntry.CPE_PROJECT) {
+ IProject refProject = wsRoot.getProject(entry.getPath().lastSegment());
+ try {
+ // ignore if it's an Android project, or if it's not a Java Project
+ if (refProject.hasNature(JavaCore.NATURE_ID) &&
+ refProject.hasNature(AdtConstants.NATURE_DEFAULT) == false) {
+ IJavaProject refJavaProject = JavaCore.create(refProject);
+
+ // get the output folder
+ IPath path = refJavaProject.getOutputLocation();
+ IResource outputResource = wsRoot.findMember(path);
+ if (outputResource != null && outputResource.getType() == IResource.FOLDER) {
+ mCompiledCodePaths.add(outputResource.getLocation().toOSString());
}
}
+ } catch (CoreException exception) {
+ // can't query the project nature? ignore
}
- }
- return oslibraryList.toArray(new String[oslibraryList.size()]);
+ } else if (entry.getEntryKind() == IClasspathEntry.CPE_LIBRARY) {
+ handleClasspathLibrary(entry, wsRoot, resMarker);
+ } else if (entry.getEntryKind() == IClasspathEntry.CPE_CONTAINER) {
+ // get the container
+ try {
+ IClasspathContainer container = JavaCore.getClasspathContainer(
+ entry.getPath(), javaProject);
+ // ignore the system and default_system types as they represent
+ // libraries that are part of the runtime.
+ if (container.getKind() == IClasspathContainer.K_APPLICATION) {
+ IClasspathEntry[] entries = container.getClasspathEntries();
+ for (IClasspathEntry cpe : entries) {
+ handleCPE(cpe, javaProject, wsRoot, resMarker);
+ }
+ }
+ } catch (JavaModelException jme) {
+ // can't resolve the container? ignore it.
+ AdtPlugin.log(jme, "Failed to resolve ClasspathContainer: %s", entry.getPath());
+ }
+ }
}
- private void handleClasspathEntry(IClasspathEntry e, IWorkspaceRoot wsRoot,
- ArrayList<String> oslibraryList, ResourceMarker resMarker) {
+ private void handleClasspathLibrary(IClasspathEntry e, IWorkspaceRoot wsRoot,
+ ResourceMarker resMarker) {
// get the IPath
IPath path = e.getPath();
@@ -1077,7 +958,7 @@ public class BuildHelper {
// case of a jar file (which could be relative to the workspace or a full path)
if (resource != null && resource.exists() &&
resource.getType() == IResource.FILE) {
- oslibraryList.add(resource.getLocation().toOSString());
+ mCompiledCodePaths.add(resource.getLocation().toOSString());
} else {
// if the jar path doesn't match a workspace resource,
// then we get an OSString and check if this links to a valid file.
@@ -1085,7 +966,7 @@ public class BuildHelper {
File f = new File(osFullPath);
if (f.isFile()) {
- oslibraryList.add(osFullPath);
+ mCompiledCodePaths.add(osFullPath);
} else {
String message = String.format( Messages.Couldnt_Locate_s_Error,
path);
@@ -1102,7 +983,7 @@ public class BuildHelper {
// this can be the case for a class folder.
if (resource != null && resource.exists() &&
resource.getType() == IResource.FOLDER) {
- oslibraryList.add(resource.getLocation().toOSString());
+ mCompiledCodePaths.add(resource.getLocation().toOSString());
} else {
// if the path doesn't match a workspace resource,
// then we get an OSString and check if this links to a valid folder.
@@ -1110,50 +991,10 @@ public class BuildHelper {
File f = new File(osFullPath);
if (f.isDirectory()) {
- oslibraryList.add(osFullPath);
- }
- }
- }
- }
-
- /**
- * Returns the list of the output folders for the specified {@link IJavaProject} objects, if
- * they are Android projects.
- *
- * @param referencedJavaProjects the java projects.
- * @return a new list object containing the output folder paths.
- * @throws CoreException
- */
- private List<String> getProjectJavaOutputs(List<IJavaProject> referencedJavaProjects)
- throws CoreException {
- ArrayList<String> list = new ArrayList<String>();
-
- IWorkspace ws = ResourcesPlugin.getWorkspace();
- IWorkspaceRoot wsRoot = ws.getRoot();
-
- for (IJavaProject javaProject : referencedJavaProjects) {
- // only include output from non android referenced project
- // (This is to handle the case of reference Android projects in the context of
- // instrumentation projects that need to reference the projects to be tested).
- if (javaProject.getProject().hasNature(AdtConstants.NATURE_DEFAULT) == false) {
- // get the output folder
- IPath path = null;
- try {
- path = javaProject.getOutputLocation();
- } catch (JavaModelException e) {
- continue;
- }
-
- IResource outputResource = wsRoot.findMember(path);
- if (outputResource != null && outputResource.getType() == IResource.FOLDER) {
- String outputOsPath = outputResource.getLocation().toOSString();
-
- list.add(outputOsPath);
+ mCompiledCodePaths.add(osFullPath);
}
}
}
-
- return list;
}
/**
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/DexWrapper.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/DexWrapper.java
index e03a150..015d230 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/DexWrapper.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/DexWrapper.java
@@ -30,6 +30,7 @@ import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
+import java.util.Collection;
/**
* Wrapper to access dx.jar through reflection.
@@ -144,7 +145,7 @@ public final class DexWrapper {
* @return the integer return code of com.android.dx.command.dexer.Main.run()
* @throws CoreException
*/
- public synchronized int run(String osOutFilePath, String[] osFilenames,
+ public synchronized int run(String osOutFilePath, Collection<String> osFilenames,
boolean verbose, PrintStream outStream, PrintStream errStream) throws CoreException {
assert mRunMethod != null;
@@ -171,7 +172,7 @@ public final class DexWrapper {
// create the Arguments object.
Object args = mArgConstructor.newInstance();
mArgOutName.set(args, osOutFilePath);
- mArgFileNames.set(args, osFilenames);
+ mArgFileNames.set(args, osFilenames.toArray(new String[osFilenames.size()]));
mArgJarOutput.set(args, false);
mArgVerbose.set(args, verbose);
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 6c4eca4..1c4f3f3 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
@@ -38,6 +38,7 @@ 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.SdkConstants;
+import com.android.sdklib.build.ApkBuilder;
import com.android.sdklib.build.ApkCreationException;
import com.android.sdklib.build.DuplicateFileException;
import com.android.sdklib.build.IArchiveBuilder;
@@ -68,6 +69,7 @@ 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;
@@ -427,7 +429,8 @@ public class PostCompilerBuilder extends BaseBuilder {
BuildHelper helper = new BuildHelper(project,
mOutStream, mErrStream,
true /*debugMode*/,
- AdtPrefs.getPrefs().getBuildVerbosity() == BuildVerbosity.VERBOSE);
+ AdtPrefs.getPrefs().getBuildVerbosity() == BuildVerbosity.VERBOSE,
+ mResourceMarker);
updateCrunchCache(project, helper);
// refresh recursively bin/res folder
@@ -542,7 +545,8 @@ public class PostCompilerBuilder extends BaseBuilder {
BuildHelper helper = new BuildHelper(project,
mOutStream, mErrStream,
true /*debugMode*/,
- AdtPrefs.getPrefs().getBuildVerbosity() == BuildVerbosity.VERBOSE);
+ AdtPrefs.getPrefs().getBuildVerbosity() == BuildVerbosity.VERBOSE,
+ mResourceMarker);
// resource to the AndroidManifest.xml file
IFile manifestFile = project.getFile(SdkConstants.FN_ANDROID_MANIFEST_XML);
@@ -637,8 +641,7 @@ public class PostCompilerBuilder extends BaseBuilder {
System.out.println("\trunning dex!");
}
try {
- String[] dxInputPaths = helper.getCompiledCodePaths(
- true /*includeProjectOutputs*/, mResourceMarker);
+ Collection<String> dxInputPaths = helper.getCompiledCodePaths();
helper.executeDx(javaProject, dxInputPaths, classesDexPath);
} catch (DexException e) {
@@ -920,8 +923,8 @@ public class PostCompilerBuilder extends BaseBuilder {
// write the class files
writeClassFilesIntoJar(jarBuilder, javaOutputFolder, javaOutputFolder);
- // now write the standard Java resources
- BuildHelper.writeResources(jarBuilder, JavaCore.create(project));
+ // 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) {
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/project/ExportHelper.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/project/ExportHelper.java
index 93fe43d..c95569b 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/project/ExportHelper.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/project/ExportHelper.java
@@ -62,6 +62,8 @@ import java.io.OutputStream;
import java.security.PrivateKey;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
import java.util.List;
import java.util.jar.JarEntry;
import java.util.jar.JarOutputStream;
@@ -122,7 +124,8 @@ public final class ExportHelper {
BuildHelper helper = new BuildHelper(project,
fakeStream, fakeStream,
- debugMode, false /*verbose*/);
+ debugMode, false /*verbose*/,
+ null /*resourceMarker*/);
// get the list of library projects
ProjectState projectState = Sdk.getProjectState(project);
@@ -200,44 +203,46 @@ public final class ExportHelper {
}
}
- String[] dxInput;
+ Collection<String> dxInput;
if (runProguard) {
- // the output of the main project (and any java-only project dependency)
- String[] projectOutputs = helper.getProjectJavaOutputs();
+ // get all the compiled code paths. This will contain both project output
+ // folder and jar files.
+ Collection<String> paths = helper.getCompiledCodePaths();
- // create a jar from the output of these projects
+ // create a jar file containing all the project output (as proguard cannot
+ // process folders of .class files).
File inputJar = File.createTempFile(TEMP_PREFIX, AdtConstants.DOT_JAR);
inputJar.deleteOnExit();
-
JarOutputStream jos = new JarOutputStream(new FileOutputStream(inputJar));
- for (String po : projectOutputs) {
- File root = new File(po);
- if (root.exists()) {
+
+ // a list of the other paths (jar files.)
+ List<String> jars = new ArrayList<String>();
+
+ for (String path : paths) {
+ File root = new File(path);
+ if (root.isDirectory()) {
addFileToJar(jos, root, root);
+ } else if (root.isFile()) {
+ jars.add(path);
}
}
jos.close();
- // get the other jar files
- String[] jarFiles = helper.getCompiledCodePaths(false /*includeProjectOutputs*/,
- null /*resourceMarker*/);
-
// destination file for proguard
File obfuscatedJar = File.createTempFile(TEMP_PREFIX, AdtConstants.DOT_JAR);
obfuscatedJar.deleteOnExit();
// run proguard
- helper.runProguard(proguardConfigFiles, inputJar, jarFiles, obfuscatedJar,
+ helper.runProguard(proguardConfigFiles, inputJar, jars, obfuscatedJar,
new File(project.getLocation().toFile(), SdkConstants.FD_PROGUARD));
// dx input is proguard's output
- dxInput = new String[] { obfuscatedJar.getAbsolutePath() };
+ dxInput = Collections.singletonList(obfuscatedJar.getAbsolutePath());
} else {
// no proguard, simply get all the compiled code path: project output(s) +
// jar file(s)
- dxInput = helper.getCompiledCodePaths(true /*includeProjectOutputs*/,
- null /*resourceMarker*/);
+ dxInput = helper.getCompiledCodePaths();
}
IJavaProject javaProject = JavaCore.create(project);
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/project/LibraryClasspathContainerInitializer.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/project/LibraryClasspathContainerInitializer.java
index f17f0c5..c2f2510 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/project/LibraryClasspathContainerInitializer.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/project/LibraryClasspathContainerInitializer.java
@@ -214,17 +214,16 @@ public class LibraryClasspathContainerInitializer extends BaseClasspathContainer
entries.add(entry);
- // now, gather the content of this library project's libs folder.
+ // process all of the library project's dependencies
+ getDependencyListFromClasspath(libProject, refProjects, jarFiles, true);
+ // and the content of its libs folder.
getJarListFromLibsFolder(libProject, jarFiles);
}
-
- // get project dependencies
- getDependencyListFromClasspath(libProject, refProjects, jarFiles, false);
}
- // now process this projects' referenced projects
- getDependencyListFromClasspath(iProject, refProjects, jarFiles, false);
- // and its own jar files from libs
+ // now process this projects' referenced projects only.
+ processReferencedProjects(iProject, refProjects, jarFiles);
+ // and the content of its libs folder
getJarListFromLibsFolder(iProject, jarFiles);
// annotations support for older version of android
@@ -311,6 +310,32 @@ public class LibraryClasspathContainerInitializer extends BaseClasspathContainer
}
/**
+ * Process reference projects from the main projects to add indirect dependencies coming
+ * from Java project.
+ * @param project the main project
+ * @param projects the project list to add to
+ * @param jarFiles the jar list to add to.
+ */
+ private static void processReferencedProjects(IProject project,
+ Set<IProject> projects, Set<File> jarFiles) {
+ try {
+ IProject[] refs = project.getReferencedProjects();
+ for (IProject p : refs) {
+ // ignore if it's an Android project, or if it's not a Java
+ // Project
+ if (p.hasNature(JavaCore.NATURE_ID)
+ && p.hasNature(AdtConstants.NATURE_DEFAULT) == false) {
+
+ // process this project's dependencies
+ getDependencyListFromClasspath(p, projects, jarFiles, true /*includeJarFiles*/);
+ }
+ }
+ } catch (CoreException e) {
+ // can't get the referenced projects? ignore
+ }
+ }
+
+ /**
* Finds all the dependencies of a given project and add them to a project list and
* a jar list.
* Only classpath entries that are exported are added, and only Java project (not Android
@@ -332,7 +357,10 @@ public class LibraryClasspathContainerInitializer extends BaseClasspathContainer
IClasspathEntry[] classpaths = javaProject.readRawClasspath();
if (classpaths != null) {
for (IClasspathEntry e : classpaths) {
- processCPE(e, javaProject, wsRoot, projects, jarFiles, includeJarFiles);
+ // ignore entries that are not exported
+ if (e.isExported()) {
+ processCPE(e, javaProject, wsRoot, projects, jarFiles, includeJarFiles);
+ }
}
}
}
@@ -351,21 +379,11 @@ public class LibraryClasspathContainerInitializer extends BaseClasspathContainer
IWorkspaceRoot wsRoot,
Set<IProject> projects, Set<File> jarFiles, boolean includeJarFiles) {
- // ignore entries that are not exported
- if (entry.isExported() == false) {
- return;
- }
-
// if this is a classpath variable reference, we resolve it.
if (entry.getEntryKind() == IClasspathEntry.CPE_VARIABLE) {
entry = JavaCore.getResolvedClasspathEntry(entry);
}
- // not sure if an exported var could resolve to an exported one?
- if (entry.isExported() == false) {
- return;
- }
-
if (entry.getEntryKind() == IClasspathEntry.CPE_PROJECT) {
IProject refProject = wsRoot.getProject(entry.getPath().lastSegment());
try {
diff --git a/sdkmanager/libs/sdklib/src/com/android/sdklib/build/ApkBuilder.java b/sdkmanager/libs/sdklib/src/com/android/sdklib/build/ApkBuilder.java
index 5c95b81..3c749c4 100644
--- a/sdkmanager/libs/sdklib/src/com/android/sdklib/build/ApkBuilder.java
+++ b/sdkmanager/libs/sdklib/src/com/android/sdklib/build/ApkBuilder.java
@@ -586,12 +586,25 @@ public final class ApkBuilder implements IArchiveBuilder {
throw new SealedApkException("APK is already sealed");
}
+ addSourceFolder(this, sourceFolder);
+ }
+
+ /**
+ * Adds the resources from a source folder to a given {@link IArchiveBuilder}
+ * @param sourceFolder the source folder.
+ * @throws ApkCreationException if an error occurred
+ * @throws SealedApkException if the APK is already sealed.
+ * @throws DuplicateFileException if a file conflicts with another already added to the APK
+ * at the same location inside the APK archive.
+ */
+ public static void addSourceFolder(IArchiveBuilder builder, File sourceFolder)
+ throws ApkCreationException, DuplicateFileException {
if (sourceFolder.isDirectory()) {
try {
// file is a directory, process its content.
File[] files = sourceFolder.listFiles();
for (File file : files) {
- processFileForResource(file, null);
+ processFileForResource(builder, file, null);
}
} catch (DuplicateFileException e) {
throw e;
@@ -799,9 +812,11 @@ public final class ApkBuilder implements IArchiveBuilder {
* @throws IOException
* @throws DuplicateFileException if a file conflicts with another already added
* to the APK at the same location inside the APK archive.
+ * @throws SealedApkException if the APK is already sealed.
+ * @throws ApkCreationException if an error occurred
*/
- private void processFileForResource(File file, String path)
- throws IOException, DuplicateFileException {
+ private static void processFileForResource(IArchiveBuilder builder, File file, String path)
+ throws IOException, DuplicateFileException, ApkCreationException, SealedApkException {
if (file.isDirectory()) {
// a directory? we check it
if (checkFolderForPackaging(file.getName())) {
@@ -815,7 +830,7 @@ public final class ApkBuilder implements IArchiveBuilder {
// and process its content.
File[] files = file.listFiles();
for (File contentFile : files) {
- processFileForResource(contentFile, path);
+ processFileForResource(builder, contentFile, path);
}
}
} else {
@@ -829,7 +844,7 @@ public final class ApkBuilder implements IArchiveBuilder {
}
// and add it to the apk
- doAddFile(file, path);
+ builder.addFile(file, path);
}
}
}