1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-06-05 16:56:04 +02:00

Bug 464636 - Modernize Run launch

Change-Id: I1c7a4cbbcd00f3967fe9cdbc1fc4b6e0b4d4d14f
Signed-off-by: Marc Khouzam <marc.khouzam@ericsson.com>
This commit is contained in:
Marc Khouzam 2015-04-15 09:12:51 -04:00 committed by Gerrit Code Review @ Eclipse.org
parent 0ad4b3660a
commit bd66f35865
6 changed files with 158 additions and 175 deletions

View file

@ -1,5 +1,5 @@
###############################################################################
# Copyright (c) 2006, 2012 Wind River Systems and others.
# Copyright (c) 2006, 2015 Wind River Systems and others.
# All rights reserved. This program and the accompanying materials
# are made available under the terms of the Eclipse Public License v1.0
# which accompanies this distribution, and is available at
@ -13,7 +13,7 @@
pluginName=GDB DSF Debugger Integration Core
providerName=Eclipse CDT
launchDelegate.localApplication.name=GDB (DSF) Create Process
launchDelegate.localApplication.name=GDB (DSF) Debug Process
launchDelegate.localApplication.description=Start new application under control of GDB debugger integrated using the Debugger Services Framework (DSF).
launchDelegate.remoteApplication.name=GDB (DSF) Manual Remote Debugging
launchDelegate.remoteApplication.description=Debug a new application that was manually started on a remote system under control of GDB debugger integrated using the Debugger Services Framework (DSF).

View file

@ -193,7 +193,7 @@
id="org.eclipse.cdt.cdi.launch.runApplicationLaunch.mainTab"
group="org.eclipse.cdt.launch.applicationRunLaunchTabGroup"
name="%MainLaunchTab.name"
class="org.eclipse.cdt.launch.ui.CMainTab">
class="org.eclipse.cdt.launch.ui.CMainTab2">
<associatedDelegate delegate="org.eclipse.cdt.cdi.launch.localCLaunch"/>
</tab>
<tab

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2010, 2012 Nokia and others.
* Copyright (c) 2010, 2015 Nokia and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@ -8,9 +8,12 @@
* Contributors:
* Ken Ryall (Nokia)
* James Blackburn (Broadcom Corp.)
* Marc Khouzam (Ericsson) - Modernize Run launch (bug 464636)
*******************************************************************************/
package org.eclipse.cdt.launch;
import java.io.File;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
@ -30,6 +33,7 @@ import org.eclipse.cdt.launch.internal.ui.BuildErrPrompter;
import org.eclipse.cdt.launch.internal.ui.LaunchMessages;
import org.eclipse.cdt.launch.internal.ui.LaunchUIPlugin;
import org.eclipse.core.resources.ICommand;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
@ -37,10 +41,12 @@ import org.eclipse.core.resources.IWorkspaceRunnable;
import org.eclipse.core.resources.IncrementalProjectBuilder;
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.IStatus;
import org.eclipse.core.runtime.MultiStatus;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.SubMonitor;
import org.eclipse.core.variables.VariablesPlugin;
@ -567,6 +573,75 @@ public abstract class AbstractCLaunchDelegate2 extends LaunchConfigurationDelega
return cproject;
}
/**
* Expands and returns the working directory attribute of the given launch
* configuration. Returns <code>null</code> if a working directory is not
* specified.
*
* @param configuration launch configuration
* @return an absolute path to a directory, or <code>null</code> if unspecified
* @throws CoreException if unable to retrieve the associated launch
* configuration attribute or if unable to resolve any variables
*
* @since 7.3
*/
protected IPath getWorkingDirectoryPath(ILaunchConfiguration config) throws CoreException {
String location = config.getAttribute(ICDTLaunchConfigurationConstants.ATTR_WORKING_DIRECTORY, (String)null);
if (location != null) {
String expandedLocation = VariablesPlugin.getDefault().getStringVariableManager().performStringSubstitution(location);;
if (!expandedLocation.isEmpty()) {
return new Path(expandedLocation);
}
}
return null;
}
/**
* Verifies the working directory specified by the given launch
* configuration exists, and returns that working directory, or
* <code>null</code> if none is specified.
*
* @param configuration
* launch configuration
* @return the working directory specified by the given launch
* configuration, or <code>null</code> if none
* @exception CoreException
* if unable to retrieve the attribute
* @since 7.3
*/
protected File verifyWorkingDirectory(ILaunchConfiguration configuration) throws CoreException {
IPath path = getWorkingDirectoryPath(configuration);
if (path == null) {
// default working dir is the project if this config has a project
ICProject cp = CDebugUtils.getCProject(configuration);
if (cp == null) {
return null;
}
IProject p = cp.getProject();
return p.getLocation().toFile();
}
if (path.isAbsolute()) {
File dir = new File(path.toOSString());
if (dir.isDirectory()) {
return dir;
}
} else {
IResource res = ResourcesPlugin.getWorkspace().getRoot().findMember(path);
if (res instanceof IContainer && res.exists()) {
return res.getLocation().toFile();
}
}
abort(LaunchMessages.AbstractCLaunchDelegate_Working_directory_does_not_exist,
new FileNotFoundException(
NLS.bind(LaunchMessages.AbstractCLaunchDelegate_WORKINGDIRECTORY_PATH_not_found,
path.toOSString())),
ICDTLaunchConfigurationConstants.ERR_WORKING_DIRECTORY_DOES_NOT_EXIST);
return null;
}
/**
* @return the ID of the plugin hosting the launch delegate. It's used to
* create {@link IStatus} objects.

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2004, 2010 QNX Software Systems and others.
* Copyright (c) 2004, 2015 QNX Software Systems and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@ -9,18 +9,17 @@
* QNX Software Systems - Initial API and implementation
* Anton Leherbauer (Wind River Systems) - bugs 205108, 212632, 224187
* Ken Ryall (Nokia) - bug 188116
* Marc Khouzam (Ericsson) - Modernize Run launch (bug 464636)
*******************************************************************************/
package org.eclipse.cdt.launch.internal;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.IBinaryParser.IBinaryObject;
import org.eclipse.cdt.core.IProcessInfo;
import org.eclipse.cdt.core.IProcessList;
import org.eclipse.cdt.core.IBinaryParser.IBinaryObject;
import org.eclipse.cdt.core.model.ICProject;
import org.eclipse.cdt.debug.core.CDIDebugModel;
import org.eclipse.cdt.debug.core.CDebugUtils;
@ -68,40 +67,16 @@ public class LocalCDILaunchDelegate extends AbstractCLaunchDelegate {
monitor = new NullProgressMonitor();
}
if (mode.equals(ILaunchManager.RUN_MODE)) {
runLocalApplication(config, launch, monitor);
// We plan on splitting the Run delegate from the Debug one.
// For now, to keep backwards-compatibility, we need to keep the same delegate (to keep its id)
// However, we can just call the new delegate class
new LocalRunLaunchDelegate().launch(config, mode, launch, monitor);
}
if (mode.equals(ILaunchManager.DEBUG_MODE)) {
launchDebugger(config, launch, monitor);
}
}
private void runLocalApplication(ILaunchConfiguration config, ILaunch launch, IProgressMonitor monitor) throws CoreException {
monitor.beginTask(LaunchMessages.LocalCDILaunchDelegate_0, 10);
if (monitor.isCanceled()) {
return;
}
monitor.worked(1);
try {
IPath exePath = CDebugUtils.verifyProgramPath(config);
File wd = getWorkingDirectory(config);
if (wd == null) {
wd = new File(System.getProperty("user.home", ".")); //$NON-NLS-1$ //$NON-NLS-2$
}
String arguments[] = getProgramArgumentsArray(config);
ArrayList command = new ArrayList(1 + arguments.length);
command.add(exePath.toOSString());
command.addAll(Arrays.asList(arguments));
String[] commandArray = (String[])command.toArray(new String[command.size()]);
boolean usePty = config.getAttribute(ICDTLaunchConfigurationConstants.ATTR_USE_TERMINAL, ICDTLaunchConfigurationConstants.USE_TERMINAL_DEFAULT);
monitor.worked(2);
Process process = exec(commandArray, getEnvironment(config), wd, usePty);
monitor.worked(6);
DebugPlugin.newProcess(launch, process, renderProcessLabel(commandArray[0]));
} finally {
monitor.done();
}
}
private void launchDebugger(ILaunchConfiguration config, ILaunch launch, IProgressMonitor monitor) throws CoreException {
monitor.beginTask(LaunchMessages.LocalCDILaunchDelegate_1, 10);
if (monitor.isCanceled()) {

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2005, 2010 QNX Software Systems and others.
* Copyright (c) 2005, 2015 QNX Software Systems and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@ -7,6 +7,7 @@
*
* Contributors:
* QNX Software Systems - initial API and implementation
* Marc Khouzam (Ericsson) - Modified to only handle Run mode and modernized (Bug 464636)
*******************************************************************************/
package org.eclipse.cdt.launch.internal;
@ -14,187 +15,118 @@ import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import org.eclipse.cdt.core.IBinaryParser.IBinaryObject;
import org.eclipse.cdt.core.model.ICProject;
import org.eclipse.cdt.debug.core.CDIDebugModel;
import org.eclipse.cdt.debug.core.CDebugUtils;
import org.eclipse.cdt.debug.core.ICDTLaunchConfigurationConstants;
import org.eclipse.cdt.debug.core.ICDebugConfiguration;
import org.eclipse.cdt.debug.core.cdi.CDIException;
import org.eclipse.cdt.debug.core.cdi.ICDISession;
import org.eclipse.cdt.debug.core.cdi.model.ICDIRuntimeOptions;
import org.eclipse.cdt.debug.core.cdi.model.ICDITarget;
import org.eclipse.cdt.launch.AbstractCLaunchDelegate;
import org.eclipse.cdt.launch.AbstractCLaunchDelegate2;
import org.eclipse.cdt.launch.internal.ui.LaunchMessages;
import org.eclipse.cdt.launch.internal.ui.LaunchUIPlugin;
import org.eclipse.cdt.utils.CommandLineUtil;
import org.eclipse.cdt.utils.pty.PTY;
import org.eclipse.cdt.utils.spawner.ProcessFactory;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.SubProgressMonitor;
import org.eclipse.core.variables.VariablesPlugin;
import org.eclipse.debug.core.DebugPlugin;
import org.eclipse.debug.core.ILaunch;
import org.eclipse.debug.core.ILaunchConfiguration;
import org.eclipse.debug.core.ILaunchManager;
import org.eclipse.debug.core.IStatusHandler;
import org.eclipse.debug.core.model.IProcess;
public class LocalRunLaunchDelegate extends AbstractCLaunchDelegate {
import com.ibm.icu.text.DateFormat;
/**
* The launch delegate for Run mode.
*/
public class LocalRunLaunchDelegate extends AbstractCLaunchDelegate2
{
public LocalRunLaunchDelegate() {
super(false);
}
@Override
public void launch(ILaunchConfiguration config, String mode, ILaunch launch, IProgressMonitor monitor) throws CoreException {
IBinaryObject exeFile = null;
if (monitor == null) {
public void launch( ILaunchConfiguration config, String mode, ILaunch launch, IProgressMonitor monitor ) throws CoreException {
// This delegate is only for Run mode
assert mode.equals(ILaunchManager.RUN_MODE);
if ( monitor == null ) {
monitor = new NullProgressMonitor();
}
monitor.beginTask(LaunchMessages.LocalRunLaunchDelegate_Launching_Local_C_Application, 10);
// check for cancellation
if ( mode.equals(ILaunchManager.RUN_MODE ) ) {
runLocalApplication( config, launch, monitor );
}
}
private void runLocalApplication(ILaunchConfiguration config, ILaunch launch, IProgressMonitor monitor) throws CoreException {
monitor.beginTask(LaunchMessages.LocalCDILaunchDelegate_0, 10);
if (monitor.isCanceled()) {
return;
}
monitor.worked(1);
try {
monitor.worked(1);
IPath exePath = CDebugUtils.verifyProgramPath(config);
ICProject project = CDebugUtils.verifyCProject(config);
if (exePath != null) {
exeFile = verifyBinary(project, exePath);
File wd = verifyWorkingDirectory(config);
if (wd == null) {
wd = new File(System.getProperty("user.home", ".")); //$NON-NLS-1$ //$NON-NLS-2$
}
String arguments[] = getProgramArgumentsArray(config);
// set the default source locator if required
setDefaultSourceLocator(launch, config);
if (mode.equals(ILaunchManager.DEBUG_MODE)) {
ICDebugConfiguration debugConfig = getDebugConfig(config);
ICDISession dsession = null;
String debugMode = config.getAttribute(ICDTLaunchConfigurationConstants.ATTR_DEBUGGER_START_MODE,
ICDTLaunchConfigurationConstants.DEBUGGER_MODE_RUN);
if (debugMode.equals(ICDTLaunchConfigurationConstants.DEBUGGER_MODE_RUN)) {
dsession = debugConfig.createDebugger().createDebuggerSession(launch, exeFile,
new SubProgressMonitor(monitor, 8));
try {
try {
ICDITarget[] dtargets = dsession.getTargets();
for (int i = 0; i < dtargets.length; ++i) {
ICDIRuntimeOptions opt = dtargets[i].getRuntimeOptions();
opt.setArguments(arguments);
File wd = getWorkingDirectory(config);
if (wd != null) {
opt.setWorkingDirectory(wd.getAbsolutePath());
}
opt.setEnvironment(getEnvironmentAsProperty(config));
}
} catch (CDIException e) {
abort(LaunchMessages.LocalRunLaunchDelegate_Failed_setting_runtime_option_though_debugger, e,
ICDTLaunchConfigurationConstants.ERR_INTERNAL_ERROR);
}
monitor.worked(1);
boolean stopInMain = config.getAttribute(
ICDTLaunchConfigurationConstants.ATTR_DEBUGGER_STOP_AT_MAIN, false);
String stopSymbol = null;
if (stopInMain) {
stopSymbol = launch.getLaunchConfiguration().getAttribute(
ICDTLaunchConfigurationConstants.ATTR_DEBUGGER_STOP_AT_MAIN_SYMBOL,
ICDTLaunchConfigurationConstants.DEBUGGER_STOP_AT_MAIN_SYMBOL_DEFAULT);
}
ICDITarget[] targets = dsession.getTargets();
for (int i = 0; i < targets.length; i++) {
Process process = targets[i].getProcess();
IProcess iprocess = null;
if (process != null) {
iprocess = DebugPlugin.newProcess(launch, process, renderProcessLabel(exePath.toOSString()), getDefaultProcessMap());
}
CDIDebugModel.newDebugTarget(launch, project.getProject(), targets[i], renderTargetLabel(debugConfig),
iprocess, exeFile, true, false, stopSymbol, true);
}
} catch (CoreException e) {
try {
dsession.terminate();
} catch (CDIException e1) {
// ignore
}
throw e;
}
}
} else {
File wd = getWorkingDirectory(config);
if (wd == null) {
wd = new File(System.getProperty("user.home", ".")); //$NON-NLS-1$ //$NON-NLS-2$
}
ArrayList<String> command = new ArrayList<String>(1 + arguments.length);
command.add(exePath.toOSString());
command.addAll(Arrays.asList(arguments));
String[] commandArray = command.toArray(new String[command.size()]);
boolean usePty = config.getAttribute(ICDTLaunchConfigurationConstants.ATTR_USE_TERMINAL,
ICDTLaunchConfigurationConstants.USE_TERMINAL_DEFAULT);
monitor.worked(5);
Process process = exec(commandArray, getEnvironment(config), wd, usePty);
monitor.worked(3);
DebugPlugin.newProcess(launch, process, renderProcessLabel(commandArray[0]));
String args = config.getAttribute(ICDTLaunchConfigurationConstants.ATTR_PROGRAM_ARGUMENTS, ""); //$NON-NLS-1$
if (args.length() != 0) {
args = VariablesPlugin.getDefault().getStringVariableManager().performStringSubstitution(args);
}
String[] arguments = CommandLineUtil.argumentsToArray(args);
ArrayList<String> command = new ArrayList<>(1 + arguments.length);
command.add(exePath.toOSString());
command.addAll(Arrays.asList(arguments));
monitor.worked(2);
String[] commandArray = command.toArray(new String[command.size()]);
String[] environment = DebugPlugin.getDefault().getLaunchManager().getEnvironment(config);
Process process = exec(commandArray, environment, wd);
monitor.worked(6);
String timestamp = DateFormat.getInstance().format(new Date(System.currentTimeMillis()));
String processLabel = String.format("%s (%s)", commandArray[0], timestamp); //$NON-NLS-1$
DebugPlugin.newProcess(launch, process, processLabel);
} finally {
monitor.done();
}
}
}
/**
* Performs a runtime exec on the given command line in the context of the
* specified working directory, and returns the resulting process. If the
* current runtime does not support the specification of a working
* directory, the status handler for error code
* <code>ERR_WORKING_DIRECTORY_NOT_SUPPORTED</code> is queried to see if
* the exec should be re-executed without specifying a working directory.
* specified working directory, and returns the resulting process.
*
* @param cmdLine
* the command line
* @param environ
* @param workingDirectory
* the working directory, or <code>null</code>
* @return the resulting process or <code>null</code> if the exec is
* cancelled
* @return the resulting process or <code>null</code> if the exec is cancelled
* @see Runtime
* @since 4.7
*/
protected Process exec(String[] cmdLine, String[] environ, File workingDirectory, boolean usePty) throws CoreException {
Process p = null;
protected Process exec(String[] cmdLine, String[] environ, File workingDirectory) throws CoreException {
try {
if (workingDirectory == null) {
p = ProcessFactory.getFactory().exec(cmdLine, environ);
if (PTY.isSupported()) {
return ProcessFactory.getFactory().exec(cmdLine, environ, workingDirectory, new PTY());
} else {
if (usePty && PTY.isSupported()) {
p = ProcessFactory.getFactory().exec(cmdLine, environ, workingDirectory, new PTY());
} else {
p = ProcessFactory.getFactory().exec(cmdLine, environ, workingDirectory);
}
return ProcessFactory.getFactory().exec(cmdLine, environ, workingDirectory);
}
} catch (IOException e) {
if (p != null) {
p.destroy();
}
abort(LaunchMessages.LocalRunLaunchDelegate_Error_starting_process, e,
ICDTLaunchConfigurationConstants.ERR_INTERNAL_ERROR);
} catch (NoSuchMethodError e) {
//attempting launches on 1.2.* - no ability to set working
// directory
IStatus status = new Status(IStatus.ERROR, LaunchUIPlugin.getUniqueIdentifier(),
ICDTLaunchConfigurationConstants.ERR_WORKING_DIRECTORY_NOT_SUPPORTED,
LaunchMessages.LocalRunLaunchDelegate_Does_not_support_working_dir,
e);
IStatusHandler handler = DebugPlugin.getDefault().getStatusHandler(status);
if (handler != null) {
Object result = handler.handleStatus(status, this);
if (result instanceof Boolean && ((Boolean) result).booleanValue()) {
p = exec(cmdLine, environ, null, usePty);
}
}
abort(LaunchMessages.LocalCDILaunchDelegate_8, e, ICDTLaunchConfigurationConstants.ERR_INTERNAL_ERROR);
}
return p;
return null;
}
@Override
public boolean preLaunchCheck(ILaunchConfiguration config, String mode, IProgressMonitor monitor) throws CoreException {
return super.preLaunchCheck(config, mode, monitor);
}
@Override

View file

@ -76,7 +76,8 @@ public class CMainTab2 extends CAbstractMainTab {
* <code>org.eclipse.debug.ui.launchConfigurationTabs</code>
* extension point.
*/
public static final String TAB_ID = "org.eclipse.cdt.launch.mainTab2"; //$NON-NLS-1$
// Keep the same id as the original Run launch main tab for backwards-compatibility
public static final String TAB_ID = "org.eclipse.cdt.cdi.launch.mainTab"; //$NON-NLS-1$
private static final String CORE_FILE = LaunchMessages.CMainTab2_CoreFile_type;
private static final String TRACE_FILE = LaunchMessages.CMainTab2_TraceFile_type;
@ -441,7 +442,7 @@ public class CMainTab2 extends CAbstractMainTab {
}
IPath exePath = new Path(programName);
if (exePath.isAbsolute()) {
// For absolute paths, we don't need a project, we can debug the binary directly
// For absolute paths, we don't need a project, we can debug or run the binary directly
// as long as it exists
File executable = exePath.toFile();
if (!executable.exists()) {