Skip to content

Commit 9e60988

Browse files
Add UI for specifying CMake tools and generators locations
Adding UI into CMake Preference page that allow user to specify the location of the CMake tool and the location of CMake generators. Addresses Issue: CDT CMake Improvements #1000, IDE-82683-REQ-004 and IDE-82683-REQ-005
1 parent 11dfaa4 commit 9e60988

File tree

6 files changed

+402
-0
lines changed

6 files changed

+402
-0
lines changed

cmake/org.eclipse.cdt.cmake.ui/src/org/eclipse/cdt/cmake/ui/internal/CMakePreferencePage.java

+244
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,10 @@
1010
*******************************************************************************/
1111
package org.eclipse.cdt.cmake.ui.internal;
1212

13+
import java.io.BufferedReader;
14+
import java.io.File;
15+
import java.io.IOException;
16+
import java.io.InputStreamReader;
1317
import java.nio.file.Path;
1418
import java.util.ArrayList;
1519
import java.util.Collections;
@@ -20,44 +24,75 @@
2024
import org.eclipse.cdt.cmake.core.ICMakeToolChainFile;
2125
import org.eclipse.cdt.cmake.core.ICMakeToolChainManager;
2226
import org.eclipse.cdt.cmake.core.internal.CMakeToolChainManager;
27+
import org.eclipse.cdt.core.CCorePlugin;
2328
import org.eclipse.cdt.core.build.IToolChain;
29+
import org.eclipse.cdt.core.cdtvariables.CdtVariableException;
30+
import org.eclipse.cdt.core.cdtvariables.ICdtVariable;
31+
import org.eclipse.cdt.core.cdtvariables.ICdtVariableManager;
32+
import org.eclipse.cdt.core.settings.model.ICConfigurationDescription;
33+
import org.eclipse.cdt.ui.newui.BuildVarListDialog;
34+
import org.eclipse.cdt.utils.ui.controls.FileListControl;
2435
import org.eclipse.core.runtime.CoreException;
36+
import org.eclipse.core.runtime.preferences.InstanceScope;
37+
import org.eclipse.jface.dialogs.Dialog;
2538
import org.eclipse.jface.dialogs.MessageDialog;
2639
import org.eclipse.jface.layout.TableColumnLayout;
2740
import org.eclipse.jface.preference.PreferencePage;
2841
import org.eclipse.jface.viewers.ColumnWeightData;
2942
import org.eclipse.jface.window.Window;
3043
import org.eclipse.jface.wizard.WizardDialog;
3144
import org.eclipse.swt.SWT;
45+
import org.eclipse.swt.events.ModifyEvent;
46+
import org.eclipse.swt.events.ModifyListener;
3247
import org.eclipse.swt.events.SelectionAdapter;
3348
import org.eclipse.swt.events.SelectionEvent;
3449
import org.eclipse.swt.layout.GridData;
3550
import org.eclipse.swt.layout.GridLayout;
3651
import org.eclipse.swt.widgets.Button;
3752
import org.eclipse.swt.widgets.Composite;
3853
import org.eclipse.swt.widgets.Control;
54+
import org.eclipse.swt.widgets.DirectoryDialog;
3955
import org.eclipse.swt.widgets.Group;
56+
import org.eclipse.swt.widgets.Label;
57+
import org.eclipse.swt.widgets.Shell;
4058
import org.eclipse.swt.widgets.Table;
4159
import org.eclipse.swt.widgets.TableColumn;
4260
import org.eclipse.swt.widgets.TableItem;
61+
import org.eclipse.swt.widgets.Text;
4362
import org.eclipse.ui.IWorkbench;
4463
import org.eclipse.ui.IWorkbenchPreferencePage;
64+
import org.osgi.service.prefs.Preferences;
4565

4666
/**
4767
* GUI page to configure workbench preferences for cmake.
4868
*/
4969
public class CMakePreferencePage extends PreferencePage implements IWorkbenchPreferencePage {
5070

71+
private static final String NODENAME = "cmakeEnvironment"; //$NON-NLS-1$
72+
private static final String VALUE_DELIMITER = " || "; //$NON-NLS-1$
73+
5174
private ICMakeToolChainManager manager;
5275
private Table filesTable;
5376
private Button removeButton;
77+
private Button variablesButton;
78+
private Button testButton;
79+
private Button browseButton;
80+
private Button editButton;
81+
82+
private Text cmakeLocationTextBox;
83+
private Text generatorLocationTextBox;
84+
85+
private String[] generatorLocations;
86+
private String cmakeLocation;
87+
private boolean useCmakeToolLocation;
5488

5589
private Map<Path, ICMakeToolChainFile> filesToAdd = new HashMap<>();
5690
private Map<Path, ICMakeToolChainFile> filesToRemove = new HashMap<>();
5791

5892
@Override
5993
public void init(IWorkbench workbench) {
6094
manager = Activator.getService(ICMakeToolChainManager.class);
95+
updateCmakeToolGroupData();
6196
}
6297

6398
@Override
@@ -141,11 +176,138 @@ public void widgetSelected(SelectionEvent e) {
141176
}
142177
});
143178

179+
// CMake tools section
180+
Group cmakeToolsGroup = new Group(control, SWT.NONE);
181+
cmakeToolsGroup.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
182+
cmakeToolsGroup.setText(Messages.CMakePreferencePage_CMakeTools);
183+
cmakeToolsGroup.setLayout(new GridLayout(1, false));
184+
185+
Composite checkBoxComp = new Composite(cmakeToolsGroup, SWT.NONE);
186+
checkBoxComp.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
187+
checkBoxComp.setLayout(new GridLayout());
188+
189+
Button useCMakeToolLocCheckBox = new Button(checkBoxComp, SWT.CHECK);
190+
useCMakeToolLocCheckBox.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false, 3, 1));
191+
useCMakeToolLocCheckBox.setText(Messages.CMakePreferencePage_UseCMakeToolLocationsInCMakeBuilds);
192+
useCMakeToolLocCheckBox.setToolTipText(Messages.CMakePreferencePage_UseCMakeToolLocationsInCMakeBuildsTooltip);
193+
useCMakeToolLocCheckBox.setSelection(useCmakeToolLocation);
194+
useCMakeToolLocCheckBox.addListener(SWT.Selection, e -> {
195+
useCmakeToolLocation = useCMakeToolLocCheckBox.getSelection();
196+
updateCMakeGroup(useCmakeToolLocation);
197+
});
198+
199+
Composite locationComp = new Composite(cmakeToolsGroup, SWT.NONE);
200+
locationComp.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false));
201+
locationComp.setLayout(new GridLayout(3, false));
202+
203+
Label cmakeLocationLabel = new Label(locationComp, SWT.NONE);
204+
cmakeLocationLabel.setText(Messages.CMakePreferencePage_CMakeLocation);
205+
cmakeLocationLabel.setToolTipText(Messages.CMakePreferencePage_CMakeLocationTooltip);
206+
207+
cmakeLocationTextBox = new Text(locationComp, SWT.BORDER);
208+
cmakeLocationTextBox.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, true));
209+
cmakeLocationTextBox.setText(cmakeLocation);
210+
cmakeLocationTextBox.addModifyListener(new ModifyListener() {
211+
@Override
212+
public void modifyText(ModifyEvent evt) {
213+
cmakeLocation = resolveVariableValue(cmakeLocationTextBox.getText());
214+
}
215+
});
216+
217+
Composite cmakeLocationButtonComp = new Composite(locationComp, SWT.NONE);
218+
cmakeLocationButtonComp.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false));
219+
cmakeLocationButtonComp.setLayout(new GridLayout(3, true));
220+
221+
variablesButton = new Button(cmakeLocationButtonComp, SWT.PUSH);
222+
variablesButton.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
223+
variablesButton.setText(Messages.CMakePreferencePage_Variables);
224+
variablesButton.setData(cmakeLocationTextBox);
225+
variablesButton.addListener(SWT.Selection, e -> {
226+
String x = null;
227+
if (variablesButton.getData() instanceof Text t) {
228+
x = getVariableDialog(getShell(), null);
229+
if (x != null) {
230+
t.insert(x);
231+
}
232+
}
233+
});
234+
235+
testButton = new Button(cmakeLocationButtonComp, SWT.PUSH);
236+
testButton.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
237+
testButton.setText(Messages.CMakePreferencePage_Test);
238+
testButton.setToolTipText(Messages.CMakePreferencePage_TestTooltip);
239+
testButton.setData(cmakeLocationTextBox);
240+
testButton.addListener(SWT.Selection, e -> {
241+
try {
242+
Process p = Runtime.getRuntime()
243+
.exec(new String[] { cmakeLocation + File.separatorChar + "cmake", "--version" }); //$NON-NLS-1$ //$NON-NLS-2$
244+
List<String> buf = new ArrayList<>();
245+
BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream()));
246+
String line;
247+
while ((line = br.readLine()) != null) {
248+
buf.add(line);
249+
}
250+
MessageDialog.openInformation(getShell(), Messages.CMakePreferencePage_TestCmakeLocation_Title,
251+
Messages.CMakePreferencePage_TestCmakeLocation_Body + String.join(System.lineSeparator(), buf));
252+
} catch (IOException e1) {
253+
MessageDialog.openError(getShell(), Messages.CMakePreferencePage_FailToTestCmakeLocation_Title,
254+
Messages.CMakePreferencePage_FailToTestCmakeLocation_Body + e1.getMessage());
255+
}
256+
});
257+
258+
browseButton = new Button(cmakeLocationButtonComp, SWT.PUSH);
259+
browseButton.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
260+
browseButton.setText(Messages.CMakePreferencePage_Browse);
261+
browseButton.setData(cmakeLocationTextBox);
262+
browseButton.addListener(SWT.Selection, e -> {
263+
DirectoryDialog dirDialog = new DirectoryDialog(getShell());
264+
String browsedDirectory = dirDialog.open();
265+
if (browsedDirectory != null && browseButton.getData() instanceof Text t) {
266+
t.setText(browsedDirectory);
267+
}
268+
});
269+
270+
Label generatorLocationsLabel = new Label(locationComp, SWT.NONE);
271+
generatorLocationsLabel.setText(Messages.CMakePreferencePage_GeneratorLocation);
272+
generatorLocationsLabel.setToolTipText(Messages.CMakePreferencePage_GeneratorLocationTooltip);
273+
274+
generatorLocationTextBox = new Text(locationComp, SWT.BORDER);
275+
generatorLocationTextBox.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
276+
generatorLocationTextBox.setEditable(false);
277+
generatorLocationTextBox.setText(String.join(VALUE_DELIMITER, generatorLocations));
278+
279+
Composite generatorLocationButtonComp = new Composite(locationComp, SWT.NONE);
280+
generatorLocationButtonComp.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false));
281+
generatorLocationButtonComp.setLayout(new GridLayout(3, true));
282+
283+
editButton = new Button(generatorLocationButtonComp, SWT.PUSH);
284+
editButton.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
285+
editButton.setText(Messages.CMakePreferencePage_Edit);
286+
editButton.setData(generatorLocationTextBox);
287+
editButton.addListener(SWT.Selection, e -> {
288+
EditGenerationLocationDialog dialog = new EditGenerationLocationDialog(getShell(),
289+
Messages.CMakePreferencePage_EditGeneratorLocations_Title, generatorLocations);
290+
if (dialog.open() == Window.OK && editButton.getData() instanceof Text t) {
291+
generatorLocations = dialog.getValues();
292+
t.setText(String.join(VALUE_DELIMITER, generatorLocations));
293+
}
294+
});
295+
144296
updateTable();
297+
updateCMakeGroup(useCmakeToolLocation);
145298

146299
return control;
147300
}
148301

302+
protected void updateCMakeGroup(boolean enable) {
303+
cmakeLocationTextBox.setEnabled(enable);
304+
generatorLocationTextBox.setEnabled(enable);
305+
variablesButton.setEnabled(enable);
306+
testButton.setEnabled(enable);
307+
browseButton.setEnabled(enable);
308+
editButton.setEnabled(enable);
309+
}
310+
149311
private void updateTable() {
150312
List<ICMakeToolChainFile> sorted = new ArrayList<>(getFiles().values());
151313
Collections.sort(sorted, (o1, o2) -> o1.getPath().toString().compareToIgnoreCase(o2.getPath().toString()));
@@ -205,7 +367,89 @@ public boolean performOk() {
205367
filesToAdd.clear();
206368
filesToRemove.clear();
207369

370+
// Update Preferences for cmakeSupplier
371+
getPreferences().putBoolean("useCmakeToolLocation", useCmakeToolLocation); //$NON-NLS-1$
372+
getPreferences().put("cmakeLocation", cmakeLocation); //$NON-NLS-1$
373+
getPreferences().put("generatorLocations", String.join(VALUE_DELIMITER, generatorLocations)); //$NON-NLS-1$
374+
208375
return true;
209376
}
210377

378+
public void updateCmakeToolGroupData() {
379+
useCmakeToolLocation = getPreferences().getBoolean("useCmakeToolLocation", false); //$NON-NLS-1$
380+
cmakeLocation = getPreferences().get("cmakeLocation", ""); //$NON-NLS-1$ //$NON-NLS-2$
381+
String genLocations = getPreferences().get("generatorLocations", ""); //$NON-NLS-1$ //$NON-NLS-2$
382+
generatorLocations = genLocations.length() > 0 ? genLocations.split(" \\|\\| ") : new String[0]; //$NON-NLS-1$
383+
}
384+
385+
private String resolveVariableValue(String value) {
386+
try {
387+
ICdtVariableManager vm = CCorePlugin.getDefault().getCdtVariableManager();
388+
return vm.resolveValue(value, null, "", null); //$NON-NLS-1$
389+
} catch (CdtVariableException e) {
390+
e.printStackTrace();
391+
}
392+
return null;
393+
}
394+
395+
private String getVariableDialog(Shell shell, ICConfigurationDescription cfgd) {
396+
ICdtVariableManager vm = CCorePlugin.getDefault().getCdtVariableManager();
397+
BuildVarListDialog dialog = new BuildVarListDialog(shell, vm.getVariables(cfgd));
398+
dialog.setTitle(Messages.VariablesDialog_Title);
399+
if (dialog.open() == Window.OK) {
400+
Object[] selected = dialog.getResult();
401+
if (selected.length > 0) {
402+
String s = ((ICdtVariable) selected[0]).getName();
403+
return "${" + s.trim() + "}"; //$NON-NLS-1$//$NON-NLS-2$
404+
}
405+
}
406+
return null;
407+
}
408+
409+
class EditGenerationLocationDialog extends Dialog {
410+
411+
private String fTitle;
412+
private FileListControl fListEditor;
413+
private String[] fGeneratorLocations;
414+
415+
public EditGenerationLocationDialog(Shell parentShell, String title, String[] generatorLocations) {
416+
super(parentShell);
417+
this.fGeneratorLocations = generatorLocations;
418+
}
419+
420+
@Override
421+
protected void configureShell(Shell shell) {
422+
super.configureShell(shell);
423+
if (fTitle != null) {
424+
shell.setText(fTitle);
425+
}
426+
}
427+
428+
@Override
429+
protected Control createDialogArea(Composite parent) {
430+
Composite comp = new Composite(parent, SWT.NULL);
431+
comp.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
432+
comp.setLayout(new GridLayout());
433+
fListEditor = new FileListControl(comp,
434+
Messages.cMakePreferencePage_EditGeneratorLocations_GeneratorLocation, 0);
435+
if (fGeneratorLocations != null) {
436+
fListEditor.setList(fGeneratorLocations);
437+
}
438+
return comp;
439+
}
440+
441+
@Override
442+
protected void okPressed() {
443+
fGeneratorLocations = fListEditor.getItems();
444+
super.okPressed();
445+
}
446+
447+
public String[] getValues() {
448+
return fGeneratorLocations;
449+
}
450+
}
451+
452+
private Preferences getPreferences() {
453+
return InstanceScope.INSTANCE.getNode(CCorePlugin.PLUGIN_ID).node(NODENAME);
454+
}
211455
}

cmake/org.eclipse.cdt.cmake.ui/src/org/eclipse/cdt/cmake/ui/internal/Messages.java

+21
Original file line numberDiff line numberDiff line change
@@ -27,12 +27,31 @@ public class Messages extends NLS {
2727
public static String CMakeBuildTab_useUICmakeSettings;
2828
public static String CMakeBuildTab_useUICmakeSettingsTip;
2929
public static String CMakePreferencePage_Add;
30+
public static String CMakePreferencePage_Browse;
31+
public static String CMakePreferencePage_CMakeLocation;
32+
public static String CMakePreferencePage_CMakeLocationTooltip;
33+
public static String CMakePreferencePage_CMakeTools;
3034
public static String CMakePreferencePage_ConfirmRemoveDesc;
3135
public static String CMakePreferencePage_ConfirmRemoveTitle;
36+
public static String CMakePreferencePage_Delete;
37+
public static String CMakePreferencePage_Edit;
38+
public static String CMakePreferencePage_EditGeneratorLocations_Title;
39+
public static String cMakePreferencePage_EditGeneratorLocations_GeneratorLocation;
40+
public static String CMakePreferencePage_FailToTestCmakeLocation_Body;
41+
public static String CMakePreferencePage_FailToTestCmakeLocation_Title;
3242
public static String CMakePreferencePage_Files;
43+
public static String CMakePreferencePage_GeneratorLocation;
44+
public static String CMakePreferencePage_GeneratorLocationTooltip;
3345
public static String CMakePreferencePage_Path;
3446
public static String CMakePreferencePage_Remove;
47+
public static String CMakePreferencePage_Test;
48+
public static String CMakePreferencePage_TestCmakeLocation_Body;
49+
public static String CMakePreferencePage_TestCmakeLocation_Title;
50+
public static String CMakePreferencePage_TestTooltip;
3551
public static String CMakePreferencePage_Toolchain;
52+
public static String CMakePreferencePage_UseCMakeToolLocationsInCMakeBuilds;
53+
public static String CMakePreferencePage_UseCMakeToolLocationsInCMakeBuildsTooltip;
54+
public static String CMakePreferencePage_Variables;
3655
public static String CMakePropertyPage_FailedToStartCMakeGui_Body;
3756
public static String CMakePropertyPage_FailedToStartCMakeGui_Title;
3857
public static String CMakePropertyPage_FailedToGetOS_Body;
@@ -54,6 +73,8 @@ public class Messages extends NLS {
5473
public static String NewCMakeToolChainFilePage_Title;
5574
public static String NewCMakeToolChainFilePage_Toolchain;
5675

76+
public static String VariablesDialog_Title;
77+
5778
static {
5879
// initialize resource bundle
5980
NLS.initializeMessages("org.eclipse.cdt.cmake.ui.internal.messages", Messages.class); //$NON-NLS-1$

cmake/org.eclipse.cdt.cmake.ui/src/org/eclipse/cdt/cmake/ui/internal/messages.properties

+20
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,31 @@ CMakeBuildTab_UnixMakefiles=Unix Makefiles
1111
CMakeBuildTab_useUICmakeSettings=Use these settings
1212
CMakeBuildTab_useUICmakeSettingsTip=Use these settings instead of the operating system defaults
1313
CMakePreferencePage_Add=Add...
14+
CMakePreferencePage_Browse=Browse...
15+
CMakePreferencePage_CMakeLocation=CMake location:
16+
CMakePreferencePage_CMakeLocationTooltip=The directory containing the CMake tool.
17+
CMakePreferencePage_CMakeTools=CMake Tools
1418
CMakePreferencePage_ConfirmRemoveDesc=Do you wish to deregister the selected files?
1519
CMakePreferencePage_ConfirmRemoveTitle=Deregister CMake ToolChain File
20+
CMakePreferencePage_Delete=Delete
21+
CMakePreferencePage_Edit=Edit...
22+
CMakePreferencePage_EditGeneratorLocations_Title=Edit generator locations
23+
cMakePreferencePage_EditGeneratorLocations_GeneratorLocation=Generator location:
24+
CMakePreferencePage_FailToTestCmakeLocation_Body=Fail to test CMake in selected location:\u000a
25+
CMakePreferencePage_FailToTestCmakeLocation_Title=Fail to test CMake location
1626
CMakePreferencePage_Files=Toolchain Files
27+
CMakePreferencePage_GeneratorLocation=Generator location(s):
28+
CMakePreferencePage_GeneratorLocationTooltip=The directory(s) containing the CMake generators (eg Ninja, Makefiles). Separate locations using the ';'.
1729
CMakePreferencePage_Path=Toolchain File
1830
CMakePreferencePage_Remove=Remove
31+
CMakePreferencePage_Test=Test...
32+
CMakePreferencePage_TestCmakeLocation_Body=Found:\u0020
33+
CMakePreferencePage_TestCmakeLocation_Title=Test result
34+
CMakePreferencePage_TestTooltip=Tests that the CMake binary is found and executable.
1935
CMakePreferencePage_Toolchain=Toolchain
36+
CMakePreferencePage_UseCMakeToolLocationsInCMakeBuilds=Use CMake tool locations in CMake builds
37+
CMakePreferencePage_UseCMakeToolLocationsInCMakeBuildsTooltip=The listed directories are added to the CMake execution environment so the CMake tool and generators are available for building and debugging. Uncheck to use locations already specified on system PATH environment.
38+
CMakePreferencePage_Variables=Variables...
2039
CMakePropertyPage_FailedToStartCMakeGui_Body=Failed to run the CMake GUI:\u0020
2140
CMakePropertyPage_FailedToStartCMakeGui_Title=Failed to run CMake GUI
2241
CMakePropertyPage_FailedToGetOS_Body=Failed to get target OS for CMake project:
@@ -35,3 +54,4 @@ NewCMakeToolChainFilePage_Path=Path:
3554
NewCMakeToolChainFilePage_Select=Select location for CMake toolchain file
3655
NewCMakeToolChainFilePage_Title=New CMake ToolChain File
3756
NewCMakeToolChainFilePage_Toolchain=Toolchain:
57+
VariablesDialog_Title=Select CMake variable

0 commit comments

Comments
 (0)