1 /* 2 * Copyright (C) 2012 The Android Open Source Project 3 * 4 * Licensed under the Eclipse Public License, Version 1.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.eclipse.org/org/documents/epl-v10.php 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.ide.eclipse.ndk.internal; 18 19 import com.android.ide.eclipse.adt.AdtPlugin; 20 import com.android.ide.eclipse.ndk.internal.launch.NdkLaunchConstants; 21 22 import org.eclipse.cdt.core.CommandLauncher; 23 import org.eclipse.cdt.core.ICommandLauncher; 24 import org.eclipse.cdt.debug.core.ICDTLaunchConfigurationConstants; 25 import org.eclipse.cdt.dsf.gdb.IGDBLaunchConfigurationConstants; 26 import org.eclipse.core.resources.IProject; 27 import org.eclipse.core.runtime.CoreException; 28 import org.eclipse.core.runtime.IPath; 29 import org.eclipse.core.runtime.IProgressMonitor; 30 import org.eclipse.core.runtime.Path; 31 import org.eclipse.core.runtime.Platform; 32 import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy; 33 34 import java.io.ByteArrayOutputStream; 35 import java.io.File; 36 import java.util.ArrayList; 37 import java.util.Collection; 38 import java.util.Collections; 39 import java.util.EnumSet; 40 import java.util.List; 41 import java.util.Set; 42 43 @SuppressWarnings("restriction") 44 public class NdkHelper { 45 private static final String MAKE = "make"; //$NON-NLS-1$ 46 private static final String CORE_MAKEFILE_PATH = "/build/core/build-local.mk"; //$NON-NLS-1$ 47 48 /** 49 * Obtain the ABI's the application is compatible with. 50 * The ABI's are obtained by reading the result of the following command: 51 * make --no-print-dir -f ${NdkRoot}/build/core/build-local.mk -C <project-root> DUMP_APP_ABI 52 */ getApplicationAbis(IProject project, IProgressMonitor monitor)53 public static Collection<NativeAbi> getApplicationAbis(IProject project, 54 IProgressMonitor monitor) { 55 ICommandLauncher launcher = new CommandLauncher(); 56 launcher.setProject(project); 57 String[] args = new String[] { 58 "--no-print-dir", //$NON-NLS-1$ 59 "-f", //$NON-NLS-1$ 60 NdkManager.getNdkLocation() + CORE_MAKEFILE_PATH, 61 "-C", //$NON-NLS-1$ 62 project.getLocation().toOSString(), 63 "DUMP_APP_ABI", //$NON-NLS-1$ 64 }; 65 try { 66 launcher.execute(getPathToMake(), args, null, project.getLocation(), monitor); 67 } catch (CoreException e) { 68 AdtPlugin.printErrorToConsole(e.getLocalizedMessage()); 69 return Collections.emptyList(); 70 } 71 72 ByteArrayOutputStream stdout = new ByteArrayOutputStream(); 73 ByteArrayOutputStream stderr = new ByteArrayOutputStream(); 74 launcher.waitAndRead(stdout, stderr, monitor); 75 76 String abis = stdout.toString().trim(); 77 Set<NativeAbi> nativeAbis = EnumSet.noneOf(NativeAbi.class); 78 for (String abi: abis.split(" ")) { //$NON-NLS-1$ 79 if (abi.equals("all")) { //$NON-NLS-1$ 80 return EnumSet.allOf(NativeAbi.class); 81 } 82 83 try { 84 nativeAbis.add(NativeAbi.getByString(abi)); 85 } catch (IllegalArgumentException e) { 86 AdtPlugin.printErrorToConsole(project, "Unknown Application ABI: ", abi); 87 } 88 } 89 90 return nativeAbis; 91 } 92 93 /** 94 * Obtain the toolchain prefix to use for given project and abi. 95 * The prefix is obtained by reading the result of: 96 * make --no-print-dir -f ${NdkRoot}/build/core/build-local.mk \ 97 * -C <project-root> \ 98 * DUMP_TOOLCHAIN_PREFIX APP_ABI=abi 99 */ getToolchainPrefix(IProject project, NativeAbi abi, IProgressMonitor monitor)100 public static String getToolchainPrefix(IProject project, NativeAbi abi, 101 IProgressMonitor monitor) { 102 ICommandLauncher launcher = new CommandLauncher(); 103 launcher.setProject(project); 104 String[] args = new String[] { 105 "--no-print-dir", //$NON-NLS-1$ 106 "-f", //$NON-NLS-1$ 107 NdkManager.getNdkLocation() + CORE_MAKEFILE_PATH, 108 "-C", //$NON-NLS-1$ 109 project.getLocation().toOSString(), 110 "DUMP_TOOLCHAIN_PREFIX", //$NON-NLS-1$ 111 "APP_ABI=" + abi.getAbi(), //$NON-NLS-1$ 112 }; 113 try { 114 launcher.execute(getPathToMake(), args, null, project.getLocation(), monitor); 115 } catch (CoreException e) { 116 AdtPlugin.printErrorToConsole(e.getLocalizedMessage()); 117 return null; 118 } 119 120 ByteArrayOutputStream stdout = new ByteArrayOutputStream(); 121 ByteArrayOutputStream stderr = new ByteArrayOutputStream(); 122 launcher.waitAndRead(stdout, stderr, monitor); 123 return stdout.toString().trim(); 124 } 125 getPathToMake()126 private static IPath getPathToMake() { 127 return getFullPathTo(MAKE); 128 } 129 130 /** 131 * Obtain a path to the utilities prebuilt folder in NDK. This is typically 132 * "${NdkRoot}/prebuilt/<platform>/bin/". If the executable is not found, it simply returns 133 * the name of the executable (which is equal to assuming that it is available on the path). 134 */ getFullPathTo(String executable)135 private static synchronized IPath getFullPathTo(String executable) { 136 if (Platform.getOS().equals(Platform.OS_WIN32)) { 137 executable += ".exe"; 138 } 139 140 IPath ndkRoot = new Path(NdkManager.getNdkLocation()); 141 IPath prebuilt = ndkRoot.append("prebuilt"); //$NON-NLS-1$ 142 if (!prebuilt.toFile().exists() || !prebuilt.toFile().canRead()) { 143 return new Path(executable); 144 } 145 146 File[] platforms = prebuilt.toFile().listFiles(); 147 if (platforms != null) { 148 for (File p: platforms) { 149 IPath exePath = prebuilt.append(p.getName()) 150 .append("bin") //$NON-NLS-1$ 151 .append(executable); 152 if (exePath.toFile().exists()) { 153 return exePath; 154 } 155 } 156 } 157 158 return new Path(executable); 159 } 160 setLaunchConfigDefaults(ILaunchConfigurationWorkingCopy config)161 public static void setLaunchConfigDefaults(ILaunchConfigurationWorkingCopy config) { 162 config.setAttribute(IGDBLaunchConfigurationConstants.ATTR_REMOTE_TCP, true); 163 config.setAttribute(NdkLaunchConstants.ATTR_NDK_GDB, NdkLaunchConstants.DEFAULT_GDB); 164 config.setAttribute(IGDBLaunchConfigurationConstants.ATTR_GDB_INIT, 165 NdkLaunchConstants.DEFAULT_GDBINIT); 166 config.setAttribute(IGDBLaunchConfigurationConstants.ATTR_PORT, 167 NdkLaunchConstants.DEFAULT_GDB_PORT); 168 config.setAttribute(IGDBLaunchConfigurationConstants.ATTR_HOST, "localhost"); //$NON-NLS-1$ 169 config.setAttribute(ICDTLaunchConfigurationConstants.ATTR_DEBUGGER_STOP_AT_MAIN, false); 170 config.setAttribute(ICDTLaunchConfigurationConstants.ATTR_DEBUGGER_START_MODE, 171 IGDBLaunchConfigurationConstants.DEBUGGER_MODE_REMOTE_ATTACH); 172 config.setAttribute(ICDTLaunchConfigurationConstants.ATTR_PROGRAM_NAME, 173 NdkLaunchConstants.DEFAULT_PROGRAM); 174 175 config.setAttribute(ICDTLaunchConfigurationConstants.ATTR_DEBUGGER_START_MODE, 176 IGDBLaunchConfigurationConstants.DEBUGGER_MODE_REMOTE); 177 config.setAttribute(ICDTLaunchConfigurationConstants.ATTR_DEBUGGER_ID, 178 "gdbserver"); //$NON-NLS-1$ 179 180 List<String> solibPaths = new ArrayList<String>(2); 181 solibPaths.add(NdkLaunchConstants.DEFAULT_SOLIB_PATH); 182 config.setAttribute(NdkLaunchConstants.ATTR_NDK_SOLIB, solibPaths); 183 } 184 } 185