From 7399469d5950f2ece206265ba9395b4eed84d157 Mon Sep 17 00:00:00 2001
From: Jeff Johnston
Date: Tue, 6 Jan 2015 16:29:13 -0500
Subject: Fix for bug 456247 - gcov not working on Windows/Cygwin
- old code was looking for the name of the compiler tool being
"GCC C Compiler". This does not work because Cygwin's C compiler
tool has a different name, as does MacOSx's gcc compiler
- change code to look for the base gnu compiler id which never changes
and all gcc-compiler tools superclass eventually to this tool (C
or C++ compiler)
- deprecate the public APIs that were exposed to take the tool name
instead of superclass id so we can remove them in next major release
Change-Id: I3fe809a93bc8ba8d57a5c64e61528c0186ee0424
Reviewed-on: https://git.eclipse.org/r/39078
Tested-by: Hudson CI
Reviewed-by: Roland Grunberg This class is focused on automating the proccess of enabling profing plugins. This class is focused on automating the process of enabling profiling plugins. It supports c/c++ in Managed and Autotools projects, Common steps:
- * Used in conjunctin with {@link CProjectBuildHelpers#getProjectType getProjectType} Can be set to one of the following:
- * - AUTO_TOOLS A project can be of different types.
+ * Used in conjunction with {@link CProjectBuildHelpers#getProjectType getProjectType} Can be set to one of the following:
+ * - AUTO_TOOLS A project can be of different types.
- * Some dialogues (initially in gCov and gProf) distinguish between these when displaying dialogues. This code is used
- * by these dialogues.
- *
- * The method was writen with extensibility in mind.
- * Projects can be c or cpp based.
- * Projects can be c or cpp based.
- * Commonly used when launching a plugin and you want to check if flags are set correctly.
- *
- * An example of an option id is: {@code gnu.cpp.compiler.option.debugging.gprof } To find the option id, check/uncheck it in
- * your project. Then inspect the .cproject file.
- *
- * This method serves as a model to easily add similar methods. find what subclasses the iPrefernce store, it is
- * likley that your desired option is in one of those stores.
- * The tools prefernce store is where most compiler build flags are stored. If you don't know how to get your IProject, see example: Related wiki:
- *
- * Programmaticall check option wiki page. Check to see if an option is enabled in the .autotools configuration. Set an option (as well as flags) in the .autotools configuration and update gui. It is designed so that it can be ran from a background thread.
- * It syncs with the GUI thread to avoid concurrency exceptions. *this modifies gui checkbox options* as well as *saving the option to disk*. Given a project, it finds the active configuration and rebuilds the project. This works with C/C++ Managed Builds as well as Autotools. Most useful for when you have added a flag to a project programatically and want to rebuild
- * the project so that the program is rebuild with that flag. The Rebuild triggers an update of the makefile
- * automatically. Helper to get the active build configuration. For a project, retrieve the parent toolname underwhich we expect the tool to be under. Each option has a parent tool. this aquires the 'ITool' The parent tool is later read to aquire the option template, which is used to set an option. C and C++ Project configuration and build helpers.
- *
+ *
* Used primarily for gcov gprof.
@@ -47,11 +47,11 @@ import org.eclipse.swt.widgets.Display;
*
*
*
- *
@@ -60,468 +60,594 @@ import org.eclipse.swt.widgets.Display;
*/
public class CProjectBuildHelpers {
- /**
- * Custom Project Type enumirator.
- *
- *
- * Check the return value against these constants.
- *
- * - MANAGED_MAKEFILE
- * - OTHER Finds out the type of the project as defined by {@link ProjectBuildType ProjectBuildType}.
- *
- *
- * Common types are:
+ /**
+ * Custom Project Type enumerator.
+ *
+ *
+ * Check the return value against these constants.
+ *
+ * - MANAGED_MAKEFILE
+ * - OTHER Finds out the type of the project as defined by {@link ProjectBuildType ProjectBuildType}.
+ *
+ *
+ * Common types are:
* - Autotools
- * - Managed Make project
- * - Manual Makefiles
- * Other routines check for autotools/Managed make, and if those are not present, then it shows generic advice about
- * adding flags. MAKEFILE per-se isn't really checked. I.e this means that it should be safe to add additional
- * project types.
- *
- * AUTO_TOOLS,
- * MANAGED_MAKEFILE,
- * OTHER
- */
- public static ProjectBuildType getProjectType(IProject project) {
- // AUTOTOOLS
- // Autotools has an 'Autotools' nature by which we can identify it.
- if (isAutoTools(project)) {
- return ProjectBuildType.AUTO_TOOLS;
- }
-
- IConfiguration defaultConfiguration = helperGetActiveConfiguration(project);
- IBuilder builder = defaultConfiguration.getBuilder();
- Boolean projIsManaged = builder.isManagedBuildOn();
-
- // MANAGED PROJECT
- if (projIsManaged) {
- return ProjectBuildType.MANAGED_MAKEFILE;
- }
- else {
- return ProjectBuildType.OTHER; //E.g a manual makefile.
- }
- }
-
- /**
- * Differentiate C++ from C projects.
- *
- *
- * Cpp projects have a ccnature as well as a cnature,
- * where as C projects only have a cnature.
- * Differentiates C from C++ projects.
- *
- *
- * Cpp projects have a ccnature as well as a cnature,
- * where as C projects only have a cnature.
- * Autotools projects have an Autotools Nature.
- *
- * @param project IProject that you're dealing with.
- * @return true if the project has an autotools nautre.
- */
- public static boolean isAutoTools(IProject project) {
- try {
- if (project.hasNature(AutotoolsNewProjectNature.AUTOTOOLS_NATURE_ID)) { // this guy throws.
- return true;
- } else {
- return false;
- }
- } catch (CoreException e) {
- // should never really reach this unless .cproject is broken.
- MessageDialogSyncedRunnable.openErrorSyncedRunnable(ProfilingMessages.errorTitle, ProfilingMessages.errorGetProjectType);
- return false;
- }
- }
-
- /**
- * Check if an option is set in the CDT settings.
- *
- * gnu.cpp.compiler.option.debugging.codecov
- * @return true if the option is set.
- */
- public static boolean isOptionCheckedInCDT(IProject project, String optionIDString) {
- //Set Tool Name.
- String parentToolName = helperGetToolName(project);
- if (parentToolName == null) {
- return false;
- }
- return isOptionCheckedInCDT(project, optionIDString, parentToolName);
- }
-
- /**
- * Check if an option is set
- * Same as {@link #isOptionCheckedInCDT(IProject project, String optionIDString) isOptionChecked_inCDT },
- * except you specify tool name manually.
- *
- * (e.g you need to check something that's not supported in the implementation above.
- * @param project the IProject project which will be read to check if it is c or cpp
- * @param optionIDString for example gnu.cpp.compiler.option.debugging.codecov
- * @param parentToolName name of the parent tool. see {@link #helperGetToolName helper_GetToolName}
- * @return true if the option is set
- */
- public static boolean isOptionCheckedInCDT(IProject project, String optionIDString, String parentToolName) {
-
- IConfiguration activeConf = helperGetActiveConfiguration(project);
-
- //Get Compiler tool.
- ITool gccCompileriTool = helperGetGccCompilerTool(parentToolName, activeConf);
-
- //(Get immutable option: This is like a 'templete' that we will use to get the actual option)
- IOption optionTemplate = gccCompileriTool.getOptionById(optionIDString);
-
- //Check that we got a good option.
- if (optionTemplate == null) {
- MessageDialogSyncedRunnable.openErrorSyncedRunnable(ProfilingMessages.errorTitle, ProfilingMessages.errorGetOptionTemplate);
- return false;
- }
-
- // Get Actual Option
- // (Now we acquire the actual option from which we can read the value)
- try {
- IOption mutableOptionToSet = gccCompileriTool.getOptionToSet(optionTemplate, false);
- return (boolean) mutableOptionToSet.getValue();
- } catch (BuildException e) {
- //This is reached if the template that was provided was bad.
- MessageDialogSyncedRunnable.openErrorSyncedRunnable(ProfilingMessages.errorTitle, ProfilingMessages.errorGetOptionForWriting);
- }
- return false;
-
- }
-
- /**
- * Enable a checkbox in the tools preference store and save to disk.
- *
- * More specifically for 'debug' flags like gprof and gCov
- * org.eclipse.linuxtools.internal.gprof.launch.GprofLaunchConfigurationDelegate.getProject()
Set Option in CDT
- * Same as {@link #setOptionInCDT(IProject project, String optionIDString, boolean value) setOption_in }
- * except you can specify the parent tool manually (in case current implementation does not support what yon need.
- *
- * @param project an IProject
- * @param optionIDString ID of option as defined in plugin.xml. e.g gnu.cpp.compiler.option.debugging.gprof
- * @param value true/false
- * @param parentToolName
- * Name of the tool where the option resides. E.g 'GCC C Compiler' or 'GCC C++ Compiler'.
- * To find out, check/uncheck an option, inspect the .cproject file, look for the option,
- * then see what tool it's under. See the name property
- * @return true if all went well, false otherwise
- */
- public static boolean setOptionInCDT(IProject project, String optionIDString, boolean value, String parentToolName) {
-
- // Get configuration
- IConfiguration activeConf = helperGetActiveConfiguration(project);
-
- // Get the ITool the option.
- ITool gccCompileriTool = helperGetGccCompilerTool(parentToolName, activeConf);
-
- // Get Template Opiton.
- //Get Option ~Immutable. This is like a 'templete' that we will base the actual option on.
- IOption optionTemplate = gccCompileriTool.getOptionById(optionIDString);
-
- //Check that we got a good option template.
- if (optionTemplate == null) {
- //This could fail if the specified option doesn't exist or is miss-spelled.
- MessageDialogSyncedRunnable.openErrorSyncedRunnable(ProfilingMessages.errorTitle, ProfilingMessages.errorGetOptionTemplate);
- return false;
- }
-
- // Get Actual Option
- //
- // Now we acquire an option that can be 'set' to something.
- // In contrast to the immutable option above, if the user never checked/unchecked the option by hand,
- // then the first time 'set' of this option will work correctly. Whereas
- // the immutable option would only work if the user checked/unchecked the option by hand before.
- IOption mutableOptionToSet = null;
- try {
- mutableOptionToSet = gccCompileriTool.getOptionToSet(optionTemplate, false);
- mutableOptionToSet.setValue(value);
- } catch (BuildException e) {
- //This is reached if the template that was provided was bad.
- MessageDialogSyncedRunnable.openErrorSyncedRunnable(ProfilingMessages.errorTitle, ProfilingMessages.errorGetOptionForWriting);
- }
-
- // get resource info. (where things are saved to).
- IResourceInfo resourceInfo = activeConf.getResourceInfos()[0];
-
- // Mark the option as enabled in the build manager.
- ManagedBuildManager.setOption(resourceInfo, gccCompileriTool, mutableOptionToSet,
- true);
-
- // Save this business to disk.
- ManagedBuildManager.saveBuildInfo(project, true);
- return true;
- }
-
-
- /**
- * Option enabled check
- * Set Autotools option and write to disk.
- *
- *
- * It is oblivious as to whether the option ID is an option or a flag, it just looks at the ID in the xml. Trigger a re-build of the project.
- *
- * Get the tool that holds the option 'template'.
- *
- *
- * based on it's name from the active configuration.
+ * - Manual Makefiles
+ * Some dialogues (initially in gCov and gProf) distinguish between these when displaying dialogues. This code is used + * by these dialogues. + *
+ * + *
+ * The method was written with extensibility in mind.
+ * Other routines check for autotools/Managed make, and if those are not present, then it shows generic advice about
+ * adding flags. MAKEFILE per-se isn't really checked. I.e this means that it should be safe to add additional
+ * project types.
+ *
+ * Projects can be c or cpp based.
+ * Cpp projects have a ccnature as well as a cnature,
+ * where as C projects only have a cnature.
+ *
+ * Projects can be c or cpp based.
+ * Cpp projects have a ccnature as well as a cnature,
+ * where as C projects only have a cnature.
+ *
+ * Commonly used when launching a plugin and you want to check if flags are set correctly. + *
+ * + *+ * An example of an option id is: {@code gnu.cpp.compiler.option.debugging.gprof } To find the option id, check/uncheck it in + * your project. Then inspect the .cproject file. + *
+ * + *+ * This method serves as a model to easily add similar methods. find what subclasses the iPrefernce store, it is + * likeley that your desired option is in one of those stores. + *
+ * @param project the IProject project which will be read to check if it is c or cpp. + * @param optionIDString for example gnu.cpp.compiler.option.debugging.codecov
+ * @return true if the option is set.
+ */
+ public static boolean isOptionCheckedInCDT(IProject project, String optionIDString) {
+ //Set Tool Name.
+ String toolSuperclassId = helperGetToolSuperClassId(project);
+ if (toolSuperclassId == null) {
+ return false;
+ }
+ return isOptionCheckedInCDTTool(project, optionIDString, toolSuperclassId);
+ }
+
+ /**
+ * gnu.cpp.compiler.option.debugging.codecov
+ * @param parentToolName name of the parent tool.
+ * @return true if the option is set
+ */
+ @Deprecated
+ public static boolean isOptionCheckedInCDT(IProject project, String optionIDString, String parentToolName) {
+
+ IConfiguration activeConf = helperGetActiveConfiguration(project);
+
+ //Get Compiler tool.
+ ITool gccCompileriTool = helperGetGccCompilerTool(parentToolName, activeConf);
+
+ //(Get immutable option: This is like a 'templete' that we will use to get the actual option)
+ IOption optionTemplate = gccCompileriTool.getOptionById(optionIDString);
+
+ //Check that we got a good option.
+ if (optionTemplate == null) {
+ MessageDialogSyncedRunnable.openErrorSyncedRunnable(ProfilingMessages.errorTitle, ProfilingMessages.errorGetOptionTemplate);
+ return false;
+ }
+
+ // Get Actual Option
+ // (Now we acquire the actual option from which we can read the value)
+ try {
+ IOption mutableOptionToSet = gccCompileriTool.getOptionToSet(optionTemplate, false);
+ return (boolean) mutableOptionToSet.getValue();
+ } catch (BuildException e) {
+ //This is reached if the template that was provided was bad.
+ MessageDialogSyncedRunnable.openErrorSyncedRunnable(ProfilingMessages.errorTitle, ProfilingMessages.errorGetOptionForWriting);
+ }
+ return false;
+
+ }
+
+ /**
+ * gnu.cpp.compiler.option.debugging.codecov
+ * @param toolSuperClassId superclass id of the parent tool. see {@link #helperGetToolSuperClassId helper_GetToolSuperClassId}
+ * @return true if the option is set
+ */
+ private static boolean isOptionCheckedInCDTTool(IProject project, String optionIDString, String toolSuperClassId) {
+
+ IConfiguration activeConf = helperGetActiveConfiguration(project);
+
+ //Get Compiler tool.
+ ITool gccCompileriTool = helperGetGccCompilerToolBySuperClass(toolSuperClassId, activeConf);
+
+ //(Get immutable option: This is like a 'template' that we will use to get the actual option)
+ IOption optionTemplate = gccCompileriTool.getOptionById(optionIDString);
+
+ //Check that we got a good option.
+ if (optionTemplate == null) {
+ MessageDialogSyncedRunnable.openErrorSyncedRunnable(ProfilingMessages.errorTitle, ProfilingMessages.errorGetOptionTemplate);
+ return false;
+ }
+
+ // Get Actual Option
+ // (Now we acquire the actual option from which we can read the value)
+ try {
+ IOption mutableOptionToSet = gccCompileriTool.getOptionToSet(optionTemplate, false);
+ return (boolean) mutableOptionToSet.getValue();
+ } catch (BuildException e) {
+ //This is reached if the template that was provided was bad.
+ MessageDialogSyncedRunnable.openErrorSyncedRunnable(ProfilingMessages.errorTitle, ProfilingMessages.errorGetOptionForWriting);
+ }
+ return false;
+
+ }
+
+ /**
+ * The tools prefernce store is where most compiler build flags are stored.
+ * More specifically for 'debug' flags like gprof and gCov
If you don't know how to get your IProject, see example:
+ * org.eclipse.linuxtools.internal.gprof.launch.GprofLaunchConfigurationDelegate.getProject()
Related wiki: + * + * Programmaticall check option wiki page.
+ * + * @param project + * I project for which to set the flag + * @param optionIDString + * ID of option as defined in plugin.xml. e.g gnu.cpp.compiler.option.debugging.gprof + * @param value + * true or false + * @return false if something went wrong. True otherwise + */ + public static boolean setOptionInCDT(IProject project, String optionIDString, boolean value) { + // Set Tool Name. + String toolSuperClassId = helperGetToolSuperClassId(project); + if (toolSuperClassId == null) { + return false; + } + return setOptionInCDTTool(project, optionIDString, value, toolSuperClassId); + } + + /** + *Check to see if an option is enabled in the .autotools configuration.
+ * + * @param project the IProject project which will be read to check if it is c or cpp. + * @param optionId copy paste directly from .autotools. pick the 'ID' field value. + * @return true if it is + */ + public static boolean isOptionCheckedInAutotoolsPrefStore(final IProject project, final String optionId) { + + //We define a 'final' variable that will be accessible in the runnable object. + final BooleanWithGetSet userChoiceBool = new BooleanWithGetSet(false); + + // need to run this in the ui thread otherwise get SWT Exceptions + // based on concurrency issues. + Display.getDefault().syncExec(new Runnable() { + @Override + public void run() { + + //Code copied from private methd: SetAutotoolsStringOptionValue.setOptionValue() + //Except I added a line to save the configuration to disk as well. + AutotoolsConfigurationManager.getInstance().syncConfigurations(project); + ICConfigurationDescription cfgds = CoreModel.getDefault() + .getProjectDescription(project).getActiveConfiguration(); + if (cfgds != null) { + IAConfiguration iaConfig = AutotoolsConfigurationManager.getInstance() + .getConfiguration(project, cfgds.getId()); + + //Read option value + IConfigureOption option = iaConfig.getOption(optionId); + String optValString = option.getValue(); + boolean optVal = Boolean.parseBoolean(optValString); + userChoiceBool.setVal(optVal); + } + } + }); + + return userChoiceBool.getVal(); + } + + /** + * Set an option (as well as flags) in the .autotools configuration and update gui.
+ * It is oblivious as to whether the option ID is an option or a flag, it just looks at the ID in the xml.
It is designed so that it can be ran from a background thread. + * It syncs with the GUI thread to avoid concurrency exceptions.
+ * + **this modifies gui checkbox options* as well as *saving the option to disk*.
+ * + * @param project the IProject project which will be read to check if it is c or cpp. + * @param optId Id of option to set. Take directly out of .autotools. a 'flag' is also an option. + * @param optVal string value of the option. e.g "true" "1234"; + */ + public static void setOptionInAutotools(final IProject project, final String optId, final String optVal) { + + // need to run this in the ui thread otherwise get SWT Exceptions + // based on concurrency issues. + Display.getDefault().syncExec(new Runnable() { + @Override + public void run() { + + //Code copied from private methd: SetAutotoolsStringOptionValue.setOptionValue() + //Except I added a line to save the configuration to disk as well. + AutotoolsConfigurationManager.getInstance().syncConfigurations(project); + ICConfigurationDescription cfgds = CoreModel.getDefault(). + getProjectDescription(project).getActiveConfiguration(); + + if (cfgds != null) { + IAConfiguration iaConfig = AutotoolsConfigurationManager.getInstance() + .getConfiguration(project, cfgds.getId()); + + //Set option value. + iaConfig.setOption(optId, optVal); + + //Save option to disk. + AutotoolsConfigurationManager.getInstance().saveConfigs(project); + } + } + }); + } + + /** + *Given a project, it finds the active configuration and rebuilds the project.
+ * + *This works with C/C++ Managed Builds as well as Autotools.
+ * + *Most useful for when you have added a flag to a project programmatically and want to rebuild + * the project so that the program is rebuild with that flag. The Rebuild triggers an update of the makefile + * automatically.
+ * + * @param project to rebuild + */ + public static void rebuildProject(IProject project) { + //rebuild does not generate an analysis file (e.g gmon.out) But since -pg flag is added, profiling support is added to the binary. + try { + IBuildConfiguration buildConfiguration = project.getActiveBuildConfig(); + + //force a full rebuild which is usually needed for when you add profiling flags to the build options. + project.build(buildConfiguration, IncrementalProjectBuilder.FULL_BUILD, null); + } catch (CoreException e) { + + //This is a very rare occurrence. Usually rebuilds don't fail if they worked the first time. + MessageDialogSyncedRunnable.openErrorSyncedRunnable(ProfilingMessages.errorTitle, ProfilingMessages.errorRebuilding); + } + } + + /* + * PRIVATE HELPERS BELOW + */ + + /** + *Helper to get the active build configuration.
+ * @param project IProject for which to get the configuration. + * @return IConfiguration of that project. + */ + private static IConfiguration helperGetActiveConfiguration(IProject project) { + IManagedBuildInfo buildInfo = ManagedBuildManager.getBuildInfo(project); + return buildInfo.getDefaultConfiguration(); + } + + /** + * Each option has a parent tool. this acquires the 'ITool'
+ * based on it's name from the active configuration.
The parent tool is later read to acquire the option template, which is used to set an option.
+ * + * @param parentToolName a string representing the parent of the option. (like 'GCC C++ Compiler'). + * @param activeConf The current active configuration of the project, from which we should be able to find the ITool name. + * @return the parent 'ITool' instance. + */ + @Deprecated + private static ITool helperGetGccCompilerTool(String parentToolName, IConfiguration activeConf) { + ITool[] tools = activeConf.getTools(); + ITool gccCompileriTool = null; + for (ITool iTool : tools) { + if (iTool.getName().equals(parentToolName)) { + gccCompileriTool = iTool; + break; + } + } + return gccCompileriTool; + } + + /** + *For a project, calculate the expected superclass id of the compiler tool we expect the compiler tool to be under.
+ * + * @param project IProject for which to get the tool superclass id. + * @return superclass id of the parent tool. + */ + private static String helperGetToolSuperClassId(IProject project) { + String superClassId = null; + if (isCType(project)) { + superClassId = "cdt.managedbuild.tool.gnu.c.compiler"; //$NON-NLS-1$ + } else if (isCppType(project)) { + superClassId = "cdt.managedbuild.tool.gnu.cpp.compiler"; //$NON-NLS-1$ + } else { + //This should happen only if project natures are broken. Maybe the .project file is corrupted. + MessageDialogSyncedRunnable.openErrorSyncedRunnable(ProfilingMessages.errorTitle, ProfilingMessages.errorGetProjectToolname); + return null; + } + return superClassId; + } + + /** + *