Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve CMake build option handling and API #1046

Merged
merged 1 commit into from
Jan 27, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions NewAndNoteworthy/CDT-12.0.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,21 @@ The minimum version of GLIBC required is now 2.31.
This version can be found in Ubuntu 20.04 and later, RHEL 9.0 and later and other distros as well.
CDT's native components will likely work with older versions of glibc too, assuming they provide the required APIs for Eclipse CDT.

# Core Build

## More CMake build settings are now available in the user interface

The CMake build setting GUI has been updated to include more CMake settings, and some of the settings that did not used to do the correct thing have been updated for more consistent behavior.
The way these settings are saved has been slightly modified, meaning workspaces with CMake projects from before CDT 12 will have their build settings restored to defaults.
Build settings can be customized by unchecking "Use default CMake settings".

TODO: Before release add the final screenshot for the build settings here. I am not including it now because the UI keeps changing.

## Default build system generator for CMake changed to Ninja on all platforms

The default for CMake's build system generator is now Ninja on all platforms.
Users who want to use other build system generators can select their desired generator in the build settings.

# Managed Build

## New *C Project* and new *C++ Project* available via *New C/C++ Project* wizard
Expand Down
17 changes: 17 additions & 0 deletions NewAndNoteworthy/CHANGELOG-API.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,23 @@ This section describes API removals that occurred in past releases, and upcoming

Below is the detailed descriptions of API changes and mitigation efforts API consumers need to take.

## API Changes in CDT 12.0.

### org.eclipse.cdt.cmake.core.properties refactored

A significant simplification to the CMake build properties was completed, this included removing some API that was not used.
The following classes have been removed or modified in API breaking ways:

- org.eclipse.cdt.cmake.core.properties.ICMakePropertiesController removed
- org.eclipse.cdt.cmake.core.properties.IGeneralProperties removed
- org.eclipse.cdt.cmake.core.properties.IOsOverrides removed
- org.eclipse.cdt.cmake.core.properties.ICMakeProperties:
- new methods added to compensate for removal of IOsOverrides
- reset method removed
- spelling corrected for methods with Uninitialized in the name
- setWarnUnused renamed to setWarnUnusedVars and isWarnUnused renamed to isWarnUnusedVars


## API Changes in CDT 11.5.

### org.eclipse.cdt.make.ui.dialogs.DiscoveredPathContainerPage removed
Expand Down
7 changes: 5 additions & 2 deletions cmake/org.eclipse.cdt.cmake.core.tests/META-INF/MANIFEST.MF
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,12 @@ Bundle-SymbolicName: org.eclipse.cdt.cmake.core.tests
Bundle-Version: 1.0.0.qualifier
Fragment-Host: org.eclipse.cdt.cmake.core;bundle-version="1.5.0"
Import-Package: org.assertj.core.api;version="[3.24.2,4.0.0)",
org.junit.jupiter.api;version="[5.9.3,6.0.0)"
org.junit.jupiter.api;version="[5.9.3,6.0.0)",
org.mockito;version="[5.15.0,6.0.0)",
org.mockito.stubbing;version="[5.15.0,6.0.0)"
Automatic-Module-Name: org.eclipse.cdt.cmake.core.tests
Bundle-Vendor: %Bundle-Vendor
Bundle-Copyright: %Bundle-Copyright
Require-Bundle: org.junit
Require-Bundle: org.junit,
org.eclipse.cdt.core.tests;bundle-version="[5.4.0,6.0.0)"

jonahgraham marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,299 @@
/*******************************************************************************
jonahgraham marked this conversation as resolved.
Show resolved Hide resolved
* Copyright (c) 2025 Renesas Electronics Europe.
*
* 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.cmake.core;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.contains;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.nullValue;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.eclipse.cdt.cmake.core.properties.CMakeGenerator;
import org.eclipse.cdt.cmake.core.properties.ICMakeGenerator;
import org.eclipse.cdt.cmake.core.properties.ICMakeProperties;
import org.eclipse.cdt.core.CCProjectNature;
import org.eclipse.cdt.core.CProjectNature;
import org.eclipse.cdt.core.build.IToolChain;
import org.eclipse.cdt.core.testplugin.ResourceHelper;
import org.eclipse.cdt.core.testplugin.util.BaseTestCase5;
import org.eclipse.cdt.utils.CommandLineUtil;
import org.eclipse.core.resources.IBuildConfiguration;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IProjectDescription;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

/**
* Tests a new API added to the CMake Build Configuration which allows default CMake properties to be set.
* See the new interface {@link ICMakeBuildConfiguration}.
*/
public class CMakeBuildConfigurationTests extends BaseTestCase5 {
private IBuildConfiguration buildConfig;
private IToolChain mockToolchain;

@BeforeEach
public void setup() throws Exception {
// Create a CMake project
IProject project = createCMakeProject();
// Get the default build config from the project (it always has one)
buildConfig = project.getBuildConfig(IBuildConfiguration.DEFAULT_CONFIG_NAME);
// 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");
}

/**
* Test for {@link ICMakeProperties#setGenerator()}.
*
* This test also verifies that what the ISV overrides in getCMakeProperties is what takes effect.
*/
@Test
public void getCMakePropertiesTestSetGenerator() throws Exception {
CMakeBuildConfiguration cmBuildConfig = new CMakeBuildConfiguration(buildConfig, "cmBuildConfigName",
mockToolchain) {

@Override
public ICMakeProperties getCMakeProperties() {
ICMakeProperties properties = super.getCMakeProperties();
properties.setGenerator(CMakeGenerator.WatcomWMake);
return properties;
}
};

// Call the new method on ICMakeBuildConfiguration to get the default CMake properties.
ICMakeProperties cMakeProperties = cmBuildConfig.getCMakeProperties();
assertThat(cMakeProperties.getGenerator(), is(CMakeGenerator.WatcomWMake));
}

/**
* Test for {@link ICMakeProperties#setExtraArguments()}
*
* This test also verifies that what the ISV overrides in getCMakeProperties is what takes effect.
*/
@Test
public void getCMakePropertiesTestSetExtraArguments() throws Exception {
// Create a C Build Configuration using the default build config and an arbitrary name
CMakeBuildConfiguration cmBuildConfig = new CMakeBuildConfiguration(buildConfig, "cmBuildConfigName",
mockToolchain) {

@Override
public ICMakeProperties getCMakeProperties() {
ICMakeProperties properties = super.getCMakeProperties();
properties.setExtraArguments(
new ArrayList<>((List.of("-DplatformAgnosticArgsTest0=0", "-DplatformAgnosticArgsTest1=1"))));
return properties;
}
};
// Call the new method on ICMakeBuildConfiguration to get the default CMake properties.
ICMakeProperties cMakeProperties = cmBuildConfig.getCMakeProperties();
List<String> extraArguments = cMakeProperties.getExtraArguments();
assertThat(extraArguments, contains("-DplatformAgnosticArgsTest0=0", "-DplatformAgnosticArgsTest1=1"));
}

/**
* Test for {@link CMakeBuildConfiguration#getDefaultProperties()}
*/
@Test
public void getDefaultProperties() throws Exception {
// Create a C Build Configuration using the default build config and an arbitrary name
CMakeBuildConfiguration cmBuildConfig = new CMakeBuildConfiguration(buildConfig, "cmBuildConfigName",
mockToolchain) {

@Override
public Map<String, String> getDefaultProperties() {
var defs = new HashMap<>(super.getDefaultProperties());
defs.put(CMAKE_GENERATOR, CMakeGenerator.WatcomWMake.getCMakeName());
return defs;
}
};
// Call the new method on ICMakeBuildConfiguration to get the default CMake properties.
ICMakeProperties cMakeProperties = cmBuildConfig.getCMakeProperties();
assertThat(cMakeProperties.getGenerator(), is(CMakeGenerator.WatcomWMake));
}

@Test
public void getDefaultPropertiesTestExtraArgs() throws Exception {
// Create a C Build Configuration using the default build config and an arbitrary name
CMakeBuildConfiguration cmBuildConfig = new CMakeBuildConfiguration(buildConfig, "cmBuildConfigName",
mockToolchain) {
@Override
public Map<String, String> getDefaultProperties() {
var defs = new HashMap<>(super.getDefaultProperties());
defs.put(CMAKE_ARGUMENTS, "-Dtest0=0 -Dtest1=1");
return defs;
}
};
// Call the new method on ICMakeBuildConfiguration to get the default CMake properties.
ICMakeProperties cMakeProperties = cmBuildConfig.getCMakeProperties();
List<String> extraArguments = cMakeProperties.getExtraArguments();
assertThat(extraArguments, contains("-Dtest0=0", "-Dtest1=1"));
}

/**
* Test that a custom cmake generator can be entered and auto-created
*/
@Test
public void customCMakeGeneratorEntryAuto() throws Exception {
// Create a C Build Configuration using the default build config and an arbitrary name
CMakeBuildConfiguration cmBuildConfig = new CMakeBuildConfiguration(buildConfig, "cmBuildConfigName",
mockToolchain) {
@Override
public Map<String, String> getDefaultProperties() {
var defs = new HashMap<>(super.getDefaultProperties());
// A custom generator for a custom cmake version
defs.put(CMAKE_GENERATOR, "My Personal Generator");
return defs;
}
};

// Call the new method on ICMakeBuildConfiguration to get the default CMake properties.
ICMakeProperties cMakeProperties = cmBuildConfig.getCMakeProperties();
assertThat(cMakeProperties.getGenerator().getCMakeName(), is("My Personal Generator"));
assertThat(cMakeProperties.getGenerator().getIgnoreErrOption(), is(nullValue()));
assertThat(cMakeProperties.getGenerator().getMakefileName(), is(nullValue()));
}

/**
* Test that a custom cmake generator can be entered and manually-created
*/
@Test
public void customCMakeGeneratorEntryManual() throws Exception {
// Create a C Build Configuration using the default build config and an arbitrary name
CMakeBuildConfiguration cmBuildConfig = new CMakeBuildConfiguration(buildConfig, "cmBuildConfigName",
mockToolchain) {
@Override
public Map<String, String> getDefaultProperties() {
var defs = new HashMap<>(super.getDefaultProperties());
// A custom generator for a custom cmake version
defs.put(CMAKE_GENERATOR, "My Personal Generator");
return defs;
}

@Override
public ICMakeProperties getCMakeProperties() {
ICMakeProperties properties = super.getCMakeProperties();
if ("My Personal Generator".equals(properties.getGenerator().getCMakeName())) {
var generator = new ICMakeGenerator() {
@Override
public String getMakefileName() {
return "MyMak.mak";
}

@Override
public String getIgnoreErrOption() {
return "-mycustom";
}

@Override
public String getCMakeName() {
return "My Personal Generator";
}
};
properties.setGenerator(generator);
}
return properties;
}
};

// Call the new method on ICMakeBuildConfiguration to get the default CMake properties.
ICMakeProperties cMakeProperties = cmBuildConfig.getCMakeProperties();
assertThat(cMakeProperties.getGenerator().getCMakeName(), is("My Personal Generator"));
assertThat(cMakeProperties.getGenerator().getIgnoreErrOption(), is("-mycustom"));
assertThat(cMakeProperties.getGenerator().getMakefileName(), is("MyMak.mak"));
}

/**
* Test all and clean targets and cmake command have working defaults
*/
@Test
public void targetsAndCommandDefaults() throws Exception {
// Create a C Build Configuration using the default build config and an arbitrary name
CMakeBuildConfiguration cmBuildConfig = new CMakeBuildConfiguration(buildConfig, "cmBuildConfigName",
mockToolchain);

// Call the new method on ICMakeBuildConfiguration to get the default CMake properties.
ICMakeProperties cMakeProperties = cmBuildConfig.getCMakeProperties();
assertThat(cMakeProperties.getCommand(), is("cmake"));
assertThat(cMakeProperties.getAllTarget(), is("all"));
assertThat(cMakeProperties.getCleanTarget(), is("clean"));
}

/**
* Test all and clean targets and cmake command can be overridden
*/
@Test
public void targetsAndCommand() throws Exception {
// Create a C Build Configuration using the default build config and an arbitrary name
CMakeBuildConfiguration cmBuildConfig = new CMakeBuildConfiguration(buildConfig, "cmBuildConfigName",
mockToolchain) {
@Override
public Map<String, String> getDefaultProperties() {
var defs = new HashMap<>(super.getDefaultProperties());
defs.put(CMAKE_BUILD_COMMAND, "mycmake");
defs.put(CMAKE_ALL_TARGET, "myall");
defs.put(CMAKE_CLEAN_TARGET, "myclean");
return defs;
}
};

// Call the new method on ICMakeBuildConfiguration to get the default CMake properties.
ICMakeProperties cMakeProperties = cmBuildConfig.getCMakeProperties();
assertThat(cMakeProperties.getCommand(), is("mycmake"));
assertThat(cMakeProperties.getAllTarget(), is("myall"));
assertThat(cMakeProperties.getCleanTarget(), is("myclean"));
}

/**
* Test that extra arguments parse correctly, e.g. handles ".
*
* Note that this test is minimal here as the real functionality is in {@link CommandLineUtil}
* and all the special cases are tested in CommandLineUtilTest.
*/
@Test
public void extraArgumentsParseCorrectly() throws Exception {
// Create a C Build Configuration using the default build config and an arbitrary name
CMakeBuildConfiguration cmBuildConfig = new CMakeBuildConfiguration(buildConfig, "cmBuildConfigName",
mockToolchain) {
@Override
public Map<String, String> getDefaultProperties() {
var defs = new HashMap<>(super.getDefaultProperties());
defs.put(CMAKE_ARGUMENTS, "-Da=\"something with space and quotes\" \"-Danother=quoted\"");
return defs;
}
};

// Call the new method on ICMakeBuildConfiguration to get the default CMake properties.
ICMakeProperties cMakeProperties = cmBuildConfig.getCMakeProperties();
assertThat(cMakeProperties.getExtraArguments(),
is(List.of("-Da=something with space and quotes", "-Danother=quoted")));
}

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;
}
}
Loading
Loading