1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-04-23 14:42:11 +02:00

Bug 317796 - Build before launch should be cleverer about which configuration is built.

Add option to LaunchConfig Main Tab to automatically choose a build configuration appropriate to the binary being debugged.
This commit is contained in:
James Blackburn 2010-08-26 15:36:21 +00:00
parent 97c334a819
commit 5294511318
9 changed files with 176 additions and 14 deletions

View file

@ -9,6 +9,7 @@
* QNX Software Systems - initial API and implementation * QNX Software Systems - initial API and implementation
* Ken Ryall (Nokia) - bug 118894 * Ken Ryall (Nokia) - bug 118894
* Ken Ryall (Nokia) - bug 178731 * Ken Ryall (Nokia) - bug 178731
* Alex Collins (Broadcom Corp.) - choose build config automatically
*******************************************************************************/ *******************************************************************************/
package org.eclipse.cdt.debug.core; package org.eclipse.cdt.debug.core;
@ -120,6 +121,13 @@ public interface ICDTLaunchConfigurationConstants {
*/ */
public static final String ATTR_PROJECT_BUILD_CONFIG_ID = CDT_LAUNCH_ID + ".PROJECT_BUILD_CONFIG_ID_ATTR"; //$NON-NLS-1$ public static final String ATTR_PROJECT_BUILD_CONFIG_ID = CDT_LAUNCH_ID + ".PROJECT_BUILD_CONFIG_ID_ATTR"; //$NON-NLS-1$
/**
* Automatically choose build configuration for launch key. The value indicates whether the ID of the build configuration
* to be built before launch should be calculated based on the path to the application being launched.
* @since 7.1
*/
public static final String ATTR_PROJECT_BUILD_CONFIG_AUTO = CDT_LAUNCH_ID + ".PROJECT_BUILD_CONFIG_AUTO_ATTR"; //$NON-NLS-1$
/** /**
* Launch configuration attribute key. The value is a string specifying * Launch configuration attribute key. The value is a string specifying
* application a C/C++ launch configuration. * application a C/C++ launch configuration.

View file

@ -522,6 +522,10 @@ public class CMainTab extends CAbstractMainTab {
config.setAttribute(ICDTLaunchConfigurationConstants.ATTR_PROJECT_BUILD_CONFIG_ID, EMPTY_STRING); config.setAttribute(ICDTLaunchConfigurationConstants.ATTR_PROJECT_BUILD_CONFIG_ID, EMPTY_STRING);
config.setAttribute(ICDTLaunchConfigurationConstants.ATTR_COREFILE_PATH, EMPTY_STRING); config.setAttribute(ICDTLaunchConfigurationConstants.ATTR_COREFILE_PATH, EMPTY_STRING);
// Set the auto choose build configuration to true for new configurations.
// Existing configurations created before this setting was introduced will have this disabled.
config.setAttribute(ICDTLaunchConfigurationConstants.ATTR_PROJECT_BUILD_CONFIG_AUTO, true);
ICElement cElement = null; ICElement cElement = null;
cElement = getContext(config, getPlatform(config)); cElement = getContext(config, getPlatform(config));
if (cElement != null) { if (cElement != null) {

View file

@ -2,7 +2,7 @@ Manifest-Version: 1.0
Bundle-ManifestVersion: 2 Bundle-ManifestVersion: 2
Bundle-Name: %pluginName Bundle-Name: %pluginName
Bundle-SymbolicName: org.eclipse.cdt.launch; singleton:=true Bundle-SymbolicName: org.eclipse.cdt.launch; singleton:=true
Bundle-Version: 6.1.0.qualifier Bundle-Version: 6.2.0.qualifier
Bundle-Activator: org.eclipse.cdt.launch.internal.ui.LaunchUIPlugin Bundle-Activator: org.eclipse.cdt.launch.internal.ui.LaunchUIPlugin
Bundle-Vendor: %providerName Bundle-Vendor: %providerName
Bundle-Localization: plugin Bundle-Localization: plugin

View file

@ -10,6 +10,7 @@
* Andrew Ferguson (andrew.ferguson@arm.com) - bug 123997 * Andrew Ferguson (andrew.ferguson@arm.com) - bug 123997
* Ken Ryall (Nokia) - bug 178731 * Ken Ryall (Nokia) - bug 178731
* Anton Leherbauer (Wind River Systems) - bug 224187 * Anton Leherbauer (Wind River Systems) - bug 224187
* Alex Collins (Broadcom Corp.) - choose build config automatically
*******************************************************************************/ *******************************************************************************/
package org.eclipse.cdt.launch; package org.eclipse.cdt.launch;
@ -126,6 +127,7 @@ abstract public class AbstractCLaunchDelegate extends LaunchConfigurationDelegat
} }
} }
private static final String EMPTY_STR = ""; //$NON-NLS-1$
public AbstractCLaunchDelegate() { public AbstractCLaunchDelegate() {
super(); super();
@ -619,18 +621,29 @@ abstract public class AbstractCLaunchDelegate extends LaunchConfigurationDelegat
} }
/** /**
* Sets up a project for building by making sure the active configuration is the one used * Sets up a project for building by making sure the active configuration is set to the configuration chosen to
* when the launch was created. * be built before the launch.
* @param configuration *
* @param buildProject * If the configuration to be built before launch was set to be automatically discovered, it is set to the unique
* build configuration for the project that outputs to the directory containing the program to be launched.
*
* @param configuration The launch configuration being launched.
* @param buildProject The project to be build before the launch configuration is launched.
*/ */
private void setBuildConfiguration(ILaunchConfiguration configuration, IProject buildProject) { private void setBuildConfiguration(ILaunchConfiguration configuration, IProject buildProject) {
try { try {
String buildConfigID = configuration.getAttribute(ICDTLaunchConfigurationConstants.ATTR_PROJECT_BUILD_CONFIG_ID, ""); //$NON-NLS-1$
ICProjectDescription projDes = CDTPropertyManager.getProjectDescription(buildProject); ICProjectDescription projDes = CDTPropertyManager.getProjectDescription(buildProject);
String buildConfigID = null;
if (configuration.getAttribute(ICDTLaunchConfigurationConstants.ATTR_PROJECT_BUILD_CONFIG_AUTO, false)) {
String programPath = configuration.getAttribute(ICDTLaunchConfigurationConstants.ATTR_PROGRAM_NAME, EMPTY_STR);
ICConfigurationDescription buildConfig = LaunchUtils.getBuildConfigByProgramPath(buildProject, programPath);
if (buildConfig != null)
buildConfigID = buildConfig.getId();
} else
buildConfigID = configuration.getAttribute(ICDTLaunchConfigurationConstants.ATTR_PROJECT_BUILD_CONFIG_ID, EMPTY_STR);
if (buildConfigID.length() > 0 && projDes != null) if (buildConfigID != null && buildConfigID.length() > 0 && projDes != null)
{ {
ICConfigurationDescription buildConfiguration = projDes.getConfigurationById(buildConfigID); ICConfigurationDescription buildConfiguration = projDes.getConfigurationById(buildConfigID);
if (buildConfiguration != null) { if (buildConfiguration != null) {

View file

@ -242,11 +242,23 @@ public abstract class AbstractCLaunchDelegate2 extends LaunchConfigurationDelega
if (buildBeforeLaunchValue == ICDTLaunchConfigurationConstants.BUILD_BEFORE_LAUNCH_DISABLED) { if (buildBeforeLaunchValue == ICDTLaunchConfigurationConstants.BUILD_BEFORE_LAUNCH_DISABLED) {
return false; return false;
} }
String buildConfigID = null;
// If automatic configuration detection then discover the build config corresponding to the executable
if (configuration.getAttribute(ICDTLaunchConfigurationConstants.ATTR_PROJECT_BUILD_CONFIG_AUTO, false)) {
String programPath = configuration.getAttribute(ICDTLaunchConfigurationConstants.ATTR_PROGRAM_NAME, ""); //$NON-NLS-1$
ICConfigurationDescription buildConfig = LaunchUtils.getBuildConfigByProgramPath(project, programPath);
if (buildConfig != null)
buildConfigID = buildConfig.getId();
}
// The attribute value will be "" if 'Use Active' is selected // The attribute value will be "" if 'Use Active' is selected
String buildConfigID = configuration.getAttribute(ICDTLaunchConfigurationConstants.ATTR_PROJECT_BUILD_CONFIG_ID, ""); //$NON-NLS-1$ if (buildConfigID == null) {
if (buildConfigID.length() == 0) { buildConfigID = configuration.getAttribute(ICDTLaunchConfigurationConstants.ATTR_PROJECT_BUILD_CONFIG_ID, ""); //$NON-NLS-1$
buildConfigID = null; if (buildConfigID.length() == 0) {
buildConfigID = null;
}
} }
// There's no guarantee the ID stored in the launch config is valid. // There's no guarantee the ID stored in the launch config is valid.

View file

@ -7,6 +7,7 @@
* *
* Contributors: * Contributors:
* QNX Software Systems - Initial API and implementation * QNX Software Systems - Initial API and implementation
* Alex Collins (Broadcom Corp.) - choose build config automatically
*******************************************************************************/ *******************************************************************************/
package org.eclipse.cdt.launch; package org.eclipse.cdt.launch;
@ -18,8 +19,17 @@ import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.IBinaryParser; import org.eclipse.cdt.core.IBinaryParser;
import org.eclipse.cdt.core.IBinaryParser.IBinaryObject; import org.eclipse.cdt.core.IBinaryParser.IBinaryObject;
import org.eclipse.cdt.core.ICExtensionReference; import org.eclipse.cdt.core.ICExtensionReference;
import org.eclipse.cdt.core.model.CoreModel;
import org.eclipse.cdt.core.settings.model.ICConfigurationDescription;
import org.eclipse.cdt.core.settings.model.ICOutputEntry;
import org.eclipse.cdt.core.settings.model.ICProjectDescription;
import org.eclipse.cdt.core.settings.model.extension.CBuildData;
import org.eclipse.cdt.core.settings.model.extension.CConfigurationData;
import org.eclipse.cdt.core.settings.model.util.CDataUtil;
import org.eclipse.cdt.debug.core.ICDTLaunchConfigurationConstants; import org.eclipse.cdt.debug.core.ICDTLaunchConfigurationConstants;
import org.eclipse.cdt.internal.core.resources.ResourceLookup;
import org.eclipse.cdt.utils.CommandLineUtil; import org.eclipse.cdt.utils.CommandLineUtil;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.CoreException;
@ -141,4 +151,63 @@ public class LaunchUtils {
} }
/**
* Get the build configuration that most likely builds the given program path.
* The build configuration is chosen as the one that outputs to a directory that contains
* the given program.
*
* @param projectDesc The description for the project in which to search for the configuration.
* @param programPath The path to the program to search the build configurations for
* @return The build configuration that builds programName; or null if none or more than one were found.
* @since 6.2
*/
public static ICConfigurationDescription getBuildConfigByProgramPath(IProject project, String programPath) {
if (project == null || programPath == null)
return null;
ICProjectDescription projectDesc = CoreModel.getDefault().getProjectDescription(project, false);
if (projectDesc == null)
return null;
// If the program path is relative, it must be relative to the projects root
IPath path = new Path(programPath);
if (!path.isAbsolute()) {
IPath projLocation = project.getLocation();
if (projLocation == null)
return null;
path = projLocation.append(path);
}
// Get all possible files that the program path could refer to
IFile[] files = ResourceLookup.findFilesForLocation(path);
// Find the build config whose output directory matches one of the possible files
ICConfigurationDescription buildConfig = null;
findCfg: for (ICConfigurationDescription cfgDes : projectDesc.getConfigurations()) {
CConfigurationData cfgData = cfgDes.getConfigurationData();
if (cfgData == null)
continue;
CBuildData buildData = cfgData.getBuildData();
if (buildData == null)
continue;
for (ICOutputEntry dir : buildData.getOutputDirectories()) {
ICOutputEntry absoluteDir = CDataUtil.makeAbsolute(project, dir);
if (absoluteDir == null)
continue;
IPath dirLocation = absoluteDir.getLocation();
if (dirLocation == null)
continue;
for (IFile file : files) {
if (dirLocation.isPrefixOf(file.getLocation())) {
if (buildConfig != null && buildConfig != cfgDes) {
// Matched more than one, so use the active configuration
buildConfig = null;
break findCfg;
}
buildConfig = cfgDes;
}
}
}
}
return buildConfig;
}
} }

View file

@ -87,6 +87,7 @@ CMainTab.Program_is_not_a_recongnized_executable=Program is not a recognized exe
CMainTab.Program_invalid_proj_path=Program specification is not a valid project-relative path. CMainTab.Program_invalid_proj_path=Program specification is not a valid project-relative path.
CMainTab.Build_Config=Build configuration: CMainTab.Build_Config=Build configuration:
CMainTab.Use_Active=Use Active CMainTab.Use_Active=Use Active
CMainTab.Build_Config_Auto=Select configuration using 'C/C++ Application'
#For CMainTab.Configuration_name: {0} - project name; {1} - configuration name #For CMainTab.Configuration_name: {0} - project name; {1} - configuration name
CMainTab.Configuration_name={0} {1} CMainTab.Configuration_name={0} {1}
CMainTab.Build_options=Build (if required) before launching CMainTab.Build_options=Build (if required) before launching

View file

@ -8,6 +8,7 @@
* Contributors: * Contributors:
* Ken Ryall (Nokia) - initial API and implementation * Ken Ryall (Nokia) - initial API and implementation
* IBM Corporation * IBM Corporation
* Alex Collins (Broadcom Corp.) - choose build config automatically
*******************************************************************************/ *******************************************************************************/
package org.eclipse.cdt.launch.ui; package org.eclipse.cdt.launch.ui;
@ -16,8 +17,8 @@ import java.util.HashMap;
import java.util.Map; import java.util.Map;
import org.eclipse.cdt.core.CCorePlugin; import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.ICDescriptor;
import org.eclipse.cdt.core.IBinaryParser.IBinaryObject; import org.eclipse.cdt.core.IBinaryParser.IBinaryObject;
import org.eclipse.cdt.core.ICDescriptor;
import org.eclipse.cdt.core.model.CModelException; import org.eclipse.cdt.core.model.CModelException;
import org.eclipse.cdt.core.model.CoreModel; import org.eclipse.cdt.core.model.CoreModel;
import org.eclipse.cdt.core.model.IBinary; import org.eclipse.cdt.core.model.IBinary;
@ -72,6 +73,12 @@ public abstract class CAbstractMainTab extends CLaunchConfigurationTab {
* @since 6.0 * @since 6.0
*/ */
protected Combo fBuildConfigCombo; protected Combo fBuildConfigCombo;
/** @since 6.2 */
protected Button fBuildConfigAuto;
/** Indicates whether the user has clicked on the build config auto button
* Prevents causing a delta to the underlying launch configuration if the user hasn't touched this setting.
* @since 6.2 */
protected boolean fBuildConfigAutoChanged;
/** @since 6.1 */ /** @since 6.1 */
protected Button fDisableBuildButton; protected Button fDisableBuildButton;
/** @since 6.1 */ /** @since 6.1 */
@ -262,6 +269,7 @@ public abstract class CAbstractMainTab extends CLaunchConfigurationTab {
protected void updateBuildConfigCombo(String selectedConfigID) { protected void updateBuildConfigCombo(String selectedConfigID) {
if (fBuildConfigCombo != null) if (fBuildConfigCombo != null)
{ {
fBuildConfigCombo.setEnabled(!fBuildConfigAuto.getSelection());
fBuildConfigCombo.removeAll(); fBuildConfigCombo.removeAll();
fBuildConfigCombo.add(LaunchMessages.getString("CMainTab.Use_Active")); //$NON-NLS-1$ fBuildConfigCombo.add(LaunchMessages.getString("CMainTab.Use_Active")); //$NON-NLS-1$
fBuildConfigCombo.setData("0", ""); //$NON-NLS-1$ //$NON-NLS-2$ fBuildConfigCombo.setData("0", ""); //$NON-NLS-1$ //$NON-NLS-2$
@ -272,6 +280,14 @@ public abstract class CAbstractMainTab extends CLaunchConfigurationTab {
ICProjectDescription projDes = CDTPropertyManager.getProjectDescription(cproject.getProject()); ICProjectDescription projDes = CDTPropertyManager.getProjectDescription(cproject.getProject());
if (projDes != null) if (projDes != null)
{ {
// Find the config that should be automatically selected
String autoConfigId = null;
if (fBuildConfigAuto.getSelection()) {
ICConfigurationDescription autoConfig = LaunchUtils.getBuildConfigByProgramPath(cproject.getProject(), fProgText.getText());
if (autoConfig != null)
autoConfigId = autoConfig.getId();
}
int selIndex = 0; int selIndex = 0;
ICConfigurationDescription[] configurations = projDes.getConfigurations(); ICConfigurationDescription[] configurations = projDes.getConfigurations();
ICConfigurationDescription selectedConfig = projDes.getConfigurationById(selectedConfigID); ICConfigurationDescription selectedConfig = projDes.getConfigurationById(selectedConfigID);
@ -279,8 +295,10 @@ public abstract class CAbstractMainTab extends CLaunchConfigurationTab {
String configName = configurations[i].getName(); String configName = configurations[i].getName();
fBuildConfigCombo.add(configName); fBuildConfigCombo.add(configName);
fBuildConfigCombo.setData(Integer.toString(i + 1), configurations[i].getId()); fBuildConfigCombo.setData(Integer.toString(i + 1), configurations[i].getId());
if (selectedConfig != null && selectedConfigID.equals(configurations[i].getId())) if (selectedConfig != null && selectedConfigID.equals(configurations[i].getId()) ||
fBuildConfigAuto.getSelection() && configurations[i].getId().equals(autoConfigId)) {
selIndex = i + 1; selIndex = i + 1;
}
} }
fBuildConfigCombo.select(selIndex); fBuildConfigCombo.select(selIndex);
} }
@ -313,6 +331,26 @@ public abstract class CAbstractMainTab extends CLaunchConfigurationTab {
updateLaunchConfigurationDialog(); updateLaunchConfigurationDialog();
} }
}); });
new Label(comboComp, SWT.NONE).setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
fBuildConfigAuto = new Button(comboComp, SWT.CHECK);
fBuildConfigAuto.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
fBuildConfigAuto.setText(LaunchMessages.getString("CMainTab.Build_Config_Auto")); //$NON-NLS-1$
fBuildConfigAuto.addSelectionListener(new SelectionListener() {
public void widgetSelected(SelectionEvent e) {
fBuildConfigAutoChanged = true;
fBuildConfigCombo.setEnabled(false);
updateBuildConfigCombo(""); //$NON-NLS-1$
updateLaunchConfigurationDialog();
}
public void widgetDefaultSelected(SelectionEvent e) {
fBuildConfigAutoChanged = true;
fBuildConfigCombo.setEnabled(true);
updateBuildConfigCombo(""); //$NON-NLS-1$
updateLaunchConfigurationDialog();
}
});
} }
/** @since 6.1 */ /** @since 6.1 */
@ -377,13 +415,20 @@ public abstract class CAbstractMainTab extends CLaunchConfigurationTab {
/** @since 6.1 */ /** @since 6.1 */
protected void updateBuildOptionFromConfig(ILaunchConfiguration config) { protected void updateBuildOptionFromConfig(ILaunchConfiguration config) {
boolean configAuto = false;
int buildBeforeLaunchValue = ICDTLaunchConfigurationConstants.BUILD_BEFORE_LAUNCH_USE_WORKSPACE_SETTING; int buildBeforeLaunchValue = ICDTLaunchConfigurationConstants.BUILD_BEFORE_LAUNCH_USE_WORKSPACE_SETTING;
try { try {
buildBeforeLaunchValue = config.getAttribute(ICDTLaunchConfigurationConstants.ATTR_BUILD_BEFORE_LAUNCH, buildBeforeLaunchValue); buildBeforeLaunchValue = config.getAttribute(ICDTLaunchConfigurationConstants.ATTR_BUILD_BEFORE_LAUNCH, buildBeforeLaunchValue);
configAuto = config.getAttribute(ICDTLaunchConfigurationConstants.ATTR_PROJECT_BUILD_CONFIG_AUTO, false);
} catch (CoreException e) { } catch (CoreException e) {
LaunchUIPlugin.log(e); LaunchUIPlugin.log(e);
} }
if (fBuildConfigAuto != null) {
fBuildConfigAuto.setSelection(configAuto);
if (configAuto)
updateBuildConfigCombo(""); //$NON-NLS-1$
}
if (fDisableBuildButton != null) if (fDisableBuildButton != null)
fDisableBuildButton.setSelection(buildBeforeLaunchValue == ICDTLaunchConfigurationConstants.BUILD_BEFORE_LAUNCH_DISABLED); fDisableBuildButton.setSelection(buildBeforeLaunchValue == ICDTLaunchConfigurationConstants.BUILD_BEFORE_LAUNCH_DISABLED);
if (fEnableBuildButton != null) if (fEnableBuildButton != null)
@ -501,6 +546,10 @@ public abstract class CAbstractMainTab extends CLaunchConfigurationTab {
config.setAttribute(ICDTLaunchConfigurationConstants.ATTR_PROJECT_BUILD_CONFIG_ID, (String)fBuildConfigCombo.getData(Integer.toString(fBuildConfigCombo.getSelectionIndex()))); config.setAttribute(ICDTLaunchConfigurationConstants.ATTR_PROJECT_BUILD_CONFIG_ID, (String)fBuildConfigCombo.getData(Integer.toString(fBuildConfigCombo.getSelectionIndex())));
} }
if (fBuildConfigAutoChanged && fBuildConfigAuto != null) {
config.setAttribute(ICDTLaunchConfigurationConstants.ATTR_PROJECT_BUILD_CONFIG_AUTO, fBuildConfigAuto.getSelection());
}
if (fDisableBuildButton != null) { if (fDisableBuildButton != null) {
int buildBeforeLaunchValue = ICDTLaunchConfigurationConstants.BUILD_BEFORE_LAUNCH_USE_WORKSPACE_SETTING; int buildBeforeLaunchValue = ICDTLaunchConfigurationConstants.BUILD_BEFORE_LAUNCH_USE_WORKSPACE_SETTING;
if (fDisableBuildButton.getSelection()) { if (fDisableBuildButton.getSelection()) {
@ -545,6 +594,8 @@ public abstract class CAbstractMainTab extends CLaunchConfigurationTab {
*/ */
@Override @Override
protected void updateLaunchConfigurationDialog() { protected void updateLaunchConfigurationDialog() {
if (fBuildConfigAuto.getSelection())
updateBuildConfigCombo(""); //$NON-NLS-1$
super.updateLaunchConfigurationDialog(); super.updateLaunchConfigurationDialog();
} }

View file

@ -535,6 +535,10 @@ public class CMainTab extends CAbstractMainTab {
config.setAttribute(ICDTLaunchConfigurationConstants.ATTR_PROJECT_BUILD_CONFIG_ID, EMPTY_STRING); config.setAttribute(ICDTLaunchConfigurationConstants.ATTR_PROJECT_BUILD_CONFIG_ID, EMPTY_STRING);
config.setAttribute(ICDTLaunchConfigurationConstants.ATTR_COREFILE_PATH, EMPTY_STRING); config.setAttribute(ICDTLaunchConfigurationConstants.ATTR_COREFILE_PATH, EMPTY_STRING);
// Set the auto choose build configuration to true for new configurations.
// Existing configurations created before this setting was introduced will have this disabled.
config.setAttribute(ICDTLaunchConfigurationConstants.ATTR_PROJECT_BUILD_CONFIG_AUTO, true);
ICElement cElement = null; ICElement cElement = null;
cElement = getContext(config, getPlatform(config)); cElement = getContext(config, getPlatform(config));
if (cElement != null) { if (cElement != null) {