Skip to content

Commit

Permalink
Bug579242: allow user to override CMake Settings
Browse files Browse the repository at this point in the history
The Launch Bar Launch Configuration, Build Settings tab allows the user
to customise the CMake Settings (CMake generator, extra arguments, build
command and clean command). But changing these settings did not affect
the CMake build. This is now fixed.
A "Use these settings" checkbox allows the user to choose settings from
the UI or use the operating system defaults.
  • Loading branch information
betamaxbandit committed Feb 5, 2024
1 parent 61c3568 commit ec2f40e
Show file tree
Hide file tree
Showing 13 changed files with 160 additions and 20 deletions.
11 changes: 11 additions & 0 deletions NewAndNoteworthy/CDT-11.5.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,17 @@ This is the New & Noteworthy page for CDT 11.5 which is part of Eclipse 2024-03

# Release Notes

# CMake
The Launch Bar Launch Configuration Build Settings tab has been updated so it can now correctly control the CMake Generator setting. The "Additional CMake arguments" field can also be used to inject CMake defines into the CMakeCache.txt file to populate it with customizable settings for the project. Use the new "Use these settings" checkbox to control whether to use either the operating system defaults or settings from the UI.

When "Use these settings" checkbox is unchecked, the operating system defaults are used during the CMake build.

<p align="center"><img src="images/CDT-11.5-Build_Settings_Use_these_settings_unchecked.PNG" width="50%"></p>

When the "Use these settings" checkbox is checked, the UI settings are used during the CMake build.

<p align="center"><img src="images/CDT-11.5-Build_Settings_Use_these_settings_checked.PNG" width="50%"></p>


# API Changes, current and planned

Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
8 changes: 8 additions & 0 deletions TESTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -117,3 +117,11 @@ DISPLAY=:99 mvn verify
or specify the `DISPLAY` in the Eclipse JUnit launch configuration:

![junit_env_display.png](images/junit_env_display.png "screenshot of how to set custom DISPLAY")

## Manual Testing
### CMake Build Settings tab
A set of manual tests that check it is possible to control the CMake build using the Launch Bar Launch Configuration > Build Settings tab.

[CMake Build Settings](https://github.com/eclipse-cdt/cdt/files/14087582/Bug579242_manual_tests.md)


2 changes: 1 addition & 1 deletion cmake/org.eclipse.cdt.cmake.core/META-INF/MANIFEST.MF
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: %pluginName
Bundle-SymbolicName: org.eclipse.cdt.cmake.core;singleton:=true
Bundle-Version: 1.5.400.qualifier
Bundle-Version: 1.5.500.qualifier
Bundle-Activator: org.eclipse.cdt.cmake.core.internal.Activator
Bundle-Vendor: %providerName
Require-Bundle: org.eclipse.core.runtime,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,13 @@
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.function.Consumer;
import java.util.stream.Collectors;

import org.eclipse.cdt.cmake.core.CMakeErrorParser;
import org.eclipse.cdt.cmake.core.CMakeExecutionMarkerFactory;
Expand Down Expand Up @@ -66,14 +68,19 @@
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.jobs.Job;
import org.osgi.service.prefs.Preferences;

public class CMakeBuildConfiguration extends CBuildConfiguration {

public static final String CMAKE_USE_UI_OVERRIDES = "cmake.use.ui.overrides"; //$NON-NLS-1$
public static final boolean CMAKE_USE_UI_OVERRIDES_DEFAULT = false;
public static final String CMAKE_GENERATOR = "cmake.generator"; //$NON-NLS-1$
public static final String CMAKE_ARGUMENTS = "cmake.arguments"; //$NON-NLS-1$
public static final String CMAKE_ENV = "cmake.environment"; //$NON-NLS-1$
public static final String BUILD_COMMAND = "cmake.command.build"; //$NON-NLS-1$
public static final String BUILD_COMMAND_DEFAULT = "cmake"; //$NON-NLS-1$
public static final String CLEAN_COMMAND = "cmake.command.clean"; //$NON-NLS-1$
public static final String CLEAN_COMMAND_DEFAULT = "clean"; //$NON-NLS-1$

private ICMakeToolChainFile toolChainFile;

Expand Down Expand Up @@ -261,6 +268,23 @@ public IProject[] build(int kind, Map<String, String> args, IConsole console, IP
}
}

/**
* When UI overrides are in force, gets the user specified clean target (if not blank), otherwise the default clean target.
* @return Always a non-null String indicating the clean target.
*/
private String getCleanCommand() {
String retVal = CLEAN_COMMAND_DEFAULT;
Preferences settings = this.getSettings();
boolean useUiOverrides = settings.getBoolean(CMAKE_USE_UI_OVERRIDES, CMAKE_USE_UI_OVERRIDES_DEFAULT);
if (useUiOverrides) {
String cleanCommand = settings.get(CLEAN_COMMAND, CLEAN_COMMAND_DEFAULT);
if (!cleanCommand.isBlank()) {
retVal = cleanCommand;
}
}
return retVal;
}

@Override
public void clean(IConsole console, IProgressMonitor monitor) throws CoreException {
IProject project = getProject();
Expand All @@ -271,7 +295,7 @@ public void clean(IConsole console, IProgressMonitor monitor) throws CoreExcepti
ICMakeProperties cmakeProperties = getPropertiesController().load();
CommandDescriptorBuilder cmdBuilder = new CommandDescriptorBuilder(cmakeProperties,
new SimpleOsOverridesSelector());
CommandDescriptor command = cmdBuilder.makeCMakeBuildCommandline("clean"); //$NON-NLS-1$
CommandDescriptor command = cmdBuilder.makeCMakeBuildCommandline(getCleanCommand());
ConsoleOutputStream outStream = console.getOutputStream();

Path buildDir = getBuildDirectory();
Expand Down Expand Up @@ -547,7 +571,12 @@ public void shutdown() {
}
} // CMakeIndexerInfoConsumer

private static class SimpleOsOverridesSelector implements IOsOverridesSelector {
/**
* Supports OS overrides and also User Interface (UI) overrides, provided in the CMakeBuildTab. The UI
* overrides are stored in the intermediary CBuildConfiguration Preferences (CBuildConfiguration.getSettings())
* and used only when CMAKE_USE_UI_OVERRIDES is true.
*/
private class SimpleOsOverridesSelector implements IOsOverridesSelector {

@Override
public IOsOverrides getOsOverrides(ICMakeProperties cmakeProperties) {
Expand All @@ -561,7 +590,31 @@ public IOsOverrides getOsOverrides(ICMakeProperties cmakeProperties) {
// fall back to linux, if OS is unknown
overrides = cmakeProperties.getLinuxOverrides();
}
return overrides;
return getUiOrOsOverrides(overrides);
}

private IOsOverrides getUiOrOsOverrides(IOsOverrides osOverrides) {
IOsOverrides retVal = Objects.requireNonNull(osOverrides, "osOverrides must not be null"); //$NON-NLS-1$
Preferences settings = getSettings();
boolean useUiOverrides = settings.getBoolean(CMAKE_USE_UI_OVERRIDES, CMAKE_USE_UI_OVERRIDES_DEFAULT);
if (useUiOverrides) {
// Set UI override for generator
String gen = settings.get(CMAKE_GENERATOR, ""); //$NON-NLS-1$
retVal.setGenerator(CMakeGenerator.getGenerator(gen));
// Set UI override for Extra Arguments
String extraArgsStr = settings.get(CMAKE_ARGUMENTS, ""); //$NON-NLS-1$
// Convert String of args, separated by 1 or more spaces, into list of Strings
List<String> extraArgs = Arrays.stream(extraArgsStr.split("\\s+")).map(entry -> entry.trim()) //$NON-NLS-1$
.collect(Collectors.toList());
retVal.setExtraArguments(extraArgs);
// Set UI override for cmake build command, unless it's the default
String buildCommand = settings.get(BUILD_COMMAND, BUILD_COMMAND_DEFAULT);
if (!buildCommand.isBlank() && !BUILD_COMMAND_DEFAULT.equals(buildCommand)) {
retVal.setUseDefaultCommand(false);
retVal.setCommand(buildCommand);
}
}
return retVal;
}
} // SimpleOsOverridesSelector
}
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ CommandDescriptor makeCMakeCommandline(Path toolChainFile) throws CoreException
List<String> env = new ArrayList<>();

// defaults for all OSes...
args.add("cmake"); //$NON-NLS-1$
args.add(CMakeBuildConfiguration.BUILD_COMMAND_DEFAULT);
/* add general settings */
if (cmakeProperties.isWarnNoDev())
args.add("-Wno-dev"); //$NON-NLS-1$
Expand Down Expand Up @@ -111,7 +111,7 @@ CommandDescriptor makeCMakeBuildCommandline(String buildscriptTarget) throws Cor

IOsOverrides osOverrides = overridesSelector.getOsOverrides(cmakeProperties);
if (osOverrides.getUseDefaultCommand()) {
args.add("cmake"); //$NON-NLS-1$
args.add(CMakeBuildConfiguration.BUILD_COMMAND_DEFAULT);
} else {
IStringVariableManager varManager = VariablesPlugin.getDefault().getStringVariableManager();
String cmd = varManager.performStringSubstitution(osOverrides.getCommand());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import java.util.List;
import java.util.Objects;

import org.eclipse.cdt.cmake.core.internal.CMakeBuildConfiguration;
import org.eclipse.cdt.cmake.core.properties.CMakeGenerator;
import org.eclipse.cdt.cmake.core.properties.IOsOverrides;

Expand Down Expand Up @@ -42,7 +43,7 @@ public AbstractOsOverrides() {
* Sets each value to its default.
*/
public void reset() {
setCommand("cmake"); //$NON-NLS-1$
setCommand(CMakeBuildConfiguration.BUILD_COMMAND_DEFAULT);
useDefaultCommand = true;
setGenerator(CMakeGenerator.UnixMakefiles);
extraArguments.clear();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,4 +81,16 @@ public String getMakefileName() {
public String getIgnoreErrOption() {
return ignoreErrOption;
}

/**
* @since 1.5
*/
public static CMakeGenerator getGenerator(String generatorName) {
for (CMakeGenerator gen : values()) {
if (gen.getCMakeName().equals(generatorName)) {
return gen;
}
}
return null;
}
}
2 changes: 1 addition & 1 deletion cmake/org.eclipse.cdt.cmake.ui/META-INF/MANIFEST.MF
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: %pluginName
Bundle-SymbolicName: org.eclipse.cdt.cmake.ui;singleton:=true
Bundle-Version: 1.4.300.qualifier
Bundle-Version: 1.4.400.qualifier
Bundle-Activator: org.eclipse.cdt.cmake.ui.internal.Activator
Bundle-Vendor: %providerName
Require-Bundle: org.eclipse.core.runtime,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
*******************************************************************************/
package org.eclipse.cdt.cmake.ui.internal;

import java.util.HashMap;
import java.util.Map;

import org.eclipse.cdt.cmake.core.internal.CMakeBuildConfiguration;
Expand All @@ -32,11 +33,20 @@

public class CMakeBuildTab extends CommonBuildTab {

/**
* Checkbox allowing user to choose these settings over the default operating system defaults.
* This is connected to the CMakeBuildConfiguration.CMAKE_USE_UI_OVERRIDES preference.
*/
private Button useUiCmakeSettings;
private Button unixGenButton;
private Button ninjaGenButton;
private Text cmakeArgsText;
private Text buildCommandText;
private Text cleanCommandText;
private Label generatorLabel;
private Label cmakeArgsLabel;
private Label buildCommandLabel;
private Label cleanCommandLabel;

@Override
protected String getBuildConfigProviderId() {
Expand All @@ -57,8 +67,19 @@ public void createControl(Composite parent) {
cmakeGroup.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
cmakeGroup.setLayout(new GridLayout());

Label label = new Label(cmakeGroup, SWT.NONE);
label.setText(Messages.CMakeBuildTab_Generator);
useUiCmakeSettings = new Button(cmakeGroup, SWT.CHECK);
useUiCmakeSettings.setText(Messages.CMakeBuildTab_useUICmakeSettings);
useUiCmakeSettings.setToolTipText(Messages.CMakeBuildTab_useUICmakeSettingsTip);
useUiCmakeSettings.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
updateEnablement();
updateLaunchConfigurationDialog();
}
});

generatorLabel = new Label(cmakeGroup, SWT.NONE);
generatorLabel.setText(Messages.CMakeBuildTab_Generator);

Composite genComp = new Composite(cmakeGroup, SWT.BORDER);
genComp.setLayout(new GridLayout(2, true));
Expand All @@ -81,31 +102,50 @@ public void widgetSelected(SelectionEvent e) {
}
});

label = new Label(cmakeGroup, SWT.NONE);
label.setText(Messages.CMakeBuildTab_CMakeArgs);
cmakeArgsLabel = new Label(cmakeGroup, SWT.NONE);
cmakeArgsLabel.setText(Messages.CMakeBuildTab_CMakeArgs);

cmakeArgsText = new Text(cmakeGroup, SWT.BORDER);
cmakeArgsText.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
cmakeArgsText.addModifyListener(e -> updateLaunchConfigurationDialog());

label = new Label(cmakeGroup, SWT.NONE);
label.setText(Messages.CMakeBuildTab_BuildCommand);
buildCommandLabel = new Label(cmakeGroup, SWT.NONE);
buildCommandLabel.setText(Messages.CMakeBuildTab_BuildCommand);

buildCommandText = new Text(cmakeGroup, SWT.BORDER);
buildCommandText.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
buildCommandText.addModifyListener(e -> updateLaunchConfigurationDialog());

label = new Label(cmakeGroup, SWT.NONE);
label.setText(Messages.CMakeBuildTab_CleanCommand);
cleanCommandLabel = new Label(cmakeGroup, SWT.NONE);
cleanCommandLabel.setText(Messages.CMakeBuildTab_CleanCommand);

cleanCommandText = new Text(cmakeGroup, SWT.BORDER);
cleanCommandText.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
cleanCommandText.addModifyListener(e -> updateLaunchConfigurationDialog());
}

/**
* Updates the enabled state of the CMake settings controls based on useUiCmakeSettings checkbox
*/
private void updateEnablement() {
boolean isSelected = useUiCmakeSettings.getSelection();
generatorLabel.setEnabled(isSelected);
unixGenButton.setEnabled(isSelected);
ninjaGenButton.setEnabled(isSelected);
cmakeArgsLabel.setEnabled(isSelected);
cmakeArgsText.setEnabled(isSelected);
buildCommandLabel.setEnabled(isSelected);
buildCommandText.setEnabled(isSelected);
cleanCommandLabel.setEnabled(isSelected);
cleanCommandText.setEnabled(isSelected);
}

@Override
public void setDefaults(ILaunchConfigurationWorkingCopy configuration) {
// TODO
// Set defaults for Build Settings
ICBuildConfiguration buildConfig = getBuildConfiguration();
buildConfig.setProperty(CMakeBuildConfiguration.CMAKE_USE_UI_OVERRIDES,
Boolean.toString(CMakeBuildConfiguration.CMAKE_USE_UI_OVERRIDES_DEFAULT));
}

@Override
Expand Down Expand Up @@ -133,10 +173,14 @@ public void initializeFrom(ILaunchConfiguration configuration) {

String cleanCommand = buildConfig.getProperty(CMakeBuildConfiguration.CLEAN_COMMAND);
if (cleanCommand != null) {
cleanCommandText.setText(buildCommand);
cleanCommandText.setText(cleanCommand);
} else {
cleanCommandText.setText(""); //$NON-NLS-1$
}

boolean isSelected = Boolean.valueOf(buildConfig.getProperty(CMakeBuildConfiguration.CMAKE_USE_UI_OVERRIDES));
useUiCmakeSettings.setSelection(isSelected);
updateEnablement();
}

private void updateGeneratorButtons(String generator) {
Expand All @@ -153,8 +197,8 @@ public void performApply(ILaunchConfigurationWorkingCopy configuration) {

ICBuildConfiguration buildConfig = getBuildConfiguration();

buildConfig.setProperty(CMakeBuildConfiguration.CMAKE_GENERATOR,
ninjaGenButton.getSelection() ? "Ninja" : "Unix Makefiles"); //$NON-NLS-1$ //$NON-NLS-2$
String gen = ninjaGenButton.getSelection() ? "Ninja" : "Unix Makefiles"; //$NON-NLS-1$ //$NON-NLS-2$
buildConfig.setProperty(CMakeBuildConfiguration.CMAKE_GENERATOR, gen);

String cmakeArgs = cmakeArgsText.getText().trim();
if (!cmakeArgs.isEmpty()) {
Expand All @@ -176,6 +220,13 @@ public void performApply(ILaunchConfigurationWorkingCopy configuration) {
} else {
buildConfig.removeProperty(CMakeBuildConfiguration.CLEAN_COMMAND);
}

boolean isSelected = useUiCmakeSettings.getSelection();
buildConfig.setProperty(CMakeBuildConfiguration.CMAKE_USE_UI_OVERRIDES, Boolean.toString(isSelected));

Map<String, String> saved = new HashMap<>();
saved.put(CMakeBuildConfiguration.CMAKE_USE_UI_OVERRIDES, Boolean.toString(isSelected));
getBuildConfiguration().setProperties(saved);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ public class Messages extends NLS {
public static String CMakeBuildTab_Settings;
public static String CMakeBuildTab_Toolchain;
public static String CMakeBuildTab_UnixMakefiles;
public static String CMakeBuildTab_useUICmakeSettings;
public static String CMakeBuildTab_useUICmakeSettingsTip;
public static String CMakePreferencePage_Add;
public static String CMakePreferencePage_ConfirmRemoveDesc;
public static String CMakePreferencePage_ConfirmRemoveTitle;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ CMakeBuildTab_NoneAvailable=No Toolchains Available for this Target
CMakeBuildTab_Settings=CMake Settings
CMakeBuildTab_Toolchain=Toolchain
CMakeBuildTab_UnixMakefiles=Unix Makefiles
CMakeBuildTab_useUICmakeSettings=Use these settings
CMakeBuildTab_useUICmakeSettingsTip=Use these settings instead of the operating system defaults
CMakePreferencePage_Add=Add...
CMakePreferencePage_ConfirmRemoveDesc=Do you wish to deregister the selected files?
CMakePreferencePage_ConfirmRemoveTitle=Deregister CMake ToolChain File
Expand Down

0 comments on commit ec2f40e

Please sign in to comment.