diff options
Diffstat (limited to 'eclipse/plugins')
16 files changed, 273 insertions, 77 deletions
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/plugin.xml b/eclipse/plugins/com.android.ide.eclipse.adt/plugin.xml index 6bd16ee..77108c8 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/plugin.xml +++ b/eclipse/plugins/com.android.ide.eclipse.adt/plugin.xml @@ -81,6 +81,13 @@ <persistent value="false" /> </extension> <extension + id="com.android.ide.eclipse.adt.buildToolsProblem" + name="Android Build Tools Problem" + point="org.eclipse.core.resources.markers"> + <super type="org.eclipse.core.resources.problemmarker" /> + <persistent value="false" /> + </extension> + <extension id="com.android.ide.eclipse.adt.dependencyProblem" name="Android Dependency 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 edfc30c..76808e4 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 @@ -151,6 +151,10 @@ public class AdtConstants { * when an AndroidClasspathContainerInitializer has succeeded in creating an * AndroidClasspathContainer */ public final static String MARKER_TARGET = AdtPlugin.PLUGIN_ID + ".targetProblem"; //$NON-NLS-1$ + /** Marker for Android Build Tools errors. + * This is not cleared on each build like other markers. Instead, it's cleared + * when the build tools are setup in the projectState. */ + public final static String MARKER_BUILD_TOOLS = AdtPlugin.PLUGIN_ID + ".buildToolsProblem"; //$NON-NLS-1$ /** Marker for Android Dependency errors. * This is not cleared on each build like other markers. Instead, it's cleared * when a LibraryClasspathContainerInitializer has succeeded in creating a diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/AdtPlugin.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/AdtPlugin.java index 88e9c15..7aec8f5 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/AdtPlugin.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/AdtPlugin.java @@ -1433,7 +1433,7 @@ public class AdtPlugin extends AbstractUIPlugin implements ILogger { // project that have been resolved before the sdk was loaded // will have a ProjectState where the IAndroidTarget is null // so we load the target now that the SDK is loaded. - sdk.loadTarget(Sdk.getProjectState(iProject)); + sdk.loadTargetAndBuildTools(Sdk.getProjectState(iProject)); list.add(javaProject); } } diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/actions/SdkManagerAction.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/actions/SdkManagerAction.java index 71c8263..9d33230 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/actions/SdkManagerAction.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/actions/SdkManagerAction.java @@ -20,15 +20,14 @@ import com.android.SdkConstants; import com.android.annotations.NonNull; import com.android.annotations.Nullable; import com.android.ide.eclipse.adt.AdtPlugin; -import com.android.ide.eclipse.adt.internal.build.DexWrapper; import com.android.ide.eclipse.adt.internal.preferences.AdtPrefs; import com.android.ide.eclipse.adt.internal.sdk.AdtConsoleSdkLog; import com.android.ide.eclipse.adt.internal.sdk.Sdk; import com.android.sdklib.io.FileOp; +import com.android.sdklib.repository.ISdkChangeListener; import com.android.sdklib.util.GrabProcessOutput; import com.android.sdklib.util.GrabProcessOutput.IProcessOutput; import com.android.sdklib.util.GrabProcessOutput.Wait; -import com.android.sdklib.repository.ISdkChangeListener; import com.android.sdkuilib.repository.SdkUpdaterWindow; import com.android.sdkuilib.repository.SdkUpdaterWindow.SdkInvocationContext; @@ -313,9 +312,7 @@ public class SdkManagerAction implements IWorkbenchWindowActionDelegate, IObject if (sdk != null) { sdk.unloadTargetData(true /*preventReload*/); - - DexWrapper dx = sdk.getDexWrapper(); - dx.unload(); + sdk.unloadDexWrappers(); } } diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/AidlProcessor.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/AidlProcessor.java index fa878cf..806fa9c 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/AidlProcessor.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/AidlProcessor.java @@ -17,12 +17,14 @@ package com.android.ide.eclipse.adt.internal.build; import com.android.SdkConstants; +import com.android.annotations.NonNull; import com.android.ide.eclipse.adt.AdtConstants; import com.android.ide.eclipse.adt.AdtPlugin; import com.android.ide.eclipse.adt.internal.build.builders.BaseBuilder; 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.sdklib.BuildToolInfo; import com.android.sdklib.IAndroidTarget; import com.android.sdklib.io.FileOp; @@ -81,8 +83,9 @@ public class AidlProcessor extends SourceProcessor { // "^\\s*interface\\s+([a-zA-Z_][a-zA-Z0-9_]*)\\s*(?:\\{.*)?$"); - public AidlProcessor(IJavaProject javaProject, IFolder genFolder) { - super(javaProject, genFolder); + public AidlProcessor(@NonNull IJavaProject javaProject, @NonNull BuildToolInfo buildToolInfo, + @NonNull IFolder genFolder) { + super(javaProject, buildToolInfo, genFolder); } @Override @@ -95,7 +98,6 @@ public class AidlProcessor extends SourceProcessor { return PROPERTY_COMPILE_AIDL; } - @SuppressWarnings("deprecation") @Override protected void doCompileFiles(List<IFile> sources, BaseBuilder builder, IProject project, IAndroidTarget projectTarget, @@ -104,7 +106,7 @@ public class AidlProcessor extends SourceProcessor { // create the command line List<String> commandList = new ArrayList<String>( 4 + sourceFolders.size() + libraryProjectsOut.size()); - commandList.add(projectTarget.getPath(IAndroidTarget.AIDL)); + commandList.add(getBuildToolInfo().getPath(BuildToolInfo.PathId.AIDL)); commandList.add(quote("-p" + projectTarget.getPath(IAndroidTarget.ANDROID_AIDL))); //$NON-NLS-1$ // since the path are relative to the workspace and not the project itself, we need 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 c94ef9a..da8c2ea 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 @@ -27,6 +27,7 @@ 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.sdk.Sdk; import com.android.prefs.AndroidLocation.AndroidLocationException; +import com.android.sdklib.BuildToolInfo; import com.android.sdklib.IAndroidTarget; import com.android.sdklib.IAndroidTarget.IOptionalLibrary; import com.android.sdklib.build.ApkBuilder; @@ -105,8 +106,13 @@ public class BuildHelper { private static final String COMMAND_CRUNCH = "crunch"; //$NON-NLS-1$ private static final String COMMAND_PACKAGE = "package"; //$NON-NLS-1$ + @NonNull private final IProject mProject; + @NonNull + private final BuildToolInfo mBuildToolInfo; + @NonNull private final AndroidPrintStream mOutStream; + @NonNull private final AndroidPrintStream mErrStream; private final boolean mForceJumbo; private final boolean mDisableDexMerger; @@ -139,11 +145,13 @@ public class BuildHelper { * @throws CoreException */ public BuildHelper(@NonNull IProject project, + @NonNull BuildToolInfo buildToolInfo, @NonNull AndroidPrintStream outStream, @NonNull AndroidPrintStream errStream, boolean forceJumbo, boolean disableDexMerger, boolean debugMode, boolean verbose, ResourceMarker resMarker) throws CoreException { mProject = project; + mBuildToolInfo = buildToolInfo; mOutStream = outStream; mErrStream = errStream; mDebugMode = debugMode; @@ -693,7 +701,7 @@ public class BuildHelper { // get the dex wrapper Sdk sdk = Sdk.getCurrent(); - DexWrapper wrapper = sdk.getDexWrapper(); + DexWrapper wrapper = sdk.getDexWrapper(mBuildToolInfo); if (wrapper == null) { throw new CoreException(new Status(IStatus.ERROR, AdtPlugin.PLUGIN_ID, @@ -833,7 +841,7 @@ public class BuildHelper { String configFilter, int versionCode) throws AaptExecException, AaptResultException { IAndroidTarget target = Sdk.getCurrent().getTarget(mProject); - @SuppressWarnings("deprecation") String aapt = target.getPath(IAndroidTarget.AAPT); + String aapt = mBuildToolInfo.getPath(BuildToolInfo.PathId.AAPT); // Create the command line. ArrayList<String> commandArray = new ArrayList<String>(); diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/RenderScriptProcessor.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/RenderScriptProcessor.java index 2652866..af58e41 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/RenderScriptProcessor.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/RenderScriptProcessor.java @@ -17,6 +17,7 @@ package com.android.ide.eclipse.adt.internal.build; import com.android.SdkConstants; +import com.android.annotations.NonNull; import com.android.ide.eclipse.adt.AdtConstants; import com.android.ide.eclipse.adt.AdtPlugin; import com.android.ide.eclipse.adt.internal.build.builders.BaseBuilder; @@ -25,6 +26,7 @@ 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.sdk.Sdk; import com.android.resources.ResourceFolderType; +import com.android.sdklib.BuildToolInfo; import com.android.sdklib.IAndroidTarget; import com.google.common.collect.Sets; @@ -145,8 +147,9 @@ public class RenderScriptProcessor extends SourceProcessor { private int mTargetApi = 11; - public RenderScriptProcessor(IJavaProject javaProject, IFolder genFolder) { - super(javaProject, genFolder, new RsChangeHandler()); + public RenderScriptProcessor(@NonNull IJavaProject javaProject, + @NonNull BuildToolInfo buildToolInfo, @NonNull IFolder genFolder) { + super(javaProject, buildToolInfo, genFolder, new RsChangeHandler()); } public void setTargetApi(int targetApi) { @@ -164,7 +167,6 @@ public class RenderScriptProcessor extends SourceProcessor { return PROPERTY_COMPILE_RS; } - @SuppressWarnings("deprecation") @Override protected void doCompileFiles(List<IFile> sources, BaseBuilder builder, IProject project, IAndroidTarget projectTarget, @@ -186,9 +188,9 @@ public class RenderScriptProcessor extends SourceProcessor { command[index++] = quote(sdkOsPath + SdkConstants.OS_SDK_PLATFORM_TOOLS_FOLDER + SdkConstants.FN_RENDERSCRIPT); command[index++] = "-I"; //$NON-NLS-1$ - command[index++] = quote(projectTarget.getPath(IAndroidTarget.ANDROID_RS_CLANG)); + command[index++] = quote(getBuildToolInfo().getPath(BuildToolInfo.PathId.ANDROID_RS_CLANG)); command[index++] = "-I"; //$NON-NLS-1$ - command[index++] = quote(projectTarget.getPath(IAndroidTarget.ANDROID_RS)); + command[index++] = quote(getBuildToolInfo().getPath(BuildToolInfo.PathId.ANDROID_RS)); command[index++] = "-p"; //$NON-NLS-1$ command[index++] = quote(genFolder.getLocation().toOSString()); command[index++] = "-o"; //$NON-NLS-1$ diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/SourceProcessor.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/SourceProcessor.java index 4ecb91d..a82d54d 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/SourceProcessor.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/SourceProcessor.java @@ -17,9 +17,11 @@ package com.android.ide.eclipse.adt.internal.build; import com.android.SdkConstants; +import com.android.annotations.NonNull; import com.android.ide.eclipse.adt.internal.build.builders.BaseBuilder; import com.android.ide.eclipse.adt.internal.project.BaseProjectHelper; import com.android.ide.eclipse.adt.internal.project.ProjectHelper; +import com.android.sdklib.BuildToolInfo; import com.android.sdklib.IAndroidTarget; import org.eclipse.core.resources.IFile; @@ -59,6 +61,7 @@ public abstract class SourceProcessor { private final Map<IFile, SourceFileData> mFiles = new HashMap<IFile, SourceFileData>(); private final IJavaProject mJavaProject; + private BuildToolInfo mBuildToolInfo; private final IFolder mGenFolder; private final SourceChangeHandler mDeltaVisitor; @@ -83,9 +86,11 @@ public abstract class SourceProcessor { return path; } - protected SourceProcessor(IJavaProject javaProject, IFolder genFolder, - SourceChangeHandler deltaVisitor) { + protected SourceProcessor(@NonNull IJavaProject javaProject, + @NonNull BuildToolInfo buildToolInfo, @NonNull IFolder genFolder, + @NonNull SourceChangeHandler deltaVisitor) { mJavaProject = javaProject; + mBuildToolInfo = buildToolInfo; mGenFolder = genFolder; mDeltaVisitor = deltaVisitor; @@ -109,8 +114,13 @@ public abstract class SourceProcessor { } } - protected SourceProcessor(IJavaProject javaProject, IFolder genFolder) { - this(javaProject, genFolder, new SourceChangeHandler()); + protected SourceProcessor(@NonNull IJavaProject javaProject, + @NonNull BuildToolInfo buildToolInfo, @NonNull IFolder genFolder) { + this(javaProject, buildToolInfo, genFolder, new SourceChangeHandler()); + } + + public void setBuildToolInfo(BuildToolInfo buildToolInfo) { + mBuildToolInfo = buildToolInfo; } @@ -168,6 +178,10 @@ public abstract class SourceProcessor { return mJavaProject; } + final BuildToolInfo getBuildToolInfo() { + return mBuildToolInfo; + } + final IFolder getGenFolder() { return mGenFolder; } 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 f58af56..1cbf7f2 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 @@ -16,19 +16,24 @@ 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 org.eclipse.core.resources.IContainer; @@ -64,6 +69,13 @@ public abstract class BaseBuilder extends IncrementalProjectBuilder { 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 { @@ -293,9 +305,11 @@ public abstract class BaseBuilder extends IncrementalProjectBuilder { * 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(IJavaProject javaProject) throws AbortBuildException { + 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(); @@ -303,8 +317,12 @@ public abstract class BaseBuilder extends IncrementalProjectBuilder { throw new AbortBuildException(); } + if (projectState == null) { + projectState = Sdk.getProjectState(javaProject.getProject()); + } + // get the target for the project - IAndroidTarget target = sdk.getTarget(javaProject.getProject()); + IAndroidTarget target = projectState.getTarget(); if (target == null) { throw new AbortBuildException(); @@ -315,6 +333,20 @@ public abstract class BaseBuilder extends IncrementalProjectBuilder { throw new AbortBuildException(); } + mBuildToolInfo = projectState.getBuildToolInfo(); + if (mBuildToolInfo == null) { + mBuildToolInfo = sdk.getLatestBuildTool(); + + if (mBuildToolInfo == null) { + 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*/); 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 6e3dce3..baeb154 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 @@ -341,7 +341,7 @@ public class PostCompilerBuilder extends BaseBuilder { // Top level check to make sure the build can move forward. Only do this after recording // delta changes. - abortOnBadSetup(javaProject); + abortOnBadSetup(javaProject, projectState); // Get the output stream. Since the builder is created for the life of the // project, they can be kept around. @@ -369,7 +369,7 @@ public class PostCompilerBuilder extends BaseBuilder { if (DEBUG_LOG) { AdtPlugin.log(IStatus.INFO, "%s running crunch!", project.getName()); } - BuildHelper helper = new BuildHelper(project, + BuildHelper helper = new BuildHelper(project, mBuildToolInfo, mOutStream, mErrStream, false /*jumbo mode doesn't matter here*/, false /*dex merger doesn't matter here*/, @@ -484,7 +484,7 @@ public class PostCompilerBuilder extends BaseBuilder { AdtConstants.DEX_OPTIONS_DISABLE_MERGER); Boolean dexMerger = Boolean.valueOf(dexMergerStr); - BuildHelper helper = new BuildHelper(project, + BuildHelper helper = new BuildHelper(project, mBuildToolInfo, mOutStream, mErrStream, jumbo.booleanValue(), dexMerger.booleanValue(), @@ -913,8 +913,9 @@ public class PostCompilerBuilder extends BaseBuilder { } @Override - protected void abortOnBadSetup(IJavaProject javaProject) throws AbortBuildException { - super.abortOnBadSetup(javaProject); + protected void abortOnBadSetup(IJavaProject javaProject, ProjectState projectState) + throws AbortBuildException, CoreException { + super.abortOnBadSetup(javaProject, projectState); IProject iProject = getProject(); 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 0f0cbcc..ae6b3f5 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 @@ -47,6 +47,7 @@ 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.internal.build.BuildConfigGenerator; import com.android.sdklib.internal.build.SymbolLoader; @@ -95,7 +96,6 @@ import javax.xml.parsers.ParserConfigurationException; * </ul> * */ -@SuppressWarnings("deprecation") public class PreCompilerBuilder extends BaseBuilder { /** This ID is used in plugin.xml and in each project's .project file. @@ -144,6 +144,7 @@ public class PreCompilerBuilder extends BaseBuilder { */ private DerivedProgressMonitor mDerivedProgressMonitor; + private AidlProcessor mAidlProcessor; private RenderScriptProcessor mRenderScriptProcessor; /** @@ -276,7 +277,9 @@ public class PreCompilerBuilder extends BaseBuilder { IJavaProject javaProject = JavaCore.create(project); // Top level check to make sure the build can move forward. - abortOnBadSetup(javaProject); + abortOnBadSetup(javaProject, projectState); + + setupSourceProcessors(javaProject, projectState); // now we need to get the classpath list List<IPath> sourceFolderPathList = BaseProjectHelper.getSourceClasspaths(javaProject); @@ -707,8 +710,8 @@ public class PreCompilerBuilder extends BaseBuilder { proguardFile = androidOutputFolder.getFile(AdtConstants.FN_AAPT_PROGUARD); } - handleResources(project, javaPackage, projectTarget, manifestFile, libProjects, - isLibrary, proguardFile); + handleResources(project, javaPackage, projectTarget, manifestFile, + libProjects, isLibrary, proguardFile); } if (processorStatus == SourceProcessor.COMPILE_STATUS_NONE && @@ -796,18 +799,25 @@ public class PreCompilerBuilder extends BaseBuilder { mLastBuildConfigMode = v; } - IJavaProject javaProject = JavaCore.create(project); - - // load the source processors - SourceProcessor aidlProcessor = new AidlProcessor(javaProject, mGenFolder); - mRenderScriptProcessor = new RenderScriptProcessor(javaProject, mGenFolder); - mProcessors.add(aidlProcessor); - mProcessors.add(mRenderScriptProcessor); } catch (Throwable throwable) { AdtPlugin.log(throwable, "Failed to finish PrecompilerBuilder#startupOnInitialize()"); } } + private void setupSourceProcessors(@NonNull IJavaProject javaProject, + @NonNull ProjectState projectState) { + if (mAidlProcessor == null) { + mAidlProcessor = new AidlProcessor(javaProject, mBuildToolInfo, mGenFolder); + mRenderScriptProcessor = new RenderScriptProcessor(javaProject, mBuildToolInfo, + mGenFolder); + mProcessors.add(mAidlProcessor); + mProcessors.add(mRenderScriptProcessor); + } else { + mAidlProcessor.setBuildToolInfo(mBuildToolInfo); + mRenderScriptProcessor.setBuildToolInfo(mBuildToolInfo); + } + } + @SuppressWarnings("deprecation") private void handleBuildConfig(@SuppressWarnings("rawtypes") Map args) throws IOException, CoreException { @@ -916,7 +926,7 @@ public class PreCompilerBuilder extends BaseBuilder { outFile.getLocation().toFile(), manifest.getLocation().toFile(), libManifests, - null /*injectAttributes*/) == false) { + null /*injectAttributes*/, null /*packageOverride*/) == false) { if (errors.size() > 1) { StringBuilder sb = new StringBuilder(); for (String s : errors) { @@ -1054,7 +1064,7 @@ public class PreCompilerBuilder extends BaseBuilder { // launch aapt: create the command line ArrayList<String> array = new ArrayList<String>(); - String aaptPath = projectTarget.getPath(IAndroidTarget.AAPT); + String aaptPath = mBuildToolInfo.getPath(BuildToolInfo.PathId.AAPT); array.add(aaptPath); array.add("package"); //$NON-NLS-1$ 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 index 39f7d1f..770710d 100644 --- 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 @@ -24,8 +24,6 @@ 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.sdklib.IAndroidTarget; import com.android.utils.Pair; import org.eclipse.core.resources.IFolder; @@ -87,7 +85,7 @@ public class ResourceManagerBuilder extends BaseBuilder { // check for existing target marker, in which case we abort. // (this means: no SDK, no target, or unresolvable target.) try { - abortOnBadSetup(javaProject); + abortOnBadSetup(javaProject, null); } catch (AbortBuildException e) { return null; } @@ -129,13 +127,6 @@ public class ResourceManagerBuilder extends BaseBuilder { return null; } - // check the project has a target - IAndroidTarget projectTarget = Sdk.getCurrent().getTarget(project); - if (projectTarget == null) { - // no target. marker has been set by the container initializer: exit silently. - return null; - } - // check the 'gen' source folder is present boolean hasGenSrcFolder = false; // whether the project has a 'gen' source folder setup diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/project/AndroidClasspathContainerInitializer.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/project/AndroidClasspathContainerInitializer.java index f3d6371..c526edf 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/project/AndroidClasspathContainerInitializer.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/project/AndroidClasspathContainerInitializer.java @@ -586,7 +586,8 @@ public class AndroidClasspathContainerInitializer extends BaseClasspathContainer // project that have been resolved before the sdk was loaded // will have a ProjectState where the IAndroidTarget is null // so we load the target now that the SDK is loaded. - IAndroidTarget target = currentSdk.loadTarget(Sdk.getProjectState(iProject)); + IAndroidTarget target = currentSdk.loadTargetAndBuildTools( + Sdk.getProjectState(iProject)); if (target == null) { // this is really not supposed to happen. This would mean there are cached paths, // but project.properties was deleted. Keep the project in the list to force 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 d215f2f..52870a4 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 @@ -31,6 +31,7 @@ import com.android.ide.eclipse.adt.internal.preferences.AdtPrefs; 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.sdklib.BuildToolInfo; import com.android.sdklib.build.ApkCreationException; import com.android.sdklib.build.DuplicateFileException; import com.android.sdklib.internal.project.ProjectProperties; @@ -132,7 +133,17 @@ public final class ExportHelper { String dexMergerStr = projectState.getProperty(AdtConstants.DEX_OPTIONS_DISABLE_MERGER); Boolean dexMerger = Boolean.valueOf(dexMergerStr); - BuildHelper helper = new BuildHelper(project, + BuildToolInfo buildToolInfo = projectState.getBuildToolInfo(); + if (buildToolInfo == null) { + buildToolInfo = Sdk.getCurrent().getLatestBuildTool(); + } + + if (buildToolInfo == null) { + throw new CoreException(new Status(IStatus.ERROR, AdtPlugin.PLUGIN_ID, + "No Build Tools installed in the SDK.")); + } + + BuildHelper helper = new BuildHelper(project, buildToolInfo, fakeStream, fakeStream, jumbo.booleanValue(), dexMerger.booleanValue(), 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 64053ad..4628509 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 @@ -19,6 +19,7 @@ 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.BuildToolInfo; import com.android.sdklib.IAndroidTarget; import com.android.sdklib.internal.project.ProjectProperties; import com.android.sdklib.internal.project.ProjectPropertiesWorkingCopy; @@ -160,6 +161,7 @@ public final class ProjectState { private final IProject mProject; private final ProjectProperties mProperties; private IAndroidTarget mTarget; + private BuildToolInfo mBuildToolInfo; /** * list of libraries. Access to this list must be protected by @@ -240,6 +242,23 @@ public final class ProjectState { return mTarget; } + public void setBuildToolInfo(BuildToolInfo buildToolInfo) { + mBuildToolInfo = buildToolInfo; + } + + public BuildToolInfo getBuildToolInfo() { + return mBuildToolInfo; + } + + /** + * Returns the build tools version from the project's properties. + * @return the value or null + */ + @Nullable + public String getBuildToolInfoVersion() { + return mProperties.getProperty(ProjectProperties.PROPERTY_BUILD_TOOLS); + } + public static class LibraryDifference { public boolean removed = false; public boolean added = false; diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk/Sdk.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk/Sdk.java index 16df952..74f08c2 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk/Sdk.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk/Sdk.java @@ -43,6 +43,7 @@ import com.android.ide.eclipse.adt.internal.sdk.ProjectState.LibraryState; import com.android.io.StreamException; import com.android.prefs.AndroidLocation.AndroidLocationException; import com.android.sdklib.AndroidVersion; +import com.android.sdklib.BuildToolInfo; import com.android.sdklib.IAndroidTarget; import com.android.sdklib.SdkManager; import com.android.sdklib.devices.DeviceManager; @@ -50,10 +51,13 @@ import com.android.sdklib.internal.avd.AvdManager; import com.android.sdklib.internal.project.ProjectProperties; import com.android.sdklib.internal.project.ProjectProperties.PropertyType; import com.android.sdklib.internal.project.ProjectPropertiesWorkingCopy; +import com.android.sdklib.repository.FullRevision; import com.android.utils.ILogger; +import com.google.common.collect.Maps; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IFolder; +import org.eclipse.core.resources.IMarker; import org.eclipse.core.resources.IMarkerDelta; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; @@ -130,7 +134,7 @@ public final class Sdk { } private final SdkManager mManager; - private final DexWrapper mDexWrapper; + private final Map<String, DexWrapper> mDexWrappers = Maps.newHashMap(); private final AvdManager mAvdManager; private final DeviceManager mDeviceManager; @@ -265,17 +269,6 @@ public final class Sdk { // get an SdkManager object for the location SdkManager manager = SdkManager.createManager(sdkLocation, log); if (manager != null) { - // load DX. - DexWrapper dexWrapper = new DexWrapper(); - String dexLocation = - sdkLocation + File.separator + - SdkConstants.OS_SDK_PLATFORM_TOOLS_LIB_FOLDER + SdkConstants.FN_DX_JAR; - IStatus res = dexWrapper.loadDex(dexLocation); - if (res != Status.OK_STATUS) { - log.error(null, res.getMessage()); - dexWrapper = null; - } - // create the AVD Manager AvdManager avdManager = null; try { @@ -283,7 +276,7 @@ public final class Sdk { } catch (AndroidLocationException e) { log.error(e, "Error parsing the AVDs"); } - sCurrentSdk = new Sdk(manager, dexWrapper, avdManager); + sCurrentSdk = new Sdk(manager, avdManager); return sCurrentSdk; } else { StringBuilder sb = new StringBuilder("Error Loading the SDK:\n"); @@ -376,6 +369,24 @@ public final class Sdk { return mManager.getTargetFromHashString(hash); } + @Nullable + public BuildToolInfo getBuildToolInfo(@Nullable String buildToolVersion) { + if (buildToolVersion != null) { + try { + return mManager.getBuildTool(FullRevision.parseRevision(buildToolVersion)); + } catch (Exception e) { + // ignore, return null below. + } + } + + return null; + } + + @Nullable + public BuildToolInfo getLatestBuildTool() { + return mManager.getLatestBuildTool(false /*isPreview*/); + } + /** * Initializes a new project with a target. This creates the <code>project.properties</code> * file. @@ -487,7 +498,7 @@ public final class Sdk { // try to resolve the target if (AdtPlugin.getDefault().getSdkLoadStatus() == LoadStatus.LOADED) { - sCurrentSdk.loadTarget(state); + sCurrentSdk.loadTargetAndBuildTools(state); } } @@ -513,26 +524,84 @@ public final class Sdk { } /** - * Loads the {@link IAndroidTarget} for a given project. + * Loads the {@link IAndroidTarget} and BuildTools for a given project. * <p/>This method will get the target hash string from the project properties, and resolve * it to an {@link IAndroidTarget} object and store it inside the {@link ProjectState}. * @param state the state representing the project to load. * @return the target that was loaded. */ @Nullable - public IAndroidTarget loadTarget(ProjectState state) { + public IAndroidTarget loadTargetAndBuildTools(ProjectState state) { IAndroidTarget target = null; if (state != null) { String hash = state.getTargetHashString(); if (hash != null) { state.setTarget(target = getTargetFromHashString(hash)); } + + String markerMessage = null; + String buildToolInfoVersion = state.getBuildToolInfoVersion(); + if (buildToolInfoVersion != null) { + BuildToolInfo buildToolsInfo = getBuildToolInfo(buildToolInfoVersion); + + if (buildToolsInfo != null) { + state.setBuildToolInfo(buildToolsInfo); + } else { + markerMessage = String.format("Unable to resolve %s property value '%s'", + ProjectProperties.PROPERTY_BUILD_TOOLS, + buildToolInfoVersion); + } + } else { + // this is ok, we'll use the latest one automatically. + state.setBuildToolInfo(null); + } + + handleBuildToolsMarker(state.getProject(), markerMessage); } return target; } /** + * Adds or edit a build tools marker from the given project. This is done through a Job. + * @param project the project + * @param markerMessage the message. if null the marker is removed. + */ + private void handleBuildToolsMarker(final IProject project, final String markerMessage) { + Job markerJob = new Job("Android SDK: Build Tools Marker") { + @Override + protected IStatus run(IProgressMonitor monitor) { + try { + if (project.isAccessible()) { + // always delete existing marker first + project.deleteMarkers(AdtConstants.MARKER_BUILD_TOOLS, true, + IResource.DEPTH_ZERO); + + // add the new one if needed. + if (markerMessage != null) { + BaseProjectHelper.markProject(project, + AdtConstants.MARKER_BUILD_TOOLS, + markerMessage, IMarker.SEVERITY_ERROR, + IMarker.PRIORITY_HIGH); + } + } + } catch (CoreException e2) { + AdtPlugin.log(e2, null); + // Don't return e2.getStatus(); the job control will then produce + // a popup with this error, which isn't very interesting for the + // user. + } + + return Status.OK_STATUS; + } + }; + + // build jobs are run after other interactive jobs + markerJob.setPriority(Job.BUILD); + markerJob.schedule(); + } + + /** * Checks and loads (if needed) the data for a given target. * <p/> The data is loaded in a separate {@link Job}, and opened editors will be notified * through their implementation of {@link ITargetChangeListener#onTargetLoaded(IAndroidTarget)}. @@ -668,8 +737,38 @@ public final class Sdk { * Returns a {@link DexWrapper} object to be used to execute dx commands. If dx.jar was not * loaded properly, then this will return <code>null</code>. */ - public DexWrapper getDexWrapper() { - return mDexWrapper; + @Nullable + public DexWrapper getDexWrapper(@Nullable BuildToolInfo buildToolInfo) { + if (buildToolInfo == null) { + return null; + } + synchronized (LOCK) { + String dexLocation = buildToolInfo.getPath(BuildToolInfo.PathId.DX_JAR); + DexWrapper dexWrapper = mDexWrappers.get(dexLocation); + + if (dexWrapper == null) { + // load DX. + dexWrapper = new DexWrapper(); + IStatus res = dexWrapper.loadDex(dexLocation); + if (res != Status.OK_STATUS) { + AdtPlugin.log(null, res.getMessage()); + dexWrapper = null; + } else { + mDexWrappers.put(dexLocation, dexWrapper); + } + } + + return dexWrapper; + } + } + + public void unloadDexWrappers() { + synchronized (LOCK) { + for (DexWrapper wrapper : mDexWrappers.values()) { + wrapper.unload(); + } + mDexWrappers.clear(); + } } /** @@ -763,9 +862,8 @@ public final class Sdk { } } - private Sdk(SdkManager manager, DexWrapper dexWrapper, AvdManager avdManager) { + private Sdk(SdkManager manager, AvdManager avdManager) { mManager = manager; - mDexWrapper = dexWrapper; mAvdManager = avdManager; // listen to projects closing @@ -787,8 +885,7 @@ public final class Sdk { // update whatever ProjectState is already present with new IAndroidTarget objects. synchronized (LOCK) { for (Entry<IProject, ProjectState> entry: sProjectStateMap.entrySet()) { - entry.getValue().setTarget( - getTargetFromHashString(entry.getValue().getTargetHashString())); + loadTargetAndBuildTools(entry.getValue()); } } } @@ -1042,7 +1139,7 @@ public final class Sdk { ProjectState state = Sdk.getProjectState(iProject); - // get the current target + // get the current target and build tools IAndroidTarget oldTarget = state.getTarget(); // get the current library flag @@ -1051,7 +1148,7 @@ public final class Sdk { LibraryDifference diff = state.reloadProperties(); // load the (possibly new) target. - IAndroidTarget newTarget = loadTarget(state); + IAndroidTarget newTarget = loadTargetAndBuildTools(state); // reload the libraries if needed if (diff.hasDiff()) { |