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 `$<TARGET_FILE:${cxx}>`. 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 `$<TARGET_FILE:${cxx}>`, 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 <frantisek.hrbata@espressif.com>
This commit is contained in:
Frantisek Hrbata
2026-05-27 08:02:03 +02:00
committed by BOT
parent 6498d81eb4
commit 841faa3614

View File

@@ -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_FILE:${cxx}>)
target_link_libraries(${COMPONENT_LIB} PUBLIC libgcc_cxx)
# Link as INTERFACE, not PUBLIC: libgcc_cxx references $<TARGET_FILE:${cxx}>, 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")