aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/AdtConstants.java16
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/AdtPlugin.java5
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/BuildHelper.java43
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/DefaultSourceChangeHandler.java105
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/RenderScriptLauncher.java244
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/RenderScriptProcessor.java552
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/RsSourceChangeHandler.java90
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/SourceChangeHandler.java99
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/SourceProcessor.java22
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/builders/ChangedFileSetHelper.java17
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/builders/PatternBasedDeltaVisitor.java2
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/builders/PostCompilerBuilder.java8
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/builders/PreCompilerBuilder.java196
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/builders/PreCompilerDeltaVisitor.java19
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/project/AndroidClasspathContainerInitializer.java115
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/project/BaseProjectHelper.java6
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/project/ExportHelper.java4
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/project/LibraryClasspathContainerInitializer.java113
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk/ProjectState.java9
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk/Sdk.java4
20 files changed, 828 insertions, 841 deletions
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 5330e08..0e3b783 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
@@ -94,9 +94,19 @@ public class AdtConstants {
/** Absolute path of the resource folder, e.g. "/res".<br> This is a workspace path. */
public final static String WS_RESOURCES = WS_SEP + SdkConstants.FD_RESOURCES;
- /** Absolute path of the crunch cache folder, e.g. "/bin/res".<br> This is a workspace path. */
- public final static String WS_CRUNCHCACHE = WS_SEP + SdkConstants.FD_OUTPUT
- + WS_SEP + SdkConstants.FD_RESOURCES;
+ public final static String FD_CRUNCH = "crunch"; //$NON-NLS-1$
+ public final static String FD_BC = "bc"; //$NON-NLS-1$
+
+ /** Path of crunch cache folder relative to the output folder.<br> This is a workspace path. */
+ public final static String WS_BIN_RELATIVE_CRUNCHCACHE = SdkConstants.FD_RESOURCES
+ + WS_SEP + FD_CRUNCH;
+
+ /** Path of bc output folder relative to the output folder.<br> This is a workspace path. */
+ public final static String WS_BIN_RELATIVE_BC = SdkConstants.FD_RESOURCES
+ + WS_SEP + FD_BC;
+
+ /** Path of rs libs output folder relative to the output folder.<br> This is a workspace path. */
+ public final static String WS_BIN_RELATIVE_RS_LIBS = SdkConstants.FD_RS_LIBS;
/** Absolute path of the resource folder, e.g. "/assets".<br> This is a workspace path. */
public final static String WS_ASSETS = WS_SEP + SdkConstants.FD_ASSETS;
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 c5d95af..cbeb274 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
@@ -51,6 +51,7 @@ import com.android.io.StreamException;
import com.android.resources.ResourceFolderType;
import com.android.sdklib.IAndroidTarget;
import com.android.utils.ILogger;
+import com.google.common.collect.Sets;
import com.google.common.io.Closeables;
import org.eclipse.core.commands.Command;
@@ -123,6 +124,7 @@ import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
+import java.util.Set;
/**
* The activator class controls the plug-in life cycle
@@ -153,8 +155,7 @@ public class AdtPlugin extends AbstractUIPlugin implements ILogger {
private LoadStatus mSdkLoadedStatus = LoadStatus.LOADING;
/** Project to update once the SDK is loaded.
* Any access MUST be in a synchronized(mPostLoadProjectsToResolve) block */
- private final ArrayList<IJavaProject> mPostLoadProjectsToResolve =
- new ArrayList<IJavaProject>();
+ private final Set<IJavaProject> mPostLoadProjectsToResolve = Sets.newHashSet();
/** Project to check validity of cache vs actual once the SDK is loaded.
* Any access MUST be in a synchronized(mPostLoadProjectsToResolve) block */
private final ArrayList<IJavaProject> mPostLoadProjectsToCheck = new ArrayList<IJavaProject>();
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 cda1da0..8e831b7 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
@@ -25,6 +25,7 @@ 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.sdk.ProjectState;
import com.android.ide.eclipse.adt.internal.sdk.Sdk;
import com.android.prefs.AndroidLocation.AndroidLocationException;
import com.android.sdklib.BuildToolInfo;
@@ -35,6 +36,7 @@ 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.RenderScriptProcessor;
import com.android.sdklib.build.SealedApkException;
import com.android.sdklib.internal.build.DebugKeyProvider;
import com.android.sdklib.internal.build.DebugKeyProvider.KeytoolException;
@@ -107,6 +109,8 @@ public class BuildHelper {
private static final String COMMAND_PACKAGE = "package"; //$NON-NLS-1$
@NonNull
+ private final ProjectState mProjectState;
+ @NonNull
private final IProject mProject;
@NonNull
private final BuildToolInfo mBuildToolInfo;
@@ -144,13 +148,14 @@ public class BuildHelper {
* @param verbose
* @throws CoreException
*/
- public BuildHelper(@NonNull IProject project,
+ public BuildHelper(@NonNull ProjectState projectState,
@NonNull BuildToolInfo buildToolInfo,
@NonNull AndroidPrintStream outStream,
@NonNull AndroidPrintStream errStream,
boolean forceJumbo, boolean disableDexMerger, boolean debugMode,
boolean verbose, ResourceMarker resMarker) throws CoreException {
- mProject = project;
+ mProjectState = projectState;
+ mProject = projectState.getProject();
mBuildToolInfo = buildToolInfo;
mOutStream = outStream;
mErrStream = errStream;
@@ -177,7 +182,8 @@ public class BuildHelper {
resPaths.add(resFolder.getLocation().toOSString());
// Get the output folder where the cache is stored.
- IFolder cacheFolder = mProject.getFolder(AdtConstants.WS_CRUNCHCACHE);
+ IFolder binFolder = BaseProjectHelper.getAndroidOutputFolder(mProject);
+ IFolder cacheFolder = binFolder.getFolder(AdtConstants.WS_BIN_RELATIVE_CRUNCHCACHE);
String cachePath = cacheFolder.getLocation().toOSString();
/* For crunching, we don't need the osManifestPath, osAssetsPath, or the configFilter
@@ -219,9 +225,13 @@ public class BuildHelper {
}
// need to figure out some path before we can execute aapt;
+ IFolder binFolder = BaseProjectHelper.getAndroidOutputFolder(mProject);
// get the cache folder
- IFolder cacheFolder = mProject.getFolder(AdtConstants.WS_CRUNCHCACHE);
+ IFolder cacheFolder = binFolder.getFolder(AdtConstants.WS_BIN_RELATIVE_CRUNCHCACHE);
+
+ // get the BC folder
+ IFolder bcFolder = binFolder.getFolder(AdtConstants.WS_BIN_RELATIVE_BC);
// get the resource folder
IFolder resFolder = mProject.getFolder(AdtConstants.WS_RESOURCES);
@@ -244,6 +254,7 @@ public class BuildHelper {
// png cache folder first.
addFolderToList(osResPaths, cacheFolder);
+ addFolderToList(osResPaths, bcFolder);
// regular res folder next.
osResPaths.add(resLocation.toOSString());
@@ -252,9 +263,14 @@ public class BuildHelper {
if (libProjects != null) {
for (IProject lib : libProjects) {
// png cache folder first
- IFolder libCacheFolder = lib.getFolder(AdtConstants.WS_CRUNCHCACHE);
+ IFolder libBinFolder = BaseProjectHelper.getAndroidOutputFolder(lib);
+
+ IFolder libCacheFolder = libBinFolder.getFolder(AdtConstants.WS_BIN_RELATIVE_CRUNCHCACHE);
addFolderToList(osResPaths, libCacheFolder);
+ IFolder libBcFolder = libBinFolder.getFolder(AdtConstants.WS_BIN_RELATIVE_BC);
+ addFolderToList(osResPaths, libBcFolder);
+
// regular res folder next.
IFolder libResFolder = lib.getFolder(AdtConstants.WS_RESOURCES);
addFolderToList(osResPaths, libResFolder);
@@ -452,6 +468,23 @@ public class BuildHelper {
apkBuilder.addNativeLibraries(libFolder.getLocation().toFile());
}
+ // next the native libraries for the renderscript support mode.
+ if (mProjectState.getRenderScriptSupportMode()) {
+ IFolder androidOutputFolder = BaseProjectHelper.getAndroidOutputFolder(mProject);
+ IResource rsLibFolder = androidOutputFolder.getFolder(
+ AdtConstants.WS_BIN_RELATIVE_RS_LIBS);
+ File rsLibFolderFile = rsLibFolder.getLocation().toFile();
+ if (rsLibFolderFile.isDirectory()) {
+ apkBuilder.addNativeLibraries(rsLibFolderFile);
+ }
+
+ File rsLibs = RenderScriptProcessor.getSupportNativeLibFolder(
+ mBuildToolInfo.getLocation().getAbsolutePath());
+ if (rsLibs.isDirectory()) {
+ apkBuilder.addNativeLibraries(rsLibs);
+ }
+ }
+
// write the native libraries for the library projects.
if (libProjects != null) {
for (IProject lib : libProjects) {
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/DefaultSourceChangeHandler.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/DefaultSourceChangeHandler.java
new file mode 100644
index 0000000..ea0d695
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/DefaultSourceChangeHandler.java
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Eclipse Public License, Version 1.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.eclipse.org/org/documents/epl-v10.php
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.ide.eclipse.adt.internal.build;
+
+import org.eclipse.core.resources.IContainer;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IResourceDelta;
+
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * Base source change handler for the {@link SourceProcessor} classes.
+ *
+ * It can be used as is, as long as the matching {@link SourceProcessor} properly implements
+ * its abstract methods, and the processor does not output resource files,
+ * or can be extended to provide custom implementation for:
+ * {@link #handleSourceFile(IFile, int)}
+ * {@link #handleGeneratedFile(IFile, int)}
+ * {@link #handleResourceFile(IFile, int)}
+ * {@link #filterResourceFolder(IContainer)}
+ *
+ */
+public class DefaultSourceChangeHandler implements SourceChangeHandler {
+
+ private SourceProcessor mProcessor;
+
+ /** List of source files found that are modified or new. */
+ private final Set<IFile> mToCompile = new HashSet<IFile>();
+
+ /** List of source files that have been removed. */
+ private final Set<IFile> mRemoved = new HashSet<IFile>();
+
+ @Override
+ public boolean handleGeneratedFile(IFile file, int kind) {
+ if (kind == IResourceDelta.REMOVED || kind == IResourceDelta.CHANGED) {
+ IFile sourceFile = mProcessor.isOutput(file);
+ if (sourceFile != null) {
+ mToCompile.add(sourceFile);
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ @Override
+ public void handleSourceFile(IFile file, int kind) {
+ // first the file itself if this is a match for the processor's extension
+ if (mProcessor.getExtensions().contains(file.getFileExtension())) {
+ if (kind == IResourceDelta.REMOVED) {
+ mRemoved.add(file);
+ } else {
+ mToCompile.add(file);
+ }
+ }
+
+ // now the dependencies. In all case we compile the files that depend on the
+ // added/changed/removed file.
+ mToCompile.addAll(mProcessor.isDependency(file));
+ }
+
+ protected void addFileToCompile(IFile file) {
+ mToCompile.add(file);
+ }
+
+ Set<IFile> getFilesToCompile() {
+ return mToCompile;
+ }
+
+ protected void addRemovedFile(IFile file) {
+ mRemoved.add(file);
+ }
+
+ Set<IFile> getRemovedFiles() {
+ return mRemoved;
+ }
+
+ public void reset() {
+ mToCompile.clear();
+ mRemoved.clear();
+ }
+
+ protected SourceProcessor getProcessor() {
+ return mProcessor;
+ }
+
+ void init(SourceProcessor processor) {
+ mProcessor = processor;
+ }
+}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/RenderScriptLauncher.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/RenderScriptLauncher.java
new file mode 100644
index 0000000..1d3c7bd
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/RenderScriptLauncher.java
@@ -0,0 +1,244 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Eclipse Public License, Version 1.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.eclipse.org/org/documents/epl-v10.php
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.ide.eclipse.adt.internal.build;
+
+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.project.BaseProjectHelper;
+import com.android.sdklib.build.RenderScriptProcessor.CommandLineLauncher;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IFolder;
+import org.eclipse.core.resources.IMarker;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Path;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * A {@link SourceProcessor} for RenderScript files.
+ */
+public class RenderScriptLauncher implements CommandLineLauncher {
+
+ /**
+ * Single line llvm-rs-cc error: {@code <path>:<line>:<col>: <error>}
+ */
+ private static Pattern sLlvmPattern1 = Pattern.compile("^(.+?):(\\d+):(\\d+):\\s(.+)$"); //$NON-NLS-1$
+
+ @NonNull
+ private final IProject mProject;
+ @NonNull
+ private final IFolder mSourceOutFolder;
+ @NonNull
+ private final IFolder mResOutFolder;
+ @NonNull
+ private final IProgressMonitor mMonitor;
+ private final boolean mVerbose;
+
+ public RenderScriptLauncher(
+ @NonNull IProject project,
+ @NonNull IFolder sourceOutFolder,
+ @NonNull IFolder resOutFolder,
+ @NonNull IProgressMonitor monitor,
+ boolean verbose) {
+ mProject = project;
+ mSourceOutFolder = sourceOutFolder;
+ mResOutFolder = resOutFolder;
+ mMonitor = monitor;
+ mVerbose = verbose;
+ }
+
+ @Override
+ public void launch(File executable, List<String> arguments, Map<String, String> envVariableMap)
+ throws IOException, InterruptedException {
+ // do the exec
+ try {
+ if (mVerbose) {
+ StringBuilder sb = new StringBuilder(executable.getAbsolutePath());
+ for (String c : arguments) {
+ sb.append(' ').append(c);
+ }
+ String cmd_line = sb.toString();
+ AdtPlugin.printToConsole(mProject, cmd_line);
+ }
+
+ String[] commandArray = new String[1 + arguments.size()];
+ commandArray[0] = executable.getAbsolutePath();
+ System.arraycopy(arguments.toArray(), 0, commandArray, 1, arguments.size());
+
+ ProcessBuilder processBuilder = new ProcessBuilder(commandArray);
+ Map<String, String> processEnvs = processBuilder.environment();
+ for (Map.Entry<String, String> entry : envVariableMap.entrySet()) {
+ processEnvs.put(entry.getKey(), entry.getValue());
+ }
+
+ Process p = processBuilder.start();
+
+ // list to store each line of stderr
+ ArrayList<String> stdErr = new ArrayList<String>();
+
+ // get the output and return code from the process
+ int returnCode = BuildHelper.grabProcessOutput(mProject, p, stdErr);
+
+ if (stdErr.size() > 0) {
+ // attempt to parse the error output
+ boolean parsingError = parseLlvmOutput(stdErr);
+
+ // If the process failed and we couldn't parse the output
+ // we print a message, mark the project and exit
+ if (returnCode != 0) {
+
+ if (parsingError || mVerbose) {
+ // display the message in the console.
+ if (parsingError) {
+ AdtPlugin.printErrorToConsole(mProject, stdErr.toArray());
+
+ // mark the project
+ BaseProjectHelper.markResource(mProject,
+ AdtConstants.MARKER_RENDERSCRIPT,
+ "Unparsed Renderscript error! Check the console for output.",
+ IMarker.SEVERITY_ERROR);
+ } else {
+ AdtPlugin.printToConsole(mProject, stdErr.toArray());
+ }
+ }
+ return;
+ }
+ } else if (returnCode != 0) {
+ // no stderr output but exec failed.
+ String msg = String.format("Error executing Renderscript: Return code %1$d",
+ returnCode);
+
+ BaseProjectHelper.markResource(mProject, AdtConstants.MARKER_AIDL,
+ msg, IMarker.SEVERITY_ERROR);
+
+ return;
+ }
+ } catch (IOException e) {
+ // mark the project and exit
+ String msg = String.format(
+ "Error executing Renderscript. Please check %1$s is present at %2$s",
+ executable.getName(), executable.getAbsolutePath());
+ AdtPlugin.log(IStatus.ERROR, msg);
+ BaseProjectHelper.markResource(mProject, AdtConstants.MARKER_RENDERSCRIPT, msg,
+ IMarker.SEVERITY_ERROR);
+ throw e;
+ } catch (InterruptedException e) {
+ // mark the project and exit
+ String msg = String.format(
+ "Error executing Renderscript. Please check %1$s is present at %2$s",
+ executable.getName(), executable.getAbsolutePath());
+ AdtPlugin.log(IStatus.ERROR, msg);
+ BaseProjectHelper.markResource(mProject, AdtConstants.MARKER_RENDERSCRIPT, msg,
+ IMarker.SEVERITY_ERROR);
+ throw e;
+ }
+
+ try {
+ mSourceOutFolder.refreshLocal(IResource.DEPTH_ONE, mMonitor);
+ mResOutFolder.refreshLocal(IResource.DEPTH_ONE, mMonitor);
+ } catch (CoreException e) {
+ AdtPlugin.log(e, "failed to refresh folders");
+ }
+
+ return;
+ }
+
+ /**
+ * Parse the output of llvm-rs-cc and mark the file with any errors.
+ * @param lines The output to parse.
+ * @return true if the parsing failed, false if success.
+ */
+ private boolean parseLlvmOutput(ArrayList<String> lines) {
+ // nothing to parse? just return false;
+ if (lines.size() == 0) {
+ return false;
+ }
+
+ // get the root folder for the project as we're going to ignore everything that's
+ // not in the project
+ String rootPath = mProject.getLocation().toOSString();
+ int rootPathLength = rootPath.length();
+
+ Matcher m;
+
+ boolean parsing = false;
+
+ for (int i = 0; i < lines.size(); i++) {
+ String p = lines.get(i);
+
+ m = sLlvmPattern1.matcher(p);
+ if (m.matches()) {
+ // get the file path. This may, or may not be the main file being compiled.
+ String filePath = m.group(1);
+ if (filePath.startsWith(rootPath) == false) {
+ // looks like the error in a non-project file. Keep parsing, but
+ // we'll return true
+ parsing = true;
+ continue;
+ }
+
+ // get the actual file.
+ filePath = filePath.substring(rootPathLength);
+ // remove starting separator since we want the path to be relative
+ if (filePath.startsWith(File.separator)) {
+ filePath = filePath.substring(1);
+ }
+
+ // get the file
+ IFile f = mProject.getFile(new Path(filePath));
+
+ String lineStr = m.group(2);
+ // ignore group 3 for now, this is the col number
+ String msg = m.group(4);
+
+ // get the line number
+ int line = 0;
+ try {
+ line = Integer.parseInt(lineStr);
+ } catch (NumberFormatException e) {
+ // looks like the string we extracted wasn't a valid
+ // file number. Parsing failed and we return true
+ return true;
+ }
+
+ // mark the file
+ BaseProjectHelper.markResource(f, AdtConstants.MARKER_RENDERSCRIPT, msg, line,
+ IMarker.SEVERITY_ERROR);
+
+ // success, go to the next line
+ continue;
+ }
+
+ // invalid line format, flag as error, and keep going
+ parsing = true;
+ }
+
+ return parsing;
+ }
+}
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
deleted file mode 100644
index 806e4e2..0000000
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/RenderScriptProcessor.java
+++ /dev/null
@@ -1,552 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Eclipse Public License, Version 1.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.eclipse.org/org/documents/epl-v10.php
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.ide.eclipse.adt.internal.build;
-
-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.resources.ResourceFolderType;
-import com.android.sdklib.BuildToolInfo;
-import com.android.sdklib.IAndroidTarget;
-import com.google.common.collect.Sets;
-
-import org.eclipse.core.resources.IContainer;
-import org.eclipse.core.resources.IFile;
-import org.eclipse.core.resources.IFolder;
-import org.eclipse.core.resources.IMarker;
-import org.eclipse.core.resources.IProject;
-import org.eclipse.core.resources.IResource;
-import org.eclipse.core.resources.IResourceDelta;
-import org.eclipse.core.resources.IWorkspaceRoot;
-import org.eclipse.core.resources.ResourcesPlugin;
-import org.eclipse.core.runtime.CoreException;
-import org.eclipse.core.runtime.IPath;
-import org.eclipse.core.runtime.IProgressMonitor;
-import org.eclipse.core.runtime.Path;
-import org.eclipse.jdt.core.IJavaProject;
-
-import java.io.File;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-/**
- * A {@link SourceProcessor} for RenderScript files.
- *
- */
-public class RenderScriptProcessor extends SourceProcessor {
-
- private static final String PROPERTY_COMPILE_RS = "compileRenderScript"; //$NON-NLS-1$
-
- /**
- * Single line llvm-rs-cc error: {@code <path>:<line>:<col>: <error>}
- */
- private static Pattern sLlvmPattern1 = Pattern.compile("^(.+?):(\\d+):(\\d+):\\s(.+)$"); //$NON-NLS-1$
-
- private final static Set<String> EXTENSIONS = Sets.newHashSetWithExpectedSize(2);
- static {
- EXTENSIONS.add(SdkConstants.EXT_RS);
- EXTENSIONS.add(SdkConstants.EXT_FS);
- }
-
- private static class RsChangeHandler extends SourceChangeHandler {
-
- @Override
- public boolean handleGeneratedFile(IFile file, int kind) {
- boolean r = super.handleGeneratedFile(file, kind);
- if (r == false &&
- kind == IResourceDelta.REMOVED &&
- SdkConstants.EXT_DEP.equalsIgnoreCase(file.getFileExtension())) {
- // This looks to be a dependency file.
- // For future-proofness let's make sure this dependency file was generated by
- // this processor even if it's the only processor using them for now.
-
- // look for the original file.
- // We know we are in the gen folder, so make a path to the dependency file
- // relative to the gen folder. Convert this into a Renderscript source file,
- // and look to see if this file exists.
- SourceProcessor processor = getProcessor();
- IFolder genFolder = processor.getGenFolder();
- IPath relative = file.getFullPath().makeRelativeTo(genFolder.getFullPath());
- // remove the file name segment
- relative = relative.removeLastSegments(1);
- // add the file name of a Renderscript file.
- relative = relative.append(file.getName().replaceAll(
- AdtConstants.RE_DEP_EXT, SdkConstants.DOT_RS));
-
- if (!findInSourceFolders(processor, genFolder, relative)) {
- // could be a FilterScript file?
- relative = file.getFullPath().makeRelativeTo(genFolder.getFullPath());
- // remove the file name segment
- relative = relative.removeLastSegments(1);
- // add the file name of a FilterScript file.
- relative = relative.append(file.getName().replaceAll(
- AdtConstants.RE_DEP_EXT, SdkConstants.DOT_FS));
-
- return findInSourceFolders(processor, genFolder, relative);
- }
-
- return true;
- }
-
- return r;
- }
-
- private boolean findInSourceFolders(SourceProcessor processor, IFolder genFolder,
- IPath relative) {
- // now look for a match in the source folders.
- List<IPath> sourceFolders = BaseProjectHelper.getSourceClasspaths(
- processor.getJavaProject());
- IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
-
- for (IPath sourceFolderPath : sourceFolders) {
- IFolder sourceFolder = root.getFolder(sourceFolderPath);
- // we don't look in the 'gen' source folder as there will be no source in there.
- if (sourceFolder.exists() && sourceFolder.equals(genFolder) == false) {
- IFile sourceFile = sourceFolder.getFile(relative);
- SourceFileData data = processor.getFileData(sourceFile);
- if (data != null) {
- addFileToCompile(sourceFile);
- return true;
- }
- }
- }
-
- return false;
- }
-
- @Override
- protected boolean filterResourceFolder(IContainer folder) {
- return ResourceFolderType.RAW.getName().equals(folder.getName());
- }
- }
-
- private int mTargetApi = 11;
-
- public RenderScriptProcessor(@NonNull IJavaProject javaProject,
- @NonNull BuildToolInfo buildToolInfo, @NonNull IFolder genFolder) {
- super(javaProject, buildToolInfo, genFolder, new RsChangeHandler());
- }
-
- public void setTargetApi(int targetApi) {
- // make sure the target api value is good. Must be 11+ or llvm-rs-cc complains.
- mTargetApi = targetApi < 11 ? 11 : targetApi;
- }
-
- @Override
- protected Set<String> getExtensions() {
- return EXTENSIONS;
- }
-
- @Override
- protected String getSavePropertyName() {
- return PROPERTY_COMPILE_RS;
- }
-
- @Override
- protected void doCompileFiles(List<IFile> sources, BaseBuilder builder,
- IProject project, IAndroidTarget projectTarget,
- List<IPath> sourceFolders, List<IFile> notCompiledOut, List<File> libraryProjectsOut,
- IProgressMonitor monitor) throws CoreException {
-
- IFolder genFolder = getGenFolder();
-
- IFolder rawFolder = project.getFolder(
- new Path(SdkConstants.FD_RES).append(SdkConstants.FD_RES_RAW));
-
- int depIndex;
-
- BuildToolInfo buildToolInfo = getBuildToolInfo();
-
- // create the command line
- String[] command = new String[15];
- int index = 0;
- command[index++] = buildToolInfo.getPath(BuildToolInfo.PathId.LLVM_RS_CC);
- command[index++] = "-I"; //$NON-NLS-1$
- command[index++] = buildToolInfo.getPath(BuildToolInfo.PathId.ANDROID_RS_CLANG);
- command[index++] = "-I"; //$NON-NLS-1$
- command[index++] = buildToolInfo.getPath(BuildToolInfo.PathId.ANDROID_RS);
- command[index++] = "-p"; //$NON-NLS-1$
- command[index++] = genFolder.getLocation().toOSString();
- command[index++] = "-o"; //$NON-NLS-1$
- command[index++] = rawFolder.getLocation().toOSString();
-
- command[index++] = "-target-api"; //$NON-NLS-1$
- command[index++] = Integer.toString(mTargetApi);
-
- command[index++] = "-d"; //$NON-NLS-1$
- command[depIndex = index++] = null;
- command[index++] = "-MD"; //$NON-NLS-1$
-
- boolean verbose = AdtPrefs.getPrefs().getBuildVerbosity() == BuildVerbosity.VERBOSE;
- boolean someSuccess = false;
-
- // remove the generic marker from the project
- builder.removeMarkersFromResource(project, AdtConstants.MARKER_RENDERSCRIPT);
-
- // loop until we've compile them all
- for (IFile sourceFile : sources) {
- if (verbose) {
- String name = sourceFile.getName();
- IPath sourceFolderPath = getSourceFolderFor(sourceFile);
- if (sourceFolderPath != null) {
- // make a path to the source file relative to the source folder.
- IPath relative = sourceFile.getFullPath().makeRelativeTo(sourceFolderPath);
- name = relative.toString();
- }
- AdtPlugin.printToConsole(project, "RenderScript: " + name);
- }
-
- // Remove the RS error markers from the source file and the dependencies
- builder.removeMarkersFromResource(sourceFile, AdtConstants.MARKER_RENDERSCRIPT);
- SourceFileData data = getFileData(sourceFile);
- if (data != null) {
- for (IFile dep : data.getDependencyFiles()) {
- builder.removeMarkersFromResource(dep, AdtConstants.MARKER_RENDERSCRIPT);
- }
- }
-
- // get the path of the source file.
- IPath sourcePath = sourceFile.getLocation();
- String osSourcePath = sourcePath.toOSString();
-
- // finish to set the command line.
- command[depIndex] = quote(getDependencyFolder(sourceFile).getLocation().toOSString());
- command[index] = quote(osSourcePath);
-
- // launch the process
- if (!execLlvmRsCc(builder, project, command, sourceFile, buildToolInfo.getLocation(),
- verbose)) {
- // llvm-rs-cc failed. File should be marked. We add the file to the list
- // of file that will need compilation again.
- notCompiledOut.add(sourceFile);
- } else {
- // Success. we'll return that we generated code and resources.
- setCompilationStatus(COMPILE_STATUS_CODE | COMPILE_STATUS_RES);
-
- // need to parse the .d file to figure out the dependencies and the generated file
- parseDependencyFileFor(sourceFile);
- someSuccess = true;
- }
- }
-
- if (someSuccess) {
- rawFolder.refreshLocal(IResource.DEPTH_ONE, monitor);
- }
- }
-
- private boolean execLlvmRsCc(BaseBuilder builder, IProject project, String[] command,
- IFile sourceFile, File buildToolRoot, boolean verbose) {
- // do the exec
- try {
- if (verbose) {
- StringBuilder sb = new StringBuilder();
- for (String c : command) {
- sb.append(c);
- sb.append(' ');
- }
- String cmd_line = sb.toString();
- AdtPlugin.printToConsole(project, cmd_line);
- }
-
- ProcessBuilder processBuilder = new ProcessBuilder(command);
- Map<String, String> env = processBuilder.environment();
- if (SdkConstants.CURRENT_PLATFORM == SdkConstants.PLATFORM_DARWIN) {
- env.put("DYLD_LIBRARY_PATH", buildToolRoot.getAbsolutePath());
- } else if (SdkConstants.CURRENT_PLATFORM == SdkConstants.PLATFORM_LINUX) {
- env.put("LD_LIBRARY_PATH", buildToolRoot.getAbsolutePath());
- }
-
- Process p = processBuilder.start();
-
- // list to store each line of stderr
- ArrayList<String> stdErr = new ArrayList<String>();
-
- // get the output and return code from the process
- int returnCode = BuildHelper.grabProcessOutput(project, p, stdErr);
-
- if (stdErr.size() > 0) {
- // attempt to parse the error output
- boolean parsingError = parseLlvmOutput(stdErr);
-
- // If the process failed and we couldn't parse the output
- // we print a message, mark the project and exit
- if (returnCode != 0) {
-
- if (parsingError || verbose) {
- // display the message in the console.
- if (parsingError) {
- AdtPlugin.printErrorToConsole(project, stdErr.toArray());
-
- // mark the project
- BaseProjectHelper.markResource(project,
- AdtConstants.MARKER_RENDERSCRIPT,
- "Unparsed Renderscript error! Check the console for output.",
- IMarker.SEVERITY_ERROR);
- } else {
- AdtPlugin.printToConsole(project, stdErr.toArray());
- }
- }
- return false;
- }
- } else if (returnCode != 0) {
- // no stderr output but exec failed.
- String msg = String.format("Error executing Renderscript: Return code %1$d",
- returnCode);
-
- BaseProjectHelper.markResource(project, AdtConstants.MARKER_AIDL,
- msg, IMarker.SEVERITY_ERROR);
-
- return false;
- }
- } catch (IOException e) {
- // mark the project and exit
- String msg = String.format(
- "Error executing Renderscript. Please check llvm-rs-cc is present at %1$s",
- command[0]);
- BaseProjectHelper.markResource(project, AdtConstants.MARKER_RENDERSCRIPT, msg,
- IMarker.SEVERITY_ERROR);
- return false;
- } catch (InterruptedException e) {
- // mark the project and exit
- String msg = String.format(
- "Error executing Renderscript. Please check llvm-rs-cc is present at %1$s",
- command[0]);
- BaseProjectHelper.markResource(project, AdtConstants.MARKER_RENDERSCRIPT, msg,
- IMarker.SEVERITY_ERROR);
- return false;
- }
-
- return true;
- }
-
- /**
- * Parse the output of llvm-rs-cc and mark the file with any errors.
- * @param lines The output to parse.
- * @return true if the parsing failed, false if success.
- */
- private boolean parseLlvmOutput(ArrayList<String> lines) {
- // nothing to parse? just return false;
- if (lines.size() == 0) {
- return false;
- }
-
- // get the root folder for the project as we're going to ignore everything that's
- // not in the project
- IProject project = getJavaProject().getProject();
- String rootPath = project.getLocation().toOSString();
- int rootPathLength = rootPath.length();
-
- Matcher m;
-
- boolean parsing = false;
-
- for (int i = 0; i < lines.size(); i++) {
- String p = lines.get(i);
-
- m = sLlvmPattern1.matcher(p);
- if (m.matches()) {
- // get the file path. This may, or may not be the main file being compiled.
- String filePath = m.group(1);
- if (filePath.startsWith(rootPath) == false) {
- // looks like the error in a non-project file. Keep parsing, but
- // we'll return true
- parsing = true;
- continue;
- }
-
- // get the actual file.
- filePath = filePath.substring(rootPathLength);
- // remove starting separator since we want the path to be relative
- if (filePath.startsWith(File.separator)) {
- filePath = filePath.substring(1);
- }
-
- // get the file
- IFile f = project.getFile(new Path(filePath));
-
- String lineStr = m.group(2);
- // ignore group 3 for now, this is the col number
- String msg = m.group(4);
-
- // get the line number
- int line = 0;
- try {
- line = Integer.parseInt(lineStr);
- } catch (NumberFormatException e) {
- // looks like the string we extracted wasn't a valid
- // file number. Parsing failed and we return true
- return true;
- }
-
- // mark the file
- BaseProjectHelper.markResource(f, AdtConstants.MARKER_RENDERSCRIPT, msg, line,
- IMarker.SEVERITY_ERROR);
-
- // success, go to the next line
- continue;
- }
-
- // invalid line format, flag as error, and keep going
- parsing = true;
- }
-
- return parsing;
- }
-
-
- @Override
- protected void doRemoveFiles(SourceFileData bundle) throws CoreException {
- // call the super implementation, it will remove the output files
- super.doRemoveFiles(bundle);
-
- // now remove the dependency file.
- IFile depFile = getDependencyFileFor(bundle.getSourceFile());
- if (depFile.exists()) {
- depFile.getLocation().toFile().delete();
- }
- }
-
- @Override
- protected void loadOutputAndDependencies() {
- Collection<SourceFileData> dataList = getAllFileData();
- for (SourceFileData data : dataList) {
- // parse the dependency file. If this fails, force compilation of the file.
- if (parseDependencyFileFor(data.getSourceFile()) == false) {
- addFileToCompile(data.getSourceFile());
- }
- }
- }
-
- private boolean parseDependencyFileFor(IFile sourceFile) {
- IFile depFile = getDependencyFileFor(sourceFile);
- File f = depFile.getLocation().toFile();
- if (f.exists()) {
- SourceFileData data = getFileData(sourceFile);
- if (data == null) {
- data = new SourceFileData(sourceFile);
- addData(data);
- }
- parseDependencyFile(data, f);
- return true;
- }
-
- return false;
- }
-
- private IFolder getDependencyFolder(IFile sourceFile) {
- IPath sourceFolderPath = getSourceFolderFor(sourceFile);
-
- // this really shouldn't happen since the sourceFile must be in a source folder
- // since it comes from the delta visitor
- if (sourceFolderPath != null) {
- // make a path to the source file relative to the source folder.
- IPath relative = sourceFile.getFullPath().makeRelativeTo(sourceFolderPath);
- // remove the file name. This is now the destination folder.
- relative = relative.removeLastSegments(1);
-
- return getGenFolder().getFolder(relative);
- }
-
- return null;
- }
-
- private IFile getDependencyFileFor(IFile sourceFile) {
- IFolder depFolder = getDependencyFolder(sourceFile);
- return depFolder.getFile(sourceFile.getName().replaceAll(AdtConstants.RE_RS_EXT,
- SdkConstants.DOT_DEP));
- }
-
- /**
- * Parses the given dependency file and fills the given {@link SourceFileData} with it.
- *
- * @param data the bundle to fill.
- * @param file the dependency file
- */
- private void parseDependencyFile(SourceFileData data, File dependencyFile) {
- //contents = file.getContents();
- String content = AdtPlugin.readFile(dependencyFile);
-
- // we're going to be pretty brutal here.
- // The format is something like:
- // output1 output2 [...]: dep1 dep2 [...]
- // expect it's likely split on several lines. So let's move it back on a single line
- // first
- String[] lines = content.split("\n"); //$NON-NLS-1$
- StringBuilder sb = new StringBuilder();
- for (String line : lines) {
- line = line.trim();
- if (line.endsWith("\\")) { //$NON-NLS-1$
- line = line.substring(0, line.length() - 1);
- }
-
- sb.append(line);
- }
-
- // split the left and right part
- String[] files = sb.toString().split(":"); //$NON-NLS-1$
-
- // get the output files:
- String[] outputs = files[0].trim().split(" "); //$NON-NLS-1$
-
- // and the dependency files:
- String[] dependencies = files[1].trim().split(" "); //$NON-NLS-1$
-
- List<IFile> outputFiles = new ArrayList<IFile>();
- List<IFile> dependencyFiles = new ArrayList<IFile>();
-
- fillList(outputs, outputFiles);
- fillList(dependencies, dependencyFiles);
-
- data.setOutputFiles(outputFiles);
- data.setDependencyFiles(dependencyFiles);
- }
-
- private void fillList(String[] paths, List<IFile> list) {
- // get the root folder for the project as we're going to ignore everything that's
- // not in the project
- IProject project = getJavaProject().getProject();
- String rootPath = project.getLocation().toOSString();
- int rootPathLength = rootPath.length();
-
- // all those should really be in the project
- for (String p : paths) {
-
- if (p.startsWith(rootPath)) {
- p = p.substring(rootPathLength);
- // remove starting separator since we want the path to be relative
- if (p.startsWith(File.separator)) {
- p = p.substring(1);
- }
-
- // get the file
- IFile f = project.getFile(new Path(p));
- list.add(f);
- }
- }
- }
-}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/RsSourceChangeHandler.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/RsSourceChangeHandler.java
new file mode 100644
index 0000000..715895a
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/RsSourceChangeHandler.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Eclipse Public License, Version 1.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.eclipse.org/org/documents/epl-v10.php
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.ide.eclipse.adt.internal.build;
+
+import com.android.SdkConstants;
+import com.android.annotations.NonNull;
+import com.android.ide.eclipse.adt.AdtPlugin;
+import com.android.sdklib.build.RenderScriptChecker;
+
+import org.eclipse.core.resources.IFile;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Set;
+
+public class RsSourceChangeHandler implements SourceChangeHandler {
+
+ private final RenderScriptChecker mChecker;
+ private boolean mIsCheckerLoaded = false;
+
+ private boolean mMustCompile = false;
+
+ public RsSourceChangeHandler(@NonNull RenderScriptChecker checker) {
+ mChecker = checker;
+ }
+
+ @Override
+ public boolean handleGeneratedFile(IFile file, int kind) {
+ if (mMustCompile) {
+ return false;
+ }
+
+ if (!mIsCheckerLoaded) {
+ try {
+ mChecker.loadDependencies();
+ } catch (IOException e) {
+ // failed to load the dependency files, force a compilation, log the error.
+ AdtPlugin.log(e, "Failed to read dependency files");
+ mMustCompile = true;
+ return false;
+ }
+ }
+
+ Set<File> oldOutputs = mChecker.getOldOutputs();
+ // mustCompile is always false here.
+ mMustCompile = oldOutputs.contains(file.getLocation().toFile());
+ return mMustCompile;
+ }
+
+ @Override
+ public void handleSourceFile(IFile file, int kind) {
+ if (mMustCompile) {
+ return;
+ }
+
+ String ext = file.getFileExtension();
+ if (SdkConstants.EXT_RS.equals(ext) ||
+ SdkConstants.EXT_FS.equals(ext) ||
+ SdkConstants.EXT_RSH.equals(ext)) {
+ mMustCompile = true;
+ }
+ }
+
+ public boolean mustCompile() {
+ return mMustCompile;
+ }
+
+ @NonNull
+ public RenderScriptChecker getChecker() {
+ return mChecker;
+ }
+
+ public void prepareFullBuild() {
+ mMustCompile = true;
+ }
+}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/SourceChangeHandler.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/SourceChangeHandler.java
index 5436798..12a0551 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/SourceChangeHandler.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/SourceChangeHandler.java
@@ -16,103 +16,10 @@
package com.android.ide.eclipse.adt.internal.build;
-import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile;
-import org.eclipse.core.resources.IResourceDelta;
-import java.util.HashSet;
-import java.util.Set;
+public interface SourceChangeHandler {
-/**
- * Base source change handler for the {@link SourceProcessor} classes.
- *
- * It can be used as is, as long as the matching {@link SourceProcessor} properly implements
- * its abstract methods, and the processor does not output resource files,
- * or can be extended to provide custom implementation for:
- * {@link #handleSourceFile(IFile, int)}
- * {@link #handleGeneratedFile(IFile, int)}
- * {@link #handleResourceFile(IFile, int)}
- * {@link #filterResourceFolder(IContainer)}
- *
- */
-public class SourceChangeHandler {
-
- private SourceProcessor mProcessor;
-
- /** List of source files found that are modified or new. */
- private final Set<IFile> mToCompile = new HashSet<IFile>();
-
- /** List of source files that have been removed. */
- private final Set<IFile> mRemoved = new HashSet<IFile>();
-
- public boolean handleGeneratedFile(IFile file, int kind) {
- if (kind == IResourceDelta.REMOVED || kind == IResourceDelta.CHANGED) {
- IFile sourceFile = mProcessor.isOutput(file);
- if (sourceFile != null) {
- mToCompile.add(sourceFile);
- return true;
- }
- }
-
- return false;
- }
-
- public void handleSourceFile(IFile file, int kind) {
- // first the file itself if this is a match for the processor's extension
- if (mProcessor.getExtensions().contains(file.getFileExtension())) {
- if (kind == IResourceDelta.REMOVED) {
- mRemoved.add(file);
- } else {
- mToCompile.add(file);
- }
- }
-
- // now the dependencies. In all case we compile the files that depend on the
- // added/changed/removed file.
- mToCompile.addAll(mProcessor.isDependency(file));
- }
-
- public void handleResourceFile(IFile file, int kind) {
- if (filterResourceFolder(file.getParent())) {
- handleGeneratedFile(file, kind);
- }
- }
-
- /**
- * Called to restrict {@link #handleResourceFile(IFile, int)} on selected resource folders.
- * @param folder
- * @return
- */
- protected boolean filterResourceFolder(IContainer folder) {
- return false;
- }
-
- protected void addFileToCompile(IFile file) {
- mToCompile.add(file);
- }
-
- Set<IFile> getFilesToCompile() {
- return mToCompile;
- }
-
- protected void addRemovedFile(IFile file) {
- mRemoved.add(file);
- }
-
- Set<IFile> getRemovedFiles() {
- return mRemoved;
- }
-
- public void reset() {
- mToCompile.clear();
- mRemoved.clear();
- }
-
- protected SourceProcessor getProcessor() {
- return mProcessor;
- }
-
- void init(SourceProcessor processor) {
- mProcessor = processor;
- }
+ boolean handleGeneratedFile(IFile file, int kind);
+ void handleSourceFile(IFile file, int kind);
}
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 7dd92aa..1fc3e4e 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
@@ -63,7 +63,7 @@ public abstract class SourceProcessor {
private final IJavaProject mJavaProject;
private BuildToolInfo mBuildToolInfo;
private final IFolder mGenFolder;
- private final SourceChangeHandler mDeltaVisitor;
+ private final DefaultSourceChangeHandler mDeltaVisitor;
/** List of source files pending compilation at the next build */
private final List<IFile> mToCompile = new ArrayList<IFile>();
@@ -89,9 +89,11 @@ public abstract class SourceProcessor {
return path;
}
- protected SourceProcessor(@NonNull IJavaProject javaProject,
- @NonNull BuildToolInfo buildToolInfo, @NonNull IFolder genFolder,
- @NonNull SourceChangeHandler deltaVisitor) {
+ protected SourceProcessor(
+ @NonNull IJavaProject javaProject,
+ @NonNull BuildToolInfo buildToolInfo,
+ @NonNull IFolder genFolder,
+ @NonNull DefaultSourceChangeHandler deltaVisitor) {
mJavaProject = javaProject;
mBuildToolInfo = buildToolInfo;
mGenFolder = genFolder;
@@ -117,9 +119,11 @@ public abstract class SourceProcessor {
}
}
- protected SourceProcessor(@NonNull IJavaProject javaProject,
- @NonNull BuildToolInfo buildToolInfo, @NonNull IFolder genFolder) {
- this(javaProject, buildToolInfo, genFolder, new SourceChangeHandler());
+ protected SourceProcessor(
+ @NonNull IJavaProject javaProject,
+ @NonNull BuildToolInfo buildToolInfo,
+ @NonNull IFolder genFolder) {
+ this(javaProject, buildToolInfo, genFolder, new DefaultSourceChangeHandler());
}
public void setBuildToolInfo(BuildToolInfo buildToolInfo) {
@@ -173,7 +177,7 @@ public abstract class SourceProcessor {
return mFiles.values();
}
- public final SourceChangeHandler getChangeHandler() {
+ public final DefaultSourceChangeHandler getChangeHandler() {
return mDeltaVisitor;
}
@@ -414,7 +418,7 @@ public abstract class SourceProcessor {
* delta visitor
* @param visitor the delta visitor.
*/
- private void mergeFileModifications(SourceChangeHandler visitor) {
+ private void mergeFileModifications(DefaultSourceChangeHandler visitor) {
Set<IFile> toRemove = visitor.getRemovedFiles();
Set<IFile> toCompile = visitor.getFilesToCompile();
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 529dad2..9fc19a7 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
@@ -23,6 +23,7 @@ import com.android.ide.eclipse.adt.internal.project.BaseProjectHelper;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.IPath;
import java.util.ArrayList;
@@ -81,13 +82,16 @@ class ChangedFileSetHelper {
* @return a ChangeFileSet
*/
static ChangedFileSet getResCfs(@NonNull IProject project) {
+ // generated res is inside the project's android output folder
+ String path = getRelativeAndroidOut(project);
+
ChangedFileSet set = new ChangedFileSet(
"resources", //$NON-NLS-1$
SdkConstants.FD_RES + "/**", //$NON-NLS-1$
- SdkConstants.FD_ASSETS + "/**"); //$NON-NLS-1$
+ SdkConstants.FD_ASSETS + "/**", //$NON-NLS-1$
+ path + '/' + AdtConstants.WS_BIN_RELATIVE_BC + "/**"); //$NON-NLS-1$
// output file is based on the project's android output folder
- String path = getRelativeAndroidOut(project);
set.setOutput(path + '/' + AdtConstants.FN_RESOURCES_AP_);
return set;
@@ -180,14 +184,17 @@ class ChangedFileSetHelper {
return set;
}
+ private static String getRelativePath(@NonNull IProject project, @NonNull IResource resource) {
+ return resource.getFullPath().makeRelativeTo(project.getFullPath()).toString();
+ }
+
private static String getRelativeAndroidOut(@NonNull IProject project) {
IFolder folder = BaseProjectHelper.getAndroidOutputFolder(project);
- return folder.getFullPath().makeRelativeTo(project.getFullPath()).toString();
+ return getRelativePath(project, folder);
}
private static String getRelativeJavaCOut(@NonNull IProject project) {
IFolder folder = BaseProjectHelper.getJavaOutputFolder(project);
- return folder.getFullPath().makeRelativeTo(project.getFullPath()).toString();
+ return getRelativePath(project, folder);
}
-
}
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 81fceb1..b52ede9 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
@@ -90,11 +90,11 @@ class PatternBasedDeltaVisitor implements IResourceDeltaVisitor {
} else if (resource.getType() == IResource.FILE) {
IPath path = resource.getFullPath().makeRelativeTo(mDeltaProject.getFullPath());
+ String pathStr = path.toString();
// FIXME: no need to loop through all the sets once they have all said they need something (return false below and above)
for (ChangedFileSet set : mSets) {
// FIXME: should ignore sets that have already returned true.
- String pathStr = path.toString();
if (set.isInput(pathStr, path)) {
mResults.put(set, Boolean.TRUE);
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/builders/PostCompilerBuilder.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/builders/PostCompilerBuilder.java
index 093072b..8aacb44 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
@@ -371,7 +371,9 @@ public class PostCompilerBuilder extends BaseBuilder {
if (DEBUG_LOG) {
AdtPlugin.log(IStatus.INFO, "%s running crunch!", project.getName());
}
- BuildHelper helper = new BuildHelper(project, mBuildToolInfo,
+ BuildHelper helper = new BuildHelper(
+ projectState,
+ mBuildToolInfo,
mOutStream, mErrStream,
false /*jumbo mode doesn't matter here*/,
false /*dex merger doesn't matter here*/,
@@ -486,7 +488,9 @@ public class PostCompilerBuilder extends BaseBuilder {
AdtConstants.DEX_OPTIONS_DISABLE_MERGER);
Boolean dexMerger = Boolean.valueOf(dexMergerStr);
- BuildHelper helper = new BuildHelper(project, mBuildToolInfo,
+ BuildHelper helper = new BuildHelper(
+ projectState,
+ mBuildToolInfo,
mOutStream, mErrStream,
jumbo.booleanValue(),
dexMerger.booleanValue(),
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 ae6b3f5..2554c79 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
@@ -25,7 +25,8 @@ import com.android.ide.eclipse.adt.AdtPlugin;
import com.android.ide.eclipse.adt.internal.build.AaptParser;
import com.android.ide.eclipse.adt.internal.build.AidlProcessor;
import com.android.ide.eclipse.adt.internal.build.Messages;
-import com.android.ide.eclipse.adt.internal.build.RenderScriptProcessor;
+import com.android.ide.eclipse.adt.internal.build.RenderScriptLauncher;
+import com.android.ide.eclipse.adt.internal.build.RsSourceChangeHandler;
import com.android.ide.eclipse.adt.internal.build.SourceProcessor;
import com.android.ide.eclipse.adt.internal.lint.EclipseLintClient;
import com.android.ide.eclipse.adt.internal.preferences.AdtPrefs;
@@ -49,6 +50,8 @@ import com.android.manifmerger.MergerLog;
import com.android.sdklib.AndroidVersion;
import com.android.sdklib.BuildToolInfo;
import com.android.sdklib.IAndroidTarget;
+import com.android.sdklib.build.RenderScriptChecker;
+import com.android.sdklib.build.RenderScriptProcessor;
import com.android.sdklib.internal.build.BuildConfigGenerator;
import com.android.sdklib.internal.build.SymbolLoader;
import com.android.sdklib.internal.build.SymbolWriter;
@@ -67,6 +70,8 @@ import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IResourceDelta;
+import org.eclipse.core.resources.IWorkspaceRoot;
+import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
@@ -128,8 +133,6 @@ public class PreCompilerBuilder extends BaseBuilder {
* Stored persistently in the project. */
private boolean mLastBuildConfigMode;
- private final List<SourceProcessor> mProcessors = new ArrayList<SourceProcessor>(2);
-
/** cache of the java package defined in the manifest */
private String mManifestPackage;
@@ -145,7 +148,7 @@ public class PreCompilerBuilder extends BaseBuilder {
private DerivedProgressMonitor mDerivedProgressMonitor;
private AidlProcessor mAidlProcessor;
- private RenderScriptProcessor mRenderScriptProcessor;
+ private RsSourceChangeHandler mRenderScriptSourceChangeHandler;
/**
* Progress monitor waiting the end of the process to set a persistent value
@@ -253,6 +256,8 @@ public class PreCompilerBuilder extends BaseBuilder {
// as only those projects have an impact on what is generated by this builder.
IProject[] result = null;
+ IFolder resOutFolder = null;
+
try {
assert mDerivedProgressMonitor != null;
@@ -279,13 +284,16 @@ public class PreCompilerBuilder extends BaseBuilder {
// Top level check to make sure the build can move forward.
abortOnBadSetup(javaProject, projectState);
- setupSourceProcessors(javaProject, projectState);
-
// now we need to get the classpath list
List<IPath> sourceFolderPathList = BaseProjectHelper.getSourceClasspaths(javaProject);
IFolder androidOutputFolder = BaseProjectHelper.getAndroidOutputFolder(project);
+ resOutFolder = getResOutFolder(androidOutputFolder);
+
+ setupSourceProcessors(javaProject, projectState, sourceFolderPathList,
+ androidOutputFolder);
+
PreCompilerDeltaVisitor dv = null;
String javaPackage = null;
String minSdkVersion = null;
@@ -305,9 +313,8 @@ public class PreCompilerBuilder extends BaseBuilder {
mMustCompileResources = true;
mMustCreateBuildConfig = true;
- for (SourceProcessor processor : mProcessors) {
- processor.prepareFullBuild(project);
- }
+ mAidlProcessor.prepareFullBuild(project);
+ mRenderScriptSourceChangeHandler.prepareFullBuild();
} else {
AdtPlugin.printBuildToConsole(BuildVerbosity.VERBOSE, project,
Messages.Start_Inc_Pre_Compiler);
@@ -320,11 +327,12 @@ public class PreCompilerBuilder extends BaseBuilder {
if (delta == null) {
mMustCompileResources = true;
- for (SourceProcessor processor : mProcessors) {
- processor.prepareFullBuild(project);
- }
+ mAidlProcessor.prepareFullBuild(project);
+ mRenderScriptSourceChangeHandler.prepareFullBuild();
} else {
- dv = new PreCompilerDeltaVisitor(this, sourceFolderPathList, mProcessors);
+ dv = new PreCompilerDeltaVisitor(this, sourceFolderPathList,
+ mAidlProcessor.getChangeHandler(),
+ mRenderScriptSourceChangeHandler);
delta.accept(dv);
// Check to see if Manifest.xml, Manifest.java, or R.java have changed:
@@ -363,9 +371,7 @@ public class PreCompilerBuilder extends BaseBuilder {
}
} // else: already processed the deltas in ResourceManager's IRawDeltaListener
- for (SourceProcessor processor : mProcessors) {
- processor.doneVisiting(project);
- }
+ mAidlProcessor.doneVisiting(project);
// get the java package from the visitor
javaPackage = dv.getManifestPackage();
@@ -622,9 +628,8 @@ public class PreCompilerBuilder extends BaseBuilder {
mMustMergeManifest = true;
mMustCompileResources = true;
mMustCreateBuildConfig = true;
- for (SourceProcessor processor : mProcessors) {
- processor.prepareFullBuild(project);
- }
+ mAidlProcessor.prepareFullBuild(project);
+ mRenderScriptSourceChangeHandler.prepareFullBuild();
saveProjectBooleanProperty(PROPERTY_MERGE_MANIFEST, mMustMergeManifest);
saveProjectBooleanProperty(PROPERTY_COMPILE_RESOURCES, mMustCompileResources);
@@ -661,33 +666,22 @@ public class PreCompilerBuilder extends BaseBuilder {
// run the source processors
int processorStatus = SourceProcessor.COMPILE_STATUS_NONE;
- // get the renderscript target
- int rsTarget = minSdkValue == -1 ? 11 : minSdkValue;
- String rsTargetStr = projectState.getProperty(ProjectProperties.PROPERTY_RS_TARGET);
- if (rsTargetStr != null) {
- try {
- rsTarget = Integer.parseInt(rsTargetStr);
- } catch (NumberFormatException e) {
- handleException(e, String.format(
- "Property %s is not an integer.",
- ProjectProperties.PROPERTY_RS_TARGET));
- return result;
- }
- }
- mRenderScriptProcessor.setTargetApi(rsTarget);
+ try {
+ processorStatus |= mAidlProcessor.compileFiles(this,
+ project, projectTarget, sourceFolderPathList,
+ libProjectsOut, monitor);
+ } catch (Throwable t) {
+ handleException(t, "Failed to run aidl. Check workspace log for detail.");
+ return result;
+ }
- for (SourceProcessor processor : mProcessors) {
- try {
- processorStatus |= processor.compileFiles(this,
- project, projectTarget, sourceFolderPathList,
- libProjectsOut, monitor);
- } catch (Throwable t) {
- handleException(t, String.format(
- "Failed to run %s. Check workspace log for detail.",
- processor.getClass().getName()));
- return result;
- }
+ try {
+ processorStatus |= compileRs(minSdkValue, projectState, androidOutputFolder,
+ resOutFolder, monitor);
+ } catch (Throwable t) {
+ handleException(t, "Failed to run renderscript. Check workspace log for detail.");
+ return result;
}
// if a processor created some resources file, force recompilation of the resources.
@@ -710,7 +704,7 @@ public class PreCompilerBuilder extends BaseBuilder {
proguardFile = androidOutputFolder.getFile(AdtConstants.FN_AAPT_PROGUARD);
}
- handleResources(project, javaPackage, projectTarget, manifestFile,
+ handleResources(project, javaPackage, projectTarget, manifestFile, resOutFolder,
libProjects, isLibrary, proguardFile);
}
@@ -725,11 +719,18 @@ public class PreCompilerBuilder extends BaseBuilder {
// refresh the 'gen' source folder. Once this is done with the custom progress
// monitor to mark all new files as derived
mGenFolder.refreshLocal(IResource.DEPTH_INFINITE, mDerivedProgressMonitor);
+ if (resOutFolder != null) {
+ resOutFolder.refreshLocal(IResource.DEPTH_INFINITE, mDerivedProgressMonitor);
+ }
}
return result;
}
+ private IFolder getResOutFolder(IFolder androidOutputFolder) {
+ return androidOutputFolder.getFolder(AdtConstants.WS_BIN_RELATIVE_BC);
+ }
+
@Override
protected void clean(IProgressMonitor monitor) throws CoreException {
super.clean(monitor);
@@ -805,17 +806,95 @@ public class PreCompilerBuilder extends BaseBuilder {
}
private void setupSourceProcessors(@NonNull IJavaProject javaProject,
- @NonNull ProjectState projectState) {
+ @NonNull ProjectState projectState,
+ @NonNull List<IPath> sourceFolderPathList,
+ @NonNull IFolder androidOutputFolder) {
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);
}
+
+ List<File> sourceFolders = Lists.newArrayListWithCapacity(sourceFolderPathList.size());
+ IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
+
+ for (IPath path : sourceFolderPathList) {
+ IResource resource = root.findMember(path);
+ if (resource != null && resource.exists() && resource.getType() == IResource.FOLDER) {
+ IPath fullPath = resource.getLocation();
+ if (fullPath != null) {
+ sourceFolders.add(fullPath.toFile());
+ }
+ }
+ }
+
+ RenderScriptChecker checker = new RenderScriptChecker(sourceFolders,
+ androidOutputFolder.getLocation().toFile());
+ mRenderScriptSourceChangeHandler = new RsSourceChangeHandler(checker);
+ }
+
+ private int compileRs(int minSdkValue,
+ @NonNull ProjectState projectState,
+ @NonNull IFolder androidOutputFolder,
+ @NonNull IFolder resOutFolder,
+ @NonNull IProgressMonitor monitor)
+ throws IOException, InterruptedException {
+ if (!mRenderScriptSourceChangeHandler.mustCompile()) {
+ return SourceProcessor.COMPILE_STATUS_NONE;
+ }
+
+ RenderScriptChecker checker = mRenderScriptSourceChangeHandler.getChecker();
+
+ List<File> inputs = checker.findInputFiles();
+ List<File> importFolders = checker.getSourceFolders();
+ File buildFolder = androidOutputFolder.getLocation().toFile();
+
+
+ // get the renderscript target
+ int rsTarget = minSdkValue == -1 ? 11 : minSdkValue;
+ String rsTargetStr = projectState.getProperty(ProjectProperties.PROPERTY_RS_TARGET);
+ if (rsTargetStr != null) {
+ try {
+ rsTarget = Integer.parseInt(rsTargetStr);
+ } catch (NumberFormatException e) {
+ handleException(e, String.format(
+ "Property %s is not an integer.",
+ ProjectProperties.PROPERTY_RS_TARGET));
+ return SourceProcessor.COMPILE_STATUS_NONE;
+ }
+ }
+
+ RenderScriptProcessor processor = new RenderScriptProcessor(
+ inputs,
+ importFolders,
+ buildFolder,
+ mGenFolder.getLocation().toFile(),
+ resOutFolder.getLocation().toFile(),
+ new File(buildFolder, SdkConstants.FD_RS_OBJ),
+ new File(buildFolder, SdkConstants.FD_RS_LIBS),
+ mBuildToolInfo,
+ rsTarget,
+ false /*debugBuild, always false for now*/,
+ 3,
+ projectState.getRenderScriptSupportMode());
+
+ // clean old dependency files fiest
+ checker.cleanDependencies();
+
+ // then clean old output files
+ processor.cleanOldOutput(checker.getOldOutputs());
+
+ RenderScriptLauncher launcher = new RenderScriptLauncher(
+ getProject(),
+ mGenFolder,
+ resOutFolder,
+ monitor,
+ AdtPrefs.getPrefs().getBuildVerbosity() == BuildVerbosity.VERBOSE /*verbose*/);
+
+ // and run the build
+ processor.build(launcher);
+
+ return SourceProcessor.COMPILE_STATUS_CODE | SourceProcessor.COMPILE_STATUS_RES;
}
@SuppressWarnings("deprecation")
@@ -965,8 +1044,8 @@ public class PreCompilerBuilder extends BaseBuilder {
* @throws AbortBuildException
*/
private void handleResources(IProject project, String javaPackage, IAndroidTarget projectTarget,
- IFile manifest, List<IProject> libProjects, boolean isLibrary, IFile proguardFile)
- throws CoreException, AbortBuildException {
+ IFile manifest, IFolder resOutFolder, List<IProject> libProjects, boolean isLibrary,
+ IFile proguardFile) throws CoreException, AbortBuildException {
// get the resource folder
IFolder resFolder = project.getFolder(AdtConstants.WS_RESOURCES);
@@ -1025,7 +1104,10 @@ public class PreCompilerBuilder extends BaseBuilder {
String proguardFilePath = proguardFile != null ?
proguardFile.getLocation().toOSString(): null;
- execAapt(project, projectTarget, osOutputPath, osResPath, osManifestPath,
+ File resOutFile = resOutFolder.getLocation().toFile();
+ String resOutPath = resOutFile.isDirectory() ? resOutFile.getAbsolutePath() : null;
+
+ execAapt(project, projectTarget, osOutputPath, resOutPath, osResPath, osManifestPath,
mainPackageFolder, libResFolders, libRFiles, isLibrary, proguardFilePath);
}
}
@@ -1050,7 +1132,7 @@ public class PreCompilerBuilder extends BaseBuilder {
*/
@SuppressWarnings("deprecation")
private void execAapt(IProject project, IAndroidTarget projectTarget, String osOutputPath,
- String osResPath, String osManifestPath, IFolder packageFolder,
+ String osBcOutPath, String osResPath, String osManifestPath, IFolder packageFolder,
ArrayList<IFolder> libResFolders, List<Pair<File, String>> libRFiles,
boolean isLibrary, String proguardFile)
throws AbortBuildException {
@@ -1094,6 +1176,10 @@ public class PreCompilerBuilder extends BaseBuilder {
array.add(osOutputPath);
array.add("-M"); //$NON-NLS-1$
array.add(osManifestPath);
+ if (osBcOutPath != null) {
+ array.add("-S"); //$NON-NLS-1$
+ array.add(osBcOutPath);
+ }
array.add("-S"); //$NON-NLS-1$
array.add(osResPath);
for (IFolder libResFolder : libResFolders) {
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 f868224..57316f5 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
@@ -22,12 +22,12 @@ import com.android.ide.eclipse.adt.AdtConstants;
import com.android.ide.eclipse.adt.AdtPlugin;
import com.android.ide.eclipse.adt.internal.build.Messages;
import com.android.ide.eclipse.adt.internal.build.SourceChangeHandler;
-import com.android.ide.eclipse.adt.internal.build.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.google.common.collect.Lists;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile;
@@ -40,7 +40,7 @@ import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
-import java.util.ArrayList;
+import java.util.Arrays;
import java.util.List;
/**
@@ -93,22 +93,18 @@ class PreCompilerDeltaVisitor extends BaseDeltaVisitor implements IResourceDelta
private final List<IPath> mSourceFolders;
private boolean mIsGenSourceFolder = false;
- private final List<SourceChangeHandler> mSourceChangeHandlers =
- new ArrayList<SourceChangeHandler>();
+ private final List<SourceChangeHandler> mSourceChangeHandlers = Lists.newArrayList();
private final IWorkspaceRoot mRoot;
private IFolder mAndroidOutputFolder;
public PreCompilerDeltaVisitor(BaseBuilder builder, List<IPath> sourceFolders,
- List<SourceProcessor> processors) {
+ SourceChangeHandler... handlers) {
super(builder);
mSourceFolders = sourceFolders;
mRoot = ResourcesPlugin.getWorkspace().getRoot();
- for (SourceProcessor processor : processors) {
- SourceChangeHandler handler = processor.getChangeHandler();
- mSourceChangeHandlers.add(handler);
- }
+ mSourceChangeHandlers.addAll(Arrays.asList(handlers));
mAndroidOutputFolder = BaseProjectHelper.getAndroidOutputFolder(builder.getProject());
}
@@ -296,7 +292,7 @@ class PreCompilerDeltaVisitor extends BaseDeltaVisitor implements IResourceDelta
if (outputWarning) {
if (kind == IResourceDelta.REMOVED) {
- // We pring an error just so that it's red, but it's just a warning really.
+ // We print an error just so that it's red, but it's just a warning really.
String msg = String.format(Messages.s_Removed_Recreating_s, fileName);
AdtPlugin.printErrorToConsole(mBuilder.getProject(), msg);
} else if (kind == IResourceDelta.CHANGED) {
@@ -354,9 +350,6 @@ class PreCompilerDeltaVisitor extends BaseDeltaVisitor implements IResourceDelta
mBuilder.getProject(), message);
}
- for (SourceChangeHandler handler : mSourceChangeHandlers) {
- handler.handleResourceFile((IFile)resource, kind);
- }
// If it's an XML resource, check the syntax
if (SdkConstants.EXT_XML.equalsIgnoreCase(ext) && kind != IResourceDelta.REMOVED) {
// check xml Validity
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 c526edf..f9382c5 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
@@ -185,64 +185,71 @@ public class AndroidClasspathContainerInitializer extends BaseClasspathContainer
// if we are loaded and the target is non null, we create a valid
// ClassPathContainer
if (sdkIsLoaded && target != null) {
- // first make sure the target has loaded its data
- Sdk.getCurrent().checkAndLoadTargetData(target, null /*project*/);
-
- String targetName = target.getClasspathName();
-
- return new AndroidClasspathContainer(
- createClasspathEntries(iProject, target, targetName),
- new Path(AdtConstants.CONTAINER_FRAMEWORK),
- targetName,
- IClasspathContainer.K_DEFAULT_SYSTEM);
- }
-
- // In case of error, we'll try different thing to provide the best error message
- // possible.
- // Get the project's target's hash string (if it exists)
- String hashString = state.getTargetHashString();
-
- if (hashString == null || hashString.length() == 0) {
- // if there is no hash string we only show this if the SDK is loaded.
- // For a project opened at start-up with no target, this would be displayed
- // twice, once when the project is opened, and once after the SDK has
- // finished loading.
- // By testing the sdk is loaded, we only show this once in the console.
- if (sdkIsLoaded) {
- markerMessage = String.format(
- "Project has no target set. Edit the project properties to set one.");
+ // check the renderscript support mode. If support mode is enabled,
+ // target API must be 18+
+ if (!state.getRenderScriptSupportMode() ||
+ target.getVersion().getApiLevel() >= 18) {
+ // first make sure the target has loaded its data
+ Sdk.getCurrent().checkAndLoadTargetData(target, null /*project*/);
+
+ String targetName = target.getClasspathName();
+
+ return new AndroidClasspathContainer(
+ createClasspathEntries(iProject, target, targetName),
+ new Path(AdtConstants.CONTAINER_FRAMEWORK),
+ targetName,
+ IClasspathContainer.K_DEFAULT_SYSTEM);
+ } else {
+ markerMessage = "Renderscript support mode requires compilation target API to be 18+.";
}
- } else if (sdkIsLoaded) {
- markerMessage = String.format(
- "Unable to resolve target '%s'", hashString);
} else {
- // this is the case where there is a hashString but the SDK is not yet
- // loaded and therefore we can't get the target yet.
- // We check if there is a cache of the needed information.
- AndroidClasspathContainer container = getContainerFromCache(iProject,
- target);
-
- if (container == null) {
- // either the cache was wrong (ie folder does not exists anymore), or
- // there was no cache. In this case we need to make sure the project
- // is resolved again after the SDK is loaded.
- plugin.setProjectToResolve(javaProject);
-
+ // In case of error, we'll try different thing to provide the best error message
+ // possible.
+ // Get the project's target's hash string (if it exists)
+ String hashString = state.getTargetHashString();
+
+ if (hashString == null || hashString.length() == 0) {
+ // if there is no hash string we only show this if the SDK is loaded.
+ // For a project opened at start-up with no target, this would be displayed
+ // twice, once when the project is opened, and once after the SDK has
+ // finished loading.
+ // By testing the sdk is loaded, we only show this once in the console.
+ if (sdkIsLoaded) {
+ markerMessage = String.format(
+ "Project has no target set. Edit the project properties to set one.");
+ }
+ } else if (sdkIsLoaded) {
markerMessage = String.format(
- "Unable to resolve target '%s' until the SDK is loaded.",
- hashString);
-
- // let's not log this one to the console as it will happen at
- // every boot, and it's expected. (we do keep the error marker though).
- outputToConsole = false;
-
+ "Unable to resolve target '%s'", hashString);
} else {
- // we created a container from the cache, so we register the project
- // to be checked for cache validity once the SDK is loaded
- plugin.setProjectToCheck(javaProject);
-
- // and return the container
- return container;
+ // this is the case where there is a hashString but the SDK is not yet
+ // loaded and therefore we can't get the target yet.
+ // We check if there is a cache of the needed information.
+ AndroidClasspathContainer container = getContainerFromCache(iProject,
+ target);
+
+ if (container == null) {
+ // either the cache was wrong (ie folder does not exists anymore), or
+ // there was no cache. In this case we need to make sure the project
+ // is resolved again after the SDK is loaded.
+ plugin.setProjectToResolve(javaProject);
+
+ markerMessage = String.format(
+ "Unable to resolve target '%s' until the SDK is loaded.",
+ hashString);
+
+ // let's not log this one to the console as it will happen at
+ // every boot, and it's expected. (we do keep the error marker though).
+ outputToConsole = false;
+
+ } else {
+ // we created a container from the cache, so we register the project
+ // to be checked for cache validity once the SDK is loaded
+ plugin.setProjectToCheck(javaProject);
+
+ // and return the container
+ return container;
+ }
}
}
}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/project/BaseProjectHelper.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/project/BaseProjectHelper.java
index a7db983..57632ea 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/project/BaseProjectHelper.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/project/BaseProjectHelper.java
@@ -21,6 +21,7 @@ import com.android.annotations.NonNull;
import com.android.annotations.Nullable;
import com.android.ide.eclipse.adt.AdtConstants;
import com.android.ide.eclipse.adt.AdtPlugin;
+import com.google.common.collect.Lists;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IMarker;
@@ -77,8 +78,9 @@ public final class BaseProjectHelper {
* @param javaProject
* @return a list of path relative to the workspace root.
*/
+ @NonNull
public static List<IPath> getSourceClasspaths(IJavaProject javaProject) {
- ArrayList<IPath> sourceList = new ArrayList<IPath>();
+ List<IPath> sourceList = Lists.newArrayList();
IClasspathEntry[] classpaths = javaProject.readRawClasspath();
if (classpaths != null) {
for (IClasspathEntry e : classpaths) {
@@ -87,6 +89,7 @@ public final class BaseProjectHelper {
}
}
}
+
return sourceList;
}
@@ -507,6 +510,7 @@ public final class BaseProjectHelper {
* @param project the {@link IProject}
* @return an IFolder item or null.
*/
+ @Nullable
public final static IFolder getAndroidOutputFolder(IProject project) {
try {
if (project.isOpen() && project.hasNature(JavaCore.NATURE_ID)) {
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 52870a4..8168590 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
@@ -143,7 +143,9 @@ public final class ExportHelper {
"No Build Tools installed in the SDK."));
}
- BuildHelper helper = new BuildHelper(project, buildToolInfo,
+ BuildHelper helper = new BuildHelper(
+ projectState,
+ buildToolInfo,
fakeStream, fakeStream,
jumbo.booleanValue(),
dexMerger.booleanValue(),
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 3beb181..1e0ada0 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
@@ -19,14 +19,17 @@ package com.android.ide.eclipse.adt.internal.project;
import static com.android.ide.eclipse.adt.AdtConstants.CONTAINER_DEPENDENCIES;
import com.android.SdkConstants;
+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.AndroidPrintStream;
import com.android.ide.eclipse.adt.internal.sdk.ProjectState;
import com.android.ide.eclipse.adt.internal.sdk.Sdk;
+import com.android.sdklib.BuildToolInfo;
import com.android.sdklib.build.JarListSanitizer;
import com.android.sdklib.build.JarListSanitizer.DifferentLibException;
import com.android.sdklib.build.JarListSanitizer.Sha1Exception;
+import com.android.sdklib.build.RenderScriptProcessor;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
@@ -306,60 +309,88 @@ public class LibraryClasspathContainerInitializer extends BaseClasspathContainer
final Set<File> jarFiles = new HashSet<File>();
final IWorkspaceRoot workspaceRoot = ResourcesPlugin.getWorkspace().getRoot();
- // check if the project has a valid target.
- final ProjectState state = Sdk.getProjectState(iProject);
- if (state == null) {
- // getProjectState should already have logged an error. Just bail out.
+ AdtPlugin plugin = AdtPlugin.getDefault();
+ if (plugin == null) { // This is totally weird, but I've seen it happen!
return null;
}
- // annotations support for older version of android
- if (state.getTarget() != null && state.getTarget().getVersion().getApiLevel() <= 15) {
- File annotationsJar = new File(Sdk.getCurrent().getSdkLocation(),
- SdkConstants.FD_TOOLS + File.separator + SdkConstants.FD_SUPPORT +
- File.separator + SdkConstants.FN_ANNOTATIONS_JAR);
+ synchronized (Sdk.getLock()) {
+ boolean sdkIsLoaded = plugin.getSdkLoadStatus() == LoadStatus.LOADED;
- jarFiles.add(annotationsJar);
- }
+ // check if the project has a valid target.
+ final ProjectState state = Sdk.getProjectState(iProject);
+ if (state == null) {
+ // getProjectState should already have logged an error. Just bail out.
+ return null;
+ }
- // process all the libraries
+ // annotations support for older version of android
+ if (state.getTarget() != null && state.getTarget().getVersion().getApiLevel() <= 15) {
+ File annotationsJar = new File(Sdk.getCurrent().getSdkLocation(),
+ SdkConstants.FD_TOOLS + File.separator + SdkConstants.FD_SUPPORT +
+ File.separator + SdkConstants.FN_ANNOTATIONS_JAR);
- List<IProject> libProjects = state.getFullLibraryProjects();
- for (IProject libProject : libProjects) {
- // get the project output
- IFolder outputFolder = BaseProjectHelper.getAndroidOutputFolder(libProject);
-
- if (outputFolder != null) { // can happen when closing/deleting a library)
- IFile jarIFile = outputFolder.getFile(libProject.getName().toLowerCase() +
- SdkConstants.DOT_JAR);
-
- // get the source folder for the library project
- List<IPath> srcs = BaseProjectHelper.getSourceClasspaths(libProject);
- // find the first non-derived source folder.
- IPath sourceFolder = null;
- for (IPath src : srcs) {
- IFolder srcFolder = workspaceRoot.getFolder(src);
- if (srcFolder.isDerived() == false) {
- sourceFolder = src;
- break;
+ jarFiles.add(annotationsJar);
+ }
+
+ if (state.getRenderScriptSupportMode()) {
+ if (!sdkIsLoaded) {
+ return null;
+ }
+ BuildToolInfo buildToolInfo = state.getBuildToolInfo();
+ if (buildToolInfo == null) {
+ buildToolInfo = Sdk.getCurrent().getLatestBuildTool();
+
+ if (buildToolInfo == null) {
+ return null;
}
+
+ File renderScriptSupportJar = RenderScriptProcessor.getSupportJar(
+ buildToolInfo.getLocation().getAbsolutePath());
+
+ jarFiles.add(renderScriptSupportJar);
}
+ }
- // we can directly add a CPE for this jar as there's no risk of a duplicate.
- IClasspathEntry entry = JavaCore.newLibraryEntry(
- jarIFile.getLocation(),
- sourceFolder, // source attachment path
- null, // default source attachment root path.
- true /*isExported*/);
+ // process all the libraries
+
+ List<IProject> libProjects = state.getFullLibraryProjects();
+ for (IProject libProject : libProjects) {
+ // get the project output
+ IFolder outputFolder = BaseProjectHelper.getAndroidOutputFolder(libProject);
+
+ if (outputFolder != null) { // can happen when closing/deleting a library)
+ IFile jarIFile = outputFolder.getFile(libProject.getName().toLowerCase() +
+ SdkConstants.DOT_JAR);
+
+ // get the source folder for the library project
+ List<IPath> srcs = BaseProjectHelper.getSourceClasspaths(libProject);
+ // find the first non-derived source folder.
+ IPath sourceFolder = null;
+ for (IPath src : srcs) {
+ IFolder srcFolder = workspaceRoot.getFolder(src);
+ if (srcFolder.isDerived() == false) {
+ sourceFolder = src;
+ break;
+ }
+ }
- entries.add(entry);
+ // we can directly add a CPE for this jar as there's no risk of a duplicate.
+ IClasspathEntry entry = JavaCore.newLibraryEntry(
+ jarIFile.getLocation(),
+ sourceFolder, // source attachment path
+ null, // default source attachment root path.
+ true /*isExported*/);
+
+ entries.add(entry);
+ }
}
- }
- entries.addAll(convertJarsToClasspathEntries(iProject, jarFiles));
+ entries.addAll(convertJarsToClasspathEntries(iProject, jarFiles));
- return allocateContainer(javaProject, entries, new Path(CONTAINER_DEPENDENCIES),
- "Android Dependencies");
+ return allocateContainer(javaProject, entries, new Path(CONTAINER_DEPENDENCIES),
+ "Android Dependencies");
+ }
}
private static IClasspathContainer allocateContainer(IJavaProject javaProject,
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 4628509..74c9857 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
@@ -259,6 +259,15 @@ public final class ProjectState {
return mProperties.getProperty(ProjectProperties.PROPERTY_BUILD_TOOLS);
}
+ public boolean getRenderScriptSupportMode() {
+ String supportModeValue = mProperties.getProperty(ProjectProperties.PROPERTY_RS_SUPPORT);
+ if (supportModeValue != null) {
+ return Boolean.parseBoolean(supportModeValue);
+ }
+
+ return false;
+ }
+
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 ca6cc57..c8faa5e 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
@@ -1187,6 +1187,7 @@ public final class Sdk {
// get the current target and build tools
IAndroidTarget oldTarget = state.getTarget();
+ boolean oldRsSupportMode = state.getRenderScriptSupportMode();
// get the current library flag
boolean wasLibrary = state.isLibrary();
@@ -1216,7 +1217,8 @@ public final class Sdk {
}
// apply the new target if needed.
- if (newTarget != oldTarget) {
+ if (newTarget != oldTarget ||
+ oldRsSupportMode != state.getRenderScriptSupportMode()) {
IJavaProject javaProject = BaseProjectHelper.getJavaProject(
file.getProject());
if (javaProject != null) {