Add Local Debug for Core Build launches. Qt Path var for Windows.

Adds gdb launching for Core Build launches. A common class is created
for things common to run and debug (and probably others).

At the bin directory containing qmake to the PATH var for builds and
launches since that's where the DLLs are.

Adds method and variable to GDBLaunch to override the default
environment.

Change-Id: I3ab3b48a2f99eaed50cdb4cfdc03959e9700abc5
This commit is contained in:
Doug Schaefer 2016-11-07 11:28:45 -05:00 committed by Gerrit Code Review @ Eclipse.org
parent 5cafc1413a
commit e9beafae10
9 changed files with 299 additions and 91 deletions

View file

@ -11,6 +11,7 @@ Export-Package: org.eclipse.cdt.debug.core,
org.eclipse.cdt.debug.core.command,
org.eclipse.cdt.debug.core.disassembly,
org.eclipse.cdt.debug.core.executables,
org.eclipse.cdt.debug.core.launch,
org.eclipse.cdt.debug.core.model,
org.eclipse.cdt.debug.core.model.provisional;
x-friends:="org.eclipse.cdt.dsf,
@ -27,6 +28,7 @@ Export-Package: org.eclipse.cdt.debug.core,
org.eclipse.cdt.debug.internal.core.breakpoints;x-friends:="org.eclipse.cdt.debug.edc,org.eclipse.cdt.dsf.gdb",
org.eclipse.cdt.debug.internal.core.disassembly;x-internal:=true,
org.eclipse.cdt.debug.internal.core.executables;x-internal:=true,
org.eclipse.cdt.debug.internal.core.launch;x-internal:=true,
org.eclipse.cdt.debug.internal.core.model;x-friends:="org.eclipse.cdt.dsf.ui,org.eclipse.cdt.dsf.gdb",
org.eclipse.cdt.debug.internal.core.sourcelookup;
x-friends:="org.eclipse.cdt.debug.edc,

View file

@ -465,7 +465,7 @@
point="org.eclipse.debug.core.launchConfigurationTypes">
<launchConfigurationType
delegate="org.eclipse.cdt.debug.internal.core.launch.CoreBuildLocalRunLaunchDelegate"
id="org.eclipse.cdt.debug.core.localLaunchConfigurationType"
id="org.eclipse.cdt.debug.core.localCoreBuildLaunchConfigType"
modes="run"
name="%localApplicationLaunch.name"
public="false">

View file

@ -0,0 +1,105 @@
/*******************************************************************************
* 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.debug.core.launch;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import org.eclipse.cdt.core.build.ICBuildConfiguration;
import org.eclipse.cdt.core.build.ICBuildConfigurationManager;
import org.eclipse.cdt.core.build.IToolChain;
import org.eclipse.cdt.core.build.IToolChainManager;
import org.eclipse.cdt.core.model.IBinary;
import org.eclipse.cdt.debug.core.CDebugCorePlugin;
import org.eclipse.cdt.utils.Platform;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IProjectDescription;
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.ILaunchConfiguration;
import org.eclipse.launchbar.core.target.ILaunchTarget;
import org.eclipse.launchbar.core.target.launch.LaunchConfigurationTargetedDelegate;
/**
* Common launch delegate code for core build launches.
*
* @since 8.1
*/
public abstract class CoreBuildLocalLaunchConfigDelegate extends LaunchConfigurationTargetedDelegate {
protected ICBuildConfigurationManager configManager = CDebugCorePlugin
.getService(ICBuildConfigurationManager.class);
protected IToolChainManager toolChainManager = CDebugCorePlugin.getService(IToolChainManager.class);
protected IProject getProject(ILaunchConfiguration configuration) throws CoreException {
// TODO - make sure this is really the correct project
return configuration.getMappedResources()[0].getProject();
}
protected ICBuildConfiguration getBuildConfiguration(IProject project, String mode, ILaunchTarget target,
IProgressMonitor monitor) throws CoreException {
// Pick build config based on toolchain for target
Map<String, String> properties = new HashMap<>();
properties.put(IToolChain.ATTR_OS, Platform.getOS());
properties.put(IToolChain.ATTR_ARCH, Platform.getOSArch());
Collection<IToolChain> tcs = toolChainManager.getToolChainsMatching(properties);
if (!tcs.isEmpty()) {
IToolChain toolChain = tcs.iterator().next();
return configManager.getBuildConfiguration(project, toolChain, mode, monitor);
} else {
return null;
}
}
protected IBinary getBinary(ICBuildConfiguration buildConfig) throws CoreException {
IBinary[] binaries = buildConfig.getBuildOutput();
IBinary exeFile = null;
for (IBinary binary : binaries) {
if (binary.isExecutable()) {
exeFile = binary;
break;
}
}
if (exeFile == null) {
throw new CoreException(new Status(IStatus.ERROR, CDebugCorePlugin.PLUGIN_ID, "No binaries"));
}
return exeFile;
}
@Override
protected IProject[] getBuildOrder(ILaunchConfiguration configuration, String mode) throws CoreException {
// 1. Extract project from configuration
// TODO dependencies too.
IProject project = getProject(configuration);
return new IProject[] { project };
}
@Override
public boolean buildForLaunch(ILaunchConfiguration configuration, String mode, ILaunchTarget target,
IProgressMonitor monitor) throws CoreException {
IProject project = getProject(configuration);
ICBuildConfiguration buildConfig = getBuildConfiguration(project, mode, target, monitor);
if (buildConfig != null) {
IProjectDescription desc = project.getDescription();
desc.setActiveBuildConfig(buildConfig.getBuildConfiguration().getName());
project.setDescription(desc, monitor);
Map<String, String> buildProps = configuration.getAttribute("COREBUILD_" + mode, new HashMap<>()); //$NON-NLS-1$
if (!buildProps.isEmpty()) {
buildConfig.setProperties(buildProps);
}
}
// proceed with the build
return superBuildForLaunch(configuration, mode, monitor);
}
}

View file

@ -25,7 +25,7 @@ import org.eclipse.launchbar.core.target.ILaunchTargetManager;
public class CoreBuildLocalLaunchConfigProvider extends AbstractLaunchConfigProvider {
private static final String TYPE_ID = "org.eclipse.cdt.debug.core.localLaunchConfigurationType"; //$NON-NLS-1$
private static final String TYPE_ID = "org.eclipse.cdt.debug.core.localCoreBuildLaunchConfigType"; //$NON-NLS-1$
private Map<IProject, ILaunchConfiguration> configs = new HashMap<>();

View file

@ -9,19 +9,12 @@ package org.eclipse.cdt.debug.internal.core.launch;
import java.io.IOException;
import java.nio.file.Paths;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import org.eclipse.cdt.core.build.ICBuildConfiguration;
import org.eclipse.cdt.core.build.ICBuildConfigurationManager;
import org.eclipse.cdt.core.build.IToolChain;
import org.eclipse.cdt.core.build.IToolChainManager;
import org.eclipse.cdt.core.model.IBinary;
import org.eclipse.cdt.debug.core.CDebugCorePlugin;
import org.eclipse.cdt.utils.Platform;
import org.eclipse.cdt.debug.core.launch.CoreBuildLocalLaunchConfigDelegate;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IProjectDescription;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
@ -31,50 +24,8 @@ 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;
import org.eclipse.launchbar.core.target.launch.LaunchConfigurationTargetedDelegate;
public class CoreBuildLocalRunLaunchDelegate extends LaunchConfigurationTargetedDelegate {
public static final String TYPE_ID = "org.eclipse.cdt.cmake.core.launchConfigurationType"; //$NON-NLS-1$
private ICBuildConfigurationManager configManager = CDebugCorePlugin.getService(ICBuildConfigurationManager.class);
private IToolChainManager tcManager = CDebugCorePlugin.getService(IToolChainManager.class);
private IProject getProject(ILaunchConfiguration configuration) throws CoreException {
return configuration.getMappedResources()[0].getProject();
}
@Override
public boolean buildForLaunch(ILaunchConfiguration configuration, String mode, ILaunchTarget target,
IProgressMonitor monitor) throws CoreException {
// Set active build config based on toolchain for target
Map<String, String> properties = new HashMap<>();
properties.put(IToolChain.ATTR_OS, Platform.getOS());
properties.put(IToolChain.ATTR_ARCH, Platform.getOSArch());
// TODO should really use real architecture of platform, not what Eclipse is using.
// Also on 64-bit platforms, try 32-bit if toolchains not found
Collection<IToolChain> tcs = tcManager.getToolChainsMatching(properties);
if (!tcs.isEmpty()) {
IToolChain toolChain = tcs.iterator().next();
IProject project = getProject(configuration);
ICBuildConfiguration config = configManager.getBuildConfiguration(project, toolChain, "run", monitor); //$NON-NLS-1$
if (config != null) {
IProjectDescription desc = project.getDescription();
desc.setActiveBuildConfig(config.getBuildConfiguration().getName());
project.setDescription(desc, monitor);
Map<String, String> buildProps = configuration.getAttribute("COREBUILD_" + mode, new HashMap<>()); //$NON-NLS-1$
if (!buildProps.isEmpty()) {
config.setProperties(buildProps);
}
}
}
// proceed with the build
return superBuildForLaunch(configuration, mode, monitor);
}
public class CoreBuildLocalRunLaunchDelegate extends CoreBuildLocalLaunchConfigDelegate {
@Override
public void launch(ILaunchConfiguration configuration, String mode, ILaunch launch, IProgressMonitor monitor)
@ -83,17 +34,7 @@ public class CoreBuildLocalRunLaunchDelegate extends LaunchConfigurationTargeted
ILaunchTarget target = ((ITargetedLaunch) launch).getLaunchTarget();
ICBuildConfiguration buildConfig = getBuildConfiguration(project, mode, target, monitor);
IBinary[] binaries = buildConfig.getBuildOutput();
IBinary exeFile = null;
for (IBinary binary : binaries) {
if (binary.isExecutable()) {
exeFile = binary;
break;
}
}
if (exeFile == null) {
throw new CoreException(new Status(IStatus.ERROR, CDebugCorePlugin.PLUGIN_ID, "No binaries"));
}
IBinary exeFile = getBinary(buildConfig);
try {
ProcessBuilder builder = new ProcessBuilder(Paths.get(exeFile.getLocationURI()).toString());
@ -105,27 +46,4 @@ public class CoreBuildLocalRunLaunchDelegate extends LaunchConfigurationTargeted
}
}
@Override
protected IProject[] getBuildOrder(ILaunchConfiguration configuration, String mode) throws CoreException {
// 1. Extract project from configuration
// TODO dependencies too.
IProject project = getProject(configuration);
return new IProject[] { project };
}
private ICBuildConfiguration getBuildConfiguration(IProject project, String mode, ILaunchTarget target,
IProgressMonitor monitor) throws CoreException {
// Set active build config based on toolchain for target
Map<String, String> properties = new HashMap<>();
properties.put(IToolChain.ATTR_OS, Platform.getOS());
properties.put(IToolChain.ATTR_ARCH, Platform.getOSArch());
Collection<IToolChain> tcs = tcManager.getToolChainsMatching(properties);
if (!tcs.isEmpty()) {
IToolChain toolChain = tcs.iterator().next();
return configManager.getBuildConfiguration(project, toolChain, "run", monitor); //$NON-NLS-1$
} else {
return null;
}
}
}

View file

@ -85,4 +85,20 @@
</bundle>
</component>
</extension>
<extension
point="org.eclipse.debug.core.launchDelegates">
<launchDelegate
delegate="org.eclipse.cdt.dsf.gdb.internal.launching.CoreBuildLocalDebugLaunchDelegate"
id="org.eclipse.cdt.dsf.gdb.coreBuildLocalDebug"
modes="debug"
name="Core Build Local Debug"
sourceLocatorId="org.eclipse.cdt.debug.core.sourceLocator"
sourcePathComputerId="org.eclipse.cdt.debug.core.sourcePathComputer"
type="org.eclipse.cdt.debug.core.localCoreBuildLaunchConfigType">
<modeCombination
modes="debug"
perspective="org.eclipse.debug.ui.DebugPerspective">
</modeCombination>
</launchDelegate>
</extension>
</plugin>

View file

@ -0,0 +1,130 @@
/*******************************************************************************
* 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.dsf.gdb.internal.launching;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.ExecutionException;
import org.eclipse.cdt.core.build.ICBuildConfiguration;
import org.eclipse.cdt.core.build.IToolChain;
import org.eclipse.cdt.debug.core.launch.CoreBuildLocalLaunchConfigDelegate;
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.gdb.internal.GdbPlugin;
import org.eclipse.cdt.dsf.gdb.launching.GdbLaunch;
import org.eclipse.cdt.dsf.gdb.launching.GdbSourceLookupDirector;
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.core.resources.IProject;
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 CoreBuildLocalDebugLaunchDelegate extends CoreBuildLocalLaunchConfigDelegate {
@Override
public ITargetedLaunch getLaunch(ILaunchConfiguration configuration, String mode, ILaunchTarget target)
throws CoreException {
GdbLaunch launch = new GdbLaunch(configuration, mode, null);
launch.setLaunchTarget(target);
launch.initialize();
GdbSourceLookupDirector locator = new GdbSourceLookupDirector(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();
IProject project = getProject(configuration);
ICBuildConfiguration buildConfig = getBuildConfiguration(project, mode, target, monitor);
Map<String, String> buildEnv = new HashMap<>();
buildConfig.setBuildEnvironment(buildEnv);
Properties envProps = new Properties();
envProps.putAll(buildEnv);
gdbLaunch.setInitialEnvironment(envProps);
IToolChain toolChain = buildConfig.getToolChain();
gdbLaunch.setGDBPath(toolChain.getCommandPath(Paths.get("gdb")).toString()); //$NON-NLS-1$
String gdbVersion = gdbLaunch.getGDBVersion();
Path exeFile = Paths.get(getBinary(buildConfig).getLocationURI());
gdbLaunch.setProgramPath(exeFile.toString());
gdbLaunch.setServiceFactory(new GdbDebugServicesFactory(gdbVersion, configuration));
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, GdbPlugin.PLUGIN_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(
GdbPlugin.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, GdbPlugin.PLUGIN_ID, "Failure to start debug session", e));
}
}
}

View file

@ -113,6 +113,7 @@ public class GdbLaunch extends DsfLaunch implements ITerminate, IDisconnect, ITr
private IMemoryBlockRetrievalManager fMemRetrievalManager;
private IDsfDebugServicesFactory fServiceFactory;
private ILaunchTarget fLaunchTarget;
private Properties fInitialEnv;
private String fGdbVersion;
@ -897,6 +898,9 @@ public class GdbLaunch extends DsfLaunch implements ITerminate, IDisconnect, ITr
*/
public Properties getEnvironmentVariables() throws CoreException {
Properties envVariables = new Properties();
if (fInitialEnv != null) {
envVariables.putAll(fInitialEnv);
}
// if the attribute ATTR_APPEND_ENVIRONMENT_VARIABLES is set,
// the LaunchManager will return both the new variables and the
@ -984,4 +988,13 @@ public class GdbLaunch extends DsfLaunch implements ITerminate, IDisconnect, ITr
return fLaunchTarget;
}
/**
* Set the initial environment variables. These can then be overriden
* by launch configuration attributes.
*
* @since 5.2
*/
public void setInitialEnvironment(Properties initialEnv) {
this.fInitialEnv = initialEnv;
}
}

View file

@ -60,6 +60,28 @@ public class QtBuildConfiguration extends CBuildConfiguration
private final String qtInstallSpec;
private IQtInstall qtInstall;
private Map<String, String> properties;
private IEnvironmentVariable pathVar = new IEnvironmentVariable() {
@Override
public String getValue() {
return getQmakeCommand().getParent().toString();
}
@Override
public int getOperation() {
return IEnvironmentVariable.ENVVAR_PREPEND;
}
@Override
public String getName() {
return "PATH";
}
@Override
public String getDelimiter() {
return File.pathSeparator;
}
};
public QtBuildConfiguration(IBuildConfiguration config, String name) throws CoreException {
super(config, name);
@ -236,14 +258,16 @@ public class QtBuildConfiguration extends CBuildConfiguration
@Override
public IEnvironmentVariable getVariable(String name) {
// TODO Auto-generated method stub
return null;
if ("PATH".equals(name)) {
return pathVar;
} else {
return null;
}
}
@Override
public IEnvironmentVariable[] getVariables() {
// TODO
return new IEnvironmentVariable[0];
return new IEnvironmentVariable[] { pathVar };
}
@Override