mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-04-23 22:52:11 +02:00
Bug 486509 - Add support for debugging local Qt apps.
We reuse GDBLaunch but need to override some settings that are normally in the launch configuration. These things are calculated at launch time. Note there is also an added dependency to the launch bar core to make GDBLaunch a targeted launch so we can set the target properly. At some point we'll move this launch target stuff lower down, maybe to the debug platform. Change-Id: Ibbf6b794a9ecf25b79d46093cc624ea69dc04641
This commit is contained in:
parent
99426ce65a
commit
192bfff688
13 changed files with 1615 additions and 1061 deletions
|
@ -18,6 +18,7 @@ import java.util.Map;
|
||||||
|
|
||||||
import org.eclipse.cdt.build.core.CBuildConfiguration;
|
import org.eclipse.cdt.build.core.CBuildConfiguration;
|
||||||
import org.eclipse.cdt.build.core.IBuildConfigurationManager;
|
import org.eclipse.cdt.build.core.IBuildConfigurationManager;
|
||||||
|
import org.eclipse.cdt.core.CProjectNature;
|
||||||
import org.eclipse.core.resources.IBuildConfiguration;
|
import org.eclipse.core.resources.IBuildConfiguration;
|
||||||
import org.eclipse.core.resources.IProject;
|
import org.eclipse.core.resources.IProject;
|
||||||
import org.eclipse.core.resources.IResource;
|
import org.eclipse.core.resources.IResource;
|
||||||
|
@ -67,6 +68,13 @@ public class CBuildConfigurationManager
|
||||||
if (event.getType() == IResourceChangeEvent.PRE_CLOSE || event.getType() == IResourceChangeEvent.PRE_DELETE) {
|
if (event.getType() == IResourceChangeEvent.PRE_CLOSE || event.getType() == IResourceChangeEvent.PRE_DELETE) {
|
||||||
if (event.getResource().getType() == IResource.PROJECT) {
|
if (event.getResource().getType() == IResource.PROJECT) {
|
||||||
IProject project = event.getResource().getProject();
|
IProject project = event.getResource().getProject();
|
||||||
|
try {
|
||||||
|
if (!project.hasNature(CProjectNature.C_NATURE_ID))
|
||||||
|
return;
|
||||||
|
} catch (CoreException e) {
|
||||||
|
Activator.log(e.getStatus());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Clean up the configMap
|
// Clean up the configMap
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -14,7 +14,8 @@ Require-Bundle: org.eclipse.core.runtime,
|
||||||
org.eclipse.core.variables,
|
org.eclipse.core.variables,
|
||||||
org.eclipse.cdt.launch;bundle-version="6.1.0",
|
org.eclipse.cdt.launch;bundle-version="6.1.0",
|
||||||
org.eclipse.cdt.gdb;bundle-version="7.0.0",
|
org.eclipse.cdt.gdb;bundle-version="7.0.0",
|
||||||
org.eclipse.core.resources
|
org.eclipse.core.resources,
|
||||||
|
org.eclipse.launchbar.core;bundle-version="2.0.0";visibility:=reexport
|
||||||
Bundle-ActivationPolicy: lazy
|
Bundle-ActivationPolicy: lazy
|
||||||
Bundle-RequiredExecutionEnvironment: JavaSE-1.7
|
Bundle-RequiredExecutionEnvironment: JavaSE-1.7
|
||||||
Export-Package: org.eclipse.cdt.dsf.gdb,
|
Export-Package: org.eclipse.cdt.dsf.gdb,
|
||||||
|
|
|
@ -13,12 +13,32 @@
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
package org.eclipse.cdt.dsf.gdb.launching;
|
package org.eclipse.cdt.dsf.gdb.launching;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.io.Reader;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Map.Entry;
|
||||||
|
import java.util.Properties;
|
||||||
import java.util.concurrent.Callable;
|
import java.util.concurrent.Callable;
|
||||||
import java.util.concurrent.ExecutionException;
|
import java.util.concurrent.ExecutionException;
|
||||||
import java.util.concurrent.RejectedExecutionException;
|
import java.util.concurrent.RejectedExecutionException;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.core.CCorePlugin;
|
||||||
|
import org.eclipse.cdt.core.cdtvariables.CdtVariableException;
|
||||||
|
import org.eclipse.cdt.core.cdtvariables.ICdtVariable;
|
||||||
|
import org.eclipse.cdt.core.envvar.IEnvironmentVariable;
|
||||||
|
import org.eclipse.cdt.core.model.CoreModel;
|
||||||
|
import org.eclipse.cdt.core.model.ICProject;
|
||||||
|
import org.eclipse.cdt.core.parser.util.StringUtil;
|
||||||
|
import org.eclipse.cdt.core.settings.model.ICConfigurationDescription;
|
||||||
|
import org.eclipse.cdt.core.settings.model.ICProjectDescription;
|
||||||
|
import org.eclipse.cdt.debug.core.ICDTLaunchConfigurationConstants;
|
||||||
import org.eclipse.cdt.debug.internal.core.CRequest;
|
import org.eclipse.cdt.debug.internal.core.CRequest;
|
||||||
import org.eclipse.cdt.dsf.concurrent.ConfinedToDsfExecutor;
|
import org.eclipse.cdt.dsf.concurrent.ConfinedToDsfExecutor;
|
||||||
import org.eclipse.cdt.dsf.concurrent.DefaultDsfExecutor;
|
import org.eclipse.cdt.dsf.concurrent.DefaultDsfExecutor;
|
||||||
|
@ -36,7 +56,9 @@ import org.eclipse.cdt.dsf.debug.internal.provisional.model.IMemoryBlockRetrieva
|
||||||
import org.eclipse.cdt.dsf.debug.model.DsfLaunch;
|
import org.eclipse.cdt.dsf.debug.model.DsfLaunch;
|
||||||
import org.eclipse.cdt.dsf.debug.service.IDsfDebugServicesFactory;
|
import org.eclipse.cdt.dsf.debug.service.IDsfDebugServicesFactory;
|
||||||
import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService.ICommandControlShutdownDMEvent;
|
import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService.ICommandControlShutdownDMEvent;
|
||||||
|
import org.eclipse.cdt.dsf.gdb.IGDBLaunchConfigurationConstants;
|
||||||
import org.eclipse.cdt.dsf.gdb.IGdbDebugConstants;
|
import org.eclipse.cdt.dsf.gdb.IGdbDebugConstants;
|
||||||
|
import org.eclipse.cdt.dsf.gdb.IGdbDebugPreferenceConstants;
|
||||||
import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin;
|
import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin;
|
||||||
import org.eclipse.cdt.dsf.gdb.internal.memory.GdbMemoryBlockRetrievalManager;
|
import org.eclipse.cdt.dsf.gdb.internal.memory.GdbMemoryBlockRetrievalManager;
|
||||||
import org.eclipse.cdt.dsf.gdb.service.command.IGDBControl;
|
import org.eclipse.cdt.dsf.gdb.service.command.IGDBControl;
|
||||||
|
@ -44,15 +66,28 @@ import org.eclipse.cdt.dsf.mi.service.command.AbstractCLIProcess;
|
||||||
import org.eclipse.cdt.dsf.service.DsfServiceEventHandler;
|
import org.eclipse.cdt.dsf.service.DsfServiceEventHandler;
|
||||||
import org.eclipse.cdt.dsf.service.DsfServicesTracker;
|
import org.eclipse.cdt.dsf.service.DsfServicesTracker;
|
||||||
import org.eclipse.cdt.dsf.service.DsfSession;
|
import org.eclipse.cdt.dsf.service.DsfSession;
|
||||||
|
import org.eclipse.cdt.utils.CommandLineUtil;
|
||||||
|
import org.eclipse.cdt.utils.spawner.ProcessFactory;
|
||||||
|
import org.eclipse.core.resources.IContainer;
|
||||||
|
import org.eclipse.core.resources.IProject;
|
||||||
|
import org.eclipse.core.resources.IResource;
|
||||||
|
import org.eclipse.core.resources.ResourcesPlugin;
|
||||||
import org.eclipse.core.runtime.CoreException;
|
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.IStatus;
|
||||||
import org.eclipse.core.runtime.MultiStatus;
|
import org.eclipse.core.runtime.MultiStatus;
|
||||||
|
import org.eclipse.core.runtime.Path;
|
||||||
import org.eclipse.core.runtime.Platform;
|
import org.eclipse.core.runtime.Platform;
|
||||||
import org.eclipse.core.runtime.Status;
|
import org.eclipse.core.runtime.Status;
|
||||||
|
import org.eclipse.core.runtime.jobs.Job;
|
||||||
|
import org.eclipse.core.variables.VariablesPlugin;
|
||||||
import org.eclipse.debug.core.DebugException;
|
import org.eclipse.debug.core.DebugException;
|
||||||
import org.eclipse.debug.core.DebugPlugin;
|
import org.eclipse.debug.core.DebugPlugin;
|
||||||
import org.eclipse.debug.core.ILaunch;
|
import org.eclipse.debug.core.ILaunch;
|
||||||
import org.eclipse.debug.core.ILaunchConfiguration;
|
import org.eclipse.debug.core.ILaunchConfiguration;
|
||||||
|
import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
|
||||||
|
import org.eclipse.debug.core.ILaunchManager;
|
||||||
import org.eclipse.debug.core.IStatusHandler;
|
import org.eclipse.debug.core.IStatusHandler;
|
||||||
import org.eclipse.debug.core.commands.IDebugCommandRequest;
|
import org.eclipse.debug.core.commands.IDebugCommandRequest;
|
||||||
import org.eclipse.debug.core.commands.IDisconnectHandler;
|
import org.eclipse.debug.core.commands.IDisconnectHandler;
|
||||||
|
@ -60,14 +95,14 @@ import org.eclipse.debug.core.commands.ITerminateHandler;
|
||||||
import org.eclipse.debug.core.model.IDisconnect;
|
import org.eclipse.debug.core.model.IDisconnect;
|
||||||
import org.eclipse.debug.core.model.ISourceLocator;
|
import org.eclipse.debug.core.model.ISourceLocator;
|
||||||
import org.eclipse.debug.core.model.ITerminate;
|
import org.eclipse.debug.core.model.ITerminate;
|
||||||
|
import org.eclipse.launchbar.core.target.ILaunchTarget;
|
||||||
|
import org.eclipse.launchbar.core.target.launch.ITargetedLaunch;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The only object in the model that implements the traditional interfaces.
|
* The only object in the model that implements the traditional interfaces.
|
||||||
*/
|
*/
|
||||||
@ThreadSafe
|
@ThreadSafe
|
||||||
public class GdbLaunch extends DsfLaunch
|
public class GdbLaunch extends DsfLaunch implements ITerminate, IDisconnect, ITracedLaunch, ITargetedLaunch {
|
||||||
implements ITerminate, IDisconnect, ITracedLaunch
|
|
||||||
{
|
|
||||||
private DefaultDsfExecutor fExecutor;
|
private DefaultDsfExecutor fExecutor;
|
||||||
private DsfSession fSession;
|
private DsfSession fSession;
|
||||||
private DsfServicesTracker fTracker;
|
private DsfServicesTracker fTracker;
|
||||||
|
@ -75,6 +110,7 @@ public class GdbLaunch extends DsfLaunch
|
||||||
private boolean fShutDown = false;
|
private boolean fShutDown = false;
|
||||||
private IMemoryBlockRetrievalManager fMemRetrievalManager;
|
private IMemoryBlockRetrievalManager fMemRetrievalManager;
|
||||||
private IDsfDebugServicesFactory fServiceFactory;
|
private IDsfDebugServicesFactory fServiceFactory;
|
||||||
|
private ILaunchTarget fLaunchTarget;
|
||||||
|
|
||||||
public GdbLaunch(ILaunchConfiguration launchConfiguration, String mode, ISourceLocator locator) {
|
public GdbLaunch(ILaunchConfiguration launchConfiguration, String mode, ISourceLocator locator) {
|
||||||
super(launchConfiguration, mode, locator);
|
super(launchConfiguration, mode, locator);
|
||||||
|
@ -87,17 +123,21 @@ public class GdbLaunch extends DsfLaunch
|
||||||
fSession = DsfSession.startSession(fExecutor, GdbLaunchDelegate.GDB_DEBUG_MODEL_ID);
|
fSession = DsfSession.startSession(fExecutor, GdbLaunchDelegate.GDB_DEBUG_MODEL_ID);
|
||||||
}
|
}
|
||||||
|
|
||||||
public DsfExecutor getDsfExecutor() { return fExecutor; }
|
public DsfExecutor getDsfExecutor() {
|
||||||
public IDsfDebugServicesFactory getServiceFactory() { return fServiceFactory; }
|
return fExecutor;
|
||||||
|
}
|
||||||
|
|
||||||
public void initialize()
|
public IDsfDebugServicesFactory getServiceFactory() {
|
||||||
{
|
return fServiceFactory;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void initialize() {
|
||||||
/*
|
/*
|
||||||
* Registering the launch as an adapter. This ensures that this launch
|
* Registering the launch as an adapter. This ensures that this launch
|
||||||
* will be associated with all DMContexts from this session.
|
* will be associated with all DMContexts from this session. We do this
|
||||||
* We do this here because we want to have access to the launch even
|
* here because we want to have access to the launch even if we run
|
||||||
* if we run headless, but when we run headless, GdbAdapterFactory is
|
* headless, but when we run headless, GdbAdapterFactory is not
|
||||||
* not initialized.
|
* initialized.
|
||||||
*/
|
*/
|
||||||
fSession.registerModelAdapter(ILaunch.class, this);
|
fSession.registerModelAdapter(ILaunch.class, this);
|
||||||
|
|
||||||
|
@ -116,44 +156,49 @@ public class GdbLaunch extends DsfLaunch
|
||||||
try {
|
try {
|
||||||
fExecutor.submit(initRunnable).get();
|
fExecutor.submit(initRunnable).get();
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, IDsfStatusConstants.INTERNAL_ERROR, "Error initializing launch", e); //$NON-NLS-1$
|
new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, IDsfStatusConstants.INTERNAL_ERROR,
|
||||||
|
"Error initializing launch", e); //$NON-NLS-1$
|
||||||
} catch (ExecutionException e) {
|
} catch (ExecutionException e) {
|
||||||
new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, IDsfStatusConstants.INTERNAL_ERROR, "Error initializing launch", e); //$NON-NLS-1$
|
new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, IDsfStatusConstants.INTERNAL_ERROR,
|
||||||
|
"Error initializing launch", e); //$NON-NLS-1$
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void initializeControl()
|
public void initializeControl() throws CoreException {
|
||||||
throws CoreException
|
|
||||||
{
|
|
||||||
// Create a memory retrieval manager and register it with the session
|
// Create a memory retrieval manager and register it with the session
|
||||||
// To maintain a mapping of memory contexts to the corresponding memory retrieval in this session
|
// To maintain a mapping of memory contexts to the corresponding memory
|
||||||
|
// retrieval in this session
|
||||||
try {
|
try {
|
||||||
fExecutor.submit(new Callable<Object>() {
|
fExecutor.submit(new Callable<Object>() {
|
||||||
@Override
|
@Override
|
||||||
public Object call() throws CoreException {
|
public Object call() throws CoreException {
|
||||||
fMemRetrievalManager = new GdbMemoryBlockRetrievalManager(GdbLaunchDelegate.GDB_DEBUG_MODEL_ID, getLaunchConfiguration(), fSession);
|
fMemRetrievalManager = new GdbMemoryBlockRetrievalManager(GdbLaunchDelegate.GDB_DEBUG_MODEL_ID,
|
||||||
|
getLaunchConfiguration(), fSession);
|
||||||
fSession.registerModelAdapter(IMemoryBlockRetrievalManager.class, fMemRetrievalManager);
|
fSession.registerModelAdapter(IMemoryBlockRetrievalManager.class, fMemRetrievalManager);
|
||||||
fSession.addServiceEventListener(fMemRetrievalManager, null);
|
fSession.addServiceEventListener(fMemRetrievalManager, null);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}).get();
|
}).get();
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
throw new CoreException(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, 0, "Interrupted while waiting for get process callable.", e)); //$NON-NLS-1$
|
throw new CoreException(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, 0,
|
||||||
|
"Interrupted while waiting for get process callable.", e)); //$NON-NLS-1$
|
||||||
} catch (ExecutionException e) {
|
} catch (ExecutionException e) {
|
||||||
throw (CoreException) e.getCause();
|
throw (CoreException) e.getCause();
|
||||||
} catch (RejectedExecutionException e) {
|
} catch (RejectedExecutionException e) {
|
||||||
throw new CoreException(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, 0, "Debugger shut down before launch was completed.", e)); //$NON-NLS-1$
|
throw new CoreException(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, 0,
|
||||||
|
"Debugger shut down before launch was completed.", e)); //$NON-NLS-1$
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public DsfSession getSession() { return fSession; }
|
public DsfSession getSession() {
|
||||||
|
return fSession;
|
||||||
|
}
|
||||||
|
|
||||||
@ThreadSafeAndProhibitedFromDsfExecutor("getDsfExecutor()")
|
@ThreadSafeAndProhibitedFromDsfExecutor("getDsfExecutor()")
|
||||||
public void addCLIProcess(String label) throws CoreException {
|
public void addCLIProcess(String label) throws CoreException {
|
||||||
try {
|
try {
|
||||||
// Add the CLI process object to the launch.
|
// Add the CLI process object to the launch.
|
||||||
AbstractCLIProcess cliProc =
|
AbstractCLIProcess cliProc = getDsfExecutor().submit(new Callable<AbstractCLIProcess>() {
|
||||||
getDsfExecutor().submit( new Callable<AbstractCLIProcess>() {
|
|
||||||
@Override
|
@Override
|
||||||
public AbstractCLIProcess call() throws CoreException {
|
public AbstractCLIProcess call() throws CoreException {
|
||||||
IGDBControl gdb = fTracker.getService(IGDBControl.class);
|
IGDBControl gdb = fTracker.getService(IGDBControl.class);
|
||||||
|
@ -173,11 +218,13 @@ public class GdbLaunch extends DsfLaunch
|
||||||
IGdbDebugConstants.GDB_PROCESS_CREATION_VALUE);
|
IGdbDebugConstants.GDB_PROCESS_CREATION_VALUE);
|
||||||
DebugPlugin.newProcess(this, cliProc, label, attributes);
|
DebugPlugin.newProcess(this, cliProc, label, attributes);
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
throw new CoreException(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, 0, "Interrupted while waiting for get process callable.", e)); //$NON-NLS-1$
|
throw new CoreException(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, 0,
|
||||||
|
"Interrupted while waiting for get process callable.", e)); //$NON-NLS-1$
|
||||||
} catch (ExecutionException e) {
|
} catch (ExecutionException e) {
|
||||||
throw (CoreException) e.getCause();
|
throw (CoreException) e.getCause();
|
||||||
} catch (RejectedExecutionException e) {
|
} catch (RejectedExecutionException e) {
|
||||||
throw new CoreException(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, 0, "Debugger shut down before launch was completed.", e)); //$NON-NLS-1$
|
throw new CoreException(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, 0,
|
||||||
|
"Debugger shut down before launch was completed.", e)); //$NON-NLS-1$
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -187,7 +234,8 @@ public class GdbLaunch extends DsfLaunch
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
// IServiceEventListener
|
// IServiceEventListener
|
||||||
@DsfServiceEventHandler public void eventDispatched(ICommandControlShutdownDMEvent event) {
|
@DsfServiceEventHandler
|
||||||
|
public void eventDispatched(ICommandControlShutdownDMEvent event) {
|
||||||
shutdownSession(new ImmediateRequestMonitor());
|
shutdownSession(new ImmediateRequestMonitor());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -229,7 +277,9 @@ public class GdbLaunch extends DsfLaunch
|
||||||
return fInitialized && super.canTerminate();
|
return fInitialized && super.canTerminate();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* (non-Javadoc)
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
*
|
||||||
* @see org.eclipse.debug.core.Launch#terminate()
|
* @see org.eclipse.debug.core.Launch#terminate()
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
|
@ -278,16 +328,18 @@ public class GdbLaunch extends DsfLaunch
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Terminates the gdb session, shuts down the services, the session and
|
* Terminates the gdb session, shuts down the services, the session and the
|
||||||
* the executor associated with this launch.
|
* executor associated with this launch.
|
||||||
* <p>
|
* <p>
|
||||||
* Note: The argument request monitor to this method should NOT use the
|
* Note: The argument request monitor to this method should NOT use the
|
||||||
* executor that belongs to this launch. By the time the shutdown is
|
* executor that belongs to this launch. By the time the shutdown is
|
||||||
* complete, this executor will not be dispatching anymore and the
|
* complete, this executor will not be dispatching anymore and the request
|
||||||
* request monitor will never be invoked. Instead callers should use
|
* monitor will never be invoked. Instead callers should use the
|
||||||
* the {@link ImmediateExecutor}.
|
* {@link ImmediateExecutor}.
|
||||||
* </p>
|
* </p>
|
||||||
* @param rm The request monitor invoked when the shutdown is complete.
|
*
|
||||||
|
* @param rm
|
||||||
|
* The request monitor invoked when the shutdown is complete.
|
||||||
*/
|
*/
|
||||||
@ConfinedToDsfExecutor("getSession().getExecutor()")
|
@ConfinedToDsfExecutor("getSession().getExecutor()")
|
||||||
public void shutdownSession(final RequestMonitor rm) {
|
public void shutdownSession(final RequestMonitor rm) {
|
||||||
|
@ -297,8 +349,7 @@ public class GdbLaunch extends DsfLaunch
|
||||||
}
|
}
|
||||||
fShutDown = true;
|
fShutDown = true;
|
||||||
|
|
||||||
final Sequence shutdownSeq = new ShutdownSequence(
|
final Sequence shutdownSeq = new ShutdownSequence(getDsfExecutor(), fSession.getId(),
|
||||||
getDsfExecutor(), fSession.getId(),
|
|
||||||
new RequestMonitor(fSession.getExecutor(), rm) {
|
new RequestMonitor(fSession.getExecutor(), rm) {
|
||||||
@Override
|
@Override
|
||||||
public void handleCompleted() {
|
public void handleCompleted() {
|
||||||
|
@ -309,19 +360,23 @@ public class GdbLaunch extends DsfLaunch
|
||||||
|
|
||||||
fSession.removeServiceEventListener(GdbLaunch.this);
|
fSession.removeServiceEventListener(GdbLaunch.this);
|
||||||
if (!isSuccess()) {
|
if (!isSuccess()) {
|
||||||
GdbPlugin.getDefault().getLog().log(new MultiStatus(
|
GdbPlugin.getDefault().getLog().log(new MultiStatus(GdbPlugin.PLUGIN_ID, -1,
|
||||||
GdbPlugin.PLUGIN_ID, -1, new IStatus[]{getStatus()}, "Session shutdown failed", null)); //$NON-NLS-1$
|
new IStatus[] { getStatus() }, "Session shutdown failed", null)); //$NON-NLS-1$
|
||||||
}
|
}
|
||||||
// Last order of business, shutdown the dispatch queue.
|
// Last order of business, shutdown the dispatch queue.
|
||||||
fTracker.dispose();
|
fTracker.dispose();
|
||||||
fTracker = null;
|
fTracker = null;
|
||||||
DsfSession.endSession(fSession);
|
DsfSession.endSession(fSession);
|
||||||
|
|
||||||
// 'fireTerminate()' removes this launch from the list of 'DebugEvent'
|
// 'fireTerminate()' removes this launch from the list
|
||||||
// listeners. The launch may not be terminated at this point: the inferior
|
// of 'DebugEvent'
|
||||||
// and gdb processes are monitored in separate threads. This will prevent
|
// listeners. The launch may not be terminated at this
|
||||||
|
// point: the inferior
|
||||||
|
// and gdb processes are monitored in separate threads.
|
||||||
|
// This will prevent
|
||||||
// updating of some of the Debug view actions.
|
// updating of some of the Debug view actions.
|
||||||
// 'DebugEvent.TERMINATE' will be fired when each of the corresponding processes
|
// 'DebugEvent.TERMINATE' will be fired when each of the
|
||||||
|
// corresponding processes
|
||||||
// exits and handled by 'handleDebugEvents()' method.
|
// exits and handled by 'handleDebugEvents()' method.
|
||||||
if (isTerminated()) {
|
if (isTerminated()) {
|
||||||
fireTerminate();
|
fireTerminate();
|
||||||
|
@ -332,8 +387,7 @@ public class GdbLaunch extends DsfLaunch
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
final Step[] steps = new Step[] {
|
final Step[] steps = new Step[] { new Step() {
|
||||||
new Step() {
|
|
||||||
@Override
|
@Override
|
||||||
public void execute(RequestMonitor rm) {
|
public void execute(RequestMonitor rm) {
|
||||||
IGDBControl control = fTracker.getService(IGDBControl.class);
|
IGDBControl control = fTracker.getService(IGDBControl.class);
|
||||||
|
@ -350,8 +404,7 @@ public class GdbLaunch extends DsfLaunch
|
||||||
public void execute(RequestMonitor rm) {
|
public void execute(RequestMonitor rm) {
|
||||||
fExecutor.execute(shutdownSeq);
|
fExecutor.execute(shutdownSeq);
|
||||||
}
|
}
|
||||||
}
|
} };
|
||||||
};
|
|
||||||
|
|
||||||
fExecutor.execute(new Sequence(fExecutor) {
|
fExecutor.execute(new Sequence(fExecutor) {
|
||||||
|
|
||||||
|
@ -383,4 +436,471 @@ public class GdbLaunch extends DsfLaunch
|
||||||
}
|
}
|
||||||
super.launchRemoved(launch);
|
super.launchRemoved(launch);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the path to gdb.
|
||||||
|
*
|
||||||
|
* @since 5.0
|
||||||
|
*/
|
||||||
|
public IPath getGDBPath() {
|
||||||
|
String defaultGdbCommand = Platform.getPreferencesService().getString(GdbPlugin.PLUGIN_ID,
|
||||||
|
IGdbDebugPreferenceConstants.PREF_DEFAULT_GDB_COMMAND,
|
||||||
|
IGDBLaunchConfigurationConstants.DEBUGGER_DEBUG_NAME_DEFAULT, null);
|
||||||
|
|
||||||
|
IPath retVal = new Path(defaultGdbCommand);
|
||||||
|
try {
|
||||||
|
String gdb = getAttribute(IGDBLaunchConfigurationConstants.ATTR_DEBUG_NAME);
|
||||||
|
if (gdb == null) {
|
||||||
|
gdb = getLaunchConfiguration().getAttribute(IGDBLaunchConfigurationConstants.ATTR_DEBUG_NAME,
|
||||||
|
defaultGdbCommand);
|
||||||
|
}
|
||||||
|
gdb = VariablesPlugin.getDefault().getStringVariableManager().performStringSubstitution(gdb, false);
|
||||||
|
retVal = new Path(gdb);
|
||||||
|
} catch (CoreException e) {
|
||||||
|
}
|
||||||
|
return retVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the path to gdb
|
||||||
|
*
|
||||||
|
* @param path
|
||||||
|
* the path to gdb
|
||||||
|
* @since 5.0
|
||||||
|
*/
|
||||||
|
public void setGDBPath(String path) {
|
||||||
|
setAttribute(IGDBLaunchConfigurationConstants.ATTR_DEBUG_NAME, path);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method actually launches 'gdb --version' to determine the version of
|
||||||
|
* the GDB that is being used. This method should ideally be called only
|
||||||
|
* once per session and the resulting version string stored for future uses.
|
||||||
|
*
|
||||||
|
* A timeout is scheduled which will kill the process if it takes too long.
|
||||||
|
*
|
||||||
|
* @since 5.0
|
||||||
|
*/
|
||||||
|
public String getGDBVersion() throws CoreException {
|
||||||
|
String cmd = getGDBPath().toOSString() + " --version"; //$NON-NLS-1$
|
||||||
|
|
||||||
|
// Parse cmd to properly handle spaces and such things (bug 458499)
|
||||||
|
String[] args = CommandLineUtil.argumentsToArray(cmd);
|
||||||
|
|
||||||
|
Process process = null;
|
||||||
|
Job timeoutJob = null;
|
||||||
|
try {
|
||||||
|
process = ProcessFactory.getFactory().exec(args, getLaunchEnvironment());
|
||||||
|
|
||||||
|
// Start a timeout job to make sure we don't get stuck waiting for
|
||||||
|
// an answer from a gdb that is hanging
|
||||||
|
// Bug 376203
|
||||||
|
final Process finalProc = process;
|
||||||
|
timeoutJob = new Job("GDB version timeout job") { //$NON-NLS-1$
|
||||||
|
{
|
||||||
|
setSystem(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected IStatus run(IProgressMonitor arg) {
|
||||||
|
// Took too long. Kill the gdb process and
|
||||||
|
// let things clean up.
|
||||||
|
finalProc.destroy();
|
||||||
|
return Status.OK_STATUS;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
timeoutJob.schedule(10000);
|
||||||
|
|
||||||
|
String streamOutput = readStream(process.getInputStream());
|
||||||
|
|
||||||
|
String gdbVersion = LaunchUtils.getGDBVersionFromText(streamOutput);
|
||||||
|
if (gdbVersion == null || gdbVersion.isEmpty()) {
|
||||||
|
Exception detailedException = null;
|
||||||
|
if (!streamOutput.isEmpty()) {
|
||||||
|
// We got some output but couldn't parse it. Make that
|
||||||
|
// output visible to the user in the error dialog.
|
||||||
|
detailedException = new Exception("Unexpected output format: \n\n" + streamOutput); //$NON-NLS-1$
|
||||||
|
} else {
|
||||||
|
// We got no output. Check if we got something on the error
|
||||||
|
// stream.
|
||||||
|
streamOutput = readStream(process.getErrorStream());
|
||||||
|
if (!streamOutput.isEmpty()) {
|
||||||
|
detailedException = new Exception(streamOutput);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new DebugException(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, DebugException.REQUEST_FAILED,
|
||||||
|
"Could not determine GDB version using command: " + StringUtil.join(args, " "), //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
|
detailedException));
|
||||||
|
}
|
||||||
|
return gdbVersion;
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new DebugException(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, DebugException.REQUEST_FAILED,
|
||||||
|
"Error with command: " + StringUtil.join(args, " "), e));//$NON-NLS-1$ //$NON-NLS-2$
|
||||||
|
} finally {
|
||||||
|
// If we get here we are obviously not stuck reading the stream so
|
||||||
|
// we can cancel the timeout job.
|
||||||
|
// Note that it may already have executed, but that is not a
|
||||||
|
// problem.
|
||||||
|
if (timeoutJob != null) {
|
||||||
|
timeoutJob.cancel();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (process != null) {
|
||||||
|
process.destroy();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read from the specified stream and return what was read.
|
||||||
|
*
|
||||||
|
* @param stream
|
||||||
|
* The input stream to be used to read the data. This method will
|
||||||
|
* close the stream.
|
||||||
|
* @return The data read from the stream
|
||||||
|
* @throws IOException
|
||||||
|
* If an IOException happens when reading the stream
|
||||||
|
*/
|
||||||
|
private static String readStream(InputStream stream) throws IOException {
|
||||||
|
StringBuilder cmdOutput = new StringBuilder(200);
|
||||||
|
try {
|
||||||
|
Reader r = new InputStreamReader(stream);
|
||||||
|
BufferedReader reader = new BufferedReader(r);
|
||||||
|
|
||||||
|
String line;
|
||||||
|
while ((line = reader.readLine()) != null) {
|
||||||
|
cmdOutput.append(line);
|
||||||
|
cmdOutput.append('\n');
|
||||||
|
}
|
||||||
|
return cmdOutput.toString();
|
||||||
|
} finally {
|
||||||
|
// Cleanup to avoid leaking pipes
|
||||||
|
// Bug 345164
|
||||||
|
if (stream != null) {
|
||||||
|
try {
|
||||||
|
stream.close();
|
||||||
|
} catch (IOException e) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the CDT environment from the CDT project's configuration referenced
|
||||||
|
* by the launch
|
||||||
|
*
|
||||||
|
* @since 5.0
|
||||||
|
*/
|
||||||
|
public String[] getLaunchEnvironment() throws CoreException {
|
||||||
|
// Get the project
|
||||||
|
String projectName = getLaunchConfiguration().getAttribute(ICDTLaunchConfigurationConstants.ATTR_PROJECT_NAME,
|
||||||
|
(String) null);
|
||||||
|
IProject project = null;
|
||||||
|
if (projectName == null) {
|
||||||
|
IResource[] resources = getLaunchConfiguration().getMappedResources();
|
||||||
|
if (resources != null && resources.length > 0 && resources[0] instanceof IProject) {
|
||||||
|
project = (IProject) resources[0];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
projectName = projectName.trim();
|
||||||
|
if (projectName.length() == 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
project = ResourcesPlugin.getWorkspace().getRoot().getProject(projectName);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (project == null || !project.isAccessible()) {
|
||||||
|
// No project
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
HashMap<String, String> envMap = new HashMap<String, String>();
|
||||||
|
ICProjectDescription projDesc = CoreModel.getDefault().getProjectDescription(project, false);
|
||||||
|
if (projDesc != null) {
|
||||||
|
String buildConfigID = getLaunchConfiguration()
|
||||||
|
.getAttribute(ICDTLaunchConfigurationConstants.ATTR_PROJECT_BUILD_CONFIG_ID, ""); //$NON-NLS-1$
|
||||||
|
ICConfigurationDescription cfg = null;
|
||||||
|
if (buildConfigID.length() != 0) {
|
||||||
|
cfg = projDesc.getConfigurationById(buildConfigID);
|
||||||
|
}
|
||||||
|
|
||||||
|
// if configuration is null fall-back to active
|
||||||
|
if (cfg == null) {
|
||||||
|
cfg = projDesc.getActiveConfiguration();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Environment variables and inherited vars
|
||||||
|
IEnvironmentVariable[] vars = CCorePlugin.getDefault().getBuildEnvironmentManager().getVariables(cfg, true);
|
||||||
|
for (IEnvironmentVariable var : vars) {
|
||||||
|
envMap.put(var.getName(), var.getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add variables from build info
|
||||||
|
ICdtVariable[] buildVars = CCorePlugin.getDefault().getCdtVariableManager().getVariables(cfg);
|
||||||
|
for (ICdtVariable var : buildVars) {
|
||||||
|
try {
|
||||||
|
// The project_classpath variable contributed by JDT is
|
||||||
|
// useless
|
||||||
|
// for running C/C++
|
||||||
|
// binaries, but it can be lethal if it has a very large
|
||||||
|
// value
|
||||||
|
// that exceeds shell
|
||||||
|
// limit. See
|
||||||
|
// http://bugs.eclipse.org/bugs/show_bug.cgi?id=408522
|
||||||
|
if (!"project_classpath".equals(var.getName())) {//$NON-NLS-1$
|
||||||
|
envMap.put(var.getName(), var.getStringValue());
|
||||||
|
}
|
||||||
|
} catch (CdtVariableException e) {
|
||||||
|
// Some Eclipse dynamic variables can't be resolved
|
||||||
|
// dynamically... we don't care.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Turn it into an envp format
|
||||||
|
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()]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the location of the gdbinit file.
|
||||||
|
*
|
||||||
|
* @return gdbinit file location
|
||||||
|
* @throws CoreException
|
||||||
|
* @since 5.0
|
||||||
|
*/
|
||||||
|
public String getGDBInitFile() throws CoreException {
|
||||||
|
String defaultGdbInit = Platform.getPreferencesService().getString(GdbPlugin.PLUGIN_ID,
|
||||||
|
IGdbDebugPreferenceConstants.PREF_DEFAULT_GDB_INIT,
|
||||||
|
IGDBLaunchConfigurationConstants.DEBUGGER_GDB_INIT_DEFAULT, null);
|
||||||
|
|
||||||
|
return getLaunchConfiguration().getAttribute(IGDBLaunchConfigurationConstants.ATTR_GDB_INIT, defaultGdbInit);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the working directory.
|
||||||
|
*
|
||||||
|
* @return the working directory
|
||||||
|
* @throws CoreException
|
||||||
|
* @since 5.0
|
||||||
|
*/
|
||||||
|
public IPath getGDBWorkingDirectory() throws CoreException {
|
||||||
|
// First try to use the user-specified working directory for the
|
||||||
|
// debugged program.
|
||||||
|
// This is fine only with local debug.
|
||||||
|
// For remote debug, the working dir of the debugged program will be
|
||||||
|
// on remote device
|
||||||
|
// and hence not applicable. In such case we may just use debugged
|
||||||
|
// program path on host
|
||||||
|
// as the working dir for GDB.
|
||||||
|
// However, we cannot find a standard/common way to distinguish
|
||||||
|
// remote debug from local
|
||||||
|
// debug. For instance, a local debug may also use gdbserver+gdb. So
|
||||||
|
// it's up to each
|
||||||
|
// debugger implementation to make the distinction.
|
||||||
|
//
|
||||||
|
IPath path = null;
|
||||||
|
String location = getLaunchConfiguration().getAttribute(ICDTLaunchConfigurationConstants.ATTR_WORKING_DIRECTORY,
|
||||||
|
(String) null);
|
||||||
|
|
||||||
|
if (location != null) {
|
||||||
|
String expandedLocation = VariablesPlugin.getDefault().getStringVariableManager()
|
||||||
|
.performStringSubstitution(location);
|
||||||
|
if (!expandedLocation.isEmpty()) {
|
||||||
|
path = new Path(expandedLocation);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (path != null) {
|
||||||
|
// Some validity check. Should have been done by UI code.
|
||||||
|
if (path.isAbsolute()) {
|
||||||
|
File dir = new File(path.toPortableString());
|
||||||
|
if (!dir.isDirectory())
|
||||||
|
path = null;
|
||||||
|
} else {
|
||||||
|
IResource res = ResourcesPlugin.getWorkspace().getRoot().findMember(path);
|
||||||
|
if (res instanceof IContainer && res.exists()) {
|
||||||
|
path = res.getLocation();
|
||||||
|
} else
|
||||||
|
// Relative but not found in workspace.
|
||||||
|
path = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (path == null) {
|
||||||
|
// default working dir is the project if this config has a
|
||||||
|
// project
|
||||||
|
ICProject cp = LaunchUtils.getCProject(getLaunchConfiguration());
|
||||||
|
if (cp != null) {
|
||||||
|
IProject p = cp.getProject();
|
||||||
|
path = p.getLocation();
|
||||||
|
} else {
|
||||||
|
// no meaningful value found. Just return null.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the program arguments
|
||||||
|
*
|
||||||
|
* @return program arguments
|
||||||
|
* @throws CoreException
|
||||||
|
* @since 5.0
|
||||||
|
*/
|
||||||
|
public String getProgramArguments() throws CoreException {
|
||||||
|
String programArguments = getLaunchConfiguration()
|
||||||
|
.getAttribute(ICDTLaunchConfigurationConstants.ATTR_PROGRAM_ARGUMENTS, (String) null);
|
||||||
|
|
||||||
|
if (programArguments != null) {
|
||||||
|
programArguments = VariablesPlugin.getDefault().getStringVariableManager()
|
||||||
|
.performStringSubstitution(programArguments);
|
||||||
|
}
|
||||||
|
|
||||||
|
return programArguments;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the program path
|
||||||
|
*
|
||||||
|
* @return the program path
|
||||||
|
* @since 5.0
|
||||||
|
*/
|
||||||
|
public String getProgramPath() throws CoreException {
|
||||||
|
String programPath = getAttribute(ICDTLaunchConfigurationConstants.ATTR_PROGRAM_NAME);
|
||||||
|
if (programPath == null) {
|
||||||
|
programPath = getLaunchConfiguration().getAttribute(ICDTLaunchConfigurationConstants.ATTR_PROGRAM_NAME,
|
||||||
|
(String) null);
|
||||||
|
}
|
||||||
|
return programPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the program path
|
||||||
|
*
|
||||||
|
* @param programPath
|
||||||
|
* the program path
|
||||||
|
* @throws CoreException
|
||||||
|
* @since 5.0
|
||||||
|
*/
|
||||||
|
public void setProgramPath(String programPath) throws CoreException {
|
||||||
|
setAttribute(ICDTLaunchConfigurationConstants.ATTR_PROGRAM_NAME, programPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return shared library paths
|
||||||
|
*
|
||||||
|
* @return shared library paths
|
||||||
|
* @throws CoreException
|
||||||
|
* @since 5.0
|
||||||
|
*/
|
||||||
|
public List<String> getSharedLibraryPaths() throws CoreException {
|
||||||
|
return getLaunchConfiguration().getAttribute(IGDBLaunchConfigurationConstants.ATTR_DEBUGGER_SOLIB_PATH,
|
||||||
|
new ArrayList<String>(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* return the environment
|
||||||
|
*
|
||||||
|
* @return the environment
|
||||||
|
* @throws CoreException
|
||||||
|
* @since 5.0
|
||||||
|
*/
|
||||||
|
public Properties getEnvironmentVariables() throws CoreException {
|
||||||
|
Properties envVariables = new Properties();
|
||||||
|
|
||||||
|
// if the attribute ATTR_APPEND_ENVIRONMENT_VARIABLES is set,
|
||||||
|
// the LaunchManager will return both the new variables and the
|
||||||
|
// existing ones.
|
||||||
|
// That would force us to delete all the variables in GDB, and then
|
||||||
|
// re-create then all
|
||||||
|
// that is not very efficient. So, let's fool the LaunchManager into
|
||||||
|
// returning just the
|
||||||
|
// list of new variables.
|
||||||
|
|
||||||
|
boolean append = getLaunchConfiguration().getAttribute(ILaunchManager.ATTR_APPEND_ENVIRONMENT_VARIABLES, true);
|
||||||
|
|
||||||
|
String[] properties;
|
||||||
|
if (append) {
|
||||||
|
ILaunchConfigurationWorkingCopy wc = getLaunchConfiguration().copy(""); //$NON-NLS-1$
|
||||||
|
// Don't save this change, it is just temporary, and in just a
|
||||||
|
// copy of our launchConfig.
|
||||||
|
wc.setAttribute(ILaunchManager.ATTR_APPEND_ENVIRONMENT_VARIABLES, false);
|
||||||
|
properties = DebugPlugin.getDefault().getLaunchManager().getEnvironment(wc);
|
||||||
|
} else {
|
||||||
|
// We're getting rid of the environment anyway, so this call
|
||||||
|
// will only yield the new variables.
|
||||||
|
properties = DebugPlugin.getDefault().getLaunchManager().getEnvironment(getLaunchConfiguration());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (properties == null) {
|
||||||
|
properties = new String[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
for (String property : properties) {
|
||||||
|
int idx = property.indexOf('=');
|
||||||
|
if (idx != -1) {
|
||||||
|
String key = property.substring(0, idx);
|
||||||
|
String value = property.substring(idx + 1);
|
||||||
|
envVariables.setProperty(key, value);
|
||||||
|
} else {
|
||||||
|
envVariables.setProperty(property, ""); //$NON-NLS-1$
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return envVariables;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get whether to clear the environment before applying the variables
|
||||||
|
*
|
||||||
|
* @return clear
|
||||||
|
* @throws CoreException
|
||||||
|
* @since 5.0
|
||||||
|
*/
|
||||||
|
public boolean getClearEnvironment() throws CoreException {
|
||||||
|
return !getLaunchConfiguration().getAttribute(ILaunchManager.ATTR_APPEND_ENVIRONMENT_VARIABLES, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get whether to update thread list on suspend
|
||||||
|
*
|
||||||
|
* @return whether
|
||||||
|
* @throws CoreException
|
||||||
|
* @since 5.0
|
||||||
|
*/
|
||||||
|
public boolean getUpdateThreadListOnSuspend() throws CoreException {
|
||||||
|
return getLaunchConfiguration().getAttribute(
|
||||||
|
IGDBLaunchConfigurationConstants.ATTR_DEBUGGER_UPDATE_THREADLIST_ON_SUSPEND,
|
||||||
|
IGDBLaunchConfigurationConstants.DEBUGGER_UPDATE_THREADLIST_ON_SUSPEND_DEFAULT);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the launch target
|
||||||
|
*
|
||||||
|
* @param launchTarget
|
||||||
|
* the launch target
|
||||||
|
* @since 5.0
|
||||||
|
*/
|
||||||
|
public void setLaunchTarget(ILaunchTarget launchTarget) {
|
||||||
|
this.fLaunchTarget = launchTarget;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the launch target
|
||||||
|
*
|
||||||
|
* @since 5.0
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public ILaunchTarget getLaunchTarget() {
|
||||||
|
return fLaunchTarget;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -296,11 +296,12 @@ public class GdbLaunchDelegate extends AbstractCLaunchDelegate2
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the GDB version.
|
* Returns the GDB version. Subclass can override for special need.
|
||||||
* Subclass can override for special need.
|
|
||||||
*
|
*
|
||||||
* @since 2.0
|
* @since 2.0
|
||||||
|
* @deprecated Replaced by GdbLaunch.getGDBVersion() which can also be overridden
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
protected String getGDBVersion(ILaunchConfiguration config) throws CoreException {
|
protected String getGDBVersion(ILaunchConfiguration config) throws CoreException {
|
||||||
return LaunchUtils.getGDBVersion(config);
|
return LaunchUtils.getGDBVersion(config);
|
||||||
}
|
}
|
||||||
|
|
|
@ -273,7 +273,10 @@ public class LaunchUtils {
|
||||||
* only once per session and the resulting version string stored for future uses.
|
* only once per session and the resulting version string stored for future uses.
|
||||||
*
|
*
|
||||||
* A timeout is scheduled which will kill the process if it takes too long.
|
* A timeout is scheduled which will kill the process if it takes too long.
|
||||||
|
*
|
||||||
|
* @deprecated Replaced with GdbLaunch.getLaunchEnvironment()
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public static String getGDBVersion(final ILaunchConfiguration configuration) throws CoreException {
|
public static String getGDBVersion(final ILaunchConfiguration configuration) throws CoreException {
|
||||||
String cmd = getGDBPath(configuration).toOSString() + " --version"; //$NON-NLS-1$
|
String cmd = getGDBPath(configuration).toOSString() + " --version"; //$NON-NLS-1$
|
||||||
|
|
||||||
|
@ -476,7 +479,9 @@ public class LaunchUtils {
|
||||||
* Gets the CDT environment from the CDT project's configuration referenced by the
|
* Gets the CDT environment from the CDT project's configuration referenced by the
|
||||||
* launch
|
* launch
|
||||||
* @since 3.0
|
* @since 3.0
|
||||||
|
* @deprecated Replaced with GdbLaunch.getLaunchEnvironment()
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public static String[] getLaunchEnvironment(ILaunchConfiguration config) throws CoreException {
|
public static String[] getLaunchEnvironment(ILaunchConfiguration config) throws CoreException {
|
||||||
// Get the project
|
// Get the project
|
||||||
String projectName = config.getAttribute(ICDTLaunchConfigurationConstants.ATTR_PROJECT_NAME, (String)null);
|
String projectName = config.getAttribute(ICDTLaunchConfigurationConstants.ATTR_PROJECT_NAME, (String)null);
|
||||||
|
|
|
@ -16,29 +16,24 @@
|
||||||
package org.eclipse.cdt.dsf.gdb.service;
|
package org.eclipse.cdt.dsf.gdb.service;
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
import java.io.BufferedReader;
|
||||||
import java.io.File;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.InputStreamReader;
|
import java.io.InputStreamReader;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Hashtable;
|
import java.util.Hashtable;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
import java.util.concurrent.ExecutionException;
|
import java.util.concurrent.ExecutionException;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
import org.eclipse.cdt.core.model.ICProject;
|
|
||||||
import org.eclipse.cdt.core.parser.util.StringUtil;
|
import org.eclipse.cdt.core.parser.util.StringUtil;
|
||||||
import org.eclipse.cdt.debug.core.ICDTLaunchConfigurationConstants;
|
|
||||||
import org.eclipse.cdt.dsf.concurrent.DsfRunnable;
|
import org.eclipse.cdt.dsf.concurrent.DsfRunnable;
|
||||||
import org.eclipse.cdt.dsf.concurrent.IDsfStatusConstants;
|
import org.eclipse.cdt.dsf.concurrent.IDsfStatusConstants;
|
||||||
import org.eclipse.cdt.dsf.concurrent.ImmediateRequestMonitor;
|
import org.eclipse.cdt.dsf.concurrent.ImmediateRequestMonitor;
|
||||||
import org.eclipse.cdt.dsf.concurrent.RequestMonitor;
|
import org.eclipse.cdt.dsf.concurrent.RequestMonitor;
|
||||||
import org.eclipse.cdt.dsf.concurrent.Sequence;
|
import org.eclipse.cdt.dsf.concurrent.Sequence;
|
||||||
import org.eclipse.cdt.dsf.gdb.IGDBLaunchConfigurationConstants;
|
|
||||||
import org.eclipse.cdt.dsf.gdb.IGdbDebugPreferenceConstants;
|
|
||||||
import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin;
|
import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin;
|
||||||
|
import org.eclipse.cdt.dsf.gdb.launching.GdbLaunch;
|
||||||
import org.eclipse.cdt.dsf.gdb.launching.LaunchUtils;
|
import org.eclipse.cdt.dsf.gdb.launching.LaunchUtils;
|
||||||
import org.eclipse.cdt.dsf.gdb.service.command.GDBControl.InitializationShutdownStep;
|
import org.eclipse.cdt.dsf.gdb.service.command.GDBControl.InitializationShutdownStep;
|
||||||
import org.eclipse.cdt.dsf.mi.service.IMIBackend;
|
import org.eclipse.cdt.dsf.mi.service.IMIBackend;
|
||||||
|
@ -50,30 +45,22 @@ import org.eclipse.cdt.dsf.service.DsfSession;
|
||||||
import org.eclipse.cdt.utils.CommandLineUtil;
|
import org.eclipse.cdt.utils.CommandLineUtil;
|
||||||
import org.eclipse.cdt.utils.spawner.ProcessFactory;
|
import org.eclipse.cdt.utils.spawner.ProcessFactory;
|
||||||
import org.eclipse.cdt.utils.spawner.Spawner;
|
import org.eclipse.cdt.utils.spawner.Spawner;
|
||||||
import org.eclipse.core.resources.IContainer;
|
|
||||||
import org.eclipse.core.resources.IProject;
|
|
||||||
import org.eclipse.core.resources.IResource;
|
|
||||||
import org.eclipse.core.resources.ResourcesPlugin;
|
|
||||||
import org.eclipse.core.runtime.CoreException;
|
import org.eclipse.core.runtime.CoreException;
|
||||||
import org.eclipse.core.runtime.IPath;
|
import org.eclipse.core.runtime.IPath;
|
||||||
import org.eclipse.core.runtime.IProgressMonitor;
|
import org.eclipse.core.runtime.IProgressMonitor;
|
||||||
import org.eclipse.core.runtime.IStatus;
|
import org.eclipse.core.runtime.IStatus;
|
||||||
import org.eclipse.core.runtime.Path;
|
import org.eclipse.core.runtime.Path;
|
||||||
import org.eclipse.core.runtime.Platform;
|
|
||||||
import org.eclipse.core.runtime.Status;
|
import org.eclipse.core.runtime.Status;
|
||||||
import org.eclipse.core.runtime.jobs.Job;
|
import org.eclipse.core.runtime.jobs.Job;
|
||||||
import org.eclipse.core.variables.VariablesPlugin;
|
|
||||||
import org.eclipse.debug.core.DebugException;
|
import org.eclipse.debug.core.DebugException;
|
||||||
import org.eclipse.debug.core.DebugPlugin;
|
import org.eclipse.debug.core.ILaunch;
|
||||||
import org.eclipse.debug.core.ILaunchConfiguration;
|
import org.eclipse.debug.core.ILaunchConfiguration;
|
||||||
import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
|
|
||||||
import org.eclipse.debug.core.ILaunchManager;
|
|
||||||
import org.osgi.framework.BundleContext;
|
import org.osgi.framework.BundleContext;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implementation of {@link IGDBBackend} for the common case where GDB is launched
|
* Implementation of {@link IGDBBackend} for the common case where GDB is
|
||||||
* in local file system on host PC where Eclipse runs. This also manages some GDB parameters
|
* launched in local file system on host PC where Eclipse runs. This also
|
||||||
* from a given launch configuration.<br>
|
* manages some GDB parameters from a given launch configuration.<br>
|
||||||
* <br>
|
* <br>
|
||||||
* You can subclass for you special needs.
|
* You can subclass for you special needs.
|
||||||
*
|
*
|
||||||
|
@ -86,18 +73,11 @@ public class GDBBackend extends AbstractDsfService implements IGDBBackend, IMIBa
|
||||||
/*
|
/*
|
||||||
* Parameters for launching GDB.
|
* Parameters for launching GDB.
|
||||||
*/
|
*/
|
||||||
private IPath fProgramPath;
|
|
||||||
private IPath fGDBWorkingDirectory;
|
|
||||||
private String fGDBInitFile;
|
|
||||||
private List<String> fSharedLibPaths;
|
|
||||||
private String fProgramArguments;
|
|
||||||
|
|
||||||
private Properties fEnvVariables;
|
|
||||||
private SessionType fSessionType;
|
private SessionType fSessionType;
|
||||||
private Boolean fAttach;
|
private Boolean fAttach;
|
||||||
private State fBackendState = State.NOT_INITIALIZED;
|
private State fBackendState = State.NOT_INITIALIZED;
|
||||||
|
|
||||||
/**
|
/*
|
||||||
* Unique ID of this service instance.
|
* Unique ID of this service instance.
|
||||||
*/
|
*/
|
||||||
private final String fBackendId;
|
private final String fBackendId;
|
||||||
|
@ -112,25 +92,15 @@ public class GDBBackend extends AbstractDsfService implements IGDBBackend, IMIBa
|
||||||
private int fGDBLaunchTimeout = 30;
|
private int fGDBLaunchTimeout = 30;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A Job that will set a failed status
|
* A Job that will set a failed status in the proper request monitor, if the
|
||||||
* in the proper request monitor, if the interrupt
|
* interrupt did not succeed after a certain time.
|
||||||
* did not succeed after a certain time.
|
|
||||||
*/
|
*/
|
||||||
private MonitorInterruptJob fInterruptFailedJob;
|
private MonitorInterruptJob fInterruptFailedJob;
|
||||||
|
|
||||||
|
|
||||||
public GDBBackend(DsfSession session, ILaunchConfiguration lc) {
|
public GDBBackend(DsfSession session, ILaunchConfiguration lc) {
|
||||||
super(session);
|
super(session);
|
||||||
|
this.fLaunchConfiguration = lc;
|
||||||
fBackendId = "gdb[" + Integer.toString(fgInstanceCounter++) + "]"; //$NON-NLS-1$//$NON-NLS-2$
|
fBackendId = "gdb[" + Integer.toString(fgInstanceCounter++) + "]"; //$NON-NLS-1$//$NON-NLS-2$
|
||||||
fLaunchConfiguration = lc;
|
|
||||||
|
|
||||||
try {
|
|
||||||
// Don't call verifyCProject, because the JUnit tests are not setting a project
|
|
||||||
ICProject cproject = LaunchUtils.getCProject(lc);
|
|
||||||
fProgramPath = LaunchUtils.verifyProgramPath(lc, cproject);
|
|
||||||
} catch (CoreException e) {
|
|
||||||
fProgramPath = new Path(""); //$NON-NLS-1$
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -152,11 +122,13 @@ public class GDBBackend extends AbstractDsfService implements IGDBBackend, IMIBa
|
||||||
final Sequence.Step[] initializeSteps = new Sequence.Step[] {
|
final Sequence.Step[] initializeSteps = new Sequence.Step[] {
|
||||||
new GDBProcessStep(InitializationShutdownStep.Direction.INITIALIZING),
|
new GDBProcessStep(InitializationShutdownStep.Direction.INITIALIZING),
|
||||||
new MonitorJobStep(InitializationShutdownStep.Direction.INITIALIZING),
|
new MonitorJobStep(InitializationShutdownStep.Direction.INITIALIZING),
|
||||||
new RegisterStep(InitializationShutdownStep.Direction.INITIALIZING),
|
new RegisterStep(InitializationShutdownStep.Direction.INITIALIZING), };
|
||||||
};
|
|
||||||
|
|
||||||
return new Sequence(getExecutor(), requestMonitor) {
|
return new Sequence(getExecutor(), requestMonitor) {
|
||||||
@Override public Step[] getSteps() { return initializeSteps; }
|
@Override
|
||||||
|
public Step[] getSteps() {
|
||||||
|
return initializeSteps;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -175,23 +147,28 @@ public class GDBBackend extends AbstractDsfService implements IGDBBackend, IMIBa
|
||||||
final Sequence.Step[] shutdownSteps = new Sequence.Step[] {
|
final Sequence.Step[] shutdownSteps = new Sequence.Step[] {
|
||||||
new RegisterStep(InitializationShutdownStep.Direction.SHUTTING_DOWN),
|
new RegisterStep(InitializationShutdownStep.Direction.SHUTTING_DOWN),
|
||||||
new MonitorJobStep(InitializationShutdownStep.Direction.SHUTTING_DOWN),
|
new MonitorJobStep(InitializationShutdownStep.Direction.SHUTTING_DOWN),
|
||||||
new GDBProcessStep(InitializationShutdownStep.Direction.SHUTTING_DOWN),
|
new GDBProcessStep(InitializationShutdownStep.Direction.SHUTTING_DOWN), };
|
||||||
};
|
|
||||||
|
|
||||||
return new Sequence(getExecutor(), requestMonitor) {
|
return new Sequence(getExecutor(), requestMonitor) {
|
||||||
@Override public Step[] getSteps() { return shutdownSteps; }
|
@Override
|
||||||
|
public Step[] getSteps() {
|
||||||
|
return shutdownSteps;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private GdbLaunch getGDBLaunch() {
|
||||||
|
return (GdbLaunch) getSession().getModelAdapter(ILaunch.class);
|
||||||
|
}
|
||||||
|
|
||||||
/** @since 4.0 */
|
/** @since 4.0 */
|
||||||
protected IPath getGDBPath() {
|
protected IPath getGDBPath() {
|
||||||
return LaunchUtils.getGDBPath(fLaunchConfiguration);
|
return getGDBLaunch().getGDBPath();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Options for GDB process.
|
* Options for GDB process. Allow subclass to override.
|
||||||
* Allow subclass to override.
|
*
|
||||||
* @deprecated Use {@link #getGDBCommandLineArray()} instead
|
* @deprecated Use {@link #getGDBCommandLineArray()} instead
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
|
@ -201,9 +178,9 @@ public class GDBBackend extends AbstractDsfService implements IGDBBackend, IMIBa
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Options for GDB process.
|
* Options for GDB process. Returns the GDB command and its arguments as an
|
||||||
* Returns the GDB command and its arguments as an array.
|
* array. Allow subclass to override.
|
||||||
* Allow subclass to override.
|
*
|
||||||
* @since 4.6
|
* @since 4.6
|
||||||
*/
|
*/
|
||||||
protected String[] getGDBCommandLineArray() {
|
protected String[] getGDBCommandLineArray() {
|
||||||
|
@ -211,8 +188,7 @@ public class GDBBackend extends AbstractDsfService implements IGDBBackend, IMIBa
|
||||||
// All configuration should be done in the final launch sequence
|
// All configuration should be done in the final launch sequence
|
||||||
// to allow for more flexibility.
|
// to allow for more flexibility.
|
||||||
|
|
||||||
String cmd = getGDBPath().toOSString() +
|
String cmd = getGDBPath().toOSString() + " --interpreter" + //$NON-NLS-1$
|
||||||
" --interpreter" + //$NON-NLS-1$
|
|
||||||
// We currently work with MI version 2. Don't use just 'mi' because it
|
// We currently work with MI version 2. Don't use just 'mi' because it
|
||||||
// points to the latest MI version, while we want mi2 specifically.
|
// points to the latest MI version, while we want mi2 specifically.
|
||||||
" mi2" + //$NON-NLS-1$
|
" mi2" + //$NON-NLS-1$
|
||||||
|
@ -226,188 +202,79 @@ public class GDBBackend extends AbstractDsfService implements IGDBBackend, IMIBa
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getGDBInitFile() throws CoreException {
|
public String getGDBInitFile() throws CoreException {
|
||||||
if (fGDBInitFile == null) {
|
return getGDBLaunch().getGDBInitFile();
|
||||||
String defaultGdbInit = Platform.getPreferencesService().getString(GdbPlugin.PLUGIN_ID,
|
|
||||||
IGdbDebugPreferenceConstants.PREF_DEFAULT_GDB_INIT,
|
|
||||||
IGDBLaunchConfigurationConstants.DEBUGGER_GDB_INIT_DEFAULT, null);
|
|
||||||
|
|
||||||
fGDBInitFile = fLaunchConfiguration.getAttribute(IGDBLaunchConfigurationConstants.ATTR_GDB_INIT, defaultGdbInit);
|
|
||||||
}
|
|
||||||
|
|
||||||
return fGDBInitFile;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public IPath getGDBWorkingDirectory() throws CoreException {
|
public IPath getGDBWorkingDirectory() throws CoreException {
|
||||||
if (fGDBWorkingDirectory == null) {
|
return getGDBLaunch().getGDBWorkingDirectory();
|
||||||
|
|
||||||
// First try to use the user-specified working directory for the debugged program.
|
|
||||||
// This is fine only with local debug.
|
|
||||||
// For remote debug, the working dir of the debugged program will be on remote device
|
|
||||||
// and hence not applicable. In such case we may just use debugged program path on host
|
|
||||||
// as the working dir for GDB.
|
|
||||||
// However, we cannot find a standard/common way to distinguish remote debug from local
|
|
||||||
// debug. For instance, a local debug may also use gdbserver+gdb. So it's up to each
|
|
||||||
// debugger implementation to make the distinction.
|
|
||||||
//
|
|
||||||
IPath path = null;
|
|
||||||
String location = fLaunchConfiguration.getAttribute(ICDTLaunchConfigurationConstants.ATTR_WORKING_DIRECTORY, (String)null);
|
|
||||||
|
|
||||||
if (location != null) {
|
|
||||||
String expandedLocation = VariablesPlugin.getDefault().getStringVariableManager().performStringSubstitution(location);
|
|
||||||
if (!expandedLocation.isEmpty()) {
|
|
||||||
path = new Path(expandedLocation);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (path != null) {
|
|
||||||
// Some validity check. Should have been done by UI code.
|
|
||||||
if (path.isAbsolute()) {
|
|
||||||
File dir = new File(path.toPortableString());
|
|
||||||
if (! dir.isDirectory())
|
|
||||||
path = null;
|
|
||||||
} else {
|
|
||||||
IResource res = ResourcesPlugin.getWorkspace().getRoot().findMember(path);
|
|
||||||
if (res instanceof IContainer && res.exists()) {
|
|
||||||
path = res.getLocation();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
// Relative but not found in workspace.
|
|
||||||
path = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (path == null) {
|
|
||||||
// default working dir is the project if this config has a project
|
|
||||||
ICProject cp = LaunchUtils.getCProject(fLaunchConfiguration);
|
|
||||||
if (cp != null) {
|
|
||||||
IProject p = cp.getProject();
|
|
||||||
path = p.getLocation();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// no meaningful value found. Just return null.
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fGDBWorkingDirectory = path;
|
|
||||||
}
|
|
||||||
|
|
||||||
return fGDBWorkingDirectory;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getProgramArguments() throws CoreException {
|
public String getProgramArguments() throws CoreException {
|
||||||
if (fProgramArguments == null) {
|
return getGDBLaunch().getProgramArguments();
|
||||||
fProgramArguments = fLaunchConfiguration.getAttribute(
|
|
||||||
ICDTLaunchConfigurationConstants.ATTR_PROGRAM_ARGUMENTS,
|
|
||||||
(String)null);
|
|
||||||
|
|
||||||
if (fProgramArguments != null) {
|
|
||||||
fProgramArguments = VariablesPlugin.getDefault().getStringVariableManager().performStringSubstitution(fProgramArguments);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return fProgramArguments;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public IPath getProgramPath() {
|
public IPath getProgramPath() {
|
||||||
return fProgramPath;
|
try {
|
||||||
|
return new Path(getGDBLaunch().getProgramPath());
|
||||||
|
} catch (CoreException e) {
|
||||||
|
return new Path(""); //$NON-NLS-1$
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<String> getSharedLibraryPaths() throws CoreException {
|
public List<String> getSharedLibraryPaths() throws CoreException {
|
||||||
if (fSharedLibPaths == null) {
|
return getGDBLaunch().getSharedLibraryPaths();
|
||||||
fSharedLibPaths = fLaunchConfiguration.getAttribute(IGDBLaunchConfigurationConstants.ATTR_DEBUGGER_SOLIB_PATH,
|
|
||||||
new ArrayList<String>(0));
|
|
||||||
}
|
|
||||||
|
|
||||||
return fSharedLibPaths;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @since 3.0 */
|
/** @since 3.0 */
|
||||||
@Override
|
@Override
|
||||||
public Properties getEnvironmentVariables() throws CoreException {
|
public Properties getEnvironmentVariables() throws CoreException {
|
||||||
if (fEnvVariables == null) {
|
return getGDBLaunch().getEnvironmentVariables();
|
||||||
fEnvVariables = new Properties();
|
|
||||||
|
|
||||||
// if the attribute ATTR_APPEND_ENVIRONMENT_VARIABLES is set,
|
|
||||||
// the LaunchManager will return both the new variables and the existing ones.
|
|
||||||
// That would force us to delete all the variables in GDB, and then re-create then all
|
|
||||||
// that is not very efficient. So, let's fool the LaunchManager into returning just the
|
|
||||||
// list of new variables.
|
|
||||||
|
|
||||||
boolean append = fLaunchConfiguration.getAttribute(ILaunchManager.ATTR_APPEND_ENVIRONMENT_VARIABLES, true);
|
|
||||||
|
|
||||||
String[] properties;
|
|
||||||
if (append) {
|
|
||||||
ILaunchConfigurationWorkingCopy wc = fLaunchConfiguration.copy(""); //$NON-NLS-1$
|
|
||||||
// Don't save this change, it is just temporary, and in just a copy of our launchConfig.
|
|
||||||
wc.setAttribute(ILaunchManager.ATTR_APPEND_ENVIRONMENT_VARIABLES, false);
|
|
||||||
properties = DebugPlugin.getDefault().getLaunchManager().getEnvironment(wc);
|
|
||||||
} else {
|
|
||||||
// We're getting rid of the environment anyway, so this call will only yield the new variables.
|
|
||||||
properties = DebugPlugin.getDefault().getLaunchManager().getEnvironment(fLaunchConfiguration);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (properties == null) {
|
|
||||||
properties = new String[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
for (String property : properties) {
|
|
||||||
int idx = property.indexOf('=');
|
|
||||||
if (idx != -1) {
|
|
||||||
String key = property.substring(0, idx);
|
|
||||||
String value = property.substring(idx + 1);
|
|
||||||
fEnvVariables.setProperty(key, value);
|
|
||||||
} else {
|
|
||||||
fEnvVariables.setProperty(property, ""); //$NON-NLS-1$
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return fEnvVariables;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @since 3.0 */
|
/** @since 3.0 */
|
||||||
@Override
|
@Override
|
||||||
public boolean getClearEnvironment() throws CoreException {
|
public boolean getClearEnvironment() throws CoreException {
|
||||||
return !fLaunchConfiguration.getAttribute(ILaunchManager.ATTR_APPEND_ENVIRONMENT_VARIABLES, true);
|
return getGDBLaunch().getClearEnvironment();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @since 3.0 */
|
/** @since 3.0 */
|
||||||
@Override
|
@Override
|
||||||
public boolean getUpdateThreadListOnSuspend() throws CoreException {
|
public boolean getUpdateThreadListOnSuspend() throws CoreException {
|
||||||
return fLaunchConfiguration
|
return getGDBLaunch().getUpdateThreadListOnSuspend();
|
||||||
.getAttribute(
|
|
||||||
IGDBLaunchConfigurationConstants.ATTR_DEBUGGER_UPDATE_THREADLIST_ON_SUSPEND,
|
|
||||||
IGDBLaunchConfigurationConstants.DEBUGGER_UPDATE_THREADLIST_ON_SUSPEND_DEFAULT);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private Process launchGDBProcess() throws CoreException {
|
private Process launchGDBProcess() throws CoreException {
|
||||||
// Keep calling deprecated getGDBCommandLine() in case it was overridden
|
// Keep calling deprecated getGDBCommandLine() in case it was overridden
|
||||||
String command = getGDBCommandLine();
|
String command = getGDBCommandLine();
|
||||||
// Keep calling deprecated launchGDBProcess(String) in case it was overridden
|
// Keep calling deprecated launchGDBProcess(String) in case it was
|
||||||
|
// overridden
|
||||||
return launchGDBProcess(command);
|
return launchGDBProcess(command);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Launch GDB process.
|
* Launch GDB process. Allow subclass to override.
|
||||||
* Allow subclass to override.
|
*
|
||||||
* @deprecated Use {@link #launchGDBProcess(String[])} instead
|
* @deprecated Use {@link #launchGDBProcess(String[])} instead
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
protected Process launchGDBProcess(String commandLine) throws CoreException {
|
protected Process launchGDBProcess(String commandLine) throws CoreException {
|
||||||
// Backwards-compatibility check
|
// Backwards-compatibility check
|
||||||
// If the commandLine parameter is not the same as the command line array we provide
|
// If the commandLine parameter is not the same as the command line
|
||||||
// it implies that the commandLine was modified by an extender and should be used as
|
// array we provide
|
||||||
// is. If it is the same, we can use the command line array instead using the more robust
|
// it implies that the commandLine was modified by an extender and
|
||||||
|
// should be used as
|
||||||
|
// is. If it is the same, we can use the command line array instead
|
||||||
|
// using the more robust
|
||||||
// non-deprecated call to launchGDBProcess.
|
// non-deprecated call to launchGDBProcess.
|
||||||
String unmodifiedCmdLine = StringUtil.join(getGDBCommandLineArray(), " ").trim(); //$NON-NLS-1$
|
String unmodifiedCmdLine = StringUtil.join(getGDBCommandLineArray(), " ").trim(); //$NON-NLS-1$
|
||||||
if (unmodifiedCmdLine.equals(commandLine.trim()) == false) {
|
if (unmodifiedCmdLine.equals(commandLine.trim()) == false) {
|
||||||
Process proc = null;
|
Process proc = null;
|
||||||
try {
|
try {
|
||||||
proc = ProcessFactory.getFactory().exec(commandLine, LaunchUtils.getLaunchEnvironment(fLaunchConfiguration));
|
proc = ProcessFactory.getFactory().exec(commandLine, getGDBLaunch().getLaunchEnvironment());
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
String message = "Error while launching command " + commandLine; //$NON-NLS-1$
|
String message = "Error while launching command " + commandLine; //$NON-NLS-1$
|
||||||
throw new CoreException(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, -1, message, e));
|
throw new CoreException(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, -1, message, e));
|
||||||
|
@ -420,14 +287,15 @@ public class GDBBackend extends AbstractDsfService implements IGDBBackend, IMIBa
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Launch GDB process with command and arguments.
|
* Launch GDB process with command and arguments. Allow subclass to
|
||||||
* Allow subclass to override.
|
* override.
|
||||||
|
*
|
||||||
* @since 4.6
|
* @since 4.6
|
||||||
*/
|
*/
|
||||||
protected Process launchGDBProcess(String[] commandLine) throws CoreException {
|
protected Process launchGDBProcess(String[] commandLine) throws CoreException {
|
||||||
Process proc = null;
|
Process proc = null;
|
||||||
try {
|
try {
|
||||||
proc = ProcessFactory.getFactory().exec(commandLine, LaunchUtils.getLaunchEnvironment(fLaunchConfiguration));
|
proc = ProcessFactory.getFactory().exec(commandLine, getGDBLaunch().getLaunchEnvironment());
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
String message = "Error while launching command: " + StringUtil.join(commandLine, " "); //$NON-NLS-1$ //$NON-NLS-2$
|
String message = "Error while launching command: " + StringUtil.join(commandLine, " "); //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
throw new CoreException(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, -1, message, e));
|
throw new CoreException(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, -1, message, e));
|
||||||
|
@ -473,8 +341,7 @@ public class GDBBackend extends AbstractDsfService implements IGDBBackend, IMIBa
|
||||||
// See https://bugs.eclipse.org/bugs/show_bug.cgi?id=304096#c54
|
// See https://bugs.eclipse.org/bugs/show_bug.cgi?id=304096#c54
|
||||||
if (getSessionType() == SessionType.REMOTE) {
|
if (getSessionType() == SessionType.REMOTE) {
|
||||||
gdbSpawner.interrupt();
|
gdbSpawner.interrupt();
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
gdbSpawner.interruptCTRLC();
|
gdbSpawner.interruptCTRLC();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -495,13 +362,13 @@ public class GDBBackend extends AbstractDsfService implements IGDBBackend, IMIBa
|
||||||
// See https://bugs.eclipse.org/bugs/show_bug.cgi?id=304096#c54
|
// See https://bugs.eclipse.org/bugs/show_bug.cgi?id=304096#c54
|
||||||
if (getSessionType() == SessionType.REMOTE) {
|
if (getSessionType() == SessionType.REMOTE) {
|
||||||
gdbSpawner.interrupt();
|
gdbSpawner.interrupt();
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
gdbSpawner.interruptCTRLC();
|
gdbSpawner.interruptCTRLC();
|
||||||
}
|
}
|
||||||
fInterruptFailedJob = new MonitorInterruptJob(timeout, rm);
|
fInterruptFailedJob = new MonitorInterruptJob(timeout, rm);
|
||||||
} else {
|
} else {
|
||||||
rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, IDsfStatusConstants.NOT_SUPPORTED, "Cannot interrupt.", null)); //$NON-NLS-1$
|
rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, IDsfStatusConstants.NOT_SUPPORTED,
|
||||||
|
"Cannot interrupt.", null)); //$NON-NLS-1$
|
||||||
rm.done();
|
rm.done();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -516,7 +383,8 @@ public class GDBBackend extends AbstractDsfService implements IGDBBackend, IMIBa
|
||||||
gdbSpawner.raise((int) pid, gdbSpawner.INT);
|
gdbSpawner.raise((int) pid, gdbSpawner.INT);
|
||||||
fInterruptFailedJob = new MonitorInterruptJob(timeout, rm);
|
fInterruptFailedJob = new MonitorInterruptJob(timeout, rm);
|
||||||
} else {
|
} else {
|
||||||
rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, IDsfStatusConstants.NOT_SUPPORTED, "Cannot interrupt.", null)); //$NON-NLS-1$
|
rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, IDsfStatusConstants.NOT_SUPPORTED,
|
||||||
|
"Cannot interrupt.", null)); //$NON-NLS-1$
|
||||||
rm.done();
|
rm.done();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -565,7 +433,9 @@ public class GDBBackend extends AbstractDsfService implements IGDBBackend, IMIBa
|
||||||
}
|
}
|
||||||
|
|
||||||
protected class GDBProcessStep extends InitializationShutdownStep {
|
protected class GDBProcessStep extends InitializationShutdownStep {
|
||||||
GDBProcessStep(Direction direction) { super(direction); }
|
GDBProcessStep(Direction direction) {
|
||||||
|
super(direction);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void initialize(final RequestMonitor requestMonitor) {
|
public void initialize(final RequestMonitor requestMonitor) {
|
||||||
|
@ -579,7 +449,9 @@ public class GDBBackend extends AbstractDsfService implements IGDBBackend, IMIBa
|
||||||
}
|
}
|
||||||
|
|
||||||
protected class MonitorJobStep extends InitializationShutdownStep {
|
protected class MonitorJobStep extends InitializationShutdownStep {
|
||||||
MonitorJobStep(Direction direction) { super(direction); }
|
MonitorJobStep(Direction direction) {
|
||||||
|
super(direction);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void initialize(final RequestMonitor requestMonitor) {
|
public void initialize(final RequestMonitor requestMonitor) {
|
||||||
|
@ -593,7 +465,10 @@ public class GDBBackend extends AbstractDsfService implements IGDBBackend, IMIBa
|
||||||
}
|
}
|
||||||
|
|
||||||
protected class RegisterStep extends InitializationShutdownStep {
|
protected class RegisterStep extends InitializationShutdownStep {
|
||||||
RegisterStep(Direction direction) { super(direction); }
|
RegisterStep(Direction direction) {
|
||||||
|
super(direction);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void initialize(RequestMonitor requestMonitor) {
|
public void initialize(RequestMonitor requestMonitor) {
|
||||||
doRegisterStep(requestMonitor);
|
doRegisterStep(requestMonitor);
|
||||||
|
@ -634,7 +509,8 @@ public class GDBBackend extends AbstractDsfService implements IGDBBackend, IMIBa
|
||||||
@Override
|
@Override
|
||||||
protected IStatus run(IProgressMonitor monitor) {
|
protected IStatus run(IProgressMonitor monitor) {
|
||||||
if (gdbLaunchRequestMonitor.isCanceled()) {
|
if (gdbLaunchRequestMonitor.isCanceled()) {
|
||||||
gdbLaunchRequestMonitor.setStatus(new Status(IStatus.CANCEL, GdbPlugin.PLUGIN_ID, -1, "Canceled starting GDB", null)); //$NON-NLS-1$
|
gdbLaunchRequestMonitor.setStatus(
|
||||||
|
new Status(IStatus.CANCEL, GdbPlugin.PLUGIN_ID, -1, "Canceled starting GDB", null)); //$NON-NLS-1$
|
||||||
gdbLaunchRequestMonitor.done();
|
gdbLaunchRequestMonitor.done();
|
||||||
return Status.OK_STATUS;
|
return Status.OK_STATUS;
|
||||||
}
|
}
|
||||||
|
@ -642,15 +518,18 @@ public class GDBBackend extends AbstractDsfService implements IGDBBackend, IMIBa
|
||||||
try {
|
try {
|
||||||
fProcess = launchGDBProcess();
|
fProcess = launchGDBProcess();
|
||||||
// Need to do this on the executor for thread-safety
|
// Need to do this on the executor for thread-safety
|
||||||
getExecutor().submit(
|
getExecutor().submit(new DsfRunnable() {
|
||||||
new DsfRunnable() {
|
|
||||||
@Override
|
@Override
|
||||||
public void run() { fBackendState = State.STARTED; }
|
public void run() {
|
||||||
|
fBackendState = State.STARTED;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
// Don't send the backendStarted event yet. We wait until we have registered this service
|
// Don't send the backendStarted event yet. We wait
|
||||||
|
// until we have registered this service
|
||||||
// so that other services can have access to it.
|
// so that other services can have access to it.
|
||||||
} catch (CoreException e) {
|
} catch (CoreException e) {
|
||||||
gdbLaunchRequestMonitor.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, -1, e.getMessage(), e));
|
gdbLaunchRequestMonitor
|
||||||
|
.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, -1, e.getMessage(), e));
|
||||||
gdbLaunchRequestMonitor.done();
|
gdbLaunchRequestMonitor.done();
|
||||||
return Status.OK_STATUS;
|
return Status.OK_STATUS;
|
||||||
}
|
}
|
||||||
|
@ -677,17 +556,18 @@ public class GDBBackend extends AbstractDsfService implements IGDBBackend, IMIBa
|
||||||
if (errorInfo == null) {
|
if (errorInfo == null) {
|
||||||
errorInfo = "GDB prompt not read"; //$NON-NLS-1$
|
errorInfo = "GDB prompt not read"; //$NON-NLS-1$
|
||||||
}
|
}
|
||||||
gdbLaunchRequestMonitor.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, -1, errorInfo, null));
|
gdbLaunchRequestMonitor
|
||||||
|
.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, -1, errorInfo, null));
|
||||||
}
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
success = false;
|
success = false;
|
||||||
gdbLaunchRequestMonitor.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, -1, "Error reading GDB output", e)); //$NON-NLS-1$
|
gdbLaunchRequestMonitor.setStatus(
|
||||||
|
new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, -1, "Error reading GDB output", e)); //$NON-NLS-1$
|
||||||
}
|
}
|
||||||
|
|
||||||
// In the case of failure, close the MI streams so
|
// In the case of failure, close the MI streams so
|
||||||
// they are not leaked.
|
// they are not leaked.
|
||||||
if (!success)
|
if (!success) {
|
||||||
{
|
|
||||||
if (inputReader != null) {
|
if (inputReader != null) {
|
||||||
try {
|
try {
|
||||||
inputReader.close();
|
inputReader.close();
|
||||||
|
@ -711,18 +591,20 @@ public class GDBBackend extends AbstractDsfService implements IGDBBackend, IMIBa
|
||||||
getExecutor().schedule(new Runnable() {
|
getExecutor().schedule(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
// Only process the event if we have not finished yet (hit the breakpoint).
|
// Only process the event if we have not finished yet (hit
|
||||||
|
// the breakpoint).
|
||||||
if (!fGDBLaunchMonitor.fLaunched) {
|
if (!fGDBLaunchMonitor.fLaunched) {
|
||||||
fGDBLaunchMonitor.fTimedOut = true;
|
fGDBLaunchMonitor.fTimedOut = true;
|
||||||
Thread jobThread = startGdbJob.getThread();
|
Thread jobThread = startGdbJob.getThread();
|
||||||
if (jobThread != null) {
|
if (jobThread != null) {
|
||||||
jobThread.interrupt();
|
jobThread.interrupt();
|
||||||
}
|
}
|
||||||
requestMonitor.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, DebugException.TARGET_REQUEST_FAILED, "Timed out trying to launch GDB.", null)); //$NON-NLS-1$
|
requestMonitor.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID,
|
||||||
|
DebugException.TARGET_REQUEST_FAILED, "Timed out trying to launch GDB.", null)); //$NON-NLS-1$
|
||||||
requestMonitor.done();
|
requestMonitor.done();
|
||||||
}
|
}
|
||||||
}},
|
}
|
||||||
fGDBLaunchTimeout, TimeUnit.SECONDS);
|
}, fGDBLaunchTimeout, TimeUnit.SECONDS);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @since 5.0 */
|
/** @since 5.0 */
|
||||||
|
@ -745,16 +627,15 @@ public class GDBBackend extends AbstractDsfService implements IGDBBackend, IMIBa
|
||||||
// Need to do this on the executor for thread-safety
|
// Need to do this on the executor for thread-safety
|
||||||
// And we should wait for it to complete since we then
|
// And we should wait for it to complete since we then
|
||||||
// check if the killing of GDB worked.
|
// check if the killing of GDB worked.
|
||||||
getExecutor().submit(
|
getExecutor().submit(new DsfRunnable() {
|
||||||
new DsfRunnable() {
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
destroy();
|
destroy();
|
||||||
|
|
||||||
if (fMonitorJob.fMonitorExited) {
|
if (fMonitorJob.fMonitorExited) {
|
||||||
// Now that we have destroyed the process,
|
// Now that we have destroyed the process, and
|
||||||
// and that the monitoring thread was killed,
|
// that the monitoring thread was killed, we
|
||||||
// we need to set our state and send the event
|
// need to set our state and send the event
|
||||||
fBackendState = State.TERMINATED;
|
fBackendState = State.TERMINATED;
|
||||||
getSession().dispatchEvent(
|
getSession().dispatchEvent(
|
||||||
new BackendStateChangedEvent(getSession().getId(), getId(), State.TERMINATED),
|
new BackendStateChangedEvent(getSession().getId(), getId(), State.TERMINATED),
|
||||||
|
@ -769,8 +650,10 @@ public class GDBBackend extends AbstractDsfService implements IGDBBackend, IMIBa
|
||||||
int attempts = 0;
|
int attempts = 0;
|
||||||
while (attempts < 10) {
|
while (attempts < 10) {
|
||||||
try {
|
try {
|
||||||
// Don't know if we really need the exit value... but what the heck.
|
// Don't know if we really need the exit value...
|
||||||
fGDBExitValue = fProcess.exitValue(); // throws exception if process not exited
|
// but what the heck.
|
||||||
|
// throws exception if process not exited
|
||||||
|
fGDBExitValue = fProcess.exitValue();
|
||||||
|
|
||||||
requestMonitor.done();
|
requestMonitor.done();
|
||||||
return Status.OK_STATUS;
|
return Status.OK_STATUS;
|
||||||
|
@ -782,8 +665,8 @@ public class GDBBackend extends AbstractDsfService implements IGDBBackend, IMIBa
|
||||||
}
|
}
|
||||||
attempts++;
|
attempts++;
|
||||||
}
|
}
|
||||||
requestMonitor.setStatus(new Status(
|
requestMonitor.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID,
|
||||||
IStatus.ERROR, GdbPlugin.PLUGIN_ID, IDsfStatusConstants.REQUEST_FAILED, "GDB terminate failed", null)); //$NON-NLS-1$
|
IDsfStatusConstants.REQUEST_FAILED, "GDB terminate failed", null)); //$NON-NLS-1$
|
||||||
requestMonitor.done();
|
requestMonitor.done();
|
||||||
return Status.OK_STATUS;
|
return Status.OK_STATUS;
|
||||||
}
|
}
|
||||||
|
@ -792,9 +675,7 @@ public class GDBBackend extends AbstractDsfService implements IGDBBackend, IMIBa
|
||||||
|
|
||||||
/** @since 5.0 */
|
/** @since 5.0 */
|
||||||
protected void doMonitorJobStep(final RequestMonitor requestMonitor) {
|
protected void doMonitorJobStep(final RequestMonitor requestMonitor) {
|
||||||
fMonitorJob = new MonitorJob(
|
fMonitorJob = new MonitorJob(fProcess, new DsfRunnable() {
|
||||||
fProcess,
|
|
||||||
new DsfRunnable() {
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
requestMonitor.done();
|
requestMonitor.done();
|
||||||
|
@ -813,24 +694,21 @@ public class GDBBackend extends AbstractDsfService implements IGDBBackend, IMIBa
|
||||||
|
|
||||||
/** @since 5.0 */
|
/** @since 5.0 */
|
||||||
protected void doRegisterStep(RequestMonitor requestMonitor) {
|
protected void doRegisterStep(RequestMonitor requestMonitor) {
|
||||||
register(new String[]{ IMIBackend.class.getName(),
|
register(new String[] { IMIBackend.class.getName(), IMIBackend2.class.getName(), IGDBBackend.class.getName() },
|
||||||
IMIBackend2.class.getName(),
|
|
||||||
IGDBBackend.class.getName() },
|
|
||||||
new Hashtable<String, String>());
|
new Hashtable<String, String>());
|
||||||
|
|
||||||
getSession().addServiceEventListener(GDBBackend.this, null);
|
getSession().addServiceEventListener(GDBBackend.this, null);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This event is not consumed by any one at present, instead it's
|
* This event is not consumed by any one at present, instead it's the
|
||||||
* the GDBControlInitializedDMEvent that's used to indicate that GDB
|
* GDBControlInitializedDMEvent that's used to indicate that GDB back
|
||||||
* back end is ready for MI commands. But we still fire the event as
|
* end is ready for MI commands. But we still fire the event as it does
|
||||||
* it does no harm and may be needed sometime.... 09/29/2008
|
* no harm and may be needed sometime.... 09/29/2008
|
||||||
*
|
*
|
||||||
* We send the event in the register step because that is when
|
* We send the event in the register step because that is when other
|
||||||
* other services have access to it.
|
* services have access to it.
|
||||||
*/
|
*/
|
||||||
getSession().dispatchEvent(
|
getSession().dispatchEvent(new BackendStateChangedEvent(getSession().getId(), getId(), State.STARTED),
|
||||||
new BackendStateChangedEvent(getSession().getId(), getId(), State.STARTED),
|
|
||||||
getProperties());
|
getProperties());
|
||||||
|
|
||||||
requestMonitor.done();
|
requestMonitor.done();
|
||||||
|
@ -844,8 +722,8 @@ public class GDBBackend extends AbstractDsfService implements IGDBBackend, IMIBa
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Monitors a system process, waiting for it to terminate, and
|
* Monitors a system process, waiting for it to terminate, and then notifies
|
||||||
* then notifies the associated runtime process.
|
* the associated runtime process.
|
||||||
*/
|
*/
|
||||||
private class MonitorJob extends Job {
|
private class MonitorJob extends Job {
|
||||||
boolean fMonitorExited = false;
|
boolean fMonitorExited = false;
|
||||||
|
@ -861,8 +739,7 @@ public class GDBBackend extends AbstractDsfService implements IGDBBackend, IMIBa
|
||||||
fGDBExitValue = fMonProcess.exitValue();
|
fGDBExitValue = fMonProcess.exitValue();
|
||||||
|
|
||||||
// Need to do this on the executor for thread-safety
|
// Need to do this on the executor for thread-safety
|
||||||
getExecutor().submit(
|
getExecutor().submit(new DsfRunnable() {
|
||||||
new DsfRunnable() {
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
destroy();
|
destroy();
|
||||||
|
@ -899,19 +776,17 @@ public class GDBBackend extends AbstractDsfService implements IGDBBackend, IMIBa
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Stores the request monitor that must be dealt with for
|
* Stores the request monitor that must be dealt with for the result of the
|
||||||
* the result of the interrupt operation. If the interrupt
|
* interrupt operation. If the interrupt successfully suspends the backend,
|
||||||
* successfully suspends the backend, the request monitor can
|
* the request monitor can be retrieved and completed successfully, and then
|
||||||
* be retrieved and completed successfully, and then this job
|
* this job should be canceled. If this job is not canceled before the time
|
||||||
* should be canceled. If this job is not canceled before
|
* is up, it will imply the interrupt did not successfully suspend the
|
||||||
* the time is up, it will imply the interrupt did not
|
* backend, and the current job will indicate this in the request monitor.
|
||||||
* successfully suspend the backend, and the current job will
|
|
||||||
* indicate this in the request monitor.
|
|
||||||
*
|
*
|
||||||
* The specified timeout is used to indicate how many milliseconds
|
* The specified timeout is used to indicate how many milliseconds this job
|
||||||
* this job should wait for. INTERRUPT_TIMEOUT_DEFAULT indicates
|
* should wait for. INTERRUPT_TIMEOUT_DEFAULT indicates to use the default
|
||||||
* to use the default of 5 seconds. The default is also use if the
|
* of 5 seconds. The default is also use if the timeout value is 0 or
|
||||||
* timeout value is 0 or negative.
|
* negative.
|
||||||
*
|
*
|
||||||
* @since 3.0
|
* @since 3.0
|
||||||
*/
|
*/
|
||||||
|
@ -936,19 +811,22 @@ public class GDBBackend extends AbstractDsfService implements IGDBBackend, IMIBa
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected IStatus run(IProgressMonitor monitor) {
|
protected IStatus run(IProgressMonitor monitor) {
|
||||||
getExecutor().submit(
|
getExecutor().submit(new DsfRunnable() {
|
||||||
new DsfRunnable() {
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
fInterruptFailedJob = null;
|
fInterruptFailedJob = null;
|
||||||
fRequestMonitor.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, IDsfStatusConstants.REQUEST_FAILED, "Interrupt failed.", null)); //$NON-NLS-1$
|
fRequestMonitor.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID,
|
||||||
|
IDsfStatusConstants.REQUEST_FAILED, "Interrupt failed.", null)); //$NON-NLS-1$
|
||||||
fRequestMonitor.done();
|
fRequestMonitor.done();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return Status.OK_STATUS;
|
return Status.OK_STATUS;
|
||||||
}
|
}
|
||||||
|
|
||||||
public RequestMonitor getRequestMonitor() { return fRequestMonitor; }
|
public RequestMonitor getRequestMonitor() {
|
||||||
|
return fRequestMonitor;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -18,7 +18,9 @@ Require-Bundle: org.eclipse.core.runtime,
|
||||||
org.eclipse.cdt.debug.core,
|
org.eclipse.cdt.debug.core,
|
||||||
org.freemarker;bundle-version="2.3.22",
|
org.freemarker;bundle-version="2.3.22",
|
||||||
org.eclipse.cdt.build.core;bundle-version="1.0.0",
|
org.eclipse.cdt.build.core;bundle-version="1.0.0",
|
||||||
org.eclipse.cdt.build.gcc.core;bundle-version="1.0.0"
|
org.eclipse.cdt.build.gcc.core;bundle-version="1.0.0",
|
||||||
|
org.eclipse.cdt.dsf.gdb;bundle-version="5.0.0",
|
||||||
|
org.eclipse.cdt.dsf;bundle-version="2.6.0"
|
||||||
Bundle-RequiredExecutionEnvironment: JavaSE-1.8
|
Bundle-RequiredExecutionEnvironment: JavaSE-1.8
|
||||||
Bundle-ActivationPolicy: lazy
|
Bundle-ActivationPolicy: lazy
|
||||||
Bundle-Localization: plugin
|
Bundle-Localization: plugin
|
||||||
|
|
|
@ -165,16 +165,6 @@
|
||||||
class="org.eclipse.cdt.internal.qt.core.build.QtScannerInfoProvider">
|
class="org.eclipse.cdt.internal.qt.core.build.QtScannerInfoProvider">
|
||||||
</provider>
|
</provider>
|
||||||
</extension>
|
</extension>
|
||||||
<extension
|
|
||||||
point="org.eclipse.debug.core.launchConfigurationTypes">
|
|
||||||
<launchConfigurationType
|
|
||||||
delegate="org.eclipse.cdt.internal.qt.core.launch.QtLocalRunLaunchConfigDelegate"
|
|
||||||
id="org.eclipse.cdt.qt.core.launchConfigurationType"
|
|
||||||
modes="run"
|
|
||||||
name="Qt Local Application"
|
|
||||||
public="true">
|
|
||||||
</launchConfigurationType>
|
|
||||||
</extension>
|
|
||||||
<extension
|
<extension
|
||||||
point="org.eclipse.core.runtime.adapters">
|
point="org.eclipse.core.runtime.adapters">
|
||||||
<factory
|
<factory
|
||||||
|
@ -192,4 +182,31 @@
|
||||||
targetTypeId="org.eclipse.launchbar.core.launchTargetType.local">
|
targetTypeId="org.eclipse.launchbar.core.launchTargetType.local">
|
||||||
</mapper>
|
</mapper>
|
||||||
</extension>
|
</extension>
|
||||||
|
<extension
|
||||||
|
point="org.eclipse.debug.core.launchConfigurationTypes">
|
||||||
|
<launchConfigurationType
|
||||||
|
id="org.eclipse.cdt.qt.core.launchConfigurationType"
|
||||||
|
name="Qt Local Application"
|
||||||
|
public="true">
|
||||||
|
</launchConfigurationType>
|
||||||
|
</extension>
|
||||||
|
<extension
|
||||||
|
point="org.eclipse.debug.core.launchDelegates">
|
||||||
|
<launchDelegate
|
||||||
|
delegate="org.eclipse.cdt.internal.qt.core.launch.QtLocalRunLaunchConfigDelegate"
|
||||||
|
id="org.eclipse.cdt.qt.core.launchDelegate.run.local"
|
||||||
|
modes="run"
|
||||||
|
name="Qt Local Run launcher"
|
||||||
|
type="org.eclipse.cdt.qt.core.launchConfigurationType">
|
||||||
|
</launchDelegate>
|
||||||
|
<launchDelegate
|
||||||
|
delegate="org.eclipse.cdt.internal.qt.core.launch.QtLocalDebugLaunchConfigDelegate"
|
||||||
|
id="org.eclipse.cdt.qt.core.launchDelegate.debug.local"
|
||||||
|
modes="debug"
|
||||||
|
name="Qt Local Debug launcher"
|
||||||
|
sourceLocatorId="org.eclipse.cdt.debug.core.sourceLocator"
|
||||||
|
sourcePathComputerId="org.eclipse.cdt.debug.core.sourcePathComputer"
|
||||||
|
type="org.eclipse.cdt.qt.core.launchConfigurationType">
|
||||||
|
</launchDelegate>
|
||||||
|
</extension>
|
||||||
</plugin>
|
</plugin>
|
||||||
|
|
|
@ -124,7 +124,7 @@ public class QtBuildConfigurationFactory implements IAdapterFactory {
|
||||||
for (IBuildConfiguration config : project.getBuildConfigs()) {
|
for (IBuildConfiguration config : project.getBuildConfigs()) {
|
||||||
configNames.add(config.getName());
|
configNames.add(config.getName());
|
||||||
}
|
}
|
||||||
String baseName = qtInstall.getSpec() + ":" + launchMode; //$NON-NLS-1$
|
String baseName = qtInstall.getSpec() + "." + launchMode; //$NON-NLS-1$
|
||||||
String newName = baseName;
|
String newName = baseName;
|
||||||
int n = 0;
|
int n = 0;
|
||||||
while (configNames.contains(newName)) {
|
while (configNames.contains(newName)) {
|
||||||
|
|
|
@ -0,0 +1,117 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2016 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
|
||||||
|
* http://www.eclipse.org/legal/epl-v10.html
|
||||||
|
*******************************************************************************/
|
||||||
|
package org.eclipse.cdt.internal.qt.core.launch;
|
||||||
|
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.util.concurrent.ExecutionException;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
|
||||||
|
import org.eclipse.cdt.dsf.concurrent.ImmediateExecutor;
|
||||||
|
import org.eclipse.cdt.dsf.concurrent.Query;
|
||||||
|
import org.eclipse.cdt.dsf.concurrent.RequestMonitorWithProgress;
|
||||||
|
import org.eclipse.cdt.dsf.concurrent.Sequence;
|
||||||
|
import org.eclipse.cdt.dsf.debug.sourcelookup.DsfSourceLookupDirector;
|
||||||
|
import org.eclipse.cdt.dsf.gdb.launching.GdbLaunch;
|
||||||
|
import org.eclipse.cdt.dsf.gdb.launching.ServicesLaunchSequence;
|
||||||
|
import org.eclipse.cdt.dsf.gdb.service.GdbDebugServicesFactory;
|
||||||
|
import org.eclipse.cdt.dsf.gdb.service.command.IGDBControl;
|
||||||
|
import org.eclipse.cdt.dsf.service.DsfServicesTracker;
|
||||||
|
import org.eclipse.cdt.internal.qt.core.Activator;
|
||||||
|
import org.eclipse.cdt.qt.core.QtBuildConfiguration;
|
||||||
|
import org.eclipse.cdt.qt.core.QtLaunchConfigurationDelegate;
|
||||||
|
import org.eclipse.core.runtime.CoreException;
|
||||||
|
import org.eclipse.core.runtime.IProgressMonitor;
|
||||||
|
import org.eclipse.core.runtime.IStatus;
|
||||||
|
import org.eclipse.core.runtime.Status;
|
||||||
|
import org.eclipse.debug.core.DebugException;
|
||||||
|
import org.eclipse.debug.core.ILaunch;
|
||||||
|
import org.eclipse.debug.core.ILaunchConfiguration;
|
||||||
|
import org.eclipse.launchbar.core.target.ILaunchTarget;
|
||||||
|
import org.eclipse.launchbar.core.target.launch.ITargetedLaunch;
|
||||||
|
|
||||||
|
public class QtLocalDebugLaunchConfigDelegate extends QtLaunchConfigurationDelegate {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ITargetedLaunch getLaunch(ILaunchConfiguration configuration, String mode, ILaunchTarget target)
|
||||||
|
throws CoreException {
|
||||||
|
GdbLaunch launch = new GdbLaunch(configuration, mode, null);
|
||||||
|
launch.setLaunchTarget(target);
|
||||||
|
launch.initialize();
|
||||||
|
|
||||||
|
DsfSourceLookupDirector locator = new DsfSourceLookupDirector(launch.getSession());
|
||||||
|
String memento = configuration.getAttribute(ILaunchConfiguration.ATTR_SOURCE_LOCATOR_MEMENTO, (String) null);
|
||||||
|
if (memento == null) {
|
||||||
|
locator.initializeDefaults(configuration);
|
||||||
|
} else {
|
||||||
|
locator.initializeFromMemento(memento, configuration);
|
||||||
|
}
|
||||||
|
|
||||||
|
launch.setSourceLocator(locator);
|
||||||
|
return launch;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void launch(ILaunchConfiguration configuration, String mode, ILaunch launch, IProgressMonitor monitor)
|
||||||
|
throws CoreException {
|
||||||
|
GdbLaunch gdbLaunch = (GdbLaunch) launch;
|
||||||
|
ILaunchTarget target = ((ITargetedLaunch) launch).getLaunchTarget();
|
||||||
|
QtBuildConfiguration qtBuildConfig = getQtBuildConfiguration(configuration, mode, target, monitor);
|
||||||
|
|
||||||
|
// TODO get it from the toolchain
|
||||||
|
gdbLaunch.setGDBPath("/usr/local/bin/gdb");
|
||||||
|
String gdbVersion = gdbLaunch.getGDBVersion();
|
||||||
|
|
||||||
|
Path exeFile = qtBuildConfig.getProgramPath();
|
||||||
|
gdbLaunch.setProgramPath(exeFile.toString());
|
||||||
|
|
||||||
|
gdbLaunch.setServiceFactory(new GdbDebugServicesFactory(gdbVersion));
|
||||||
|
|
||||||
|
Sequence servicesLaunchSequence = new ServicesLaunchSequence(gdbLaunch.getSession(), gdbLaunch, monitor);
|
||||||
|
gdbLaunch.getSession().getExecutor().execute(servicesLaunchSequence);
|
||||||
|
try {
|
||||||
|
servicesLaunchSequence.get();
|
||||||
|
} catch (InterruptedException | ExecutionException e) {
|
||||||
|
throw new DebugException(new Status(IStatus.ERROR, Activator.ID, "Failure launching with gdb", e));
|
||||||
|
}
|
||||||
|
|
||||||
|
gdbLaunch.initializeControl();
|
||||||
|
|
||||||
|
gdbLaunch.addCLIProcess(gdbLaunch.getGDBPath().toOSString() + " (" + gdbVersion + ")"); //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
|
|
||||||
|
Query<Object> ready = new Query<Object>() {
|
||||||
|
@Override
|
||||||
|
protected void execute(final DataRequestMonitor<Object> rm) {
|
||||||
|
DsfServicesTracker tracker = new DsfServicesTracker(
|
||||||
|
Activator.getDefault().getBundle().getBundleContext(), gdbLaunch.getSession().getId());
|
||||||
|
IGDBControl control = tracker.getService(IGDBControl.class);
|
||||||
|
tracker.dispose();
|
||||||
|
control.completeInitialization(
|
||||||
|
new RequestMonitorWithProgress(ImmediateExecutor.getInstance(), monitor) {
|
||||||
|
@Override
|
||||||
|
protected void handleCompleted() {
|
||||||
|
if (isCanceled()) {
|
||||||
|
rm.cancel();
|
||||||
|
} else {
|
||||||
|
rm.setStatus(getStatus());
|
||||||
|
}
|
||||||
|
rm.done();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Start it up
|
||||||
|
gdbLaunch.getSession().getExecutor().execute(ready);
|
||||||
|
try {
|
||||||
|
ready.get();
|
||||||
|
} catch (ExecutionException | InterruptedException e) {
|
||||||
|
throw new DebugException(new Status(IStatus.ERROR, Activator.ID, "Failure to start debug session", e));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -7,7 +7,6 @@
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
package org.eclipse.cdt.internal.qt.core.launch;
|
package org.eclipse.cdt.internal.qt.core.launch;
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
@ -18,9 +17,7 @@ import org.eclipse.cdt.qt.core.QtLaunchConfigurationDelegate;
|
||||||
import org.eclipse.core.runtime.CoreException;
|
import org.eclipse.core.runtime.CoreException;
|
||||||
import org.eclipse.core.runtime.IProgressMonitor;
|
import org.eclipse.core.runtime.IProgressMonitor;
|
||||||
import org.eclipse.core.runtime.IStatus;
|
import org.eclipse.core.runtime.IStatus;
|
||||||
import org.eclipse.core.runtime.Platform;
|
|
||||||
import org.eclipse.core.runtime.Status;
|
import org.eclipse.core.runtime.Status;
|
||||||
import org.eclipse.core.runtime.jobs.Job;
|
|
||||||
import org.eclipse.debug.core.DebugPlugin;
|
import org.eclipse.debug.core.DebugPlugin;
|
||||||
import org.eclipse.debug.core.ILaunch;
|
import org.eclipse.debug.core.ILaunch;
|
||||||
import org.eclipse.debug.core.ILaunchConfiguration;
|
import org.eclipse.debug.core.ILaunchConfiguration;
|
||||||
|
@ -34,70 +31,25 @@ public class QtLocalRunLaunchConfigDelegate extends QtLaunchConfigurationDelegat
|
||||||
@Override
|
@Override
|
||||||
public void launch(ILaunchConfiguration configuration, String mode, ILaunch launch, IProgressMonitor monitor)
|
public void launch(ILaunchConfiguration configuration, String mode, ILaunch launch, IProgressMonitor monitor)
|
||||||
throws CoreException {
|
throws CoreException {
|
||||||
new Job("Running Qt App") {
|
|
||||||
@Override
|
|
||||||
protected IStatus run(IProgressMonitor monitor) {
|
|
||||||
try {
|
|
||||||
ILaunchTarget target = ((ITargetedLaunch) launch).getLaunchTarget();
|
ILaunchTarget target = ((ITargetedLaunch) launch).getLaunchTarget();
|
||||||
QtBuildConfiguration qtBuildConfig = getQtBuildConfiguration(configuration, mode, target, monitor);
|
QtBuildConfiguration qtBuildConfig = getQtBuildConfiguration(configuration, mode, target, monitor);
|
||||||
|
|
||||||
// get the executable
|
// get the executable
|
||||||
Path buildFolder = qtBuildConfig.getBuildDirectory();
|
Path exeFile = qtBuildConfig.getProgramPath();
|
||||||
Path exeFile;
|
|
||||||
switch (Platform.getOS()) {
|
|
||||||
case Platform.OS_MACOSX:
|
|
||||||
// TODO this is mac local specific and really should be
|
|
||||||
// in the config
|
|
||||||
// TODO also need to pull the app name out of the pro
|
|
||||||
// file name
|
|
||||||
Path appFolder = buildFolder.resolve("main.app");
|
|
||||||
Path contentsFolder = appFolder.resolve("Contents");
|
|
||||||
Path macosFolder = contentsFolder.resolve("MacOS");
|
|
||||||
exeFile = macosFolder.resolve("main");
|
|
||||||
break;
|
|
||||||
case Platform.OS_WIN32:
|
|
||||||
Path releaseFolder = buildFolder.resolve("release");
|
|
||||||
exeFile = releaseFolder.resolve("main.exe");
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return new Status(IStatus.ERROR, Activator.ID, "platform not supported: " + Platform.getOS());
|
|
||||||
}
|
|
||||||
|
|
||||||
ProcessBuilder builder = new ProcessBuilder(exeFile.toString())
|
ProcessBuilder builder = new ProcessBuilder(exeFile.toString())
|
||||||
.directory(qtBuildConfig.getProject().getLocation().toFile());
|
.directory(qtBuildConfig.getProject().getLocation().toFile());
|
||||||
|
|
||||||
// need to add the Qt libraries to the env
|
// set up the environment
|
||||||
Map<String, String> env = builder.environment();
|
Map<String, String> env = builder.environment();
|
||||||
Path libPath = qtBuildConfig.getQtInstall().getLibPath();
|
qtBuildConfig.setProgramEnvironment(env);
|
||||||
switch (Platform.getOS()) {
|
|
||||||
case Platform.OS_MACOSX:
|
|
||||||
String libPathEnv = env.get("DYLD_LIBRARY_PATH");
|
|
||||||
if (libPathEnv == null) {
|
|
||||||
libPathEnv = libPath.toString();
|
|
||||||
} else {
|
|
||||||
libPathEnv = libPath.toString() + File.pathSeparator + libPathEnv;
|
|
||||||
}
|
|
||||||
env.put("DYLD_LIBRARY_PATH", libPathEnv);
|
|
||||||
break;
|
|
||||||
case Platform.OS_WIN32:
|
|
||||||
String path = env.get("PATH");
|
|
||||||
// TODO really need a bin path
|
|
||||||
// and resolve doesn't work properly on Windows
|
|
||||||
path = "C:/Qt/5.5/mingw492_32/bin;" + path;
|
|
||||||
env.put("PATH", path);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
try {
|
||||||
Process process = builder.start();
|
Process process = builder.start();
|
||||||
DebugPlugin.newProcess(launch, process, "main");
|
DebugPlugin.newProcess(launch, process, "main");
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
return new Status(IStatus.ERROR, Activator.ID, "running", e);
|
throw new CoreException(new Status(IStatus.ERROR, Activator.ID, "Failed to start", e));
|
||||||
} catch (CoreException e) {
|
|
||||||
return e.getStatus();
|
|
||||||
}
|
}
|
||||||
return Status.OK_STATUS;
|
|
||||||
}
|
|
||||||
}.schedule();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,6 +29,10 @@ import org.eclipse.cdt.core.parser.IScannerInfo;
|
||||||
import org.eclipse.cdt.internal.qt.core.Activator;
|
import org.eclipse.cdt.internal.qt.core.Activator;
|
||||||
import org.eclipse.core.resources.IBuildConfiguration;
|
import org.eclipse.core.resources.IBuildConfiguration;
|
||||||
import org.eclipse.core.resources.IResource;
|
import org.eclipse.core.resources.IResource;
|
||||||
|
import org.eclipse.core.runtime.CoreException;
|
||||||
|
import org.eclipse.core.runtime.IStatus;
|
||||||
|
import org.eclipse.core.runtime.Platform;
|
||||||
|
import org.eclipse.core.runtime.Status;
|
||||||
import org.osgi.service.prefs.BackingStoreException;
|
import org.osgi.service.prefs.BackingStoreException;
|
||||||
import org.osgi.service.prefs.Preferences;
|
import org.osgi.service.prefs.Preferences;
|
||||||
|
|
||||||
|
@ -107,6 +111,48 @@ public class QtBuildConfiguration extends CBuildConfiguration {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Path getProgramPath() throws CoreException {
|
||||||
|
switch (Platform.getOS()) {
|
||||||
|
case Platform.OS_MACOSX:
|
||||||
|
// TODO this is mac local specific and really should be
|
||||||
|
// in the config
|
||||||
|
// TODO also need to pull the app name out of the pro
|
||||||
|
// file name
|
||||||
|
Path appFolder = getBuildDirectory().resolve("main.app");
|
||||||
|
Path contentsFolder = appFolder.resolve("Contents");
|
||||||
|
Path macosFolder = contentsFolder.resolve("MacOS");
|
||||||
|
return macosFolder.resolve("main");
|
||||||
|
case Platform.OS_WIN32:
|
||||||
|
Path releaseFolder = getBuildDirectory().resolve("release");
|
||||||
|
return releaseFolder.resolve("main.exe");
|
||||||
|
default:
|
||||||
|
throw new CoreException(
|
||||||
|
new Status(IStatus.ERROR, Activator.ID, "platform not supported: " + Platform.getOS()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setProgramEnvironment(Map<String, String> env) {
|
||||||
|
Path libPath = getQtInstall().getLibPath();
|
||||||
|
switch (Platform.getOS()) {
|
||||||
|
case Platform.OS_MACOSX:
|
||||||
|
String libPathEnv = env.get("DYLD_LIBRARY_PATH");
|
||||||
|
if (libPathEnv == null) {
|
||||||
|
libPathEnv = libPath.toString();
|
||||||
|
} else {
|
||||||
|
libPathEnv = libPath.toString() + File.pathSeparator + libPathEnv;
|
||||||
|
}
|
||||||
|
env.put("DYLD_LIBRARY_PATH", libPathEnv);
|
||||||
|
break;
|
||||||
|
case Platform.OS_WIN32:
|
||||||
|
String path = env.get("PATH");
|
||||||
|
// TODO really need a bin path
|
||||||
|
// and resolve doesn't work properly on Windows
|
||||||
|
path = "C:/Qt/5.5/mingw492_32/bin;" + path;
|
||||||
|
env.put("PATH", path);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public String getProperty(String key) {
|
public String getProperty(String key) {
|
||||||
if (properties == null) {
|
if (properties == null) {
|
||||||
List<String> cmd = new ArrayList<>();
|
List<String> cmd = new ArrayList<>();
|
||||||
|
|
|
@ -86,6 +86,13 @@
|
||||||
class="org.eclipse.cdt.internal.qt.ui.launch.QtLocalLaunchConfigurationTabGroup"
|
class="org.eclipse.cdt.internal.qt.ui.launch.QtLocalLaunchConfigurationTabGroup"
|
||||||
id="org.eclipse.cdt.qt.ui.launchConfigurationTabGroup"
|
id="org.eclipse.cdt.qt.ui.launchConfigurationTabGroup"
|
||||||
type="org.eclipse.cdt.qt.core.launchConfigurationType">
|
type="org.eclipse.cdt.qt.core.launchConfigurationType">
|
||||||
|
<launchMode
|
||||||
|
mode="run">
|
||||||
|
</launchMode>
|
||||||
|
<launchMode
|
||||||
|
mode="debug"
|
||||||
|
perspective="org.eclipse.debug.ui.DebugPerspective">
|
||||||
|
</launchMode>
|
||||||
</launchConfigurationTabGroup>
|
</launchConfigurationTabGroup>
|
||||||
</extension>
|
</extension>
|
||||||
<extension
|
<extension
|
||||||
|
|
Loading…
Add table
Reference in a new issue