mirror of
https://github.com/esphome/esphome.git
synced 2026-07-10 08:55:36 +00:00
[esp32] Suppress -Wvolatile in the direct ESP-IDF build (#17404)
This commit is contained in:
@@ -6,7 +6,11 @@ from pathlib import Path
|
||||
from esphome.components.esp32 import get_esp32_variant, idf_version
|
||||
import esphome.config_validation as cv
|
||||
from esphome.core import CORE
|
||||
from esphome.framework_helpers import get_project_compile_flags, get_project_link_flags
|
||||
from esphome.framework_helpers import (
|
||||
get_project_compile_flags,
|
||||
get_project_cxx_compile_flags,
|
||||
get_project_link_flags,
|
||||
)
|
||||
from esphome.helpers import mkdir_p, write_file_if_changed
|
||||
|
||||
# Replaces the IDF default C++ standard (-std=gnu++2b appended to
|
||||
@@ -91,6 +95,14 @@ def get_project_cmakelists(minimal: bool = False) -> str:
|
||||
for flag in project_compile_opts
|
||||
)
|
||||
|
||||
# Flags registered via cg.add_cxx_build_flag() go on CXX_COMPILE_OPTIONS
|
||||
# (not COMPILE_OPTIONS) because GCC warns when a C++-only flag such as
|
||||
# -Wno-volatile is passed on a C compile.
|
||||
cxx_compile_options = "\n".join(
|
||||
f'idf_build_set_property(CXX_COMPILE_OPTIONS "{flag}" APPEND)'
|
||||
for flag in get_project_cxx_compile_flags()
|
||||
)
|
||||
|
||||
cpp_standard_options = (
|
||||
CPP_STANDARD_TEMPLATE.format(standard=CORE.cpp_standard)
|
||||
if CORE.cpp_standard
|
||||
@@ -155,6 +167,8 @@ include($ENV{{IDF_PATH}}/tools/cmake/project.cmake)
|
||||
|
||||
{cpp_standard_options}
|
||||
|
||||
{cxx_compile_options}
|
||||
|
||||
{extra_compile_options}
|
||||
|
||||
{managed_components_property}
|
||||
|
||||
@@ -108,7 +108,6 @@ Import("env")
|
||||
def write_cxx_flags_script() -> None:
|
||||
path = CORE.relative_build_path(CXX_FLAGS_FILE_NAME)
|
||||
contents = CXX_FLAGS_FILE_CONTENTS
|
||||
if not CORE.is_host:
|
||||
contents += 'env.Append(CXXFLAGS=["-Wno-volatile"])'
|
||||
contents += "\n"
|
||||
for flag in sorted(CORE.cxx_build_flags):
|
||||
contents += f'env.Append(CXXFLAGS=["{flag}"])\n'
|
||||
write_file_if_changed(path, contents)
|
||||
|
||||
@@ -25,6 +25,7 @@ from esphome.cpp_generator import ( # noqa: F401
|
||||
add,
|
||||
add_build_flag,
|
||||
add_build_unflag,
|
||||
add_cxx_build_flag,
|
||||
add_define,
|
||||
add_global,
|
||||
add_library,
|
||||
|
||||
@@ -591,6 +591,9 @@ class EsphomeCore:
|
||||
self.platformio_libraries: dict[str, Library] = {}
|
||||
# A set of build flags to set in the platformio project
|
||||
self.build_flags: set[str] = set()
|
||||
# A set of build flags that apply to C++ compiles only (CXXFLAGS /
|
||||
# CXX_COMPILE_OPTIONS), for flags GCC rejects or warns about on C
|
||||
self.cxx_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()
|
||||
@@ -650,6 +653,7 @@ class EsphomeCore:
|
||||
self.global_statements = []
|
||||
self.platformio_libraries = {}
|
||||
self.build_flags = set()
|
||||
self.cxx_build_flags = set()
|
||||
self.build_unflags = set()
|
||||
self.cpp_standard = None
|
||||
self.defines = set()
|
||||
@@ -957,6 +961,11 @@ class EsphomeCore:
|
||||
_LOGGER.debug("Adding build flag: %s", build_flag)
|
||||
return build_flag
|
||||
|
||||
def add_cxx_build_flag(self, build_flag: str) -> str:
|
||||
self.cxx_build_flags.add(build_flag)
|
||||
_LOGGER.debug("Adding C++ build flag: %s", build_flag)
|
||||
return build_flag
|
||||
|
||||
def add_build_unflag(self, build_unflag: str) -> None:
|
||||
if self.using_toolchain_esp_idf:
|
||||
# The native ESP-IDF build generator does not consume build_unflags
|
||||
|
||||
@@ -723,6 +723,15 @@ async def to_code(config: ConfigType) -> None:
|
||||
cg.add_build_flag("-Wno-unused-variable")
|
||||
cg.add_build_flag("-Wno-unused-but-set-variable")
|
||||
cg.add_build_flag("-Wno-sign-compare")
|
||||
# C++20 deprecated ++/--, compound assignment, and chained assignment on
|
||||
# volatile lvalues; GCC warns via -Wvolatile, on by default at gnu++20.
|
||||
# C++23 (P2327R1) removed the deprecation for compound assignment, so the
|
||||
# warning flags patterns that are valid again under newer standards.
|
||||
# C++-only flag: GCC warns when it is passed on a C compile, hence
|
||||
# add_cxx_build_flag. Skipped for host builds, where the compiler may be
|
||||
# clang, which does not know this GCC option.
|
||||
if not CORE.is_host:
|
||||
cg.add_cxx_build_flag("-Wno-volatile")
|
||||
if config[CONF_DEBUG_SCHEDULER]:
|
||||
cg.add_define("ESPHOME_DEBUG_SCHEDULER")
|
||||
|
||||
|
||||
@@ -699,6 +699,15 @@ def add_build_flag(build_flag: str):
|
||||
CORE.add_build_flag(build_flag)
|
||||
|
||||
|
||||
def add_cxx_build_flag(build_flag: str) -> None:
|
||||
"""Add a global build flag that applies to C++ compiles only.
|
||||
|
||||
Use for flags GCC rejects or warns about when passed on C compiles
|
||||
(e.g. ``-Wno-volatile``).
|
||||
"""
|
||||
CORE.add_cxx_build_flag(build_flag)
|
||||
|
||||
|
||||
def add_build_unflag(build_unflag: str) -> None:
|
||||
"""Add a global build unflag to the compiler flags."""
|
||||
CORE.add_build_unflag(build_unflag)
|
||||
|
||||
@@ -37,6 +37,13 @@ def get_project_compile_flags() -> list[str]:
|
||||
]
|
||||
|
||||
|
||||
def get_project_cxx_compile_flags() -> list[str]:
|
||||
"""Return the sorted flags that apply to C++ compiles only."""
|
||||
from esphome.core import CORE # local import to avoid circular dependency
|
||||
|
||||
return sorted(CORE.cxx_build_flags)
|
||||
|
||||
|
||||
def str_to_lst_of_str(a: str | list[str]) -> list[str]:
|
||||
"""
|
||||
Convert a string to a list of string
|
||||
|
||||
@@ -243,6 +243,7 @@ def test_get_project_cmakelists_no_cpp_standard(tmp_path: Path) -> None:
|
||||
patch("esphome.build_gen.espidf.get_esp32_variant", return_value="ESP32"),
|
||||
patch.object(CORE, "name", "test"),
|
||||
patch.object(CORE, "cpp_standard", None),
|
||||
patch.object(CORE, "cxx_build_flags", set()),
|
||||
):
|
||||
from esphome.build_gen.espidf import get_project_cmakelists
|
||||
|
||||
@@ -251,6 +252,28 @@ def test_get_project_cmakelists_no_cpp_standard(tmp_path: Path) -> None:
|
||||
assert "CXX_COMPILE_OPTIONS" not in content
|
||||
|
||||
|
||||
def test_get_project_cmakelists_cxx_build_flags(tmp_path: Path) -> None:
|
||||
"""Flags registered via cg.add_cxx_build_flag() are appended to
|
||||
CXX_COMPILE_OPTIONS (C++-only, GCC warns if they reach C compiles)
|
||||
between include(project.cmake) and project()."""
|
||||
with (
|
||||
patch("esphome.build_gen.espidf.get_esp32_variant", return_value="ESP32"),
|
||||
patch.object(CORE, "name", "test"),
|
||||
patch.object(CORE, "cpp_standard", None),
|
||||
patch.object(CORE, "cxx_build_flags", {"-Wno-volatile"}),
|
||||
):
|
||||
from esphome.build_gen.espidf import get_project_cmakelists
|
||||
|
||||
content = get_project_cmakelists(minimal=True)
|
||||
|
||||
flag_line = 'idf_build_set_property(CXX_COMPILE_OPTIONS "-Wno-volatile" APPEND)'
|
||||
assert flag_line in content
|
||||
include_pos = content.index("tools/cmake/project.cmake")
|
||||
flag_pos = content.index(flag_line)
|
||||
project_pos = content.index("project(test)")
|
||||
assert include_pos < flag_pos < project_pos
|
||||
|
||||
|
||||
def test_get_component_cmakelists_no_compile_features() -> None:
|
||||
"""The C++ standard is pinned project-wide via CXX_COMPILE_OPTIONS in the
|
||||
top-level CMakeLists; the src component must not set its own."""
|
||||
|
||||
@@ -200,3 +200,32 @@ def test_get_ini_content_no_cpp_standard(
|
||||
content = platformio.get_ini_content()
|
||||
|
||||
assert "-std=" not in content
|
||||
|
||||
|
||||
def test_write_cxx_flags_script_emits_registered_flags(
|
||||
tmp_path: Path, monkeypatch: pytest.MonkeyPatch
|
||||
) -> None:
|
||||
"""Flags registered via cg.add_cxx_build_flag() are emitted as CXXFLAGS,
|
||||
sorted, so they apply to C++ compiles only."""
|
||||
CORE.build_path = str(tmp_path)
|
||||
monkeypatch.setattr(CORE, "cxx_build_flags", {"-Wno-volatile", "-Wno-deprecated"})
|
||||
|
||||
platformio.write_cxx_flags_script()
|
||||
|
||||
content = (tmp_path / platformio.CXX_FLAGS_FILE_NAME).read_text()
|
||||
assert (
|
||||
'env.Append(CXXFLAGS=["-Wno-deprecated"])\n'
|
||||
'env.Append(CXXFLAGS=["-Wno-volatile"])\n'
|
||||
) in content
|
||||
|
||||
|
||||
def test_write_cxx_flags_script_no_flags(
|
||||
tmp_path: Path, monkeypatch: pytest.MonkeyPatch
|
||||
) -> None:
|
||||
CORE.build_path = str(tmp_path)
|
||||
monkeypatch.setattr(CORE, "cxx_build_flags", set())
|
||||
|
||||
platformio.write_cxx_flags_script()
|
||||
|
||||
content = (tmp_path / platformio.CXX_FLAGS_FILE_NAME).read_text()
|
||||
assert "CXXFLAGS" not in content
|
||||
|
||||
@@ -26,6 +26,7 @@ from esphome.framework_helpers import (
|
||||
create_venv,
|
||||
download_from_mirrors,
|
||||
get_project_compile_flags,
|
||||
get_project_cxx_compile_flags,
|
||||
get_project_link_flags,
|
||||
get_python_env_executable_path,
|
||||
get_system_python_path,
|
||||
@@ -1048,3 +1049,25 @@ class TestGetProjectLinkFlags:
|
||||
):
|
||||
result = get_project_link_flags()
|
||||
assert result == sorted(result)
|
||||
|
||||
|
||||
def _make_core_cxx(flags: set[str]) -> MagicMock:
|
||||
core = MagicMock()
|
||||
core.cxx_build_flags = flags
|
||||
return core
|
||||
|
||||
|
||||
class TestGetProjectCxxCompileFlags:
|
||||
def test_returns_sorted_flags(self) -> None:
|
||||
with patch(
|
||||
"esphome.core.CORE",
|
||||
_make_core_cxx({"-Wno-volatile", "-Wno-deprecated"}),
|
||||
):
|
||||
assert get_project_cxx_compile_flags() == [
|
||||
"-Wno-deprecated",
|
||||
"-Wno-volatile",
|
||||
]
|
||||
|
||||
def test_empty_flags(self) -> None:
|
||||
with patch("esphome.core.CORE", _make_core_cxx(set())):
|
||||
assert get_project_cxx_compile_flags() == []
|
||||
|
||||
Reference in New Issue
Block a user