public class RenderScriptTask extends Task {
private String mExecutable;
- private String mFramework;
+ private Path mFramework;
private String mGenFolder;
private String mResFolder;
private final List<Path> mPaths = new ArrayList<Path>();
}
public void setFramework(Path value) {
- mFramework = TaskHelper.checkSinglePath("framework", value);
+ mFramework = value;
}
public void setGenFolder(Path value) {
task.setExecutable(mExecutable);
task.setFailonerror(true);
- task.createArg().setValue("-I");
- task.createArg().setValue(mFramework);
+ for (String path : mFramework.list()) {
+ File res = new File(path);
+ if (res.isDirectory()) {
+ task.createArg().setValue("-I");
+ task.createArg().setValue(path);
+ }
+ }
+
task.createArg().setValue("-p");
task.createArg().setValue(mGenFolder);
task.createArg().setValue("-o");
String androidAidl = androidTarget.getPath(IAndroidTarget.ANDROID_AIDL);
antProject.setProperty(AntConstants.PROP_ANDROID_AIDL, androidAidl);
- String androidRS = androidTarget.getPath(IAndroidTarget.ANDROID_RS);
- antProject.setProperty(AntConstants.PROP_ANDROID_RENDERSCRIPT, androidRS);
+ Path includePath = new Path(antProject);
+ PathElement element = includePath.createPathElement();
+ element.setPath(androidTarget.getPath(IAndroidTarget.ANDROID_RS));
+ element = includePath.createPathElement();
+ element.setPath(androidTarget.getPath(IAndroidTarget.ANDROID_RS_CLANG));
+ antProject.setProperty(AntConstants.PROP_ANDROID_RENDERSCRIPT, includePath.toString());
antProject.setProperty(AntConstants.PROP_AAPT, androidTarget.getPath(IAndroidTarget.AAPT));
antProject.setProperty(AntConstants.PROP_AIDL, androidTarget.getPath(IAndroidTarget.AIDL));
antProject.setProperty(AntConstants.PROP_DX, androidTarget.getPath(IAndroidTarget.DX));
antProject.setProperty(AntConstants.PROP_RENDERSCRIPT,
sdkOsPath + SdkConstants.OS_SDK_PLATFORM_TOOLS_FOLDER +
- SdkConstants.FN_RENDERSCRIPT);
+ SdkConstants.FN_RENDERSCRIPT);
// sets up the boot classpath
Path bootclasspath = new Path(antProject);
// create a PathElement for the framework jar
- PathElement element = bootclasspath.createPathElement();
+ element = bootclasspath.createPathElement();
element.setPath(androidJar);
// create PathElement for each optional library.
<persistent value="true"/>
</extension>
<extension
+ id="com.android.ide.eclipse.common.rsProblem"
+ name="Android RenderScript Problem"
+ point="org.eclipse.core.resources.markers">
+ <super type="org.eclipse.core.resources.problemmarker"/>
+ <super type="org.eclipse.core.resources.textmarker"/>
+ <persistent value="true"/>
+ </extension>
+ <extension
id="com.android.ide.eclipse.common.androidProblem"
name="Android XML Content Problem"
point="org.eclipse.core.resources.markers">
public final static String EXT_AIDL = "aidl"; //$NON-NLS-1$
/** Extension of Renderscript files, i.e. "rs" */
public final static String EXT_RS = "rs"; //$NON-NLS-1$
+ /** Extension of dependency files, i.e. "d" */
+ public final static String EXT_DEP = "d"; //$NON-NLS-1$
/** Extension of native libraries, i.e. "so" */
public final static String EXT_NATIVE_LIB = "so"; //$NON-NLS-1$
/** Extension of dex files, i.e. "dex" */
public final static String DOT_JAR = DOT + EXT_JAR;
/** Dot-Extension of aidl files, i.e. ".aidl" */
public final static String DOT_AIDL = DOT + EXT_AIDL;
+ /** Dot-Extension of renderscript files, i.e. ".rs" */
+ public final static String DOT_RS = DOT + EXT_RS;
+ /** Dot-Extension of dependency files, i.e. ".d" */
+ public final static String DOT_DEP = DOT + EXT_DEP;
/** Dot-Extension of dex files, i.e. ".dex" */
public final static String DOT_DEX = DOT + EXT_DEX;
/** Dot-Extension for temporary resource files, ie "ap_ */
public final static String RE_DOT = "\\."; //$NON-NLS-1$
/** Regexp for java extension, i.e. "\.java$" */
- public final static String RE_JAVA_EXT = "\\.java$"; //$NON-NLS-1$
+ public final static String RE_JAVA_EXT = "\\" + DOT_JAVA + "$"; //$NON-NLS-1$ //$NON-NLS-2$
/** Regexp for aidl extension, i.e. "\.aidl$" */
- public final static String RE_AIDL_EXT = "\\.aidl$"; //$NON-NLS-1$
+ public final static String RE_AIDL_EXT = "\\" + DOT_AIDL + "$"; //$NON-NLS-1$ //$NON-NLS-2$
+ /** Regexp for rs extension, i.e. "\.rs$" */
+ public final static String RE_RS_EXT = "\\" + DOT_RS + "$"; //$NON-NLS-1$ //$NON-NLS-2$
/**
* Namespace pattern for the custom resource XML, i.e. "http://schemas.android.com/apk/res/%s"
/** aidl marker error, only to be used in {@link PreCompilerBuilder} */
public final static String MARKER_AIDL = LEGACY_PLUGIN_ID + ".aidlProblem"; //$NON-NLS-1$
+ /** renderscript marker error, only to be used in {@link PreCompilerBuilder} */
+ public final static String MARKER_RENDERSCRIPT = LEGACY_PLUGIN_ID + ".rsProblem"; //$NON-NLS-1$
+
/** android marker error, only to be used in the Manifest parsing
* from the {@link PreCompilerBuilder} */
public final static String MARKER_ANDROID = LEGACY_PLUGIN_ID + ".androidProblem"; //$NON-NLS-1$
}
@Override
+ protected int getCompilationType() {
+ return COMPILE_STATUS_CODE;
+ }
+
+ @Override
protected void doCompileFiles(List<IFile> sources, BaseBuilder builder,
IProject project, IAndroidTarget projectTarget,
List<IPath> sourceFolders, List<IFile> notCompiledOut, IProgressMonitor monitor)
command[index++] = "-I" + f.getLocation().toOSString(); //$NON-NLS-1$
}
+ boolean verbose = AdtPrefs.getPrefs().getBuildVerbosity() == BuildVerbosity.VERBOSE;
+
// loop until we've compile them all
for (IFile sourceFile : sources) {
- if (AdtPrefs.getPrefs().getBuildVerbosity() == BuildVerbosity.VERBOSE) {
+ if (verbose) {
String name = sourceFile.getName();
IPath sourceFolderPath = getSourceFolderFor(sourceFile);
if (sourceFolderPath != null) {
command[index + 1] = bundle.getOutput().getLocation().toOSString();
// launch the process
- if (execAidl(builder, project, command, sourceFile) == false) {
+ if (execAidl(builder, project, command, sourceFile, verbose) == false) {
// aidl failed. File should be marked. We add the file to the list
// of file that will need compilation again.
notCompiledOut.add(sourceFile);
}
@Override
- protected void doRemoveFiles(List<IFile> sources, IProgressMonitor monitor)
- throws CoreException {
- for (IFile sourceFile : sources) {
- // look if we already know the output
- NonJavaFileBundle bundle = getBundle(sourceFile);
- if (bundle != null) {
- IFile outputFile = bundle.getOutput();
- if (outputFile != null && outputFile.exists()) {
- // This confirms the java file was generated by the builder,
- // we can delete the aidlFile.
- outputFile.getLocation().toFile().delete();
- }
- }
- }
- }
-
- @Override
protected void loadOutputAndDependencies() {
IProgressMonitor monitor = new NullProgressMonitor();
Collection<NonJavaFileBundle> bundles = getBundles();
* @param command the String array containing the command line to execute.
* @param file The IFile object representing the aidl file being
* compiled.
+ * @param verbose the build verbosity
* @return false if the exec failed, and build needs to be aborted.
*/
- private boolean execAidl(BaseBuilder builder, IProject project, String[] command, IFile file) {
+ private boolean execAidl(BaseBuilder builder, IProject project, String[] command, IFile file,
+ boolean verbose) {
// do the exec
try {
- boolean verbose = AdtPrefs.getPrefs().getBuildVerbosity() == BuildVerbosity.VERBOSE;
if (verbose) {
StringBuilder sb = new StringBuilder();
for (String c : command) {
// display the message in the console.
if (error) {
AdtPlugin.printErrorToConsole(project, results.toArray());
+
+ // mark the project
+ BaseProjectHelper.markResource(project, AndroidConstants.MARKER_ADT,
+ Messages.Unparsed_AIDL_Errors, IMarker.SEVERITY_ERROR);
} else {
AdtPlugin.printToConsole(project, results.toArray());
}
-
- // mark the project and exit
- BaseProjectHelper.markResource(project, AndroidConstants.MARKER_ADT,
- Messages.Unparsed_AIDL_Errors, IMarker.SEVERITY_ERROR);
}
return false;
}
return null;
}
- private IPath getSourceFolderFor(IFile file) {
- // find the source folder for the class so that we can infer the package from the
- // difference between the file and its source folder.
- List<IPath> sourceFolders = BaseProjectHelper.getSourceClasspaths(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(getGenFolder()) == false) {
- // look for the source file parent, until we find this source folder.
- IResource parent = file;
- while ((parent = parent.getParent()) != null) {
- if (parent.equals(sourceFolder)) {
- return sourceFolderPath;
- }
- }
- }
- }
-
- return null;
- }
-
/**
* Creates the destination folder. Because
* {@link IFolder#create(boolean, boolean, IProgressMonitor)} only works if the parent folder
}
}
- protected boolean filterResourceFolder(IContainer parent) {
+ /**
+ * Called to restrict {@link #handleResourceFile(IFile, int)} on selected resource folders.
+ * @param folder
+ * @return
+ */
+ protected boolean filterResourceFolder(IContainer folder) {
return false;
}
*/
public abstract class JavaGenerator {
+ public final static int COMPILE_STATUS_NONE = 0;
+ public final static int COMPILE_STATUS_CODE = 0x1;
+ public final static int COMPILE_STATUS_RES = 0x2;
+
/** List of all source files, their dependencies, and their output. */
private final Map<IFile, NonJavaFileBundle> mFiles = new HashMap<IFile, NonJavaFileBundle>();
saveState(project);
}
+ /**
+ * Returns the extension of the source files handled by this generator.
+ * @return
+ */
protected abstract String getExtension();
protected abstract String getSavePropertyName();
- public final boolean compileFiles(BaseBuilder builder,
+ /**
+ * Compiles the source files and return what type of file was generated.
+ *
+ * @see #getCompilationType()
+ */
+ public final int compileFiles(BaseBuilder builder,
IProject project, IAndroidTarget projectTarget,
List<IPath> sourceFolders, IProgressMonitor monitor) throws CoreException {
if (mToCompile.size() == 0 && mRemoved.size() == 0) {
- return false;
+ return COMPILE_STATUS_NONE;
}
// if a source file is being removed before we managed to compile it, it'll be in
mToCompile.addAll(stillNeedCompilation);
// Remove the files created from source files that have been removed.
- doRemoveFiles(mRemoved, monitor);
+ for (IFile sourceFile : mRemoved) {
+ // look if we already know the output
+ NonJavaFileBundle bundle = getBundle(sourceFile);
+ if (bundle != null) {
+ doRemoveFiles(bundle);
+ }
+ }
// remove the associated bundles.
for (IFile removedFile : mRemoved) {
// before the project is closed/re-opened.)
saveState(project);
- return true;
+ return getCompilationType();
}
protected abstract void doCompileFiles(
List<IPath> sourceFolders, List<IFile> notCompiledOut, IProgressMonitor monitor)
throws CoreException;
- protected abstract void doRemoveFiles(List<IFile> sources, IProgressMonitor monitor)
- throws CoreException;
+ /**
+ * Returns the type of compilation. It can be any of (in combination too):
+ * <p/>
+ * {@link #COMPILE_STATUS_CODE} means this generator created source files.
+ * {@link #COMPILE_STATUS_RES} means this generator created resources.
+ */
+ protected abstract int getCompilationType();
+
+ protected void doRemoveFiles(NonJavaFileBundle bundle) throws CoreException {
+ List<IFile> outputFiles = bundle.getOutputFiles();
+ for (IFile outputFile : outputFiles) {
+ if (outputFile.exists()) {
+ outputFile.getLocation().toFile().delete();
+ }
+ }
+ }
public final boolean loadState(IProject project) {
return ProjectHelper.loadBooleanProperty(project, getSavePropertyName(),
protected abstract void loadOutputAndDependencies();
+
+ protected IPath getSourceFolderFor(IFile file) {
+ // find the source folder for the class so that we can infer the package from the
+ // difference between the file and its source folder.
+ List<IPath> sourceFolders = BaseProjectHelper.getSourceClasspaths(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(getGenFolder()) == false) {
+ // look for the source file parent, until we find this source folder.
+ IResource parent = file;
+ while ((parent = parent.getParent()) != null) {
+ if (parent.equals(sourceFolder)) {
+ return sourceFolderPath;
+ }
+ }
+ }
+ }
+
+ return null;
+ }
+
/**
* Goes through the build paths and fills the list of files to compile.
*
* @param project The project.
* @param sourceFolderPathList The list of source folder paths.
*/
- protected void buildSourceFileList() {
+ private final void buildSourceFileList() {
mFiles.clear();
IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
}
}
+ public void setDependencyFiles(List<IFile> depFiles) {
+ mDependencyFiles.clear();
+ if (depFiles != null) {
+ mDependencyFiles.addAll(depFiles);
+ }
+ }
+
+ public List<IFile> getDependencyFiles() {
+ return mDependencyFiles;
+ }
+
/**
* Shortcut access to the first output file. This is useful for generator that only output
* one file.
--- /dev/null
+/*
+ * 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.ide.eclipse.adt.AdtPlugin;
+import com.android.ide.eclipse.adt.AndroidConstants;
+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.ide.eclipse.adt.internal.resources.manager.ResourceFolderType;
+import com.android.ide.eclipse.adt.internal.sdk.Sdk;
+import com.android.sdklib.IAndroidTarget;
+import com.android.sdklib.SdkConstants;
+
+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.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.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * A {@link JavaGenerator} for RenderScript files.
+ *
+ */
+public class RenderScriptGenerator extends JavaGenerator {
+
+ private static final String PROPERTY_COMPILE_RS = "compileRenderScript"; //$NON-NLS-1$
+
+ /**
+ * Single line llvm-rs-cc error<br>
+ * "<path>:<line>:<col>: <error>"
+ */
+ private static Pattern sLlvmPattern1 = Pattern.compile("^(.+?):(\\d+):(\\d+):\\s(.+)$"); //$NON-NLS-1$
+
+ private static class RSDeltaVisitor extends GeneratorDeltaVisitor {
+
+ @Override
+ protected boolean filterResourceFolder(IContainer folder) {
+ return ResourceFolderType.RAW.getName().equals(folder.getName());
+ }
+ }
+
+ public RenderScriptGenerator(IJavaProject javaProject, IFolder genFolder) {
+ super(javaProject, genFolder, new RSDeltaVisitor());
+ }
+
+ @Override
+ protected String getExtension() {
+ return AndroidConstants.EXT_RS;
+ }
+
+ @Override
+ protected String getSavePropertyName() {
+ return PROPERTY_COMPILE_RS;
+ }
+
+ @Override
+ protected int getCompilationType() {
+ return COMPILE_STATUS_CODE | COMPILE_STATUS_RES;
+ }
+
+ @Override
+ protected void doCompileFiles(List<IFile> sources, BaseBuilder builder,
+ IProject project, IAndroidTarget projectTarget, List<IPath> sourceFolders,
+ List<IFile> notCompiledOut, IProgressMonitor monitor) throws CoreException {
+
+ String sdkOsPath = Sdk.getCurrent().getSdkLocation();
+
+ IFolder genFolder = getGenFolder();
+
+ IFolder rawFolder = project.getFolder(
+ new Path(SdkConstants.FD_RES).append(SdkConstants.FD_RAW));
+
+ // create the command line
+ String[] command = new String[13];
+ int index = 0;
+ command[index++] = sdkOsPath + SdkConstants.OS_SDK_PLATFORM_TOOLS_FOLDER
+ + SdkConstants.FN_RENDERSCRIPT;
+ command[index++] = "-I";
+ command[index++] = projectTarget.getPath(IAndroidTarget.ANDROID_RS_CLANG);
+ command[index++] = "-I";
+ command[index++] = projectTarget.getPath(IAndroidTarget.ANDROID_RS);
+ command[index++] = "-p";
+ command[index++] = genFolder.getLocation().toOSString();
+ command[index++] = "-o";
+ command[index++] = rawFolder.getLocation().toOSString();
+
+ command[index++] = "-d";
+ command[index++] = getDependencyFolder().getLocation().toOSString();
+ command[index++] = "-MD";
+
+ boolean verbose = AdtPrefs.getPrefs().getBuildVerbosity() == BuildVerbosity.VERBOSE;
+ boolean someSuccess = false;
+
+ // 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.removeMarkersFromFile(sourceFile, AndroidConstants.MARKER_RENDERSCRIPT);
+ NonJavaFileBundle bundle = getBundle(sourceFile);
+ if (bundle != null) {
+ for (IFile dep : bundle.getDependencyFiles()) {
+ builder.removeMarkersFromFile(dep, AndroidConstants.MARKER_RENDERSCRIPT);
+ }
+ }
+
+ // get the path of the source file.
+ IPath sourcePath = sourceFile.getLocation();
+ String osSourcePath = sourcePath.toOSString();
+
+ // finish to set the command line.
+ command[index] = osSourcePath;
+
+ // launch the process
+ if (execLlvmRsCc(builder, project, command, sourceFile, verbose) == false) {
+ // 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 {
+ // 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, 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);
+ }
+
+ Process p = Runtime.getRuntime().exec(command);
+
+ // list to store each line of stderr
+ ArrayList<String> results = new ArrayList<String>();
+
+ // get the output and return code from the process
+ int result = BuildHelper.grabProcessOutput(project, p, results);
+
+ // attempt to parse the error output
+ boolean error = parseLlvmOutput(results);
+
+ // If the process failed and we couldn't parse the output
+ // we print a message, mark the project and exit
+ if (result != 0) {
+
+ if (error || verbose) {
+ // display the message in the console.
+ if (error) {
+ AdtPlugin.printErrorToConsole(project, results.toArray());
+
+ // mark the project
+ BaseProjectHelper.markResource(project, AndroidConstants.MARKER_ADT,
+ "Unparsed Renderscript error! Check the console for output.",
+ IMarker.SEVERITY_ERROR);
+ } else {
+ AdtPlugin.printToConsole(project, results.toArray());
+ }
+ }
+ 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, AndroidConstants.MARKER_ADT, 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, AndroidConstants.MARKER_ADT, 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, AndroidConstants.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(NonJavaFileBundle 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<NonJavaFileBundle> bundles = getBundles();
+ for (NonJavaFileBundle bundle : bundles) {
+ parseDependencyFileFor(bundle.getSourceFile());
+ }
+ }
+
+ private void parseDependencyFileFor(IFile sourceFile) {
+ IFile depFile = getDependencyFileFor(sourceFile);
+ File f = depFile.getLocation().toFile();
+ if (f.exists()) {
+ NonJavaFileBundle bundle = getBundle(sourceFile);
+ if (bundle == null) {
+ bundle = new NonJavaFileBundle(sourceFile);
+ addBundle(bundle);
+ }
+ parseDependencyFile(bundle, f);
+ }
+ }
+
+ private IFolder getDependencyFolder() {
+ return getJavaProject().getProject().getFolder(SdkConstants.FD_OUTPUT);
+ }
+
+ private IFile getDependencyFileFor(IFile sourceFile) {
+ IFolder depFolder = getDependencyFolder();
+ return depFolder.getFile(sourceFile.getName().replaceAll(AndroidConstants.RE_RS_EXT,
+ AndroidConstants.DOT_DEP));
+ }
+
+ /**
+ * Parses the given dependency file and fills the given {@link NonJavaFileBundle} with it.
+ *
+ * @param bundle the bundle to fill.
+ * @param file the dependency file
+ */
+ private void parseDependencyFile(NonJavaFileBundle bundle, 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");
+ StringBuilder sb = new StringBuilder();
+ for (String line : lines) {
+ line = line.trim();
+ if (line.endsWith("\\")) {
+ line = line.substring(0, line.length() - 1);
+ }
+
+ sb.append(line);
+ }
+
+ // split the left and right part
+ String[] files = sb.toString().split(":");
+
+ // get the output files:
+ String[] outputs = files[0].trim().split(" ");
+
+ // and the dependency files:
+ String[] dependencies = files[1].trim().split(" ");
+
+ List<IFile> outputFiles = new ArrayList<IFile>();
+ List<IFile> dependencyFiles = new ArrayList<IFile>();
+
+ fillList(outputs, outputFiles);
+ fillList(dependencies, dependencyFiles);
+
+ bundle.setOutputFiles(outputFiles);
+ bundle.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);
+ }
+ }
+ }
+}
import com.android.ide.eclipse.adt.internal.build.AidlGenerator;
import com.android.ide.eclipse.adt.internal.build.JavaGenerator;
import com.android.ide.eclipse.adt.internal.build.Messages;
+import com.android.ide.eclipse.adt.internal.build.RenderScriptGenerator;
import com.android.ide.eclipse.adt.internal.preferences.AdtPrefs;
import com.android.ide.eclipse.adt.internal.preferences.AdtPrefs.BuildVerbosity;
import com.android.ide.eclipse.adt.internal.project.AndroidManifestHelper;
saveProjectBooleanProperty(PROPERTY_COMPILE_RESOURCES , mMustCompileResources);
}
- if (mMustCompileResources) {
- handleResources(project, javaPackage, projectTarget, manifestFile, libProjects);
- }
-
// run the Java generators
- boolean generatorStatus = false;
+ int generatorStatus = JavaGenerator.COMPILE_STATUS_NONE;
for (JavaGenerator generator : mGeneratorList) {
- generatorStatus |= generator.compileFiles(this,
- project, projectTarget, sourceFolderPathList, monitor);
+ try {
+ generatorStatus |= generator.compileFiles(this,
+ project, projectTarget, sourceFolderPathList, monitor);
+ } catch (Throwable t) {
+ }
+ }
+
+ // if a generator created some resources file, force recompilation of the resources.
+ if ((generatorStatus & JavaGenerator.COMPILE_STATUS_RES) != 0) {
+ mMustCompileResources = true;
+ // save the current state before attempting the compilation
+ saveProjectBooleanProperty(PROPERTY_COMPILE_RESOURCES , mMustCompileResources);
+ }
+
+ // handle the resources, after the java generators are run since some (renderscript)
+ // generate resources.
+ boolean compiledTheResources = mMustCompileResources;
+ if (mMustCompileResources) {
+ handleResources(project, javaPackage, projectTarget, manifestFile, libProjects);
+ saveProjectBooleanProperty(PROPERTY_COMPILE_RESOURCES , false);
}
- if (generatorStatus == false && mMustCompileResources == false) {
+ if (generatorStatus == JavaGenerator.COMPILE_STATUS_NONE &&
+ compiledTheResources == false) {
AdtPlugin.printBuildToConsole(BuildVerbosity.VERBOSE, project,
Messages.Nothing_To_Compile);
}
// load the java generators
JavaGenerator aidlGenerator = new AidlGenerator(javaProject, mGenFolder);
mGeneratorList.add(aidlGenerator);
+ JavaGenerator renderScriptGenerator = new RenderScriptGenerator(javaProject, mGenFolder);
+ mGeneratorList.add(renderScriptGenerator);
mDerivedProgressMonitor = new DerivedProgressMonitor(mGenFolder);
}
* <li>Any modification to aidl files.</li>
*
*/
-class PreCompilerDeltaVisitor extends BaseDeltaVisitor implements
- IResourceDeltaVisitor {
-
+class PreCompilerDeltaVisitor extends BaseDeltaVisitor implements IResourceDeltaVisitor {
// Result fields.
/**
mBuilder.getProject(), message);
}
+ for (GeneratorDeltaVisitor dv : mGeneratorDeltaVisitors) {
+ dv.handleResourceFile((IFile)resource, kind);
+ }
+
if (AndroidConstants.EXT_XML.equalsIgnoreCase(ext)) {
if (kind != IResourceDelta.REMOVED) {
// check xml Validity
folderToTypeMap);
add(ResourceType.LAYOUT, ResourceFolderType.LAYOUT, typeToFolderMap, folderToTypeMap);
add(ResourceType.MENU, ResourceFolderType.MENU, typeToFolderMap, folderToTypeMap);
+ add(ResourceType.MIPMAP, ResourceFolderType.MIPMAP, typeToFolderMap, folderToTypeMap);
add(ResourceType.PLURALS, ResourceFolderType.VALUES, typeToFolderMap, folderToTypeMap);
add(ResourceType.PUBLIC, ResourceFolderType.VALUES, typeToFolderMap, folderToTypeMap);
add(ResourceType.RAW, ResourceFolderType.RAW, typeToFolderMap, folderToTypeMap);
INTERPOLATOR(SdkConstants.FD_INTERPOLATOR),
LAYOUT(SdkConstants.FD_LAYOUT),
MENU(SdkConstants.FD_MENU),
+ MIPMAP(SdkConstants.FD_MIPMAP),
RAW(SdkConstants.FD_RAW),
VALUES(SdkConstants.FD_VALUES),
XML(SdkConstants.FD_XML);
public final static int ANT = 24;
/** OS Path to the Renderscript include folder. */
public final static int ANDROID_RS = 25;
+ /** OS Path to the Renderscript(clang) include folder. */
+ public final static int ANDROID_RS_CLANG = 26;
/**
* Return value for {@link #getUsbVendorId()} meaning no USB vendor IDs are defined by the
package com.android.sdklib;
+import com.android.sdklib.util.SparseArray;
+
import java.io.File;
import java.util.Collections;
-import java.util.HashMap;
import java.util.Map;
/**
private final String mVersionName;
private final int mRevision;
private final Map<String, String> mProperties;
- private final Map<Integer, String> mPaths = new HashMap<Integer, String>();
+ private final SparseArray<String> mPaths = new SparseArray<String>();
private String[] mSkins;
mPaths.put(SOURCES, mRootFolderOsPath + SdkConstants.FD_ANDROID_SOURCES);
mPaths.put(ANDROID_AIDL, mRootFolderOsPath + SdkConstants.FN_FRAMEWORK_AIDL);
mPaths.put(ANDROID_RS, mRootFolderOsPath + SdkConstants.OS_FRAMEWORK_RS);
+ mPaths.put(ANDROID_RS_CLANG, mRootFolderOsPath + SdkConstants.OS_FRAMEWORK_RS_CLANG);
mPaths.put(IMAGES, mRootFolderOsPath + SdkConstants.OS_IMAGES_FOLDER);
mPaths.put(SAMPLES, mRootFolderOsPath + SdkConstants.OS_PLATFORM_SAMPLES_FOLDER);
mPaths.put(SKINS, mRootFolderOsPath + SdkConstants.OS_SKINS_FOLDER);
public static final String FN_FRAMEWORK_RENDERSCRIPT = "renderscript";
/** framework include folder */
public static final String FN_FRAMEWORK_INCLUDE = "include";
+ /** framework include (clang) folder */
+ public static final String FN_FRAMEWORK_INCLUDE_CLANG = "clang-include";
/** layoutlib.jar file */
public static final String FN_LAYOUTLIB_JAR = "layoutlib.jar";
/** widget list file */
public final static String FD_LAYOUT = "layout"; //$NON-NLS-1$
/** Default menu resource folder name, i.e. "menu" */
public final static String FD_MENU = "menu"; //$NON-NLS-1$
+ /** Default menu resource folder name, i.e. "mipmap" */
+ public final static String FD_MIPMAP = "mipmap"; //$NON-NLS-1$
/** Default values resource folder name, i.e. "values" */
public final static String FD_VALUES = "values"; //$NON-NLS-1$
/** Default xml resource folder name, i.e. "xml" */
/** Path of the renderscript include folder relative to a platform folder. */
public final static String OS_FRAMEWORK_RS =
FN_FRAMEWORK_RENDERSCRIPT + File.separator + FN_FRAMEWORK_INCLUDE;
+ /** Path of the renderscript (clang) include folder relative to a platform folder. */
+ public final static String OS_FRAMEWORK_RS_CLANG =
+ FN_FRAMEWORK_RENDERSCRIPT + File.separator + FN_FRAMEWORK_INCLUDE_CLANG;
/* Folder paths relative to a addon folder */