cmake: newlib linking flags -lc and -lgcc circular dependency
Fixes: #28650 Linking with newlib now defines the following linker flags as: ``` ${CMAKE_C_LINKER_WRAPPER_FLAG}${CMAKE_LINK_LIBRARY_FLAG}c ${CMAKE_C_LINKER_WRAPPER_FLAG}${CMAKE_LINK_LIBRARY_FLAG}gcc c ``` This is needed because when linking with newlib on aarch64, then libgcc has a link dependency to libc (strchr), but libc also has dependencies to libgcc. CMake is capable of handling circular link dependencies for CMake defined static libraries, which can be further controlled using `LINK_INTERFACE_MULTIPLICITY`. However, libc and libgcc are not regular CMake libraries, and is seen as linker flags by CMake, and thus symbol de-duplications will be performed. CMake link options cannot be used, as that will place those libs first on the linker invocation. -Wl,--start-group is problematic as the placement of -lc and -lgcc is not guaranteed in case later libraries are also using -lc / -libbgcc as interface linker flags. Thus, we resort to use `${CMAKE_C_LINKER_WRAPPER_FLAG}${CMAKE_LINK_LIBRARY_FLAG}` as this ensures the uniqueness and thus avoids symbol de-duplication which means libc will be followed by libgcc, which is finally followed by libc again. It would have been possible to use `-lc` directly, but there is a risk that an externally library is also adding `-lc` and thus de-duplication and re-arrangement of this flag happens. This risk is in theory also existing with this fix, but the long nature of this link flag with using `${CMAKE_C_LINKER_WRAPPER_FLAG}` would likely indicate a similar fix and thus those libraries will stay in order. Signed-off-by: Torsten Rasmussen <Torsten.Rasmussen@nordicsemi.no>
This commit is contained in:
parent
ca61606632
commit
da3726006b
1 changed files with 27 additions and 3 deletions
|
@ -30,13 +30,38 @@ endif()
|
||||||
# used by the network stack
|
# used by the network stack
|
||||||
zephyr_compile_definitions(__LINUX_ERRNO_EXTENSIONS__)
|
zephyr_compile_definitions(__LINUX_ERRNO_EXTENSIONS__)
|
||||||
|
|
||||||
|
# We are using
|
||||||
|
# - ${CMAKE_C_LINKER_WRAPPER_FLAG}${CMAKE_LINK_LIBRARY_FLAG}c
|
||||||
|
# - ${CMAKE_C_LINKER_WRAPPER_FLAG}${CMAKE_LINK_LIBRARY_FLAG}gcc
|
||||||
|
# - c
|
||||||
|
# in code below.
|
||||||
|
# This is needed because when linking with newlib on aarch64, then libgcc has a
|
||||||
|
# link dependency to libc (strchr), but libc also has dependencies to libgcc.
|
||||||
|
#
|
||||||
|
# CMake is capable of handling circular link dependencies for CMake defined
|
||||||
|
# static libraries, which can be further controlled using LINK_INTERFACE_MULTIPLICITY.
|
||||||
|
# However, libc and libgcc are not regular CMake libraries, and is seen as linker
|
||||||
|
# flags by CMake, and thus symbol de-duplications will be performed.
|
||||||
|
# CMake link options cannot be used, as that will place those libs first on the
|
||||||
|
# linker invocation. -Wl,--start-group is problematic as the placement of -lc
|
||||||
|
# and -lgcc is not guaranteed in case later libraries are also using
|
||||||
|
# -lc / -libbgcc as interface linker flags.
|
||||||
|
#
|
||||||
|
# Thus, we resort to use `${CMAKE_C_LINKER_WRAPPER_FLAG}${CMAKE_LINK_LIBRARY_FLAG}`
|
||||||
|
# as this ensures the uniqueness and thus avoids symbol de-duplication which means
|
||||||
|
# libc will be followed by libgcc, which is finally followed by libc again.
|
||||||
|
|
||||||
|
list(JOIN CMAKE_C_LINKER_WRAPPER_FLAG "" linker_wrapper_string)
|
||||||
|
|
||||||
zephyr_link_libraries(
|
zephyr_link_libraries(
|
||||||
m
|
m
|
||||||
c
|
"${linker_wrapper_string}${CMAKE_LINK_LIBRARY_FLAG}c"
|
||||||
${LIBC_LIBRARY_DIR_FLAG} # NB: Optional
|
${LIBC_LIBRARY_DIR_FLAG} # NB: Optional
|
||||||
$<$<BOOL:${CONFIG_NEWLIB_LIBC_FLOAT_PRINTF}>:-u_printf_float>
|
$<$<BOOL:${CONFIG_NEWLIB_LIBC_FLOAT_PRINTF}>:-u_printf_float>
|
||||||
$<$<BOOL:${CONFIG_NEWLIB_LIBC_FLOAT_SCANF}>:-u_scanf_float>
|
$<$<BOOL:${CONFIG_NEWLIB_LIBC_FLOAT_SCANF}>:-u_scanf_float>
|
||||||
gcc # Lib C depends on libgcc. e.g. libc.a(lib_a-fvwrite.o) references __aeabi_idiv
|
# Lib C depends on libgcc. e.g. libc.a(lib_a-fvwrite.o) references __aeabi_idiv
|
||||||
|
"${linker_wrapper_string}${CMAKE_LINK_LIBRARY_FLAG}gcc"
|
||||||
|
c
|
||||||
)
|
)
|
||||||
|
|
||||||
if(CONFIG_NEWLIB_LIBC_NANO)
|
if(CONFIG_NEWLIB_LIBC_NANO)
|
||||||
|
@ -47,4 +72,3 @@ if(CONFIG_NEWLIB_LIBC_NANO)
|
||||||
-specs=nano.specs
|
-specs=nano.specs
|
||||||
)
|
)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue