mirror of
https://github.com/esphome/esphome.git
synced 2026-08-17 10:52:56 +08:00
[espidf] Use forward slashes in generated component CMakeLists (#17965)
Co-authored-by: J. Nick Koston <nick@koston.org>
This commit is contained in:
co-authored by
J. Nick Koston
parent
c0f494450d
commit
a199ac41ee
@@ -92,6 +92,14 @@ def generate_cmakelists_txt(component: IDFComponent) -> str:
|
||||
# In CMakeLists.txt, backslashes need to be escaped
|
||||
return f'"{str(p)}"'.replace("\\", "\\\\")
|
||||
|
||||
def escape_path(p: PathType) -> str:
|
||||
# CMake uses forward slashes for paths on every platform and treats
|
||||
# backslashes as escape characters. On Windows os.path.relpath yields
|
||||
# backslash paths, which break CMake's list re-parsing (e.g. "\b" in
|
||||
# "src\backend" is an invalid character escape). Emit forward slashes,
|
||||
# which Windows accepts too, so the generated CMakeLists is portable.
|
||||
return f'"{str(p).replace(os.sep, "/")}"'
|
||||
|
||||
# Extract the values
|
||||
build_src_dir = component.data.get("build", {}).get("srcDir", None)
|
||||
if not build_src_dir:
|
||||
@@ -173,10 +181,10 @@ def generate_cmakelists_txt(component: IDFComponent) -> str:
|
||||
# Generate the component
|
||||
content = "idf_component_register(\n"
|
||||
if build_src_files:
|
||||
str_srcs = " ".join([escape_entry(p) for p in sorted(build_src_files)])
|
||||
str_srcs = " ".join([escape_path(p) for p in sorted(build_src_files)])
|
||||
content += f" SRCS {str_srcs}\n"
|
||||
if build_include_dirs:
|
||||
str_include_dirs = " ".join([escape_entry(p) for p in build_include_dirs])
|
||||
str_include_dirs = " ".join([escape_path(p) for p in build_include_dirs])
|
||||
content += f" INCLUDE_DIRS {str_include_dirs}\n"
|
||||
# Project-managed and built-in component lists are set per-project
|
||||
# via idf_build_set_property in the top-level CMakeLists; expanded
|
||||
@@ -211,7 +219,7 @@ def generate_cmakelists_txt(component: IDFComponent) -> str:
|
||||
if link_directories:
|
||||
content += "target_link_directories(${COMPONENT_LIB} INTERFACE\n"
|
||||
for link_directory in link_directories:
|
||||
str_build_flag = escape_entry(link_directory)
|
||||
str_build_flag = escape_path(link_directory)
|
||||
content += f" {str_build_flag}\n"
|
||||
content += ")\n"
|
||||
|
||||
|
||||
@@ -169,30 +169,57 @@ def test_generate_cmakelists_txt_with_flags(tmp_component, tmp_path):
|
||||
}
|
||||
|
||||
content = generate_cmakelists_txt(tmp_component)
|
||||
sep = "\\\\" if os.name == "nt" else "/"
|
||||
# Paths are always emitted with forward slashes so the CMakeLists is
|
||||
# portable; on Windows os.path.relpath would otherwise yield backslashes
|
||||
# that break CMake's list re-parsing.
|
||||
assert (
|
||||
content
|
||||
== f"""idf_component_register(
|
||||
SRCS "src{sep}main.c"
|
||||
== """idf_component_register(
|
||||
SRCS "src/main.c"
|
||||
INCLUDE_DIRS "src"
|
||||
REQUIRES dep ${{ESPHOME_PROJECT_MANAGED_COMPONENTS}} ${{ESPHOME_PROJECT_BUILTIN_COMPONENTS}}
|
||||
REQUIRES dep ${ESPHOME_PROJECT_MANAGED_COMPONENTS} ${ESPHOME_PROJECT_BUILTIN_COMPONENTS}
|
||||
)
|
||||
target_compile_options(${{COMPONENT_LIB}} PUBLIC
|
||||
target_compile_options(${COMPONENT_LIB} PUBLIC
|
||||
"-DTEST"
|
||||
)
|
||||
target_compile_options(${{COMPONENT_LIB}} PRIVATE
|
||||
target_compile_options(${COMPONENT_LIB} PRIVATE
|
||||
"-Wall"
|
||||
)
|
||||
target_link_directories(${{COMPONENT_LIB}} INTERFACE
|
||||
target_link_directories(${COMPONENT_LIB} INTERFACE
|
||||
"lib"
|
||||
)
|
||||
target_link_libraries(${{COMPONENT_LIB}} INTERFACE
|
||||
target_link_libraries(${COMPONENT_LIB} INTERFACE
|
||||
"mylib"
|
||||
)
|
||||
"""
|
||||
)
|
||||
|
||||
|
||||
def test_generate_cmakelists_txt_uses_forward_slashes_on_windows(
|
||||
tmp_component, monkeypatch: pytest.MonkeyPatch
|
||||
) -> None:
|
||||
# os.path.relpath yields backslash paths on Windows, which CMake rejects
|
||||
# when it re-parses the SRCS list (e.g. "\b" in "src\backend" is an invalid
|
||||
# character escape). Simulate that output and confirm the generated
|
||||
# CMakeLists normalizes the separators to forward slashes.
|
||||
src_dir = tmp_component.path / "src" / "backend"
|
||||
src_dir.mkdir(parents=True)
|
||||
(src_dir / "cipher.c").write_text("int f() {}")
|
||||
|
||||
tmp_component.data = {}
|
||||
|
||||
monkeypatch.setattr("esphome.espidf.component.os.sep", "\\")
|
||||
monkeypatch.setattr(
|
||||
"esphome.espidf.component.os.path.relpath",
|
||||
lambda *args, **kwargs: "src\\backend\\cipher.c",
|
||||
)
|
||||
|
||||
content = generate_cmakelists_txt(tmp_component)
|
||||
|
||||
assert 'SRCS "src/backend/cipher.c"' in content
|
||||
assert "\\" not in content
|
||||
|
||||
|
||||
def test_generate_cmakelists_txt_multi_token_flag(tmp_component):
|
||||
# PlatformIO shell-lexes each build.flags entry, so a single entry can
|
||||
# carry a flag and its argument. The generated CMakeLists must emit them
|
||||
|
||||
Reference in New Issue
Block a user