diff --git a/eclipse-plugins/edu.wpi.first.wpilib.plugins.cpp/src/main/java/edu/wpi/first/wpilib/plugins/cpp/launching/DeployLaunchShortcut.java b/eclipse-plugins/edu.wpi.first.wpilib.plugins.cpp/src/main/java/edu/wpi/first/wpilib/plugins/cpp/launching/DeployLaunchShortcut.java index b8c3943a26..5f0dab4af8 100644 --- a/eclipse-plugins/edu.wpi.first.wpilib.plugins.cpp/src/main/java/edu/wpi/first/wpilib/plugins/cpp/launching/DeployLaunchShortcut.java +++ b/eclipse-plugins/edu.wpi.first.wpilib.plugins.cpp/src/main/java/edu/wpi/first/wpilib/plugins/cpp/launching/DeployLaunchShortcut.java @@ -12,14 +12,20 @@ import org.eclipse.cdt.debug.mi.core.IMILaunchConfigurationConstants; import org.eclipse.cdt.launch.remote.IRemoteConnectionConfigurationConstants; import org.eclipse.core.internal.resources.Resource; import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IncrementalProjectBuilder; import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IMarker; +import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.NullProgressMonitor; +import org.eclipse.core.runtime.OperationCanceledException; import org.eclipse.debug.core.DebugPlugin; import org.eclipse.debug.core.ILaunchConfigurationType; import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy; import org.eclipse.debug.core.ILaunchManager; import org.eclipse.debug.ui.DebugUITools; import org.eclipse.debug.ui.ILaunchShortcut; +import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.StructuredSelection; import org.eclipse.swt.widgets.Shell; @@ -44,7 +50,7 @@ public class DeployLaunchShortcut implements ILaunchShortcut { // Class constants - used to delineate types for launch shortcuts public static final String DEPLOY_TYPE = "edu.wpi.first.wpilib.plugins.core.deploy"; - + /** * Returns the launch type of the shortcut that was used, one of the * constants defined in BaseLaunchShortcut @@ -55,7 +61,7 @@ public class DeployLaunchShortcut implements ILaunchShortcut { return DEPLOY_TYPE; } - + @Override public void launch(ISelection selection, String mode) { @@ -68,12 +74,12 @@ public class DeployLaunchShortcut implements ILaunchShortcut WPILibCPPPlugin.logError("Selection isn't a project: "+sel.toString(), null); return; } - + // Run config using project found in extracted resource, with indicated // mode runConfig(activeProject, mode, PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell()); } - + @Override public void launch(IEditorPart editor, String mode) { @@ -82,16 +88,16 @@ public class DeployLaunchShortcut implements ILaunchShortcut IFileEditorInput input = (IFileEditorInput) editor.getEditorInput(); IFile file = input.getFile(); IProject activeProject = file.getProject(); - + // If editor existed, run config using extracted resource in // indicated mode runConfig(activeProject, mode, editor.getSite().getWorkbenchWindow().getShell()); } else { WPILibCPPPlugin.logError("Editor was null.", null); } - + } - + /** * * @param activeProj @@ -101,6 +107,55 @@ public class DeployLaunchShortcut implements ILaunchShortcut * ILaunchManager.DEBUG_MODE) */ public void runConfig(IProject activeProj, String mode, Shell shell) { + + // Checks to see if there are any build errors remaining. + boolean buildSucceeded = true; + // Unfortunately, build() does not return whether or not the + // build succeded, so we instead must check the markers for + // errors and hope that we don't accidentally catch any + // false-positives. + try { + activeProj.build(IncrementalProjectBuilder.INCREMENTAL_BUILD, null); + } + catch (CoreException e) { + buildSucceeded = false; + WPILibCPPPlugin.logError("Build failed.", e); + } + + try { + IMarker[] problems = activeProj.findMarkers(IMarker.PROBLEM, true, IResource.DEPTH_INFINITE); + for (int i = 0; i < problems.length; i++) { + if (problems[i].getAttribute(IMarker.SEVERITY, IMarker.SEVERITY_INFO) + == IMarker.SEVERITY_ERROR + && problems[i].getType() == "org.eclipse.cdt.core.problem") { + buildSucceeded = false; + break; + } + } + } + catch (CoreException e) { + buildSucceeded = false; + WPILibCPPPlugin.logError("Failed to check whether the build worked.", e); + } + + if (!buildSucceeded) { + boolean cont = MessageDialog.openQuestion(shell, "Build Failed", + "The build failed; Are you sure that you want to continue the deploy?"); + if (!cont) return; + } + + // Check to ensure that there really is a binary file to upload; this is + // only really relevant if the build fails, but we check anyways. + Collection exes = + ExecutablesManager.getExecutablesManager().getExecutablesForProject(activeProj); + if (!(exes.size() > 1 + || new File(activeProj.getLocation().toOSString() + File.separator + + "Debug" + File.separator + "FRCUserProgram").isFile())) { + MessageDialog.openWarning(shell, "Bad Executable", + "No executable binary was found to upload to the robot."); + return; + } + if(mode.equals(ILaunchManager.RUN_MODE)) { // Regular deploys are done with an ant script for now, for both // C++ and Java. @@ -110,12 +165,12 @@ public class DeployLaunchShortcut implements ILaunchShortcut } else { // Debug deploys are done with the Eclipse Remote System Explorer, // which lets it work with Eclipse's C++ debugger. - + // Kill running program before using RSE as RSE can't WPILibCPPPlugin.logInfo("Running ant file: " + activeProj.getLocation().toOSString() + File.separator + "build.xml"); WPILibCPPPlugin.logInfo("Targets: kill-program, Mode: " + mode); AntLauncher.runAntFile(new File (activeProj.getLocation().toOSString() + File.separator + "build.xml"), "kill-program", null, mode); - + // TODO: figure out UI issues. that's why this is undocumented ILaunchConfigurationWorkingCopy config; try { @@ -124,20 +179,20 @@ public class DeployLaunchShortcut implements ILaunchShortcut } catch (CoreException e) { WPILibCPPPlugin.logError("Debug attach failed.", e); } - + try { activeProj.refreshLocal(Resource.DEPTH_INFINITE, null); } catch (Exception e) {} } } - + private ILaunchConfigurationWorkingCopy getRemoteDebugConfig(IProject activeProj) throws CoreException { ILaunchManager manager = DebugPlugin.getDefault().getLaunchManager(); ILaunchConfigurationType type = manager.getLaunchConfigurationType(ICDTLaunchConfigurationConstants.ID_LAUNCH_C_REMOTE_APP); int teamNumber = WPILibCore.getDefault().getTeamNumber(activeProj); String remote_connection = RSEUtils.getTarget(teamNumber).getName(); - + ILaunchConfigurationWorkingCopy config = type.newInstance(null, activeProj.getName()); config.setAttribute(ICDTLaunchConfigurationConstants.ATTR_COREFILE_PATH, ""); config.setAttribute(ICDTLaunchConfigurationConstants.ATTR_DEBUGGER_ENABLE_REGISTER_BOOKKEEPING, false); @@ -152,14 +207,14 @@ public class DeployLaunchShortcut implements ILaunchShortcut config.setAttribute(ICDTLaunchConfigurationConstants.ATTR_PROGRAM_NAME, exes.size() > 0 ? exes.toArray(new Executable[0])[0].getPath().makeRelativeTo(activeProj.getLocation()).toString(): "Debug/FRCUserProgram"); - + config.setAttribute("org.eclipse.cdt.dsf.gdb.DEBUG_NAME", "arm-frc-linux-gnueabi-gdb"); config.setAttribute(IRemoteConnectionConfigurationConstants.ATTR_REMOTE_PATH, "/home/lvuser/FRCUserProgram"); config.setAttribute(IRemoteConnectionConfigurationConstants.ATTR_REMOTE_CONNECTION, remote_connection); config.setAttribute(IRemoteConnectionConfigurationConstants.ATTR_SKIP_DOWNLOAD_TO_TARGET, false); config.setAttribute(IRemoteConnectionConfigurationConstants.ATTR_GDBSERVER_PORT, "2345"); config.setAttribute(IRemoteConnectionConfigurationConstants.ATTR_GDBSERVER_COMMAND, "gdbserver"); - + List solibs = new ArrayList<>(); solibs.add(WPILibCPPPlugin.getDefault().getCPPDir() + "/lib"); config.setAttribute(IMILaunchConfigurationConstants.ATTR_DEBUGGER_SOLIB_PATH, solibs);