Skip to content

Commit da37260

Browse files
tejlmandnashif
authored andcommitted
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 <[email protected]>
1 parent ca61606 commit da37260

File tree

1 file changed

+27
-3
lines changed

1 file changed

+27
-3
lines changed

lib/libc/newlib/CMakeLists.txt

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,13 +30,38 @@ endif()
3030
# used by the network stack
3131
zephyr_compile_definitions(__LINUX_ERRNO_EXTENSIONS__)
3232

33+
# We are using
34+
# - ${CMAKE_C_LINKER_WRAPPER_FLAG}${CMAKE_LINK_LIBRARY_FLAG}c
35+
# - ${CMAKE_C_LINKER_WRAPPER_FLAG}${CMAKE_LINK_LIBRARY_FLAG}gcc
36+
# - c
37+
# in code below.
38+
# This is needed because when linking with newlib on aarch64, then libgcc has a
39+
# link dependency to libc (strchr), but libc also has dependencies to libgcc.
40+
#
41+
# CMake is capable of handling circular link dependencies for CMake defined
42+
# static libraries, which can be further controlled using LINK_INTERFACE_MULTIPLICITY.
43+
# However, libc and libgcc are not regular CMake libraries, and is seen as linker
44+
# flags by CMake, and thus symbol de-duplications will be performed.
45+
# CMake link options cannot be used, as that will place those libs first on the
46+
# linker invocation. -Wl,--start-group is problematic as the placement of -lc
47+
# and -lgcc is not guaranteed in case later libraries are also using
48+
# -lc / -libbgcc as interface linker flags.
49+
#
50+
# Thus, we resort to use `${CMAKE_C_LINKER_WRAPPER_FLAG}${CMAKE_LINK_LIBRARY_FLAG}`
51+
# as this ensures the uniqueness and thus avoids symbol de-duplication which means
52+
# libc will be followed by libgcc, which is finally followed by libc again.
53+
54+
list(JOIN CMAKE_C_LINKER_WRAPPER_FLAG "" linker_wrapper_string)
55+
3356
zephyr_link_libraries(
3457
m
35-
c
58+
"${linker_wrapper_string}${CMAKE_LINK_LIBRARY_FLAG}c"
3659
${LIBC_LIBRARY_DIR_FLAG} # NB: Optional
3760
$<$<BOOL:${CONFIG_NEWLIB_LIBC_FLOAT_PRINTF}>:-u_printf_float>
3861
$<$<BOOL:${CONFIG_NEWLIB_LIBC_FLOAT_SCANF}>:-u_scanf_float>
39-
gcc # Lib C depends on libgcc. e.g. libc.a(lib_a-fvwrite.o) references __aeabi_idiv
62+
# Lib C depends on libgcc. e.g. libc.a(lib_a-fvwrite.o) references __aeabi_idiv
63+
"${linker_wrapper_string}${CMAKE_LINK_LIBRARY_FLAG}gcc"
64+
c
4065
)
4166

4267
if(CONFIG_NEWLIB_LIBC_NANO)
@@ -47,4 +72,3 @@ if(CONFIG_NEWLIB_LIBC_NANO)
4772
-specs=nano.specs
4873
)
4974
endif()
50-

0 commit comments

Comments
 (0)