1
0
Fork 0
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:
Doug Schaefer 2016-01-25 15:00:32 -05:00 committed by Gerrit Code Review @ Eclipse.org
parent 99426ce65a
commit 192bfff688
13 changed files with 1615 additions and 1061 deletions

View file

@ -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 {

View file

@ -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,

View file

@ -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);
}

View file

@ -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);

View file

@ -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

View file

@ -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>

View file

@ -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)) {

View file

@ -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));
}
}
}

View file

@ -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));
}
}
}

View file

@ -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<>();

View file

@ -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