mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-06-07 17:56:01 +02:00
Bug 309126: Build before launch does too much building with project references
This commit is contained in:
parent
c58a08aaad
commit
72fbc7d394
4 changed files with 472 additions and 102 deletions
|
@ -234,6 +234,18 @@
|
||||||
plugin="org.eclipse.cdt.launch"
|
plugin="org.eclipse.cdt.launch"
|
||||||
class="org.eclipse.cdt.launch.internal.ui.CoreFilePrompter"
|
class="org.eclipse.cdt.launch.internal.ui.CoreFilePrompter"
|
||||||
id="org.eclipse.cdt.launch.statusHandler.coreFilePrompter">
|
id="org.eclipse.cdt.launch.statusHandler.coreFilePrompter">
|
||||||
|
</statusHandler>
|
||||||
|
<statusHandler
|
||||||
|
class="org.eclipse.cdt.launch.internal.ui.BuildErrPrompter"
|
||||||
|
code="1002"
|
||||||
|
id="org.eclipse.cdt.launch.statusHandler.buildErrPrompter"
|
||||||
|
plugin="org.eclipse.cdt.launch">
|
||||||
|
</statusHandler>
|
||||||
|
<statusHandler
|
||||||
|
class="org.eclipse.cdt.launch.internal.ui.BuildErrPrompter"
|
||||||
|
code="1003"
|
||||||
|
id="org.eclipse.cdt.launch.statusHandler.buildErrPrompter"
|
||||||
|
plugin="org.eclipse.cdt.launch">
|
||||||
</statusHandler>
|
</statusHandler>
|
||||||
</extension>
|
</extension>
|
||||||
|
|
||||||
|
|
|
@ -11,30 +11,44 @@
|
||||||
package org.eclipse.cdt.launch;
|
package org.eclipse.cdt.launch;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.core.CCorePlugin;
|
||||||
import org.eclipse.cdt.core.model.ICModelMarker;
|
import org.eclipse.cdt.core.model.ICModelMarker;
|
||||||
import org.eclipse.cdt.core.model.ICProject;
|
import org.eclipse.cdt.core.model.ICProject;
|
||||||
import org.eclipse.cdt.core.settings.model.ICConfigurationDescription;
|
import org.eclipse.cdt.core.settings.model.ICConfigurationDescription;
|
||||||
import org.eclipse.cdt.core.settings.model.ICProjectDescription;
|
import org.eclipse.cdt.core.settings.model.ICProjectDescription;
|
||||||
import org.eclipse.cdt.debug.core.CDebugUtils;
|
import org.eclipse.cdt.debug.core.CDebugUtils;
|
||||||
import org.eclipse.cdt.debug.core.ICDTLaunchConfigurationConstants;
|
import org.eclipse.cdt.debug.core.ICDTLaunchConfigurationConstants;
|
||||||
|
import org.eclipse.cdt.launch.internal.ui.BuildErrPrompter;
|
||||||
import org.eclipse.cdt.launch.internal.ui.LaunchMessages;
|
import org.eclipse.cdt.launch.internal.ui.LaunchMessages;
|
||||||
import org.eclipse.cdt.ui.newui.CDTPropertyManager;
|
import org.eclipse.cdt.launch.internal.ui.LaunchUIPlugin;
|
||||||
|
import org.eclipse.core.resources.ICommand;
|
||||||
import org.eclipse.core.resources.IMarker;
|
import org.eclipse.core.resources.IMarker;
|
||||||
import org.eclipse.core.resources.IProject;
|
import org.eclipse.core.resources.IProject;
|
||||||
import org.eclipse.core.resources.IResource;
|
import org.eclipse.core.resources.IResource;
|
||||||
|
import org.eclipse.core.resources.IWorkspaceRunnable;
|
||||||
import org.eclipse.core.resources.IncrementalProjectBuilder;
|
import org.eclipse.core.resources.IncrementalProjectBuilder;
|
||||||
import org.eclipse.core.resources.ResourcesPlugin;
|
import org.eclipse.core.resources.ResourcesPlugin;
|
||||||
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.MultiStatus;
|
import org.eclipse.core.runtime.MultiStatus;
|
||||||
|
import org.eclipse.core.runtime.OperationCanceledException;
|
||||||
import org.eclipse.core.runtime.Status;
|
import org.eclipse.core.runtime.Status;
|
||||||
import org.eclipse.core.runtime.SubProgressMonitor;
|
import org.eclipse.core.runtime.SubMonitor;
|
||||||
|
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.IStatusHandler;
|
||||||
import org.eclipse.debug.core.model.LaunchConfigurationDelegate;
|
import org.eclipse.debug.core.model.LaunchConfigurationDelegate;
|
||||||
|
import org.eclipse.debug.internal.core.DebugCoreMessages;
|
||||||
|
import org.eclipse.debug.internal.core.IInternalDebugCoreConstants;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* AbstractCLaunchDelegate2 is used by most DSF based debuggers. It replaces AbstractCLaunchDelegate
|
* AbstractCLaunchDelegate2 is used by most DSF based debuggers. It replaces AbstractCLaunchDelegate
|
||||||
|
@ -53,8 +67,6 @@ public abstract class AbstractCLaunchDelegate2 extends LaunchConfigurationDelega
|
||||||
|
|
||||||
private boolean workspaceBuildBeforeLaunch;
|
private boolean workspaceBuildBeforeLaunch;
|
||||||
private boolean requireCProject;
|
private boolean requireCProject;
|
||||||
private IProject project;
|
|
||||||
private String preLaunchBuildConfiguration;
|
|
||||||
|
|
||||||
public AbstractCLaunchDelegate2() {
|
public AbstractCLaunchDelegate2() {
|
||||||
super();
|
super();
|
||||||
|
@ -91,8 +103,14 @@ public abstract class AbstractCLaunchDelegate2 extends LaunchConfigurationDelega
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the order list of projects to build before launching.
|
* Even though we override the base behavior and only build the single
|
||||||
* Used in buildForLaunch()
|
* project referenced in the launch configuration (and not any of the
|
||||||
|
* projects it references), we still want to implement this as the base will
|
||||||
|
* also use the list to determine what files need be saved, and there it's
|
||||||
|
* not much of a burden to include any referenced projects
|
||||||
|
*
|
||||||
|
* @see org.eclipse.debug.core.model.LaunchConfigurationDelegate#getBuildOrder(org.eclipse.debug.core.ILaunchConfiguration,
|
||||||
|
* java.lang.String)
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
protected IProject[] getBuildOrder(ILaunchConfiguration configuration, String mode) throws CoreException {
|
protected IProject[] getBuildOrder(ILaunchConfiguration configuration, String mode) throws CoreException {
|
||||||
|
@ -133,12 +151,6 @@ public abstract class AbstractCLaunchDelegate2 extends LaunchConfigurationDelega
|
||||||
return orderedProjects;
|
return orderedProjects;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Used in finalLaunchCheck() */
|
|
||||||
@Override
|
|
||||||
protected IProject[] getProjectsForProblemSearch(ILaunchConfiguration configuration, String mode) throws CoreException {
|
|
||||||
return getBuildOrder(configuration, mode);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Searches for compile errors in the specified project
|
* Searches for compile errors in the specified project
|
||||||
* Used in finalLaunchCheck()
|
* Used in finalLaunchCheck()
|
||||||
|
@ -190,8 +202,7 @@ public abstract class AbstractCLaunchDelegate2 extends LaunchConfigurationDelega
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Builds the current project and all of it's prerequisite projects if
|
* Builds the project referenced in the launch configuration
|
||||||
* necessary. Respects specified build order if any exists.
|
|
||||||
*
|
*
|
||||||
* @param configuration
|
* @param configuration
|
||||||
* the configuration being launched
|
* the configuration being launched
|
||||||
|
@ -206,59 +217,295 @@ public abstract class AbstractCLaunchDelegate2 extends LaunchConfigurationDelega
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public boolean buildForLaunch(ILaunchConfiguration configuration, String mode, IProgressMonitor monitor) throws CoreException {
|
public boolean buildForLaunch(ILaunchConfiguration configuration, String mode, IProgressMonitor monitor) throws CoreException {
|
||||||
|
try {
|
||||||
|
SubMonitor submon = SubMonitor.convert(monitor, "", 1); //$NON-NLS-1$
|
||||||
|
|
||||||
workspaceBuildBeforeLaunch = true;
|
workspaceBuildBeforeLaunch = true;
|
||||||
|
|
||||||
// check the build before launch setting and honor it
|
IProject project = null;
|
||||||
int buildBeforeLaunchValue = configuration.getAttribute(ICDTLaunchConfigurationConstants.ATTR_BUILD_BEFORE_LAUNCH,
|
ICProject cProject = CDebugUtils.getCProject(configuration);
|
||||||
ICDTLaunchConfigurationConstants.BUILD_BEFORE_LAUNCH_USE_WORKSPACE_SETTING);
|
if (cProject != null) {
|
||||||
|
project = cProject.getProject();
|
||||||
|
}
|
||||||
|
|
||||||
// we shouldn't be getting called if the workspace setting is disabled, so assume we need to
|
if (project == null) {
|
||||||
// build unless the user explicitly disabled it in the main tab of the launch.
|
return false;
|
||||||
if (buildBeforeLaunchValue == ICDTLaunchConfigurationConstants.BUILD_BEFORE_LAUNCH_DISABLED) {
|
}
|
||||||
|
|
||||||
|
// check the build before launch setting and honor it
|
||||||
|
int buildBeforeLaunchValue = configuration.getAttribute(ICDTLaunchConfigurationConstants.ATTR_BUILD_BEFORE_LAUNCH,
|
||||||
|
ICDTLaunchConfigurationConstants.BUILD_BEFORE_LAUNCH_USE_WORKSPACE_SETTING);
|
||||||
|
|
||||||
|
// we shouldn't be getting called if the workspace setting is disabled, so assume we need to
|
||||||
|
// build unless the user explicitly disabled it in the main tab of the launch.
|
||||||
|
if (buildBeforeLaunchValue == ICDTLaunchConfigurationConstants.BUILD_BEFORE_LAUNCH_DISABLED) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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.length() == 0) {
|
||||||
|
buildConfigID = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
buildProject(project, buildConfigID, submon.newChild(1));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
finally {
|
||||||
setBuildConfiguration(configuration, project);
|
if (monitor != null) {
|
||||||
|
monitor.done();
|
||||||
return super.buildForLaunch(configuration, mode, monitor);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean preLaunchCheck(ILaunchConfiguration configuration, String mode, IProgressMonitor monitor) throws CoreException {
|
|
||||||
ICProject cProject = CDebugUtils.getCProject(configuration);
|
|
||||||
if (cProject != null) {
|
|
||||||
project = cProject.getProject();
|
|
||||||
}
|
}
|
||||||
return super.preLaunchCheck(configuration, mode, monitor);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
/**
|
||||||
public boolean finalLaunchCheck(ILaunchConfiguration configuration, String mode, IProgressMonitor monitor) throws CoreException {
|
* This is an specialization of the platform method
|
||||||
if (!workspaceBuildBeforeLaunch) {
|
* LaunchConfigurationDelegate#buildProjects(IProject[], IProgressMonitor).
|
||||||
// buildForLaunch was not called which means that the workspace pref is disabled. see if the user enabled the
|
* It builds only one project and it builds a particular CDT build
|
||||||
// launch specific setting in the main tab. if so, we do call buildBeforeLaunch here.
|
* configuration of it. It was added to address bug 309126 and 312709
|
||||||
if (ICDTLaunchConfigurationConstants.BUILD_BEFORE_LAUNCH_ENABLED == configuration.getAttribute(ICDTLaunchConfigurationConstants.ATTR_BUILD_BEFORE_LAUNCH,
|
*
|
||||||
ICDTLaunchConfigurationConstants.BUILD_BEFORE_LAUNCH_USE_WORKSPACE_SETTING)) {
|
* @param project
|
||||||
|
* the project to build
|
||||||
|
* @param buildConfigID
|
||||||
|
* the specific build configuration to build, or null to build
|
||||||
|
* the active one
|
||||||
|
* @param monitor
|
||||||
|
* progress monitor
|
||||||
|
* @throws CoreException
|
||||||
|
*/
|
||||||
|
protected void buildProject(final IProject project, final String buildConfigID, IProgressMonitor monitor) throws CoreException {
|
||||||
|
|
||||||
IProgressMonitor buildMonitor = new SubProgressMonitor(monitor, 10, SubProgressMonitor.PREPEND_MAIN_LABEL_TO_SUBTASK);
|
// Some day, this will hopefully be a simple pass-thru to a cdt.core
|
||||||
buildMonitor.beginTask(LaunchMessages.getString("AbstractCLaunchDelegate.BuildBeforeLaunch"), 10); //$NON-NLS-1$
|
// utility. See bug 313927
|
||||||
buildMonitor.subTask(LaunchMessages.getString("AbstractCLaunchDelegate.PerformingBuild")); //$NON-NLS-1$
|
|
||||||
if (buildForLaunch(configuration, mode, new SubProgressMonitor(buildMonitor, 7))) {
|
IWorkspaceRunnable build = new IWorkspaceRunnable(){
|
||||||
buildMonitor.subTask(LaunchMessages.getString("AbstractCLaunchDelegate.PerformingIncrementalBuild")); //$NON-NLS-1$
|
public void run(IProgressMonitor pm) throws CoreException {
|
||||||
ResourcesPlugin.getWorkspace().build(IncrementalProjectBuilder.INCREMENTAL_BUILD, new SubProgressMonitor(buildMonitor, 3));
|
final int TOTAL_TICKS = 1000;
|
||||||
|
SubMonitor localmonitor = SubMonitor.convert(pm, "", TOTAL_TICKS); //$NON-NLS-1$
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Number of times we'll end up calling IProject.build()
|
||||||
|
final int buildCount = (buildConfigID == null) ? 1 : project.getDescription().getBuildSpec().length;
|
||||||
|
final int subtaskTicks = TOTAL_TICKS / buildCount;
|
||||||
|
|
||||||
|
if (buildConfigID != null) {
|
||||||
|
// Build a specific configuration
|
||||||
|
|
||||||
|
// To pass args, we have to specify the builder name.
|
||||||
|
// There can be multiple so this can require multiple
|
||||||
|
// builds. Note that this happens under the covers in
|
||||||
|
// the 'else' (args-less) case below
|
||||||
|
Map<String,String> cfgIdArgs = AbstractCLaunchDelegate2.cfgIdsToMap(new String[] {buildConfigID}, new HashMap<String,String>());
|
||||||
|
cfgIdArgs.put(CONTENTS, CONTENTS_CONFIGURATION_IDS);
|
||||||
|
ICommand[] commands = project.getDescription().getBuildSpec();
|
||||||
|
assert buildCount == commands.length;
|
||||||
|
for (ICommand command : commands) {
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
Map<String, String> args = command.getArguments();
|
||||||
|
if (args == null) {
|
||||||
|
args = new HashMap<String, String>(cfgIdArgs);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
args.putAll(cfgIdArgs);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (localmonitor.isCanceled()) {
|
||||||
|
throw new OperationCanceledException();
|
||||||
|
}
|
||||||
|
project.build(IncrementalProjectBuilder.INCREMENTAL_BUILD, command.getBuilderName(), args, localmonitor.newChild(subtaskTicks));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Build the active configuration
|
||||||
|
project.build(IncrementalProjectBuilder.INCREMENTAL_BUILD, localmonitor.newChild(subtaskTicks));
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
if (pm != null) {
|
||||||
|
pm.done();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
}
|
||||||
buildMonitor.worked(3); /* No incremental build required */
|
};
|
||||||
|
ResourcesPlugin.getWorkspace().run(build, monitor);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** TODO: Temporarily duplicated from BuilderFactory. Remove when 313927 is addressed */
|
||||||
|
static final String CONFIGURATION_IDS = "org.eclipse.cdt.make.core.configurationIds"; //$NON-NLS-1$
|
||||||
|
|
||||||
|
/** TODO: Temporarily duplicated from BuilderFactory. Remove when 313927 is addressed */
|
||||||
|
static final String CONTENTS = "org.eclipse.cdt.make.core.contents"; //$NON-NLS-1$
|
||||||
|
|
||||||
|
/** TODO: Temporarily duplicated from BuilderFactory. Remove when 313927 is addressed */
|
||||||
|
static final String CONTENTS_CONFIGURATION_IDS = "org.eclipse.cdt.make.core.configurationIds"; //$NON-NLS-1$
|
||||||
|
|
||||||
|
/** TODO: Temporarily duplicated from BuilderFactory. Remove when 313927 is addressed */
|
||||||
|
private static Map<String, String> cfgIdsToMap(String ids[], Map<String, String> map){
|
||||||
|
map.put(CONFIGURATION_IDS, encodeList(Arrays.asList(ids)));
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** TODO: Temporarily duplicated from BuilderFactory. Remove when 313927 is addressed */
|
||||||
|
private static String encodeList(List<String> values) {
|
||||||
|
StringBuffer str = new StringBuffer();
|
||||||
|
Iterator<String> entries = values.iterator();
|
||||||
|
while (entries.hasNext()) {
|
||||||
|
String entry = entries.next();
|
||||||
|
str.append(escapeChars(entry, "|\\", '\\')); //$NON-NLS-1$
|
||||||
|
str.append("|"); //$NON-NLS-1$
|
||||||
|
}
|
||||||
|
return str.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** TODO: Temporarily duplicated from BuilderFactory. Remove when 313927 is addressed */
|
||||||
|
private static String escapeChars(String string, String escapeChars, char escapeChar) {
|
||||||
|
StringBuffer str = new StringBuffer(string);
|
||||||
|
for (int i = 0; i < str.length(); i++) {
|
||||||
|
if (escapeChars.indexOf(str.charAt(i)) != -1) {
|
||||||
|
str.insert(i, escapeChar);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return str.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The platform has a generic prompter object that redirects to an
|
||||||
|
* appropriate prompter based on the status object. The value-add it
|
||||||
|
* provides is that it can be invoked from a non-GUI thread.
|
||||||
|
*/
|
||||||
|
private static final IStatus uiPromptStatus = new Status(IStatus.ERROR, "org.eclipse.debug.ui", 200, IInternalDebugCoreConstants.EMPTY_STRING, null); //$NON-NLS-1$
|
||||||
|
|
||||||
|
/** Status object used to fish out our BuildErrPrompter */
|
||||||
|
private static final IStatus promptStatusMainProj = new Status(IStatus.ERROR, LaunchUIPlugin.getUniqueIdentifier(), BuildErrPrompter.STATUS_CODE_ERR_IN_MAIN_PROJ, IInternalDebugCoreConstants.EMPTY_STRING, null);
|
||||||
|
|
||||||
|
/** Status object used to fish out our BuildErrPrompter */
|
||||||
|
private static final IStatus promptStatusReferencedProjs = new Status(IStatus.ERROR, LaunchUIPlugin.getUniqueIdentifier(), BuildErrPrompter.STATUS_CODE_ERR_IN_REFERENCED_PROJS, IInternalDebugCoreConstants.EMPTY_STRING, null);
|
||||||
|
|
||||||
|
private Object[] createPrompterArgs(ILaunchConfiguration launchConfig) throws CoreException {
|
||||||
|
|
||||||
|
IProject project = CDebugUtils.getCProject(launchConfig).getProject();
|
||||||
|
|
||||||
|
Object[] args = new Object[3];
|
||||||
|
|
||||||
|
// The launch configuration
|
||||||
|
args[0] = launchConfig;
|
||||||
|
|
||||||
|
// The name of the project
|
||||||
|
args[1] = project.getName();
|
||||||
|
|
||||||
|
// The name of the build configuration. Empty string if the
|
||||||
|
// setting is "Active" or the selected configuration is the
|
||||||
|
// active one, otherwise the name of the configuration.
|
||||||
|
args[2] = ""; //$NON-NLS-1$
|
||||||
|
String buildConfigId = launchConfig.getAttribute(ICDTLaunchConfigurationConstants.ATTR_PROJECT_BUILD_CONFIG_ID, ""); //$NON-NLS-1$
|
||||||
|
if (buildConfigId.length() > 0) {
|
||||||
|
ICProjectDescription desc = CCorePlugin.getDefault().getProjectDescription(project, false);
|
||||||
|
if (desc != null) {
|
||||||
|
ICConfigurationDescription cfgDescActive = desc.getActiveConfiguration();
|
||||||
|
ICConfigurationDescription cfgDesc = desc.getConfigurationById(buildConfigId);
|
||||||
|
if (cfgDesc != cfgDescActive) {
|
||||||
|
if (cfgDesc != null) {
|
||||||
|
args[2] = cfgDesc.getName();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// TODO: not sure if and when this could ever happen, but just in case...
|
||||||
|
args[2] = "???"; //$NON-NLS-1$
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
boolean continueLaunch = super.finalLaunchCheck(configuration, mode, monitor);
|
|
||||||
|
|
||||||
if (continueLaunch) // If no problems then restore the previous build configuration. Otherwise leave it so the user can fix the build issues.
|
return args;
|
||||||
resetBuildConfiguration(project);
|
}
|
||||||
|
|
||||||
return continueLaunch;
|
/* (non-Javadoc)
|
||||||
|
* @see org.eclipse.debug.core.model.LaunchConfigurationDelegate#finalLaunchCheck(org.eclipse.debug.core.ILaunchConfiguration, java.lang.String, org.eclipse.core.runtime.IProgressMonitor)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean finalLaunchCheck(ILaunchConfiguration configuration, String mode, IProgressMonitor monitor) throws CoreException {
|
||||||
|
try {
|
||||||
|
SubMonitor localMonitor = SubMonitor.convert(monitor, LaunchMessages.getString("AbstractCLaunchDelegate.BuildBeforeLaunch"), 10); //$NON-NLS-1$
|
||||||
|
|
||||||
|
if (!workspaceBuildBeforeLaunch) {
|
||||||
|
// buildForLaunch was not called which means that the workspace pref is disabled. see if the user enabled the
|
||||||
|
// launch specific setting in the main tab. if so, we do call buildBeforeLaunch here.
|
||||||
|
if (ICDTLaunchConfigurationConstants.BUILD_BEFORE_LAUNCH_ENABLED == configuration.getAttribute(ICDTLaunchConfigurationConstants.ATTR_BUILD_BEFORE_LAUNCH,
|
||||||
|
ICDTLaunchConfigurationConstants.BUILD_BEFORE_LAUNCH_USE_WORKSPACE_SETTING)) {
|
||||||
|
|
||||||
|
localMonitor.subTask(LaunchMessages.getString("AbstractCLaunchDelegate.PerformingBuild")); //$NON-NLS-1$
|
||||||
|
if (buildForLaunch(configuration, mode, localMonitor.newChild(7))) {
|
||||||
|
localMonitor.subTask(LaunchMessages.getString("AbstractCLaunchDelegate.PerformingIncrementalBuild")); //$NON-NLS-1$
|
||||||
|
ResourcesPlugin.getWorkspace().build(IncrementalProjectBuilder.INCREMENTAL_BUILD, localMonitor.newChild(3));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// We can just call our super's implementation to have it check for
|
||||||
|
// build errors, but it is too generic. It doesn't know the concept
|
||||||
|
// of a CDT build configuration, and the fact that we requested the
|
||||||
|
// build of a particular one (which, btw, may not be the active one
|
||||||
|
// for the project). We want to put up a more informative error
|
||||||
|
// dialog if there are errors.
|
||||||
|
boolean continueLaunch = true;
|
||||||
|
ICProject cproject = CDebugUtils.getCProject(configuration);
|
||||||
|
if (cproject != null) {
|
||||||
|
IProject project = cproject.getProject();
|
||||||
|
localMonitor.subTask(DebugCoreMessages.LaunchConfigurationDelegate_6);
|
||||||
|
if (existsProblems(project)) {
|
||||||
|
// There's a build error in the main project
|
||||||
|
|
||||||
|
// Put up the error dialog.
|
||||||
|
IStatusHandler prompter = DebugPlugin.getDefault().getStatusHandler(uiPromptStatus);
|
||||||
|
if (prompter != null) {
|
||||||
|
continueLaunch = ((Boolean) prompter.handleStatus(promptStatusMainProj, createPrompterArgs(configuration))).booleanValue();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
assert false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// No build error in the main project but see if there's one
|
||||||
|
// in any of its referenced projects
|
||||||
|
IProject[] projects = getBuildOrder(configuration, mode);
|
||||||
|
for (IProject proj : projects) {
|
||||||
|
// The array will contain the top level project.
|
||||||
|
// Ignore it since we handled it above
|
||||||
|
if (proj == project) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (existsProblems(proj)) {
|
||||||
|
// Put up the error dialog.
|
||||||
|
IStatusHandler prompter = DebugPlugin.getDefault().getStatusHandler(uiPromptStatus);
|
||||||
|
prompter = DebugPlugin.getDefault().getStatusHandler(uiPromptStatus);
|
||||||
|
if (prompter != null) {
|
||||||
|
continueLaunch = ((Boolean) prompter.handleStatus(promptStatusReferencedProjs, createPrompterArgs(configuration))).booleanValue();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
assert false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The error message says "one or more" and doesn't mention names.
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Note that we do not call our super implementation (platform).
|
||||||
|
// That's because it'll just re-do everything we've done here in a
|
||||||
|
// non-customized way. However, we need to keep an eye out for any
|
||||||
|
// future additions to the platform's logic.
|
||||||
|
|
||||||
|
return continueLaunch;
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
workspaceBuildBeforeLaunch = false; // reset for future run
|
||||||
|
if (monitor != null) {
|
||||||
|
monitor.done();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected ICProject verifyCProject(ILaunchConfiguration config) throws CoreException {
|
protected ICProject verifyCProject(ILaunchConfiguration config) throws CoreException {
|
||||||
|
@ -284,52 +531,6 @@ public abstract class AbstractCLaunchDelegate2 extends LaunchConfigurationDelega
|
||||||
return cproject;
|
return cproject;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets up a project for building by making sure the active configuration is the one used
|
|
||||||
* when the launch was created.
|
|
||||||
* @param configuration
|
|
||||||
* @param buildProject
|
|
||||||
*/
|
|
||||||
private void setBuildConfiguration(ILaunchConfiguration configuration, IProject buildProject) {
|
|
||||||
|
|
||||||
try {
|
|
||||||
if (buildProject != null)
|
|
||||||
{
|
|
||||||
String buildConfigID = configuration.getAttribute(ICDTLaunchConfigurationConstants.ATTR_PROJECT_BUILD_CONFIG_ID, ""); //$NON-NLS-1$
|
|
||||||
ICProjectDescription projDes = CDTPropertyManager.getProjectDescription(buildProject);
|
|
||||||
|
|
||||||
if (buildConfigID.length() > 0 && projDes != null)
|
|
||||||
{
|
|
||||||
ICConfigurationDescription buildConfiguration = projDes.getConfigurationById(buildConfigID);
|
|
||||||
if (buildConfiguration != null) {
|
|
||||||
preLaunchBuildConfiguration = projDes.getActiveConfiguration().getId();
|
|
||||||
buildConfiguration.setActive();
|
|
||||||
CDTPropertyManager.performOk(null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} catch (CoreException e) {}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void resetBuildConfiguration(IProject buildProject) {
|
|
||||||
// Restore the active configuration if it was changed for the launch
|
|
||||||
if (preLaunchBuildConfiguration != null) {
|
|
||||||
ICProjectDescription projDes = CDTPropertyManager.getProjectDescription(buildProject);
|
|
||||||
|
|
||||||
if (preLaunchBuildConfiguration.length() > 0 && projDes != null)
|
|
||||||
{
|
|
||||||
ICConfigurationDescription buildConfiguration = projDes.getConfigurationById(preLaunchBuildConfiguration);
|
|
||||||
if (buildConfiguration != null) {
|
|
||||||
buildConfiguration.setActive();
|
|
||||||
CDTPropertyManager.performOk(null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
preLaunchBuildConfiguration = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the ID of the plugin hosting the launch delegate. It's used to
|
* @return the ID of the plugin hosting the launch delegate. It's used to
|
||||||
* create {@link IStatus} objects.
|
* create {@link IStatus} objects.
|
||||||
|
|
|
@ -0,0 +1,152 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2000, 2010 IBM Corporation, Freescale Semiconductor 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
|
||||||
|
*
|
||||||
|
* Contributors:
|
||||||
|
* IBM Corporation - initial API and implementation
|
||||||
|
* Freescale Semiconductor - customized for use in CDT
|
||||||
|
*******************************************************************************/
|
||||||
|
|
||||||
|
package org.eclipse.cdt.launch.internal.ui;
|
||||||
|
|
||||||
|
import java.text.MessageFormat;
|
||||||
|
|
||||||
|
import org.eclipse.core.runtime.CoreException;
|
||||||
|
import org.eclipse.core.runtime.IStatus;
|
||||||
|
import org.eclipse.debug.core.ILaunchConfiguration;
|
||||||
|
import org.eclipse.debug.core.IStatusHandler;
|
||||||
|
import org.eclipse.debug.internal.ui.DebugUIPlugin;
|
||||||
|
import org.eclipse.debug.internal.ui.IInternalDebugUIConstants;
|
||||||
|
import org.eclipse.debug.internal.ui.launchConfigurations.LaunchConfigurationsMessages;
|
||||||
|
import org.eclipse.debug.ui.DebugUITools;
|
||||||
|
import org.eclipse.jface.dialogs.IDialogConstants;
|
||||||
|
import org.eclipse.jface.dialogs.MessageDialog;
|
||||||
|
import org.eclipse.jface.dialogs.MessageDialogWithToggle;
|
||||||
|
import org.eclipse.jface.preference.IPreferenceStore;
|
||||||
|
import org.eclipse.swt.widgets.Shell;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class is a customization of the platform's
|
||||||
|
* CompileErrorProjectPromptStatusHandler. We use it to put up a more
|
||||||
|
* CDT-centric message when building before a launch and there is an error in
|
||||||
|
* the project. We want to let the user know what specific build configuration
|
||||||
|
* is having a build error when the configuration is not the active one.
|
||||||
|
* See https://bugs.eclipse.org/bugs/show_bug.cgi?id=309126#c11
|
||||||
|
*/
|
||||||
|
public class BuildErrPrompter implements IStatusHandler {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Status code indicating there was an error in the main project. Linked to
|
||||||
|
* BuildErrPrompter via our statusHandlers extension (see plugin.xml)
|
||||||
|
*/
|
||||||
|
public static final int STATUS_CODE_ERR_IN_MAIN_PROJ = 1002;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Status code indicating there was an error in a project referenced by the
|
||||||
|
* main project. Linked to BuildErrPrompter via our statusHandlers extension
|
||||||
|
* (see plugin.xml)
|
||||||
|
*/
|
||||||
|
public static final int STATUS_CODE_ERR_IN_REFERENCED_PROJS = 1003;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Source is an array of three things, in the following order
|
||||||
|
* <ul>
|
||||||
|
* <li>launch configuration that was invoked
|
||||||
|
* <li>the name of the project the launch first attempted to build
|
||||||
|
* <li>the name of the build configuration that was built, or empty string
|
||||||
|
* if it was the active one. This argument should be non-empty ONLY if a
|
||||||
|
* not-active configuration was built.
|
||||||
|
* <ul>
|
||||||
|
*
|
||||||
|
* @see org.eclipse.debug.core.IStatusHandler#handleStatus(org.eclipse.core.runtime.IStatus,
|
||||||
|
* java.lang.Object)
|
||||||
|
*/
|
||||||
|
public Object handleStatus(IStatus status, Object source) throws CoreException {
|
||||||
|
|
||||||
|
if (!(source instanceof Object[])) {
|
||||||
|
assert false : "status handler not given expected arguments"; //$NON-NLS-1$
|
||||||
|
return Boolean.TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
Object[] args = (Object[])source;
|
||||||
|
if (args.length != 3 ||
|
||||||
|
!(args[0] instanceof ILaunchConfiguration) ||
|
||||||
|
!(args[1] instanceof String) ||
|
||||||
|
!(args[2] instanceof String)) {
|
||||||
|
assert false : "status handler not given expected arguments"; //$NON-NLS-1$
|
||||||
|
return Boolean.TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
final ILaunchConfiguration launchConfig = (ILaunchConfiguration)args[0];
|
||||||
|
final String projectName = (String)args[1];
|
||||||
|
final String buildConfigName = (String)args[2];
|
||||||
|
|
||||||
|
// The platform does this check; we should, too
|
||||||
|
if (DebugUITools.isPrivate(launchConfig)) {
|
||||||
|
return Boolean.TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
Shell shell = DebugUIPlugin.getShell();
|
||||||
|
String title = LaunchConfigurationsMessages.CompileErrorPromptStatusHandler_0;
|
||||||
|
String message;
|
||||||
|
if (status.getCode() == STATUS_CODE_ERR_IN_MAIN_PROJ) {
|
||||||
|
if (buildConfigName.length() > 0) {
|
||||||
|
message = MessageFormat.format(
|
||||||
|
LaunchMessages.getString("BuildErrPrompter.error_in_specific_config"), projectName, buildConfigName); //$NON-NLS-1$
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
message = MessageFormat.format(
|
||||||
|
LaunchMessages.getString("BuildErrPrompter.error_in_active_config"), projectName); //$NON-NLS-1$
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (status.getCode() == STATUS_CODE_ERR_IN_REFERENCED_PROJS) {
|
||||||
|
if (buildConfigName.length() > 0) {
|
||||||
|
message = MessageFormat.format(
|
||||||
|
LaunchMessages.getString("BuildErrPrompter.error_in_referenced_project_specific"), //$NON-NLS-1$
|
||||||
|
projectName, buildConfigName);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
message = MessageFormat.format(
|
||||||
|
LaunchMessages.getString("BuildErrPrompter.error_in_referenced_project_active"), //$NON-NLS-1$
|
||||||
|
projectName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
assert false : "this prompter was called for an unexpected status"; //$NON-NLS-1$
|
||||||
|
return Boolean.TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The rest is monkey-see, monkey-do (copied from
|
||||||
|
// CompileErrorProjectPromptStatusHandler)
|
||||||
|
|
||||||
|
IPreferenceStore store = DebugUIPlugin.getDefault().getPreferenceStore();
|
||||||
|
String pref = store.getString(IInternalDebugUIConstants.PREF_CONTINUE_WITH_COMPILE_ERROR);
|
||||||
|
if (pref != null) {
|
||||||
|
if (pref.equals(MessageDialogWithToggle.ALWAYS)) {
|
||||||
|
return Boolean.TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
MessageDialogWithToggle dialog = new MessageDialogWithToggle(shell,
|
||||||
|
title,
|
||||||
|
null,
|
||||||
|
message,
|
||||||
|
MessageDialog.QUESTION,
|
||||||
|
new String[] {IDialogConstants.PROCEED_LABEL, IDialogConstants.CANCEL_LABEL},
|
||||||
|
0,
|
||||||
|
LaunchConfigurationsMessages.CompileErrorProjectPromptStatusHandler_1,
|
||||||
|
false);
|
||||||
|
int open = dialog.open();
|
||||||
|
if (open == IDialogConstants.PROCEED_ID) {
|
||||||
|
if(dialog.getToggleState()) {
|
||||||
|
store.setValue(IInternalDebugUIConstants.PREF_CONTINUE_WITH_COMPILE_ERROR, MessageDialogWithToggle.ALWAYS);
|
||||||
|
}
|
||||||
|
return Boolean.TRUE;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return Boolean.FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -199,3 +199,8 @@ MultiLaunchConfigurationTabGroup.15=Launch {0} is filtered.
|
||||||
MultiLaunchConfigurationTabGroup.16=Must have at least one valid enabled launch.
|
MultiLaunchConfigurationTabGroup.16=Must have at least one valid enabled launch.
|
||||||
ProjectRenameChange.name=Update launch configuration "{0}"
|
ProjectRenameChange.name=Update launch configuration "{0}"
|
||||||
ProjectRenameChange.saveFailed=Failed to save updated launch configuration "{0}"
|
ProjectRenameChange.saveFailed=Failed to save updated launch configuration "{0}"
|
||||||
|
|
||||||
|
BuildErrPrompter.error_in_specific_config=Errors exist in project \"{0}\" having built not-active build configuration \"{1}\". Proceed with launch?
|
||||||
|
BuildErrPrompter.error_in_active_config=Errors exist in the active configuration of project \"{0}\". Proceed with launch?
|
||||||
|
BuildErrPrompter.error_in_referenced_project_specific=One or more projects referenced by project \"{0}\", build configuration \"{1}\" has build errors. See Problems view for details. Keep in mind that the errors may be in build configurations that are not the active ones. Continue anyway?
|
||||||
|
BuildErrPrompter.error_in_referenced_project_active=One or more projects referenced by the active configuration of project \"{0}\" has build errors. See Problems view for details. Keep in mind that the errors may be in build configurations that are not the active ones. Continue anyway?
|
Loading…
Add table
Reference in a new issue