[core] Make set_cpp_standard work on the native IDF toolchain (#16907)

This commit is contained in:
Jonathan Swoboda
2026-06-11 07:25:03 +12:00
committed by GitHub
parent dafc3560dd
commit 29a79b1373
6 changed files with 129 additions and 12 deletions
+19 -3
View File
@@ -8,6 +8,17 @@ import esphome.config_validation as cv
from esphome.core import CORE
from esphome.helpers import mkdir_p, write_file_if_changed
# Replaces the IDF default C++ standard (-std=gnu++2b appended to
# CXX_COMPILE_OPTIONS by project.cmake's __build_init) with the one set via
# cg.set_cpp_standard(). Emitted between include(project.cmake) and project(),
# i.e. after IDF appends its default and before the options are consumed, and
# applies project-wide like PlatformIO build_unflags.
CPP_STANDARD_TEMPLATE = """\
idf_build_get_property(esphome_cxx_compile_options CXX_COMPILE_OPTIONS)
list(FILTER esphome_cxx_compile_options EXCLUDE REGEX "^-std=")
list(APPEND esphome_cxx_compile_options "-std={standard}")
idf_build_set_property(CXX_COMPILE_OPTIONS "${{esphome_cxx_compile_options}}")"""
def get_available_components() -> list[str] | None:
"""Get list of built-in ESP-IDF components from project_description.json.
@@ -84,6 +95,12 @@ def get_project_cmakelists(minimal: bool = False) -> str:
for flag in project_compile_opts
)
cpp_standard_options = (
CPP_STANDARD_TEMPLATE.format(standard=CORE.cpp_standard)
if CORE.cpp_standard
else ""
)
# Per-project list exposed as a CMake variable so converted PIO libs
# can reference ${ESPHOME_PROJECT_MANAGED_COMPONENTS} without baking
# project-specific names into their cached CMakeLists.
@@ -140,6 +157,8 @@ set(EXTRA_COMPONENT_DIRS ${{CMAKE_SOURCE_DIR}}/src)
include($ENV{{IDF_PATH}}/tools/cmake/project.cmake)
{cpp_standard_options}
{extra_compile_options}
{managed_components_property}
@@ -200,9 +219,6 @@ idf_component_register(
REQUIRES ${{ESPHOME_PROJECT_BUILTIN_COMPONENTS}}
)
# Apply C++ standard
target_compile_features(${{COMPONENT_LIB}} PUBLIC cxx_std_20)
# ESPHome linker options
target_link_options(${{COMPONENT_LIB}} PUBLIC
{link_opts_str}
+15
View File
@@ -33,12 +33,27 @@ def format_ini(data: dict[str, str | list[str]]) -> str:
return content
# All -std= variants a platform/framework may set by default, in both the GNU
# and strict dialects; unflagged so the cg.set_cpp_standard() value is the
# only standard left in the build.
CPP_STD_VARIANTS = [
f"{prefix}{year}"
for year in ("11", "14", "17", "20", "23", "26", "2a", "2b", "2c")
for prefix in ("gnu++", "c++")
]
def get_ini_content():
CORE.add_platformio_option(
"lib_deps",
[x.as_lib_dep for x in CORE.platformio_libraries.values()]
+ ["${common.lib_deps}"],
)
if CORE.cpp_standard:
for variant in CPP_STD_VARIANTS:
if variant != CORE.cpp_standard:
CORE.add_build_unflag(f"-std={variant}")
CORE.add_build_flag(f"-std={CORE.cpp_standard}")
# Sort to avoid changing build flags order
CORE.add_platformio_option("build_flags", sorted(CORE.build_flags))
+3
View File
@@ -593,6 +593,8 @@ class EsphomeCore:
self.build_flags: set[str] = set()
# A set of build unflags to set in the platformio project
self.build_unflags: set[str] = set()
# The C++ language standard for the build (e.g. "gnu++20"), set via cg.set_cpp_standard()
self.cpp_standard: str | None = None
# A set of defines to set for the compile process in esphome/core/defines.h
self.defines: set[Define] = set()
# A map of all platformio options to apply
@@ -649,6 +651,7 @@ class EsphomeCore:
self.platformio_libraries = {}
self.build_flags = set()
self.build_unflags = set()
self.cpp_standard = None
self.defines = set()
self.platformio_options = {}
self.loaded_integrations = set()
+2 -9
View File
@@ -705,15 +705,8 @@ def add_build_unflag(build_unflag: str) -> None:
def set_cpp_standard(standard: str) -> None:
"""Set C++ standard with compiler flag `-std={standard}`."""
CORE.add_build_unflag("-std=gnu++11")
CORE.add_build_unflag("-std=gnu++14")
CORE.add_build_unflag("-std=gnu++17")
CORE.add_build_unflag("-std=gnu++23")
CORE.add_build_unflag("-std=gnu++2a")
CORE.add_build_unflag("-std=gnu++2b")
CORE.add_build_unflag("-std=gnu++2c")
CORE.add_build_flag(f"-std={standard}")
"""Set the C++ language standard for the build (e.g. ``gnu++20``)."""
CORE.cpp_standard = standard
def add_define(name: str, value: SafeExpType = None):