diff options
Diffstat (limited to 'eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/RenderScriptLauncher.java')
-rw-r--r-- | eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/RenderScriptLauncher.java | 244 |
1 files changed, 244 insertions, 0 deletions
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 000000000..1d3c7bd3a --- /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; + } +} |