mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-04-29 19:45:01 +02:00
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. Added Unit test Addresses Issue: CDT CMake Improvements #1000, IDE-82683-REQ-004 and IDE-82683-REQ-005
This commit is contained in:
parent
f96dd1a385
commit
5aa5354a8d
9 changed files with 764 additions and 2 deletions
|
@ -10,6 +10,10 @@
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
package org.eclipse.cdt.cmake.ui.internal;
|
package org.eclipse.cdt.cmake.ui.internal;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
@ -20,8 +24,18 @@ import java.util.Map;
|
||||||
import org.eclipse.cdt.cmake.core.ICMakeToolChainFile;
|
import org.eclipse.cdt.cmake.core.ICMakeToolChainFile;
|
||||||
import org.eclipse.cdt.cmake.core.ICMakeToolChainManager;
|
import org.eclipse.cdt.cmake.core.ICMakeToolChainManager;
|
||||||
import org.eclipse.cdt.cmake.core.internal.CMakeToolChainManager;
|
import org.eclipse.cdt.cmake.core.internal.CMakeToolChainManager;
|
||||||
|
import org.eclipse.cdt.core.CCorePlugin;
|
||||||
import org.eclipse.cdt.core.build.IToolChain;
|
import org.eclipse.cdt.core.build.IToolChain;
|
||||||
|
import org.eclipse.cdt.core.cdtvariables.CdtVariableException;
|
||||||
|
import org.eclipse.cdt.core.cdtvariables.ICdtVariable;
|
||||||
|
import org.eclipse.cdt.core.cdtvariables.ICdtVariableManager;
|
||||||
|
import org.eclipse.cdt.core.settings.model.ICConfigurationDescription;
|
||||||
|
import org.eclipse.cdt.internal.core.envvar.CMakeBuildEnvironmentSupplier;
|
||||||
|
import org.eclipse.cdt.ui.newui.BuildVarListDialog;
|
||||||
|
import org.eclipse.cdt.utils.ui.controls.FileListControl;
|
||||||
import org.eclipse.core.runtime.CoreException;
|
import org.eclipse.core.runtime.CoreException;
|
||||||
|
import org.eclipse.core.runtime.preferences.InstanceScope;
|
||||||
|
import org.eclipse.jface.dialogs.Dialog;
|
||||||
import org.eclipse.jface.dialogs.MessageDialog;
|
import org.eclipse.jface.dialogs.MessageDialog;
|
||||||
import org.eclipse.jface.layout.TableColumnLayout;
|
import org.eclipse.jface.layout.TableColumnLayout;
|
||||||
import org.eclipse.jface.preference.PreferencePage;
|
import org.eclipse.jface.preference.PreferencePage;
|
||||||
|
@ -29,6 +43,8 @@ import org.eclipse.jface.viewers.ColumnWeightData;
|
||||||
import org.eclipse.jface.window.Window;
|
import org.eclipse.jface.window.Window;
|
||||||
import org.eclipse.jface.wizard.WizardDialog;
|
import org.eclipse.jface.wizard.WizardDialog;
|
||||||
import org.eclipse.swt.SWT;
|
import org.eclipse.swt.SWT;
|
||||||
|
import org.eclipse.swt.events.ModifyEvent;
|
||||||
|
import org.eclipse.swt.events.ModifyListener;
|
||||||
import org.eclipse.swt.events.SelectionAdapter;
|
import org.eclipse.swt.events.SelectionAdapter;
|
||||||
import org.eclipse.swt.events.SelectionEvent;
|
import org.eclipse.swt.events.SelectionEvent;
|
||||||
import org.eclipse.swt.layout.GridData;
|
import org.eclipse.swt.layout.GridData;
|
||||||
|
@ -36,21 +52,40 @@ import org.eclipse.swt.layout.GridLayout;
|
||||||
import org.eclipse.swt.widgets.Button;
|
import org.eclipse.swt.widgets.Button;
|
||||||
import org.eclipse.swt.widgets.Composite;
|
import org.eclipse.swt.widgets.Composite;
|
||||||
import org.eclipse.swt.widgets.Control;
|
import org.eclipse.swt.widgets.Control;
|
||||||
|
import org.eclipse.swt.widgets.DirectoryDialog;
|
||||||
import org.eclipse.swt.widgets.Group;
|
import org.eclipse.swt.widgets.Group;
|
||||||
|
import org.eclipse.swt.widgets.Label;
|
||||||
|
import org.eclipse.swt.widgets.Shell;
|
||||||
import org.eclipse.swt.widgets.Table;
|
import org.eclipse.swt.widgets.Table;
|
||||||
import org.eclipse.swt.widgets.TableColumn;
|
import org.eclipse.swt.widgets.TableColumn;
|
||||||
import org.eclipse.swt.widgets.TableItem;
|
import org.eclipse.swt.widgets.TableItem;
|
||||||
|
import org.eclipse.swt.widgets.Text;
|
||||||
import org.eclipse.ui.IWorkbench;
|
import org.eclipse.ui.IWorkbench;
|
||||||
import org.eclipse.ui.IWorkbenchPreferencePage;
|
import org.eclipse.ui.IWorkbenchPreferencePage;
|
||||||
|
import org.osgi.service.prefs.BackingStoreException;
|
||||||
|
import org.osgi.service.prefs.Preferences;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* GUI page to configure workbench preferences for cmake.
|
* GUI page to configure workbench preferences for cmake.
|
||||||
*/
|
*/
|
||||||
public class CMakePreferencePage extends PreferencePage implements IWorkbenchPreferencePage {
|
public class CMakePreferencePage extends PreferencePage implements IWorkbenchPreferencePage {
|
||||||
|
|
||||||
|
private static final String VALUE_DELIMITER = " || "; //$NON-NLS-1$
|
||||||
|
|
||||||
private ICMakeToolChainManager manager;
|
private ICMakeToolChainManager manager;
|
||||||
private Table filesTable;
|
private Table filesTable;
|
||||||
private Button removeButton;
|
private Button removeButton;
|
||||||
|
private Button variablesButton;
|
||||||
|
private Button testButton;
|
||||||
|
private Button browseButton;
|
||||||
|
private Button editButton;
|
||||||
|
|
||||||
|
private Text cmakeLocationTextBox;
|
||||||
|
private Text generatorLocationTextBox;
|
||||||
|
|
||||||
|
private String[] generatorLocations;
|
||||||
|
private String cmakeLocation;
|
||||||
|
private boolean useCmakeToolLocation;
|
||||||
|
|
||||||
private Map<Path, ICMakeToolChainFile> filesToAdd = new HashMap<>();
|
private Map<Path, ICMakeToolChainFile> filesToAdd = new HashMap<>();
|
||||||
private Map<Path, ICMakeToolChainFile> filesToRemove = new HashMap<>();
|
private Map<Path, ICMakeToolChainFile> filesToRemove = new HashMap<>();
|
||||||
|
@ -58,6 +93,7 @@ public class CMakePreferencePage extends PreferencePage implements IWorkbenchPre
|
||||||
@Override
|
@Override
|
||||||
public void init(IWorkbench workbench) {
|
public void init(IWorkbench workbench) {
|
||||||
manager = Activator.getService(ICMakeToolChainManager.class);
|
manager = Activator.getService(ICMakeToolChainManager.class);
|
||||||
|
updateCmakeToolGroupData();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -141,11 +177,143 @@ public class CMakePreferencePage extends PreferencePage implements IWorkbenchPre
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// CMake tools section
|
||||||
|
Group cmakeToolsGroup = new Group(control, SWT.NONE);
|
||||||
|
cmakeToolsGroup.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
|
||||||
|
cmakeToolsGroup.setText(Messages.CMakePreferencePage_CMakeTools);
|
||||||
|
cmakeToolsGroup.setLayout(new GridLayout(1, false));
|
||||||
|
|
||||||
|
Composite checkBoxComp = new Composite(cmakeToolsGroup, SWT.NONE);
|
||||||
|
checkBoxComp.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
|
||||||
|
checkBoxComp.setLayout(new GridLayout());
|
||||||
|
|
||||||
|
Button useCMakeToolLocCheckBox = new Button(checkBoxComp, SWT.CHECK);
|
||||||
|
useCMakeToolLocCheckBox.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false, 3, 1));
|
||||||
|
useCMakeToolLocCheckBox.setText(Messages.CMakePreferencePage_UseCMakeToolLocationsInCMakeBuilds);
|
||||||
|
useCMakeToolLocCheckBox.setToolTipText(Messages.CMakePreferencePage_UseCMakeToolLocationsInCMakeBuildsTooltip);
|
||||||
|
useCMakeToolLocCheckBox.setSelection(useCmakeToolLocation);
|
||||||
|
useCMakeToolLocCheckBox.addListener(SWT.Selection, e -> {
|
||||||
|
useCmakeToolLocation = useCMakeToolLocCheckBox.getSelection();
|
||||||
|
updateCMakeGroup(useCmakeToolLocation);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Set width hint to avoid Preference page opens with a horizontal scroll bar when
|
||||||
|
// location in textBox got too long.
|
||||||
|
GridData gd = new GridData(SWT.FILL, SWT.FILL, false, false);
|
||||||
|
gd.widthHint = control.getSize().x;
|
||||||
|
|
||||||
|
Composite locationComp = new Composite(cmakeToolsGroup, SWT.NONE);
|
||||||
|
locationComp.setLayoutData(gd);
|
||||||
|
locationComp.setLayout(new GridLayout(3, false));
|
||||||
|
|
||||||
|
Label cmakeLocationLabel = new Label(locationComp, SWT.NONE);
|
||||||
|
cmakeLocationLabel.setText(Messages.CMakePreferencePage_CMakeLocation);
|
||||||
|
cmakeLocationLabel.setToolTipText(Messages.CMakePreferencePage_CMakeLocationTooltip);
|
||||||
|
|
||||||
|
cmakeLocationTextBox = new Text(locationComp, SWT.BORDER);
|
||||||
|
cmakeLocationTextBox.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, true));
|
||||||
|
cmakeLocationTextBox.setText(cmakeLocation);
|
||||||
|
cmakeLocationTextBox.addModifyListener(new ModifyListener() {
|
||||||
|
@Override
|
||||||
|
public void modifyText(ModifyEvent evt) {
|
||||||
|
cmakeLocation = cmakeLocationTextBox.getText().trim();
|
||||||
|
testButton.setEnabled(useCmakeToolLocation && !cmakeLocation.isBlank());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Composite cmakeLocationButtonComp = new Composite(locationComp, SWT.NONE);
|
||||||
|
cmakeLocationButtonComp.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false));
|
||||||
|
cmakeLocationButtonComp.setLayout(new GridLayout(3, true));
|
||||||
|
|
||||||
|
variablesButton = new Button(cmakeLocationButtonComp, SWT.PUSH);
|
||||||
|
variablesButton.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
|
||||||
|
variablesButton.setText(Messages.CMakePreferencePage_Variables);
|
||||||
|
variablesButton.addListener(SWT.Selection, e -> {
|
||||||
|
String variable = getVariableDialog(getShell(), null);
|
||||||
|
if (variable != null) {
|
||||||
|
cmakeLocationTextBox.insert(variable);
|
||||||
|
cmakeLocation = cmakeLocationTextBox.getText().trim();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
testButton = new Button(cmakeLocationButtonComp, SWT.PUSH);
|
||||||
|
testButton.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
|
||||||
|
testButton.setText(Messages.CMakePreferencePage_Test);
|
||||||
|
testButton.setToolTipText(Messages.CMakePreferencePage_TestTooltip);
|
||||||
|
testButton.addListener(SWT.Selection, e -> {
|
||||||
|
try {
|
||||||
|
Process p = Runtime.getRuntime().exec(new String[] {
|
||||||
|
resolveVariableValue(cmakeLocation) + File.separatorChar + "cmake", "--version" }); //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
|
List<String> buf = new ArrayList<>();
|
||||||
|
BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream()));
|
||||||
|
String line;
|
||||||
|
while ((line = br.readLine()) != null) {
|
||||||
|
buf.add(line);
|
||||||
|
}
|
||||||
|
MessageDialog.openInformation(getShell(), Messages.CMakePreferencePage_TestCmakeLocation_Title,
|
||||||
|
Messages.CMakePreferencePage_TestCmakeLocation_Body + String.join(System.lineSeparator(), buf));
|
||||||
|
} catch (IOException e1) {
|
||||||
|
MessageDialog.openError(getShell(), Messages.CMakePreferencePage_FailToTestCmakeLocation_Title,
|
||||||
|
Messages.CMakePreferencePage_FailToTestCmakeLocation_Body + e1.getMessage());
|
||||||
|
Activator.log(e1);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
browseButton = new Button(cmakeLocationButtonComp, SWT.PUSH);
|
||||||
|
browseButton.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
|
||||||
|
browseButton.setText(Messages.CMakePreferencePage_Browse);
|
||||||
|
browseButton.addListener(SWT.Selection, e -> {
|
||||||
|
DirectoryDialog dirDialog = new DirectoryDialog(getShell());
|
||||||
|
if (!cmakeLocation.isBlank()) {
|
||||||
|
dirDialog.setFilterPath(resolveVariableValue(cmakeLocation));
|
||||||
|
}
|
||||||
|
String browsedDirectory = dirDialog.open();
|
||||||
|
if (browsedDirectory != null) {
|
||||||
|
cmakeLocationTextBox.setText(browsedDirectory);
|
||||||
|
cmakeLocation = cmakeLocationTextBox.getText().trim();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Label generatorLocationsLabel = new Label(locationComp, SWT.NONE);
|
||||||
|
generatorLocationsLabel.setText(Messages.CMakePreferencePage_GeneratorLocation);
|
||||||
|
generatorLocationsLabel.setToolTipText(Messages.CMakePreferencePage_GeneratorLocationTooltip);
|
||||||
|
|
||||||
|
generatorLocationTextBox = new Text(locationComp, SWT.BORDER);
|
||||||
|
generatorLocationTextBox.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
|
||||||
|
generatorLocationTextBox.setEditable(false);
|
||||||
|
generatorLocationTextBox.setText(String.join(VALUE_DELIMITER, generatorLocations));
|
||||||
|
|
||||||
|
Composite generatorLocationButtonComp = new Composite(locationComp, SWT.NONE);
|
||||||
|
generatorLocationButtonComp.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false));
|
||||||
|
generatorLocationButtonComp.setLayout(new GridLayout(3, true));
|
||||||
|
|
||||||
|
editButton = new Button(generatorLocationButtonComp, SWT.PUSH);
|
||||||
|
editButton.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
|
||||||
|
editButton.setText(Messages.CMakePreferencePage_Edit);
|
||||||
|
editButton.addListener(SWT.Selection, e -> {
|
||||||
|
EditGeneratorLocationDialog dialog = new EditGeneratorLocationDialog(getShell(),
|
||||||
|
Messages.CMakePreferencePage_EditGeneratorLocations_Title, generatorLocations);
|
||||||
|
if (dialog.open() == Window.OK) {
|
||||||
|
generatorLocations = dialog.getValues();
|
||||||
|
generatorLocationTextBox.setText(String.join(VALUE_DELIMITER, generatorLocations));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
updateTable();
|
updateTable();
|
||||||
|
updateCMakeGroup(useCmakeToolLocation);
|
||||||
|
|
||||||
return control;
|
return control;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void updateCMakeGroup(boolean enable) {
|
||||||
|
cmakeLocationTextBox.setEnabled(enable);
|
||||||
|
generatorLocationTextBox.setEnabled(enable);
|
||||||
|
variablesButton.setEnabled(enable);
|
||||||
|
testButton.setEnabled(enable && !cmakeLocation.isBlank());
|
||||||
|
browseButton.setEnabled(enable);
|
||||||
|
editButton.setEnabled(enable);
|
||||||
|
}
|
||||||
|
|
||||||
private void updateTable() {
|
private void updateTable() {
|
||||||
List<ICMakeToolChainFile> sorted = new ArrayList<>(getFiles().values());
|
List<ICMakeToolChainFile> sorted = new ArrayList<>(getFiles().values());
|
||||||
Collections.sort(sorted, (o1, o2) -> o1.getPath().toString().compareToIgnoreCase(o2.getPath().toString()));
|
Collections.sort(sorted, (o1, o2) -> o1.getPath().toString().compareToIgnoreCase(o2.getPath().toString()));
|
||||||
|
@ -205,7 +373,121 @@ public class CMakePreferencePage extends PreferencePage implements IWorkbenchPre
|
||||||
filesToAdd.clear();
|
filesToAdd.clear();
|
||||||
filesToRemove.clear();
|
filesToRemove.clear();
|
||||||
|
|
||||||
|
// Update Preferences for cmakeSupplier
|
||||||
|
try {
|
||||||
|
getPreferences().clear();
|
||||||
|
getPreferences().node(CMakeBuildEnvironmentSupplier.CMAKE_GENERATOR_LOCATION).clear();
|
||||||
|
getPreferences().putBoolean(CMakeBuildEnvironmentSupplier.ENABLE_USE_CMAKE_LOCATION, useCmakeToolLocation);
|
||||||
|
if (!cmakeLocation.isEmpty()) {
|
||||||
|
getPreferences().put(CMakeBuildEnvironmentSupplier.CMAKE_LOCATION, cmakeLocation);
|
||||||
|
}
|
||||||
|
int index;
|
||||||
|
for (index = 0; index < generatorLocations.length; index++) {
|
||||||
|
getPreferences().node(CMakeBuildEnvironmentSupplier.CMAKE_GENERATOR_LOCATION).put(
|
||||||
|
String.format(CMakeBuildEnvironmentSupplier.LOCATION_NODE, index), generatorLocations[index]);
|
||||||
|
|
||||||
|
}
|
||||||
|
getPreferences().flush();
|
||||||
|
} catch (BackingStoreException e) {
|
||||||
|
Activator.log(e);
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void updateCmakeToolGroupData() {
|
||||||
|
try {
|
||||||
|
useCmakeToolLocation = getPreferences().getBoolean(CMakeBuildEnvironmentSupplier.ENABLE_USE_CMAKE_LOCATION,
|
||||||
|
false);
|
||||||
|
cmakeLocation = getPreferences().get(CMakeBuildEnvironmentSupplier.CMAKE_LOCATION,
|
||||||
|
CMakeBuildEnvironmentSupplier.EMPTY_STRING);
|
||||||
|
List<String> genlocs = new ArrayList<>();
|
||||||
|
String[] keys = getPreferences().node(CMakeBuildEnvironmentSupplier.CMAKE_GENERATOR_LOCATION).keys();
|
||||||
|
int index;
|
||||||
|
for (index = 0; index < keys.length; index++) {
|
||||||
|
genlocs.add(getPreferences().node(CMakeBuildEnvironmentSupplier.CMAKE_GENERATOR_LOCATION).get(
|
||||||
|
String.format(CMakeBuildEnvironmentSupplier.LOCATION_NODE, index),
|
||||||
|
CMakeBuildEnvironmentSupplier.EMPTY_STRING));
|
||||||
|
}
|
||||||
|
generatorLocations = genlocs.toArray(new String[0]);
|
||||||
|
} catch (BackingStoreException e) {
|
||||||
|
Activator.log(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String resolveVariableValue(String value) {
|
||||||
|
try {
|
||||||
|
ICdtVariableManager vm = CCorePlugin.getDefault().getCdtVariableManager();
|
||||||
|
return vm.resolveValue(value, null, CMakeBuildEnvironmentSupplier.EMPTY_STRING, null);
|
||||||
|
} catch (CdtVariableException e) {
|
||||||
|
Activator.log(e);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getVariableDialog(Shell shell, ICConfigurationDescription cfgd) {
|
||||||
|
ICdtVariableManager vm = CCorePlugin.getDefault().getCdtVariableManager();
|
||||||
|
BuildVarListDialog dialog = new BuildVarListDialog(shell, vm.getVariables(cfgd));
|
||||||
|
dialog.setTitle(Messages.VariablesDialog_Title);
|
||||||
|
if (dialog.open() == Window.OK) {
|
||||||
|
Object[] selected = dialog.getResult();
|
||||||
|
if (selected.length > 0) {
|
||||||
|
String s = ((ICdtVariable) selected[0]).getName();
|
||||||
|
return "${" + s.trim() + "}"; //$NON-NLS-1$//$NON-NLS-2$
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private class EditGeneratorLocationDialog extends Dialog {
|
||||||
|
|
||||||
|
private String title;
|
||||||
|
private FileListControl listEditor;
|
||||||
|
private String[] genLocs;
|
||||||
|
|
||||||
|
public EditGeneratorLocationDialog(Shell parentShell, String title, String[] genLocs) {
|
||||||
|
super(parentShell);
|
||||||
|
this.genLocs = genLocs;
|
||||||
|
this.title = title;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void configureShell(Shell shell) {
|
||||||
|
super.configureShell(shell);
|
||||||
|
if (title != null) {
|
||||||
|
shell.setText(title);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Control createDialogArea(Composite parent) {
|
||||||
|
Composite comp = new Composite(parent, SWT.NULL);
|
||||||
|
comp.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
|
||||||
|
comp.setLayout(new GridLayout());
|
||||||
|
listEditor = new FileListControl(comp,
|
||||||
|
Messages.CMakePreferencePage_EditGeneratorLocations_GeneratorLocation, FileListControl.BROWSE_DIR);
|
||||||
|
if (genLocs != null) {
|
||||||
|
listEditor.setList(genLocs);
|
||||||
|
}
|
||||||
|
return comp;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void okPressed() {
|
||||||
|
genLocs = listEditor.getItems();
|
||||||
|
super.okPressed();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String[] getValues() {
|
||||||
|
List<String> values = new ArrayList<>();
|
||||||
|
for (String loc : genLocs) {
|
||||||
|
// Clean up return values
|
||||||
|
values.add(loc.replace("\"", CMakeBuildEnvironmentSupplier.EMPTY_STRING).trim()); //$NON-NLS-1$
|
||||||
|
}
|
||||||
|
return values.toArray(new String[0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Preferences getPreferences() {
|
||||||
|
return InstanceScope.INSTANCE.getNode(CCorePlugin.PLUGIN_ID).node(CMakeBuildEnvironmentSupplier.NODENAME);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,12 +30,31 @@ public class Messages extends NLS {
|
||||||
public static String CMakeBuildTab_useDefaultCmakeSettingsTip;
|
public static String CMakeBuildTab_useDefaultCmakeSettingsTip;
|
||||||
public static String CMakeBuildTab_UsedForLaunchMode;
|
public static String CMakeBuildTab_UsedForLaunchMode;
|
||||||
public static String CMakePreferencePage_Add;
|
public static String CMakePreferencePage_Add;
|
||||||
|
public static String CMakePreferencePage_Browse;
|
||||||
|
public static String CMakePreferencePage_CMakeLocation;
|
||||||
|
public static String CMakePreferencePage_CMakeLocationTooltip;
|
||||||
|
public static String CMakePreferencePage_CMakeTools;
|
||||||
public static String CMakePreferencePage_ConfirmRemoveDesc;
|
public static String CMakePreferencePage_ConfirmRemoveDesc;
|
||||||
public static String CMakePreferencePage_ConfirmRemoveTitle;
|
public static String CMakePreferencePage_ConfirmRemoveTitle;
|
||||||
|
public static String CMakePreferencePage_Delete;
|
||||||
|
public static String CMakePreferencePage_Edit;
|
||||||
|
public static String CMakePreferencePage_EditGeneratorLocations_Title;
|
||||||
|
public static String CMakePreferencePage_EditGeneratorLocations_GeneratorLocation;
|
||||||
|
public static String CMakePreferencePage_FailToTestCmakeLocation_Body;
|
||||||
|
public static String CMakePreferencePage_FailToTestCmakeLocation_Title;
|
||||||
public static String CMakePreferencePage_Files;
|
public static String CMakePreferencePage_Files;
|
||||||
|
public static String CMakePreferencePage_GeneratorLocation;
|
||||||
|
public static String CMakePreferencePage_GeneratorLocationTooltip;
|
||||||
public static String CMakePreferencePage_Path;
|
public static String CMakePreferencePage_Path;
|
||||||
public static String CMakePreferencePage_Remove;
|
public static String CMakePreferencePage_Remove;
|
||||||
|
public static String CMakePreferencePage_Test;
|
||||||
|
public static String CMakePreferencePage_TestCmakeLocation_Body;
|
||||||
|
public static String CMakePreferencePage_TestCmakeLocation_Title;
|
||||||
|
public static String CMakePreferencePage_TestTooltip;
|
||||||
public static String CMakePreferencePage_Toolchain;
|
public static String CMakePreferencePage_Toolchain;
|
||||||
|
public static String CMakePreferencePage_UseCMakeToolLocationsInCMakeBuilds;
|
||||||
|
public static String CMakePreferencePage_UseCMakeToolLocationsInCMakeBuildsTooltip;
|
||||||
|
public static String CMakePreferencePage_Variables;
|
||||||
public static String CMakePropertyPage_FailedToStartCMakeGui_Body;
|
public static String CMakePropertyPage_FailedToStartCMakeGui_Body;
|
||||||
public static String CMakePropertyPage_FailedToStartCMakeGui_Title;
|
public static String CMakePropertyPage_FailedToStartCMakeGui_Title;
|
||||||
public static String CMakePropertyPage_FailedToGetOS_Body;
|
public static String CMakePropertyPage_FailedToGetOS_Body;
|
||||||
|
@ -57,6 +76,8 @@ public class Messages extends NLS {
|
||||||
public static String NewCMakeToolChainFilePage_Title;
|
public static String NewCMakeToolChainFilePage_Title;
|
||||||
public static String NewCMakeToolChainFilePage_Toolchain;
|
public static String NewCMakeToolChainFilePage_Toolchain;
|
||||||
|
|
||||||
|
public static String VariablesDialog_Title;
|
||||||
|
|
||||||
static {
|
static {
|
||||||
// initialize resource bundle
|
// initialize resource bundle
|
||||||
NLS.initializeMessages("org.eclipse.cdt.cmake.ui.internal.messages", Messages.class); //$NON-NLS-1$
|
NLS.initializeMessages("org.eclipse.cdt.cmake.ui.internal.messages", Messages.class); //$NON-NLS-1$
|
||||||
|
|
|
@ -14,12 +14,31 @@ CMakeBuildTab_useDefaultCmakeSettings=Use default CMake settings
|
||||||
CMakeBuildTab_useDefaultCmakeSettingsTip=Use the default CMake settings that are provided by the toolchain and Core Build System
|
CMakeBuildTab_useDefaultCmakeSettingsTip=Use the default CMake settings that are provided by the toolchain and Core Build System
|
||||||
CMakeBuildTab_UsedForLaunchMode=used for launch mode: {0}
|
CMakeBuildTab_UsedForLaunchMode=used for launch mode: {0}
|
||||||
CMakePreferencePage_Add=Add...
|
CMakePreferencePage_Add=Add...
|
||||||
|
CMakePreferencePage_Browse=Browse...
|
||||||
|
CMakePreferencePage_CMakeLocation=CMake location:
|
||||||
|
CMakePreferencePage_CMakeLocationTooltip=The directory containing the CMake tool.
|
||||||
|
CMakePreferencePage_CMakeTools=CMake Tools
|
||||||
CMakePreferencePage_ConfirmRemoveDesc=Do you wish to deregister the selected files?
|
CMakePreferencePage_ConfirmRemoveDesc=Do you wish to deregister the selected files?
|
||||||
CMakePreferencePage_ConfirmRemoveTitle=Deregister CMake ToolChain File
|
CMakePreferencePage_ConfirmRemoveTitle=Deregister CMake ToolChain File
|
||||||
|
CMakePreferencePage_Delete=Delete
|
||||||
|
CMakePreferencePage_Edit=Edit...
|
||||||
|
CMakePreferencePage_EditGeneratorLocations_Title=Edit generator locations
|
||||||
|
CMakePreferencePage_EditGeneratorLocations_GeneratorLocation=Generator location:
|
||||||
|
CMakePreferencePage_FailToTestCmakeLocation_Body=Fail to test CMake in selected location:\u000a
|
||||||
|
CMakePreferencePage_FailToTestCmakeLocation_Title=Fail to test CMake location
|
||||||
CMakePreferencePage_Files=Toolchain Files
|
CMakePreferencePage_Files=Toolchain Files
|
||||||
|
CMakePreferencePage_GeneratorLocation=Generator location(s):
|
||||||
|
CMakePreferencePage_GeneratorLocationTooltip=The directory(s) containing the CMake generators (eg Ninja, Makefiles). To add or modify the list, use "Edit..." button.
|
||||||
CMakePreferencePage_Path=Toolchain File
|
CMakePreferencePage_Path=Toolchain File
|
||||||
CMakePreferencePage_Remove=Remove
|
CMakePreferencePage_Remove=Remove
|
||||||
|
CMakePreferencePage_Test=Test...
|
||||||
|
CMakePreferencePage_TestCmakeLocation_Body=Found:\u0020
|
||||||
|
CMakePreferencePage_TestCmakeLocation_Title=Test result
|
||||||
|
CMakePreferencePage_TestTooltip=Tests that the CMake binary is found and executable.
|
||||||
CMakePreferencePage_Toolchain=Toolchain
|
CMakePreferencePage_Toolchain=Toolchain
|
||||||
|
CMakePreferencePage_UseCMakeToolLocationsInCMakeBuilds=Use CMake tool locations in CMake builds
|
||||||
|
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.
|
||||||
|
CMakePreferencePage_Variables=Variables...
|
||||||
CMakePropertyPage_FailedToStartCMakeGui_Body=Failed to run the CMake GUI:\u0020
|
CMakePropertyPage_FailedToStartCMakeGui_Body=Failed to run the CMake GUI:\u0020
|
||||||
CMakePropertyPage_FailedToStartCMakeGui_Title=Failed to run CMake GUI
|
CMakePropertyPage_FailedToStartCMakeGui_Title=Failed to run CMake GUI
|
||||||
CMakePropertyPage_FailedToGetOS_Body=Failed to get target OS for CMake project:
|
CMakePropertyPage_FailedToGetOS_Body=Failed to get target OS for CMake project:
|
||||||
|
@ -38,3 +57,4 @@ NewCMakeToolChainFilePage_Path=Path:
|
||||||
NewCMakeToolChainFilePage_Select=Select location for CMake toolchain file
|
NewCMakeToolChainFilePage_Select=Select location for CMake toolchain file
|
||||||
NewCMakeToolChainFilePage_Title=New CMake ToolChain File
|
NewCMakeToolChainFilePage_Title=New CMake ToolChain File
|
||||||
NewCMakeToolChainFilePage_Toolchain=Toolchain:
|
NewCMakeToolChainFilePage_Toolchain=Toolchain:
|
||||||
|
VariablesDialog_Title=Select CMake variable
|
||||||
|
|
|
@ -57,7 +57,8 @@ Bundle-Vendor: %providerName
|
||||||
Bundle-RequiredExecutionEnvironment: JavaSE-17
|
Bundle-RequiredExecutionEnvironment: JavaSE-17
|
||||||
Automatic-Module-Name: org.eclipse.cdt.core.tests
|
Automatic-Module-Name: org.eclipse.cdt.core.tests
|
||||||
Bundle-Localization: plugin
|
Bundle-Localization: plugin
|
||||||
Import-Package: org.junit.jupiter.api;version="5.9.0",
|
Import-Package: org.eclipse.launchbar.core.target,
|
||||||
|
org.junit.jupiter.api;version="5.9.0",
|
||||||
org.junit.jupiter.params;version="5.9.0",
|
org.junit.jupiter.params;version="5.9.0",
|
||||||
org.junit.jupiter.params.provider;version="5.9.0",
|
org.junit.jupiter.params.provider;version="5.9.0",
|
||||||
org.mockito;version="[5.12.0,6.0.0]",
|
org.mockito;version="[5.12.0,6.0.0]",
|
||||||
|
|
|
@ -0,0 +1,290 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2025 Renesas Electronics Europe and others.
|
||||||
|
*
|
||||||
|
* This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Eclipse Public License 2.0
|
||||||
|
* which accompanies this distribution, and is available at
|
||||||
|
* https://www.eclipse.org/legal/epl-2.0/
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: EPL-2.0
|
||||||
|
*******************************************************************************/
|
||||||
|
package org.eclipse.cdt.internal.core.envvar;
|
||||||
|
|
||||||
|
import static org.hamcrest.MatcherAssert.assertThat;
|
||||||
|
import static org.hamcrest.Matchers.arrayWithSize;
|
||||||
|
import static org.hamcrest.Matchers.containsString;
|
||||||
|
import static org.hamcrest.Matchers.equalToObject;
|
||||||
|
import static org.hamcrest.Matchers.hasItemInArray;
|
||||||
|
import static org.hamcrest.Matchers.instanceOf;
|
||||||
|
import static org.hamcrest.Matchers.is;
|
||||||
|
import static org.hamcrest.Matchers.not;
|
||||||
|
import static org.hamcrest.Matchers.nullValue;
|
||||||
|
import static org.junit.Assert.assertNotNull;
|
||||||
|
import static org.mockito.Mockito.mock;
|
||||||
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Properties;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.cmake.core.CMakeBuildConfiguration;
|
||||||
|
import org.eclipse.cdt.cmake.core.CMakeNature;
|
||||||
|
import org.eclipse.cdt.cmake.core.ICMakeToolChainFile;
|
||||||
|
import org.eclipse.cdt.core.CCProjectNature;
|
||||||
|
import org.eclipse.cdt.core.CCorePlugin;
|
||||||
|
import org.eclipse.cdt.core.CProjectNature;
|
||||||
|
import org.eclipse.cdt.core.build.ICBuildConfiguration;
|
||||||
|
import org.eclipse.cdt.core.build.ICBuildConfigurationManager;
|
||||||
|
import org.eclipse.cdt.core.build.IToolChain;
|
||||||
|
import org.eclipse.cdt.core.envvar.IEnvironmentVariable;
|
||||||
|
import org.eclipse.cdt.core.testplugin.ResourceHelper;
|
||||||
|
import org.eclipse.cdt.core.testplugin.util.BaseTestCase5;
|
||||||
|
import org.eclipse.cdt.debug.core.CDebugCorePlugin;
|
||||||
|
import org.eclipse.cdt.utils.spawner.EnvironmentReader;
|
||||||
|
import org.eclipse.core.resources.IBuildConfiguration;
|
||||||
|
import org.eclipse.core.resources.IProject;
|
||||||
|
import org.eclipse.core.resources.IProjectDescription;
|
||||||
|
import org.eclipse.core.runtime.NullProgressMonitor;
|
||||||
|
import org.eclipse.core.runtime.preferences.InstanceScope;
|
||||||
|
import org.eclipse.debug.core.ILaunchManager;
|
||||||
|
import org.eclipse.launchbar.core.target.ILaunchTarget;
|
||||||
|
import org.junit.jupiter.api.AfterEach;
|
||||||
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.osgi.service.prefs.BackingStoreException;
|
||||||
|
import org.osgi.service.prefs.Preferences;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test for IDE_82683_REQ_004_005 part of #1000<br>
|
||||||
|
* Verify behaviors of CMakeEnvironmentContextInfo.class and CMakeBuildEnvironmentSupplier.class
|
||||||
|
* <br>
|
||||||
|
* Test components:<br>
|
||||||
|
* {@link CMakeEnvironmentContextInfo}<br>
|
||||||
|
* {@link CMakeBuildEnvironmentSupplier}<br>
|
||||||
|
*/
|
||||||
|
public class CMakeBuildEnvironmentSupplierTest extends BaseTestCase5 {
|
||||||
|
|
||||||
|
protected ICBuildConfigurationManager configManager = CDebugCorePlugin
|
||||||
|
.getService(ICBuildConfigurationManager.class);
|
||||||
|
|
||||||
|
private static final String LAUNCH_MODE = "run"; //$NON-NLS-1$
|
||||||
|
private static final String pathVariableName = "PATH"; //$NON-NLS-1$
|
||||||
|
private static final String isvPath = "isvPath"; //$NON-NLS-1$
|
||||||
|
|
||||||
|
private static String cmakeLocation;
|
||||||
|
private static String[] generatorLocation;
|
||||||
|
|
||||||
|
private IBuildConfiguration buildConfig;
|
||||||
|
private IToolChain mockToolchain;
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
public void setupPreference() throws Exception {
|
||||||
|
String genLoc1 = String.join(File.separator, "generator", "location", "no", "1");
|
||||||
|
String genLoc2 = String.join(File.separator, "generator", "location", "no", "2");
|
||||||
|
cmakeLocation = String.join(File.separator, "cmake", "location", "path");
|
||||||
|
generatorLocation = new String[] { genLoc1, genLoc2 };
|
||||||
|
// Setup Preferences
|
||||||
|
getPreferences().clear();
|
||||||
|
getPreferences().node(CMakeBuildEnvironmentSupplier.CMAKE_GENERATOR_LOCATION).clear();
|
||||||
|
getPreferences().putBoolean(CMakeBuildEnvironmentSupplier.ENABLE_USE_CMAKE_LOCATION, true);
|
||||||
|
getPreferences().put(CMakeBuildEnvironmentSupplier.CMAKE_LOCATION, cmakeLocation);
|
||||||
|
int index;
|
||||||
|
for (index = 0; index < generatorLocation.length; index++) {
|
||||||
|
getPreferences().node(CMakeBuildEnvironmentSupplier.CMAKE_GENERATOR_LOCATION)
|
||||||
|
.put(String.format("location.%d", index), generatorLocation[index]);//$NON-NLS-1$
|
||||||
|
}
|
||||||
|
getPreferences().flush();
|
||||||
|
// Create a CMake project
|
||||||
|
IProject project = createCMakeProject();
|
||||||
|
// Setup a toolchain ready to use for creating the valid ICBuildConfiguration
|
||||||
|
mockToolchain = mock(IToolChain.class);
|
||||||
|
when(mockToolchain.getProperty(IToolChain.ATTR_OS)).thenReturn("osDummy");
|
||||||
|
when(mockToolchain.getProperty(IToolChain.ATTR_ARCH)).thenReturn("archDummy");
|
||||||
|
when(mockToolchain.getTypeId()).thenReturn("tc_typeId");
|
||||||
|
when(mockToolchain.getId()).thenReturn("tcId");
|
||||||
|
when(mockToolchain.getBuildConfigNameFragment()).thenReturn("buildConfigName");
|
||||||
|
|
||||||
|
ICBuildConfiguration cBuildConfiguration = configManager.getBuildConfiguration(project, mockToolchain,
|
||||||
|
ILaunchManager.DEBUG_MODE, ILaunchTarget.NULL_TARGET, new NullProgressMonitor());
|
||||||
|
buildConfig = cBuildConfiguration.getBuildConfiguration();
|
||||||
|
}
|
||||||
|
|
||||||
|
@AfterEach
|
||||||
|
public void cleanupPreference() throws BackingStoreException {
|
||||||
|
getPreferences().removeNode();
|
||||||
|
getPreferences().flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Testing for {@link CMakeEnvironmentContextInfo#getContextInfo(Object)}
|
||||||
|
* <br>
|
||||||
|
* This test verify CMakeEnvironmentContextInfo can be acquired via <code>EnvironmentVariableManager<code>
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void cMakeEnvironmentContextInfo_Aquisition() {
|
||||||
|
ICBuildConfiguration cmBuildConfig = new CMakeBuildConfiguration(buildConfig, "cmBuildConfigName",
|
||||||
|
mockToolchain, null, LAUNCH_MODE, ILaunchTarget.NULL_TARGET);
|
||||||
|
IEnvironmentContextInfo contextInfo = EnvironmentVariableManager.getDefault().getContextInfo(cmBuildConfig);
|
||||||
|
ICoreEnvironmentVariableSupplier[] sups = contextInfo.getSuppliers();
|
||||||
|
|
||||||
|
//The return IEnvironmentContextInfo is instance of CMakeEnvironmentContextInfo.class
|
||||||
|
assertThat(contextInfo, is(instanceOf(CMakeEnvironmentContextInfo.class)));
|
||||||
|
//The return IEnvironmentContextInfo contains CMakeBuildEnvironmentSupplier
|
||||||
|
assertThat(sups, hasItemInArray(EnvironmentVariableManager.fCmakeSupplier));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Testing for {@link CMakeBuildEnvironmentSupplier#getVariable(String, Object)}
|
||||||
|
* <br>
|
||||||
|
* This test verify that <code>getVariable(String, Object)<code> return the null value in case:<br>
|
||||||
|
* <li> Input variable name is not <code>"PATH"<code>, or: <br>
|
||||||
|
* <li> Input contextInfo cannot be adapted to {@link ICBuildConfiguration}</li>
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void cMakeBuildEnvironmentSupplier_getVariable_nullValueReturn() {
|
||||||
|
CMakeBuildEnvironmentSupplier sdSupplier;
|
||||||
|
IEnvironmentVariable var;
|
||||||
|
ICBuildConfiguration cmBuildConfig = new CMakeBuildConfiguration(buildConfig, "cmBuildConfigName",
|
||||||
|
mockToolchain, null, LAUNCH_MODE, ILaunchTarget.NULL_TARGET);
|
||||||
|
ICoreEnvironmentVariableSupplier sup = EnvironmentVariableManager.fCmakeSupplier;
|
||||||
|
// Variable's name not "PATH"
|
||||||
|
var = sup.getVariable("notPATH", cmBuildConfig);
|
||||||
|
assertThat(var, is(nullValue()));
|
||||||
|
// Input context cannot be adapted to ICBuildConfiguration
|
||||||
|
var = sup.getVariable(pathVariableName, null);
|
||||||
|
assertThat(var, is(nullValue()));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Testing for {@link CMakeBuildEnvironmentSupplier#getVariable(String, Object)}
|
||||||
|
* <br>
|
||||||
|
* This test verify that <code>getVariable(String, Object)<code> can return the "PATH" variable with
|
||||||
|
* CMake location and Generator location in case:<br>
|
||||||
|
* <li> Input variable name is <code>"PATH"<code>
|
||||||
|
* <li> Input contextInfo can be adapted to {@link ICBuildConfiguration}
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void cMakeBuildEnvironmentSupplier_getVariable_variableReturn() {
|
||||||
|
CMakeBuildEnvironmentSupplier sdSupplier;
|
||||||
|
IEnvironmentVariable var;
|
||||||
|
ICBuildConfiguration cmBuildConfig = new CMakeBuildConfiguration(buildConfig, "cmBuildConfigName",
|
||||||
|
mockToolchain, null, LAUNCH_MODE, ILaunchTarget.NULL_TARGET);
|
||||||
|
ICoreEnvironmentVariableSupplier sup = EnvironmentVariableManager.fCmakeSupplier;
|
||||||
|
var = sup.getVariable(pathVariableName, cmBuildConfig);
|
||||||
|
assertThat(var, not(nullValue()));
|
||||||
|
// Return "PATH" variable contains CMake location and Generator location
|
||||||
|
assertThat(var.getDelimiter(), equalToObject(EnvironmentVariableManager.getDefault().getDefaultDelimiter()));
|
||||||
|
assertThat(var.getName(), equalToObject(pathVariableName));
|
||||||
|
assertThat(var.getOperation(), equalToObject(IEnvironmentVariable.ENVVAR_PREPEND));
|
||||||
|
assertThat(var.getValue(), containsString(cmakeLocation));
|
||||||
|
assertThat(var.getValue(), containsString(generatorLocation[0]));
|
||||||
|
assertThat(var.getValue(), containsString(generatorLocation[1]));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Testing for {@link CMakeBuildEnvironmentSupplier#getVariables(Object)}
|
||||||
|
* <br>
|
||||||
|
* This test verify that <code>getVariables(Object)<code> return empty variable array in case:<br>
|
||||||
|
* <li> Input contextInfo cannot be adapted to {@link ICBuildConfiguration}
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void cMakeBuildEnvironmentSupplier_getVariables_emptyArrReturn() {
|
||||||
|
IEnvironmentVariable[] vars;
|
||||||
|
ICoreEnvironmentVariableSupplier sup = EnvironmentVariableManager.fCmakeSupplier;
|
||||||
|
// When context is null, empty array is returned
|
||||||
|
vars = sup.getVariables(null);
|
||||||
|
assertThat(vars, equalToObject(new IEnvironmentVariable[0]));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Testing for {@link CMakeBuildEnvironmentSupplier#getVariables(Object)}
|
||||||
|
* <br>
|
||||||
|
* This test verify that <code>getVariables(Object)<code> can return the PATH variables contains
|
||||||
|
* CMake location and Generator location in case:<br>
|
||||||
|
* <li> Input contextInfo can be adapted to {@link ICBuildConfiguration}
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void cMakeBuildEnvironmentSupplier_getVariables_arrReturnConntainsPathVar() {
|
||||||
|
IEnvironmentVariable[] vars;
|
||||||
|
ICBuildConfiguration cmBuildConfig = new CMakeBuildConfiguration(buildConfig, "cmBuildConfigName",
|
||||||
|
mockToolchain, null, LAUNCH_MODE, ILaunchTarget.NULL_TARGET);
|
||||||
|
ICoreEnvironmentVariableSupplier sup = EnvironmentVariableManager.fCmakeSupplier;
|
||||||
|
// When context is CMakeBuildConfiguration, return array contains PATH variable with CMake data
|
||||||
|
vars = sup.getVariables(cmBuildConfig);
|
||||||
|
assertThat(vars, arrayWithSize(1));
|
||||||
|
assertThat(vars[0], not(nullValue()));
|
||||||
|
assertThat(vars[0].getDelimiter(),
|
||||||
|
equalToObject(EnvironmentVariableManager.getDefault().getDefaultDelimiter()));
|
||||||
|
assertThat(vars[0].getName(), equalToObject(pathVariableName));
|
||||||
|
assertThat(vars[0].getValue(), containsString(cmakeLocation));
|
||||||
|
assertThat(vars[0].getValue(), containsString(generatorLocation[0]));
|
||||||
|
assertThat(vars[0].getValue(), containsString(generatorLocation[1]));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This test verify that CMake tools' locations are added into "PATH" variable following order:
|
||||||
|
* ISV > CMake > System's path
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void cMakePathAddedInOrder() {
|
||||||
|
ExtendedCMakeBuildConfiguration cmBuildConfig = new ExtendedCMakeBuildConfiguration(buildConfig,
|
||||||
|
"cmBuildConfigName", mockToolchain, null);
|
||||||
|
// Setup build environment
|
||||||
|
Properties environmentVariables = EnvironmentReader.getEnvVars();
|
||||||
|
Map<String, String> env = new HashMap<>();
|
||||||
|
for (String key : environmentVariables.stringPropertyNames()) {
|
||||||
|
String value = environmentVariables.getProperty(key);
|
||||||
|
env.put(key, value);
|
||||||
|
}
|
||||||
|
cmBuildConfig.setBuildEnvironment(env);
|
||||||
|
// Confirm CMake tool locations are added in order: ISV > CMake > System's path
|
||||||
|
String pathStr = env.get(pathVariableName);
|
||||||
|
assertNotNull(pathStr);
|
||||||
|
List<String> list = Arrays.asList(pathStr.split(File.pathSeparator)).subList(0, 4);
|
||||||
|
assertThat(list, is(List.of(isvPath, cmakeLocation, generatorLocation[0], generatorLocation[1])));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Preferences getPreferences() {
|
||||||
|
return InstanceScope.INSTANCE.getNode(CCorePlugin.PLUGIN_ID).node(CMakeBuildEnvironmentSupplier.NODENAME);
|
||||||
|
}
|
||||||
|
|
||||||
|
private class ExtendedCMakeBuildConfiguration extends CMakeBuildConfiguration {
|
||||||
|
public ExtendedCMakeBuildConfiguration(IBuildConfiguration config, String name, IToolChain toolChain,
|
||||||
|
ICMakeToolChainFile toolChainFile) {
|
||||||
|
super(config, name, toolChain, toolChainFile, LAUNCH_MODE, ILaunchTarget.NULL_TARGET);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* "The precedence of the location specified in "CMake location" is important and should be added to the PATH environment
|
||||||
|
* variable, so it is in front of other system environment locations, but behind any locations added by an ISV."
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void setBuildEnvironment(Map<String, String> env) {
|
||||||
|
super.setBuildEnvironment(env);
|
||||||
|
List<String> pathsToAdd = new ArrayList<>(List.of(isvPath));
|
||||||
|
String inheritedPath = env.get(pathVariableName);
|
||||||
|
if (inheritedPath != null) {
|
||||||
|
Collections.addAll(pathsToAdd, inheritedPath.split(File.pathSeparator));
|
||||||
|
}
|
||||||
|
String pathsToAddStr = pathsToAdd.stream().collect(Collectors.joining(File.pathSeparator));
|
||||||
|
env.put(pathVariableName, pathsToAddStr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private IProject createCMakeProject() throws Exception {
|
||||||
|
// Create a plain Eclipse project
|
||||||
|
IProject project = ResourceHelper.createProject(this.getName());
|
||||||
|
// Add C/C++ and CMake natures to make it a CMake project
|
||||||
|
IProjectDescription description = project.getDescription();
|
||||||
|
description.setNatureIds(
|
||||||
|
new String[] { CProjectNature.C_NATURE_ID, CCProjectNature.CC_NATURE_ID, CMakeNature.ID });
|
||||||
|
project.setDescription(description, null);
|
||||||
|
return project;
|
||||||
|
}
|
||||||
|
}
|
|
@ -79,7 +79,7 @@ Export-Package: org.eclipse.cdt.core,
|
||||||
org.eclipse.cdt.internal.core.dom.rewrite.changegenerator;x-internal:=true,
|
org.eclipse.cdt.internal.core.dom.rewrite.changegenerator;x-internal:=true,
|
||||||
org.eclipse.cdt.internal.core.dom.rewrite.commenthandler;x-friends:="org.eclipse.cdt.ui,org.eclipse.cdt.codan.core.cxx",
|
org.eclipse.cdt.internal.core.dom.rewrite.commenthandler;x-friends:="org.eclipse.cdt.ui,org.eclipse.cdt.codan.core.cxx",
|
||||||
org.eclipse.cdt.internal.core.dom.rewrite.util;x-friends:="org.eclipse.cdt.ui",
|
org.eclipse.cdt.internal.core.dom.rewrite.util;x-friends:="org.eclipse.cdt.ui",
|
||||||
org.eclipse.cdt.internal.core.envvar;x-friends:="org.eclipse.cdt.ui,org.eclipse.cdt.managedbuilder.core",
|
org.eclipse.cdt.internal.core.envvar;x-friends:="org.eclipse.cdt.ui,org.eclipse.cdt.managedbuilder.core,org.eclipse.cdt.cmake.ui",
|
||||||
org.eclipse.cdt.internal.core.index;x-friends:="org.eclipse.cdt.ui",
|
org.eclipse.cdt.internal.core.index;x-friends:="org.eclipse.cdt.ui",
|
||||||
org.eclipse.cdt.internal.core.index.composite;x-internal:=true,
|
org.eclipse.cdt.internal.core.index.composite;x-internal:=true,
|
||||||
org.eclipse.cdt.internal.core.index.composite.c;x-internal:=true,
|
org.eclipse.cdt.internal.core.index.composite.c;x-internal:=true,
|
||||||
|
|
|
@ -0,0 +1,98 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2025 Renesas Electronics Europe and others.
|
||||||
|
*
|
||||||
|
* This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Eclipse Public License 2.0
|
||||||
|
* which accompanies this distribution, and is available at
|
||||||
|
* https://www.eclipse.org/legal/epl-2.0/
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: EPL-2.0
|
||||||
|
*******************************************************************************/
|
||||||
|
package org.eclipse.cdt.internal.core.envvar;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.core.CCorePlugin;
|
||||||
|
import org.eclipse.cdt.core.cdtvariables.CdtVariableException;
|
||||||
|
import org.eclipse.cdt.core.cdtvariables.ICdtVariableManager;
|
||||||
|
import org.eclipse.cdt.core.envvar.EnvironmentVariable;
|
||||||
|
import org.eclipse.cdt.core.envvar.IEnvironmentVariable;
|
||||||
|
import org.eclipse.core.runtime.preferences.InstanceScope;
|
||||||
|
import org.osgi.service.prefs.BackingStoreException;
|
||||||
|
import org.osgi.service.prefs.Preferences;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is the Environment Variable Supplier used to supply CMake Tools variables
|
||||||
|
* defined through CMake preference
|
||||||
|
*/
|
||||||
|
public class CMakeBuildEnvironmentSupplier implements ICoreEnvironmentVariableSupplier {
|
||||||
|
|
||||||
|
public static final String NODENAME = "cmake_environment"; //$NON-NLS-1$
|
||||||
|
public static final String ENABLE_USE_CMAKE_LOCATION = "enable_use_cmake_location"; //$NON-NLS-1$
|
||||||
|
public static final String CMAKE_LOCATION = "cmake_location"; //$NON-NLS-1$
|
||||||
|
public static final String CMAKE_GENERATOR_LOCATION = "cmake_generator_locations"; //$NON-NLS-1$
|
||||||
|
public static final String EMPTY_STRING = ""; //$NON-NLS-1$
|
||||||
|
public static final String LOCATION_NODE = "location.%d"; //$NON-NLS-1$
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IEnvironmentVariable getVariable(String name, Object context) {
|
||||||
|
if (context != null && "PATH".equals(name)) { //$NON-NLS-1$
|
||||||
|
return getVariable();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IEnvironmentVariable[] getVariables(Object context) {
|
||||||
|
if (context != null) {
|
||||||
|
IEnvironmentVariable var = getVariable();
|
||||||
|
if (var != null)
|
||||||
|
return new IEnvironmentVariable[] { var };
|
||||||
|
}
|
||||||
|
return new IEnvironmentVariable[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean appendEnvironment(Object context) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private IEnvironmentVariable getVariable() {
|
||||||
|
try {
|
||||||
|
ArrayList<String> locations = new ArrayList<>();
|
||||||
|
boolean useCmakeToolLocation = getPreferences().getBoolean(ENABLE_USE_CMAKE_LOCATION, false);
|
||||||
|
if (useCmakeToolLocation) {
|
||||||
|
// Get CMake location
|
||||||
|
String cmakeLoc = resolveVariableValue(getPreferences().get(CMAKE_LOCATION, EMPTY_STRING));
|
||||||
|
if (cmakeLoc != null && !cmakeLoc.isBlank()) {
|
||||||
|
locations.add(cmakeLoc);
|
||||||
|
}
|
||||||
|
// Get CMake Generators' locations
|
||||||
|
String[] keys = getPreferences().node(CMakeBuildEnvironmentSupplier.CMAKE_GENERATOR_LOCATION).keys();
|
||||||
|
int index;
|
||||||
|
for (index = 0; index < keys.length; index++) {
|
||||||
|
locations.add(getPreferences().node(CMAKE_GENERATOR_LOCATION)
|
||||||
|
.get(String.format(CMakeBuildEnvironmentSupplier.LOCATION_NODE, index), EMPTY_STRING));
|
||||||
|
}
|
||||||
|
String value = String.join(EnvironmentVariableManager.getDefault().getDefaultDelimiter(), locations);
|
||||||
|
return new EnvironmentVariable("PATH", value, IEnvironmentVariable.ENVVAR_PREPEND, //$NON-NLS-1$
|
||||||
|
EnvironmentVariableManager.getDefault().getDefaultDelimiter());
|
||||||
|
}
|
||||||
|
} catch (BackingStoreException e) {
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Preferences getPreferences() {
|
||||||
|
return InstanceScope.INSTANCE.getNode(CCorePlugin.PLUGIN_ID).node(NODENAME);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String resolveVariableValue(String value) {
|
||||||
|
try {
|
||||||
|
ICdtVariableManager vm = CCorePlugin.getDefault().getCdtVariableManager();
|
||||||
|
return vm.resolveValue(value, null, CMakeBuildEnvironmentSupplier.EMPTY_STRING, null);
|
||||||
|
} catch (CdtVariableException e) {
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,44 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2025 Renesas Electronics Europe and others.
|
||||||
|
*
|
||||||
|
* This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Eclipse Public License 2.0
|
||||||
|
* which accompanies this distribution, and is available at
|
||||||
|
* https://www.eclipse.org/legal/epl-2.0/
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: EPL-2.0
|
||||||
|
*******************************************************************************/
|
||||||
|
package org.eclipse.cdt.internal.core.envvar;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
public class CMakeEnvironmentContextInfo extends DefaultEnvironmentContextInfo {
|
||||||
|
|
||||||
|
private IEnvironmentContextInfo fBaseInfo;
|
||||||
|
private ICoreEnvironmentVariableSupplier fSuppliers[];
|
||||||
|
|
||||||
|
public CMakeEnvironmentContextInfo(IEnvironmentContextInfo info) {
|
||||||
|
super(info.getContext());
|
||||||
|
fBaseInfo = info;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ICoreEnvironmentVariableSupplier[] getSuppliers() {
|
||||||
|
if (fSuppliers == null) {
|
||||||
|
ArrayList<ICoreEnvironmentVariableSupplier> suppliers = new ArrayList<>(
|
||||||
|
Arrays.asList(fBaseInfo.getSuppliers()));
|
||||||
|
suppliers.add(EnvironmentVariableManager.fCmakeSupplier);
|
||||||
|
fSuppliers = suppliers.toArray(new ICoreEnvironmentVariableSupplier[0]);
|
||||||
|
}
|
||||||
|
return fSuppliers;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IEnvironmentContextInfo getNext() {
|
||||||
|
IEnvironmentContextInfo baseNext = fBaseInfo.getNext();
|
||||||
|
if (baseNext != null)
|
||||||
|
return new CMakeEnvironmentContextInfo(baseNext);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
|
@ -19,6 +19,7 @@ import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.core.build.ICBuildConfiguration;
|
||||||
import org.eclipse.cdt.core.cdtvariables.CdtVariableException;
|
import org.eclipse.cdt.core.cdtvariables.CdtVariableException;
|
||||||
import org.eclipse.cdt.core.cdtvariables.ICdtVariable;
|
import org.eclipse.cdt.core.cdtvariables.ICdtVariable;
|
||||||
import org.eclipse.cdt.core.envvar.EnvironmentVariable;
|
import org.eclipse.cdt.core.envvar.EnvironmentVariable;
|
||||||
|
@ -35,6 +36,7 @@ import org.eclipse.cdt.utils.cdtvariables.IVariableSubstitutor;
|
||||||
import org.eclipse.cdt.utils.cdtvariables.SupplierBasedCdtVariableSubstitutor;
|
import org.eclipse.cdt.utils.cdtvariables.SupplierBasedCdtVariableSubstitutor;
|
||||||
import org.eclipse.cdt.utils.envvar.EnvVarOperationProcessor;
|
import org.eclipse.cdt.utils.envvar.EnvVarOperationProcessor;
|
||||||
import org.eclipse.core.resources.IBuildConfiguration;
|
import org.eclipse.core.resources.IBuildConfiguration;
|
||||||
|
import org.eclipse.core.runtime.Adapters;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class implements the IEnvironmentVariableProvider interface and provides all
|
* This class implements the IEnvironmentVariableProvider interface and provides all
|
||||||
|
@ -55,6 +57,7 @@ public class EnvironmentVariableManager implements IEnvironmentVariableManager {
|
||||||
public static final EclipseEnvironmentSupplier fEclipseSupplier = new EclipseEnvironmentSupplier();
|
public static final EclipseEnvironmentSupplier fEclipseSupplier = new EclipseEnvironmentSupplier();
|
||||||
public static final ToolChainEnvironmentSupplier fToolChainSupplier = new ToolChainEnvironmentSupplier();
|
public static final ToolChainEnvironmentSupplier fToolChainSupplier = new ToolChainEnvironmentSupplier();
|
||||||
public static final BuildConfigEnvironmentSupplier fBuildConfigSupplier = new BuildConfigEnvironmentSupplier();
|
public static final BuildConfigEnvironmentSupplier fBuildConfigSupplier = new BuildConfigEnvironmentSupplier();
|
||||||
|
public static final CMakeBuildEnvironmentSupplier fCmakeSupplier = new CMakeBuildEnvironmentSupplier();
|
||||||
|
|
||||||
private ContributedEnvironment fContributedEnvironment;
|
private ContributedEnvironment fContributedEnvironment;
|
||||||
|
|
||||||
|
@ -225,6 +228,9 @@ public class EnvironmentVariableManager implements IEnvironmentVariableManager {
|
||||||
* or null if the the given level is not supported
|
* or null if the the given level is not supported
|
||||||
*/
|
*/
|
||||||
public IEnvironmentContextInfo getContextInfo(Object level) {
|
public IEnvironmentContextInfo getContextInfo(Object level) {
|
||||||
|
if (Adapters.adapt(level, ICBuildConfiguration.class) != null) {
|
||||||
|
return new CMakeEnvironmentContextInfo(getDefaultContextInfo(level));
|
||||||
|
}
|
||||||
if (level instanceof ICConfigurationDescription) {
|
if (level instanceof ICConfigurationDescription) {
|
||||||
return fContributedEnvironment.appendEnvironment((ICConfigurationDescription) level)
|
return fContributedEnvironment.appendEnvironment((ICConfigurationDescription) level)
|
||||||
? getDefaultContextInfo(level)
|
? getDefaultContextInfo(level)
|
||||||
|
|
Loading…
Add table
Reference in a new issue