mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-04-23 14:42: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.IBuildConfigurationManager;
|
||||
import org.eclipse.cdt.core.CProjectNature;
|
||||
import org.eclipse.core.resources.IBuildConfiguration;
|
||||
import org.eclipse.core.resources.IProject;
|
||||
import org.eclipse.core.resources.IResource;
|
||||
|
@ -42,7 +43,7 @@ public class CBuildConfigurationManager
|
|||
// TODO
|
||||
CBuildConfiguration config = null;
|
||||
|
||||
//configMap.put(config.getBuildConfiguration(), config);
|
||||
// configMap.put(config.getBuildConfiguration(), config);
|
||||
return config;
|
||||
}
|
||||
|
||||
|
@ -67,6 +68,13 @@ public class CBuildConfigurationManager
|
|||
if (event.getType() == IResourceChangeEvent.PRE_CLOSE || event.getType() == IResourceChangeEvent.PRE_DELETE) {
|
||||
if (event.getResource().getType() == IResource.PROJECT) {
|
||||
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
|
||||
try {
|
||||
|
|
|
@ -14,7 +14,8 @@ Require-Bundle: org.eclipse.core.runtime,
|
|||
org.eclipse.core.variables,
|
||||
org.eclipse.cdt.launch;bundle-version="6.1.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-RequiredExecutionEnvironment: JavaSE-1.7
|
||||
Export-Package: org.eclipse.cdt.dsf.gdb,
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -296,11 +296,12 @@ public class GdbLaunchDelegate extends AbstractCLaunchDelegate2
|
|||
}
|
||||
|
||||
/**
|
||||
* Returns the GDB version.
|
||||
* Subclass can override for special need.
|
||||
*
|
||||
* Returns the GDB version. Subclass can override for special need.
|
||||
*
|
||||
* @since 2.0
|
||||
* @deprecated Replaced by GdbLaunch.getGDBVersion() which can also be overridden
|
||||
*/
|
||||
@Deprecated
|
||||
protected String getGDBVersion(ILaunchConfiguration config) throws CoreException {
|
||||
return LaunchUtils.getGDBVersion(config);
|
||||
}
|
||||
|
|
|
@ -273,7 +273,10 @@ public class LaunchUtils {
|
|||
* 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.
|
||||
*
|
||||
* @deprecated Replaced with GdbLaunch.getLaunchEnvironment()
|
||||
*/
|
||||
@Deprecated
|
||||
public static String getGDBVersion(final ILaunchConfiguration configuration) throws CoreException {
|
||||
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
|
||||
* launch
|
||||
* @since 3.0
|
||||
* @deprecated Replaced with GdbLaunch.getLaunchEnvironment()
|
||||
*/
|
||||
@Deprecated
|
||||
public static String[] getLaunchEnvironment(ILaunchConfiguration config) throws CoreException {
|
||||
// Get the project
|
||||
String projectName = config.getAttribute(ICDTLaunchConfigurationConstants.ATTR_PROJECT_NAME, (String)null);
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -18,7 +18,9 @@ Require-Bundle: org.eclipse.core.runtime,
|
|||
org.eclipse.cdt.debug.core,
|
||||
org.freemarker;bundle-version="2.3.22",
|
||||
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-ActivationPolicy: lazy
|
||||
Bundle-Localization: plugin
|
||||
|
|
|
@ -165,16 +165,6 @@
|
|||
class="org.eclipse.cdt.internal.qt.core.build.QtScannerInfoProvider">
|
||||
</provider>
|
||||
</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
|
||||
point="org.eclipse.core.runtime.adapters">
|
||||
<factory
|
||||
|
@ -192,4 +182,31 @@
|
|||
targetTypeId="org.eclipse.launchbar.core.launchTargetType.local">
|
||||
</mapper>
|
||||
</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>
|
||||
|
|
|
@ -124,7 +124,7 @@ public class QtBuildConfigurationFactory implements IAdapterFactory {
|
|||
for (IBuildConfiguration config : project.getBuildConfigs()) {
|
||||
configNames.add(config.getName());
|
||||
}
|
||||
String baseName = qtInstall.getSpec() + ":" + launchMode; //$NON-NLS-1$
|
||||
String baseName = qtInstall.getSpec() + "." + launchMode; //$NON-NLS-1$
|
||||
String newName = baseName;
|
||||
int n = 0;
|
||||
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;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
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.IProgressMonitor;
|
||||
import org.eclipse.core.runtime.IStatus;
|
||||
import org.eclipse.core.runtime.Platform;
|
||||
import org.eclipse.core.runtime.Status;
|
||||
import org.eclipse.core.runtime.jobs.Job;
|
||||
import org.eclipse.debug.core.DebugPlugin;
|
||||
import org.eclipse.debug.core.ILaunch;
|
||||
import org.eclipse.debug.core.ILaunchConfiguration;
|
||||
|
@ -34,70 +31,25 @@ public class QtLocalRunLaunchConfigDelegate extends QtLaunchConfigurationDelegat
|
|||
@Override
|
||||
public void launch(ILaunchConfiguration configuration, String mode, ILaunch launch, IProgressMonitor monitor)
|
||||
throws CoreException {
|
||||
new Job("Running Qt App") {
|
||||
@Override
|
||||
protected IStatus run(IProgressMonitor monitor) {
|
||||
try {
|
||||
ILaunchTarget target = ((ITargetedLaunch) launch).getLaunchTarget();
|
||||
QtBuildConfiguration qtBuildConfig = getQtBuildConfiguration(configuration, mode, target, monitor);
|
||||
ILaunchTarget target = ((ITargetedLaunch) launch).getLaunchTarget();
|
||||
QtBuildConfiguration qtBuildConfig = getQtBuildConfiguration(configuration, mode, target, monitor);
|
||||
|
||||
// get the executable
|
||||
Path buildFolder = qtBuildConfig.getBuildDirectory();
|
||||
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());
|
||||
}
|
||||
// get the executable
|
||||
Path exeFile = qtBuildConfig.getProgramPath();
|
||||
|
||||
ProcessBuilder builder = new ProcessBuilder(exeFile.toString())
|
||||
.directory(qtBuildConfig.getProject().getLocation().toFile());
|
||||
ProcessBuilder builder = new ProcessBuilder(exeFile.toString())
|
||||
.directory(qtBuildConfig.getProject().getLocation().toFile());
|
||||
|
||||
// need to add the Qt libraries to the env
|
||||
Map<String, String> env = builder.environment();
|
||||
Path libPath = qtBuildConfig.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;
|
||||
}
|
||||
// set up the environment
|
||||
Map<String, String> env = builder.environment();
|
||||
qtBuildConfig.setProgramEnvironment(env);
|
||||
|
||||
Process process = builder.start();
|
||||
DebugPlugin.newProcess(launch, process, "main");
|
||||
} catch (IOException e) {
|
||||
return new Status(IStatus.ERROR, Activator.ID, "running", e);
|
||||
} catch (CoreException e) {
|
||||
return e.getStatus();
|
||||
}
|
||||
return Status.OK_STATUS;
|
||||
}
|
||||
}.schedule();
|
||||
try {
|
||||
Process process = builder.start();
|
||||
DebugPlugin.newProcess(launch, process, "main");
|
||||
} catch (IOException e) {
|
||||
throw new CoreException(new Status(IStatus.ERROR, Activator.ID, "Failed to start", e));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -29,6 +29,10 @@ import org.eclipse.cdt.core.parser.IScannerInfo;
|
|||
import org.eclipse.cdt.internal.qt.core.Activator;
|
||||
import org.eclipse.core.resources.IBuildConfiguration;
|
||||
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.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) {
|
||||
if (properties == null) {
|
||||
List<String> cmd = new ArrayList<>();
|
||||
|
|
|
@ -86,6 +86,13 @@
|
|||
class="org.eclipse.cdt.internal.qt.ui.launch.QtLocalLaunchConfigurationTabGroup"
|
||||
id="org.eclipse.cdt.qt.ui.launchConfigurationTabGroup"
|
||||
type="org.eclipse.cdt.qt.core.launchConfigurationType">
|
||||
<launchMode
|
||||
mode="run">
|
||||
</launchMode>
|
||||
<launchMode
|
||||
mode="debug"
|
||||
perspective="org.eclipse.debug.ui.DebugPerspective">
|
||||
</launchMode>
|
||||
</launchConfigurationTabGroup>
|
||||
</extension>
|
||||
<extension
|
||||
|
|
Loading…
Add table
Reference in a new issue