From 5aa5354a8de84ef86f0556f41a0a18272c896e6f Mon Sep 17 00:00:00 2001 From: Tam Dang Date: Fri, 24 Jan 2025 23:30:55 +0700 Subject: [PATCH] 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 --- .../ui/internal/CMakePreferencePage.java | 282 +++++++++++++++++ .../cdt/cmake/ui/internal/Messages.java | 21 ++ .../cdt/cmake/ui/internal/messages.properties | 20 ++ .../META-INF/MANIFEST.MF | 3 +- .../CMakeBuildEnvironmentSupplierTest.java | 290 ++++++++++++++++++ .../org.eclipse.cdt.core/META-INF/MANIFEST.MF | 2 +- .../envvar/CMakeBuildEnvironmentSupplier.java | 98 ++++++ .../envvar/CMakeEnvironmentContextInfo.java | 44 +++ .../envvar/EnvironmentVariableManager.java | 6 + 9 files changed, 764 insertions(+), 2 deletions(-) create mode 100644 core/org.eclipse.cdt.core.tests/misc/org/eclipse/cdt/internal/core/envvar/CMakeBuildEnvironmentSupplierTest.java create mode 100644 core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/core/envvar/CMakeBuildEnvironmentSupplier.java create mode 100644 core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/core/envvar/CMakeEnvironmentContextInfo.java diff --git a/cmake/org.eclipse.cdt.cmake.ui/src/org/eclipse/cdt/cmake/ui/internal/CMakePreferencePage.java b/cmake/org.eclipse.cdt.cmake.ui/src/org/eclipse/cdt/cmake/ui/internal/CMakePreferencePage.java index 162955e6889..e0b26aafdbf 100644 --- a/cmake/org.eclipse.cdt.cmake.ui/src/org/eclipse/cdt/cmake/ui/internal/CMakePreferencePage.java +++ b/cmake/org.eclipse.cdt.cmake.ui/src/org/eclipse/cdt/cmake/ui/internal/CMakePreferencePage.java @@ -10,6 +10,10 @@ *******************************************************************************/ 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.util.ArrayList; 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.ICMakeToolChainManager; 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.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.preferences.InstanceScope; +import org.eclipse.jface.dialogs.Dialog; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.layout.TableColumnLayout; 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.wizard.WizardDialog; 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.SelectionEvent; 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.Composite; import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.DirectoryDialog; 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.TableColumn; import org.eclipse.swt.widgets.TableItem; +import org.eclipse.swt.widgets.Text; import org.eclipse.ui.IWorkbench; 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. */ public class CMakePreferencePage extends PreferencePage implements IWorkbenchPreferencePage { + private static final String VALUE_DELIMITER = " || "; //$NON-NLS-1$ + private ICMakeToolChainManager manager; private Table filesTable; 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 filesToAdd = new HashMap<>(); private Map filesToRemove = new HashMap<>(); @@ -58,6 +93,7 @@ public class CMakePreferencePage extends PreferencePage implements IWorkbenchPre @Override public void init(IWorkbench workbench) { manager = Activator.getService(ICMakeToolChainManager.class); + updateCmakeToolGroupData(); } @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 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(); + updateCMakeGroup(useCmakeToolLocation); 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() { List sorted = new ArrayList<>(getFiles().values()); 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(); 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; } + private void updateCmakeToolGroupData() { + try { + useCmakeToolLocation = getPreferences().getBoolean(CMakeBuildEnvironmentSupplier.ENABLE_USE_CMAKE_LOCATION, + false); + cmakeLocation = getPreferences().get(CMakeBuildEnvironmentSupplier.CMAKE_LOCATION, + CMakeBuildEnvironmentSupplier.EMPTY_STRING); + List 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 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); + } } diff --git a/cmake/org.eclipse.cdt.cmake.ui/src/org/eclipse/cdt/cmake/ui/internal/Messages.java b/cmake/org.eclipse.cdt.cmake.ui/src/org/eclipse/cdt/cmake/ui/internal/Messages.java index d5c2263626f..772128f755f 100644 --- a/cmake/org.eclipse.cdt.cmake.ui/src/org/eclipse/cdt/cmake/ui/internal/Messages.java +++ b/cmake/org.eclipse.cdt.cmake.ui/src/org/eclipse/cdt/cmake/ui/internal/Messages.java @@ -30,12 +30,31 @@ public class Messages extends NLS { public static String CMakeBuildTab_useDefaultCmakeSettingsTip; public static String CMakeBuildTab_UsedForLaunchMode; 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_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_GeneratorLocation; + public static String CMakePreferencePage_GeneratorLocationTooltip; public static String CMakePreferencePage_Path; 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_UseCMakeToolLocationsInCMakeBuilds; + public static String CMakePreferencePage_UseCMakeToolLocationsInCMakeBuildsTooltip; + public static String CMakePreferencePage_Variables; public static String CMakePropertyPage_FailedToStartCMakeGui_Body; public static String CMakePropertyPage_FailedToStartCMakeGui_Title; public static String CMakePropertyPage_FailedToGetOS_Body; @@ -57,6 +76,8 @@ public class Messages extends NLS { public static String NewCMakeToolChainFilePage_Title; public static String NewCMakeToolChainFilePage_Toolchain; + public static String VariablesDialog_Title; + static { // initialize resource bundle NLS.initializeMessages("org.eclipse.cdt.cmake.ui.internal.messages", Messages.class); //$NON-NLS-1$ diff --git a/cmake/org.eclipse.cdt.cmake.ui/src/org/eclipse/cdt/cmake/ui/internal/messages.properties b/cmake/org.eclipse.cdt.cmake.ui/src/org/eclipse/cdt/cmake/ui/internal/messages.properties index bd5f7e8ebd8..673a7f304a4 100644 --- a/cmake/org.eclipse.cdt.cmake.ui/src/org/eclipse/cdt/cmake/ui/internal/messages.properties +++ b/cmake/org.eclipse.cdt.cmake.ui/src/org/eclipse/cdt/cmake/ui/internal/messages.properties @@ -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_UsedForLaunchMode=used for launch mode: {0} 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_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_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_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_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_Title=Failed to run CMake GUI 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_Title=New CMake ToolChain File NewCMakeToolChainFilePage_Toolchain=Toolchain: +VariablesDialog_Title=Select CMake variable diff --git a/core/org.eclipse.cdt.core.tests/META-INF/MANIFEST.MF b/core/org.eclipse.cdt.core.tests/META-INF/MANIFEST.MF index 6472bc7bf54..b49e706340c 100644 --- a/core/org.eclipse.cdt.core.tests/META-INF/MANIFEST.MF +++ b/core/org.eclipse.cdt.core.tests/META-INF/MANIFEST.MF @@ -57,7 +57,8 @@ Bundle-Vendor: %providerName Bundle-RequiredExecutionEnvironment: JavaSE-17 Automatic-Module-Name: org.eclipse.cdt.core.tests 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.provider;version="5.9.0", org.mockito;version="[5.12.0,6.0.0]", diff --git a/core/org.eclipse.cdt.core.tests/misc/org/eclipse/cdt/internal/core/envvar/CMakeBuildEnvironmentSupplierTest.java b/core/org.eclipse.cdt.core.tests/misc/org/eclipse/cdt/internal/core/envvar/CMakeBuildEnvironmentSupplierTest.java new file mode 100644 index 00000000000..fc2582bcd8e --- /dev/null +++ b/core/org.eclipse.cdt.core.tests/misc/org/eclipse/cdt/internal/core/envvar/CMakeBuildEnvironmentSupplierTest.java @@ -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
+* Verify behaviors of CMakeEnvironmentContextInfo.class and CMakeBuildEnvironmentSupplier.class +*
+* Test components:
+* {@link CMakeEnvironmentContextInfo}
+* {@link CMakeBuildEnvironmentSupplier}
+*/ +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)} + *
+ * This test verify CMakeEnvironmentContextInfo can be acquired via EnvironmentVariableManager + */ + @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)} + *
+ * This test verify that getVariable(String, Object) return the null value in case:
+ *
  • Input variable name is not "PATH", or:
    + *
  • Input contextInfo cannot be adapted to {@link ICBuildConfiguration}
  • + */ + @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)} + *
    + * This test verify that getVariable(String, Object) can return the "PATH" variable with + * CMake location and Generator location in case:
    + *
  • Input variable name is "PATH" + *
  • 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)} + *
    + * This test verify that getVariables(Object) return empty variable array in case:
    + *
  • 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)} + *
    + * This test verify that getVariables(Object) can return the PATH variables contains + * CMake location and Generator location in case:
    + *
  • 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 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 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 env) { + super.setBuildEnvironment(env); + List 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; + } +} diff --git a/core/org.eclipse.cdt.core/META-INF/MANIFEST.MF b/core/org.eclipse.cdt.core/META-INF/MANIFEST.MF index 5883f5c456b..405af459dd9 100644 --- a/core/org.eclipse.cdt.core/META-INF/MANIFEST.MF +++ b/core/org.eclipse.cdt.core/META-INF/MANIFEST.MF @@ -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.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.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.composite;x-internal:=true, org.eclipse.cdt.internal.core.index.composite.c;x-internal:=true, diff --git a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/core/envvar/CMakeBuildEnvironmentSupplier.java b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/core/envvar/CMakeBuildEnvironmentSupplier.java new file mode 100644 index 00000000000..be5e5c28c1c --- /dev/null +++ b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/core/envvar/CMakeBuildEnvironmentSupplier.java @@ -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 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; + } +} diff --git a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/core/envvar/CMakeEnvironmentContextInfo.java b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/core/envvar/CMakeEnvironmentContextInfo.java new file mode 100644 index 00000000000..acb37c23e81 --- /dev/null +++ b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/core/envvar/CMakeEnvironmentContextInfo.java @@ -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 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; + } +} diff --git a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/core/envvar/EnvironmentVariableManager.java b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/core/envvar/EnvironmentVariableManager.java index 2f8ed695264..e09602325aa 100644 --- a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/core/envvar/EnvironmentVariableManager.java +++ b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/core/envvar/EnvironmentVariableManager.java @@ -19,6 +19,7 @@ import java.util.Iterator; import java.util.List; import java.util.Map; +import org.eclipse.cdt.core.build.ICBuildConfiguration; import org.eclipse.cdt.core.cdtvariables.CdtVariableException; import org.eclipse.cdt.core.cdtvariables.ICdtVariable; 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.envvar.EnvVarOperationProcessor; import org.eclipse.core.resources.IBuildConfiguration; +import org.eclipse.core.runtime.Adapters; /** * 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 ToolChainEnvironmentSupplier fToolChainSupplier = new ToolChainEnvironmentSupplier(); public static final BuildConfigEnvironmentSupplier fBuildConfigSupplier = new BuildConfigEnvironmentSupplier(); + public static final CMakeBuildEnvironmentSupplier fCmakeSupplier = new CMakeBuildEnvironmentSupplier(); private ContributedEnvironment fContributedEnvironment; @@ -225,6 +228,9 @@ public class EnvironmentVariableManager implements IEnvironmentVariableManager { * or null if the the given level is not supported */ public IEnvironmentContextInfo getContextInfo(Object level) { + if (Adapters.adapt(level, ICBuildConfiguration.class) != null) { + return new CMakeEnvironmentContextInfo(getDefaultContextInfo(level)); + } if (level instanceof ICConfigurationDescription) { return fContributedEnvironment.appendEnvironment((ICConfigurationDescription) level) ? getDefaultContextInfo(level)