From e7b24828b30e1f18dbff9b29ceccc9bcb4bd6bf1 Mon Sep 17 00:00:00 2001 From: Frantisek Hrbata Date: Wed, 27 May 2026 08:02:03 +0200 Subject: [PATCH] fix(cxx): avoid self-referential generator expression in libgcc_cxx The cxx component re-injects its own archive late on the link line so its stack-unwind wrappers take precedence over libgcc's (when C++ exceptions are disabled). It does this through an INTERFACE helper, libgcc_cxx, that carries `$`. That helper was linked back into the cxx target with PUBLIC, which places it in the cxx archive's own LINK_LIBRARIES, so the cxx target ends up transitively referencing its own output file. When CMake computes the cxx target's sources it walks the target's own link implementation, encounters `$`, and to resolve the file it needs the target's link language, which in turn needs its sources. This loop makes generation fail with: The SOURCES of "..." use a generator expression that depends on the SOURCES themselves. CMake only hits this when it reaches the cxx target standalone before the target has been pulled into a link by a consumer, and whether that happens depends on the project layout and target evaluation order. That is why it surfaces only in some projects, while the examples build fine. Link libgcc_cxx as INTERFACE instead of PUBLIC. A static archive is not linked, so its private LINK_LIBRARIES are inert; consumers still receive libgcc_cxx through INTERFACE_LINK_LIBRARIES, so the intended link order is preserved. Removing the self-reference makes generation independent of evaluation order. Signed-off-by: Frantisek Hrbata --- components/cxx/CMakeLists.txt | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/components/cxx/CMakeLists.txt b/components/cxx/CMakeLists.txt index 371bb2a9f19..a9fbd9fe45e 100644 --- a/components/cxx/CMakeLists.txt +++ b/components/cxx/CMakeLists.txt @@ -89,7 +89,14 @@ endif() idf_component_get_property(cxx cxx COMPONENT_LIB) add_library(libgcc_cxx INTERFACE) target_link_libraries(libgcc_cxx INTERFACE ${CONFIG_COMPILER_RT_LIB_NAME} $) -target_link_libraries(${COMPONENT_LIB} PUBLIC libgcc_cxx) +# Link as INTERFACE, not PUBLIC: libgcc_cxx references $, so adding it to the +# cxx archive's own LINK_LIBRARIES would make the target depend on its own TARGET_FILE. CMake then +# needs the link language (hence SOURCES) to resolve that TARGET_FILE, which is a self-reference and +# fails generation with "The SOURCES of '...' use a generator expression that depends on the SOURCES +# themselves" whenever the cxx target is not itself link-consumed (e.g. cmakev2, IDFGH-16748). A +# static archive isn't linked, so its private link libraries are inert; consumers still get +# libgcc_cxx through INTERFACE_LINK_LIBRARIES, preserving link order. +target_link_libraries(${COMPONENT_LIB} INTERFACE libgcc_cxx) if(NOT CONFIG_COMPILER_CXX_EXCEPTIONS) target_link_libraries(${COMPONENT_LIB} INTERFACE "-u __cxx_fatal_exception")