/*******************************************************************************
* Copyright (c) 2014, 2015 Red Hat, Inc.
* 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:
* Red Hat Inc. - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.internal.debug.application;
import java.io.File;
import java.util.Arrays;
import java.util.List;
import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.language.settings.providers.ILanguageSettingsProvider;
import org.eclipse.cdt.core.language.settings.providers.ILanguageSettingsProvidersKeeper;
import org.eclipse.cdt.core.language.settings.providers.LanguageSettingsManager;
import org.eclipse.cdt.core.settings.model.ICConfigurationDescription;
import org.eclipse.cdt.core.settings.model.ICProjectDescription;
import org.eclipse.cdt.core.settings.model.ICProjectDescriptionManager;
import org.eclipse.cdt.debug.application.Messages;
import org.eclipse.cdt.debug.core.ICDTLaunchConfigurationConstants;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IProjectDescription;
import org.eclipse.core.resources.IWorkspace;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.debug.core.DebugPlugin;
import org.eclipse.debug.core.ILaunchConfiguration;
import org.eclipse.debug.core.ILaunchConfigurationType;
import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
import org.eclipse.debug.core.ILaunchManager;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PlatformUI;
public class DebugAttachedExecutable {
private static final String GCC_BUILTIN_PROVIDER_ID = "org.eclipse.cdt.managedbuilder.core.GCCBuiltinSpecsDetector"; //$NON-NLS-1$
private static final String GCC_COMPILE_OPTIONS_PROVIDER_ID = "org.eclipse.cdt.debug.application.DwarfLanguageSettingsProvider"; //$NON-NLS-1$
private static final String GCC_BUILD_OPTIONS_PROVIDER_ID = "org.eclipse.cdt.managedbuilder.core.GCCBuildCommandParser"; //$NON-NLS-1$
private static final String DEBUG_PROJECT_ID = "org.eclipse.cdt.debug"; //$NON-NLS-1$
public DebugAttachedExecutable() {
}
public static ILaunchManager getLaunchManager() {
return DebugPlugin.getDefault().getLaunchManager();
}
// Create a new project that doesn't already exist. Use the base project name and add
// a numerical suffix as needed.
private static IProject createCProjectForExecutable(String projectName) throws OperationCanceledException, CoreException {
IWorkspace workspace = ResourcesPlugin.getWorkspace();
IProject newProjectHandle = workspace.getRoot().getProject(projectName);
int projectSuffix = 2;
while (newProjectHandle.exists()){
newProjectHandle = workspace.getRoot().getProject(projectName + projectSuffix);
projectSuffix++;
}
IProjectDescription description = workspace.newProjectDescription(newProjectHandle.getName());
description.setLocation(null);
IProject newProject = CCorePlugin.getDefault().createCProject(description, newProjectHandle, null,
DEBUG_PROJECT_ID);
return newProject;
}
/**
* Import given executable into the Executables project then create a launch configuration.
*
* @param monitor
* @param buildLog
* @throws CoreException
* @throws InterruptedException
*/
public static ILaunchConfiguration createLaunchConfig(IProgressMonitor monitor,
String buildLog)
throws CoreException, InterruptedException {
return createLaunchConfig(monitor, buildLog, null);
}
/**
* Import given executable into the Executables project then create a launch configuration.
*
* @param monitor
* @param buildLog
* @param pid
* @throws CoreException
* @throws InterruptedException
*/
public static ILaunchConfiguration createLaunchConfig(IProgressMonitor monitor,
String buildLog, String pid)
throws CoreException, InterruptedException {
ILaunchConfiguration config = null;
String defaultProjectName = "Executables"; //$NON-NLS-1$
// Create a new Executablesnn project
IProject project = createCProjectForExecutable(defaultProjectName);
monitor.worked(3);
File buildLogFile = null;
final ICProjectDescriptionManager projDescManager = CCorePlugin
.getDefault().getProjectDescriptionManager();
ICProjectDescription projectDescription = projDescManager
.getProjectDescription(project,
ICProjectDescriptionManager.GET_WRITABLE);
monitor.subTask(Messages.SetLanguageProviders);
final ICConfigurationDescription ccd = projectDescription
.getActiveConfiguration();
String[] langProviderIds = ((ILanguageSettingsProvidersKeeper) ccd)
.getDefaultLanguageSettingsProvidersIds();
boolean found = false;
for (int i = 0; i < langProviderIds.length; ++i) {
if (langProviderIds[i].equals(GCC_BUILTIN_PROVIDER_ID)) {
found = true;
break;
}
}
// Look for the GCC builtin LanguageSettingsProvider id. If it isn't already
// there, add it.
if (!found) {
langProviderIds = Arrays.copyOf(langProviderIds,
langProviderIds.length + 1);
langProviderIds[langProviderIds.length - 1] = GCC_BUILTIN_PROVIDER_ID;
}
found = false;
for (int i = 0; i < langProviderIds.length; ++i) {
if (langProviderIds[i].equals(GCC_COMPILE_OPTIONS_PROVIDER_ID)) {
found = true;
break;
}
}
// Look for our macro parser provider id. If it isn't added already, do so now.
if (!found) {
langProviderIds = Arrays.copyOf(langProviderIds,
langProviderIds.length + 1);
langProviderIds[langProviderIds.length - 1] = GCC_COMPILE_OPTIONS_PROVIDER_ID;
}
if (buildLog != null) {
File f = new File(buildLog);
if (f.exists()) {
buildLogFile = f;
found = false;
for (int i = 0; i < langProviderIds.length; ++i) {
if (langProviderIds[i].equals(GCC_BUILD_OPTIONS_PROVIDER_ID)) {
found = true;
break;
}
}
// Look for our macro parser provider id. If it isn't added already, do so now.
if (!found) {
langProviderIds = Arrays.copyOf(langProviderIds,
langProviderIds.length + 1);
langProviderIds[langProviderIds.length - 1] = GCC_BUILD_OPTIONS_PROVIDER_ID;
}
}
}
// Create all the LanguageSettingsProviders
List<ILanguageSettingsProvider> providers = LanguageSettingsManager
.createLanguageSettingsProviders(langProviderIds);
// Update the providers for the configuration.
((ILanguageSettingsProvidersKeeper) ccd)
.setLanguageSettingProviders(providers);
monitor.worked(1);
// Update the project description.
projDescManager.setProjectDescription(project,
projectDescription);
// Serialize the language settings for the project now in case we don't run a
// language settings provider which will do this in shutdown.
ICProjectDescription projDescReadOnly = projDescManager
.getProjectDescription(project,
false);
LanguageSettingsManager.serializeLanguageSettings(projDescReadOnly);
monitor.worked(1);
if (buildLogFile != null)
// We need to parse the build log to get compile options. We need to lock the
// workspace when we do this so we don't have multiple copies of GCCBuildOptionsParser
// LanguageSettingsProvider and we end up filling in the wrong one.
project.getWorkspace().run(new BuildOptionsParser(project, buildLogFile),
ResourcesPlugin.getWorkspace().getRoot(), IWorkspace.AVOID_UPDATE, new NullProgressMonitor());
// System.out.println("about to close all editors");
IWorkbench workbench = PlatformUI.getWorkbench();
if (workbench != null) {
final IWorkbenchWindow workbenchWindow = workbench.getActiveWorkbenchWindow();
if (workbenchWindow != null) {
final IWorkbenchPage activePage = workbenchWindow.getActivePage();
if (activePage != null)
activePage.closeAllEditors(false);
}
}
config = createConfiguration(pid, true);
monitor.worked(1);
return config;
}
protected static ILaunchConfigurationType getLaunchConfigType() {
return getLaunchManager().getLaunchConfigurationType(ICDTLaunchConfigurationConstants.ID_LAUNCH_C_ATTACH);
}
protected static ILaunchConfiguration createConfiguration(boolean save) {
return createConfiguration(null, save);
}
protected static ILaunchConfiguration createConfiguration(String pid, boolean save) {
ILaunchConfiguration config = null;
try {
ILaunchConfigurationType configType = getLaunchConfigType();
ILaunchConfigurationWorkingCopy wc = configType.newInstance(
null,
getLaunchManager().generateLaunchConfigurationName("CDT_DBG_ATTACH")); //$NON-NLS-1$
wc.setAttribute(ICDTLaunchConfigurationConstants.ATTR_DEBUGGER_START_MODE,
ICDTLaunchConfigurationConstants.DEBUGGER_MODE_ATTACH);
wc.setAttribute(ICDTLaunchConfigurationConstants.ATTR_PROJECT_NAME,
"Executables"); //$NON-NLS-1$
wc.setAttribute(
ICDTLaunchConfigurationConstants.ATTR_WORKING_DIRECTORY,
(String) null);
if (pid != null) {
wc.setAttribute(ICDTLaunchConfigurationConstants.ATTR_ATTACH_PROCESS_ID,
Integer.valueOf(pid));
}
if (save) {
config = wc.doSave();
} else {
config = wc;
}
} catch (CoreException e) {
e.printStackTrace();
}
return config;
}
}