aboutsummaryrefslogtreecommitdiff
path: root/eclipse/plugins/com.android.ide.eclipse.ndk/src/com/android/ide/eclipse/ndk/internal/discovery/NdkDiscoveryUpdater.java
diff options
context:
space:
mode:
Diffstat (limited to 'eclipse/plugins/com.android.ide.eclipse.ndk/src/com/android/ide/eclipse/ndk/internal/discovery/NdkDiscoveryUpdater.java')
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.ndk/src/com/android/ide/eclipse/ndk/internal/discovery/NdkDiscoveryUpdater.java314
1 files changed, 314 insertions, 0 deletions
diff --git a/eclipse/plugins/com.android.ide.eclipse.ndk/src/com/android/ide/eclipse/ndk/internal/discovery/NdkDiscoveryUpdater.java b/eclipse/plugins/com.android.ide.eclipse.ndk/src/com/android/ide/eclipse/ndk/internal/discovery/NdkDiscoveryUpdater.java
new file mode 100644
index 000000000..a6b88f462
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.ndk/src/com/android/ide/eclipse/ndk/internal/discovery/NdkDiscoveryUpdater.java
@@ -0,0 +1,314 @@
+/*
+ * 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.ndk.internal.discovery;
+
+import com.android.ide.eclipse.ndk.internal.Activator;
+import com.android.ide.eclipse.ndk.internal.build.NdkCommandLauncher;
+
+import org.eclipse.cdt.core.CCorePlugin;
+import org.eclipse.cdt.core.envvar.IEnvironmentVariable;
+import org.eclipse.cdt.core.envvar.IEnvironmentVariableManager;
+import org.eclipse.cdt.core.settings.model.ICConfigurationDescription;
+import org.eclipse.cdt.managedbuilder.core.IBuilder;
+import org.eclipse.cdt.managedbuilder.core.IManagedBuildInfo;
+import org.eclipse.cdt.managedbuilder.core.ManagedBuildManager;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.FileLocator;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.Path;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+
+public class NdkDiscoveryUpdater {
+ private final NdkDiscoveredPathInfo mPathInfo;
+ private final IProject mProject;
+
+ private boolean mCPlusPlus = false;
+ private String mCommand;
+ private List<String> mArguments = new ArrayList<String>();
+
+ public NdkDiscoveryUpdater(NdkDiscoveredPathInfo pathInfo) {
+ mPathInfo = pathInfo;
+ mProject = pathInfo.getProject();
+ }
+
+ public void runUpdate(IProgressMonitor monitor) throws CoreException {
+ try {
+ // Run ndk-build -nB to get the list of commands
+ IPath commandPath = new Path("ndk-build"); //$NON-NLS-1$
+ String[] args = {
+ "-nB"}; //$NON-NLS-1$
+ String[] env = calcEnvironment();
+ File projectDir = new File(mProject.getLocationURI());
+ IPath changeToDirectory = new Path(projectDir.getAbsolutePath());
+ Process proc = new NdkCommandLauncher().execute(commandPath, args, env,
+ changeToDirectory, monitor);
+ if (proc == null)
+ // proc failed to start
+ return;
+ BufferedReader reader = new BufferedReader(new InputStreamReader(proc.getInputStream()));
+ String line = reader.readLine();
+ while (line != null) {
+ checkBuildLine(line);
+ line = reader.readLine();
+ }
+
+ if (mCommand == null) {
+ return;
+ }
+
+ // Run the unique commands with special gcc options to extract the
+ // symbols and paths
+ // -E -P -v -dD
+ mArguments.add("-E"); //$NON-NLS-1$
+ mArguments.add("-P"); //$NON-NLS-1$
+ mArguments.add("-v"); //$NON-NLS-1$
+ mArguments.add("-dD"); //$NON-NLS-1$
+
+ URL url = Activator.findFile(new Path(
+ "discovery/" + (mCPlusPlus ? "test.cpp" : "test.c"))); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ File testFile = new File(FileLocator.toFileURL(url).toURI());
+ String testFileName = testFile.getAbsolutePath().replace('\\', '/');
+ mArguments.add(testFileName);
+
+ args = mArguments.toArray(new String[mArguments.size()]);
+ proc = new NdkCommandLauncher().execute(new Path(mCommand), args, env,
+ changeToDirectory, monitor);
+ // Error stream has the includes
+ final InputStream errStream = proc.getErrorStream();
+ new Thread() {
+ @Override
+ public void run() {
+ checkIncludes(errStream);
+ };
+ }.start();
+
+ // Input stream has the defines
+ checkDefines(proc.getInputStream());
+ } catch (IOException e) {
+ throw new CoreException(Activator.newStatus(e));
+ } catch (URISyntaxException e) {
+ throw new CoreException(Activator.newStatus(e));
+ }
+ }
+
+ private String[] calcEnvironment() throws CoreException {
+ IManagedBuildInfo info = ManagedBuildManager.getBuildInfo(mProject);
+ IBuilder builder = info.getDefaultConfiguration().getBuilder();
+ HashMap<String, String> envMap = new HashMap<String, String>();
+ if (builder.appendEnvironment()) {
+ ICConfigurationDescription cfgDes = ManagedBuildManager
+ .getDescriptionForConfiguration(builder.getParent().getParent());
+ IEnvironmentVariableManager mngr = CCorePlugin.getDefault()
+ .getBuildEnvironmentManager();
+ IEnvironmentVariable[] vars = mngr.getVariables(cfgDes, true);
+ for (IEnvironmentVariable var : vars) {
+ envMap.put(var.getName(), var.getValue());
+ }
+ }
+ // Add variables from build info
+ Map<String, String> builderEnv = builder.getExpandedEnvironment();
+ if (builderEnv != null)
+ envMap.putAll(builderEnv);
+ List<String> strings = new ArrayList<String>(envMap.size());
+ for (Entry<String, String> entry : envMap.entrySet()) {
+ StringBuffer buffer = new StringBuffer(entry.getKey());
+ buffer.append('=').append(entry.getValue());
+ strings.add(buffer.toString());
+ }
+ return strings.toArray(new String[strings.size()]);
+ }
+
+ private static class Line {
+ private final String line;
+ private int pos;
+
+ public Line(String line) {
+ this.line = line;
+ }
+
+ public Line(String line, int pos) {
+ this(line);
+ this.pos = pos;
+ }
+
+ public String getToken() {
+ skipWhiteSpace();
+ if (pos == line.length())
+ return null;
+
+ int start = pos;
+ boolean inQuote = false;
+
+ while (true) {
+ char c = line.charAt(pos);
+ if (c == ' ') {
+ if (!inQuote)
+ return line.substring(start, pos);
+ } else if (c == '"') {
+ inQuote = !inQuote;
+ }
+
+ if (++pos == line.length())
+ return null;
+ }
+
+ }
+
+ private String getRemaining() {
+ if (pos == line.length())
+ return null;
+
+ skipWhiteSpace();
+ String rc = line.substring(pos);
+ pos = line.length();
+ return rc;
+ }
+
+ private void skipWhiteSpace() {
+ while (true) {
+ if (pos == line.length())
+ return;
+ char c = line.charAt(pos);
+ if (c == ' ')
+ pos++;
+ else
+ return;
+ }
+ }
+ }
+
+ private void checkBuildLine(String text) {
+ Line line = new Line(text);
+ String cmd = line.getToken();
+ if (cmd == null) {
+ return;
+ } else if (cmd.endsWith("g++")) { //$NON-NLS-1$
+ if (mCommand == null || !mCPlusPlus) {
+ mCommand = cmd;
+ mCPlusPlus = true;
+ }
+ gatherOptions(line);
+ } else if (cmd.endsWith("gcc")) { //$NON-NLS-1$
+ if (mCommand == null)
+ mCommand = cmd;
+ gatherOptions(line);
+ }
+ }
+
+ private void gatherOptions(Line line) {
+ for (String option = line.getToken(); option != null; option = line.getToken()) {
+ if (option.startsWith("-")) { //$NON-NLS-1$
+ // only look at options
+ if (option.equals("-I")) { //$NON-NLS-1$
+ String dir = line.getToken();
+ if (dir != null)
+ addArg(option + dir);
+ } else if (option.startsWith("-I")) { //$NON-NLS-1$
+ addArg(option);
+ } else if (option.equals("-D")) { //$NON-NLS-1$
+ String def = line.getToken();
+ if (def != null)
+ addArg(option + def);
+ } else if (option.startsWith("-D")) { //$NON-NLS-1$
+ addArg(option);
+ } else if (option.startsWith("-f")) { //$NON-NLS-1$
+ addArg(option);
+ } else if (option.startsWith("-m")) { //$NON-NLS-1$
+ addArg(option);
+ } else if (option.startsWith("--sysroot")) { //$NON-NLS-1$
+ addArg(option);
+ }
+ }
+ }
+ }
+
+ private void addArg(String arg) {
+ if (!mArguments.contains(arg))
+ mArguments.add(arg);
+ }
+
+ private void checkIncludes(InputStream in) {
+ try {
+ List<String> includes = new ArrayList<String>();
+ boolean inIncludes1 = false;
+ boolean inIncludes2 = false;
+ BufferedReader reader = new BufferedReader(new InputStreamReader(in));
+ String line = reader.readLine();
+ while (line != null) {
+ if (!inIncludes1) {
+ if (line.equals("#include \"...\" search starts here:")) //$NON-NLS-1$
+ inIncludes1 = true;
+ } else {
+ if (!inIncludes2) {
+ if (line.equals("#include <...> search starts here:")) //$NON-NLS-1$
+ inIncludes2 = true;
+ else
+ includes.add(line.trim());
+ } else {
+ if (line.equals("End of search list.")) { //$NON-NLS-1$
+ mPathInfo.setIncludePaths(includes);
+ } else {
+ includes.add(line.trim());
+ }
+ }
+ }
+ line = reader.readLine();
+ }
+ } catch (IOException e) {
+ Activator.log(e);
+ }
+ }
+
+ private void checkDefines(InputStream in) {
+ try {
+ Map<String, String> defines = new HashMap<String, String>();
+ BufferedReader reader = new BufferedReader(new InputStreamReader(in));
+ String line = reader.readLine();
+ while (line != null) {
+ if (line.startsWith("#define")) { //$NON-NLS-1$
+ Line l = new Line(line, 7);
+ String var = l.getToken();
+ if (var == null)
+ continue;
+ String value = l.getRemaining();
+ if (value == null)
+ value = ""; //$NON-NLS-1$
+ defines.put(var, value);
+ }
+ line = reader.readLine();
+ }
+ mPathInfo.setSymbols(defines);
+ } catch (IOException e) {
+ Activator.log(e);
+ }
+ }
+
+}