diff --git a/CMakeLists.txt b/CMakeLists.txt index d01529f496d..c14f5f7f17a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2233,3 +2233,5 @@ add_subdirectory_ifdef( CONFIG_MAKEFILE_EXPORTS cmake/makefile_exports ) + +toolchain_linker_finalize() diff --git a/cmake/compiler/clang/target.cmake b/cmake/compiler/clang/target.cmake index 30e5da399af..d2d41e8b23c 100644 --- a/cmake/compiler/clang/target.cmake +++ b/cmake/compiler/clang/target.cmake @@ -76,8 +76,8 @@ if(NOT "${ARCH}" STREQUAL "posix") get_filename_component(RTLIB_NAME_WITH_PREFIX ${RTLIB_FILE_NAME} NAME_WLE) string(REPLACE lib "" RTLIB_NAME ${RTLIB_NAME_WITH_PREFIX}) - list(APPEND LIB_INCLUDE_DIR -L${RTLIB_DIR}) - list(APPEND TOOLCHAIN_LIBS ${RTLIB_NAME}) + set_property(TARGET linker PROPERTY lib_include_dir "-L${RTLIB_DIR}") + set_property(TARGET linker PROPERTY rt_library "-l${RTLIB_NAME}") list(APPEND CMAKE_REQUIRED_FLAGS -nostartfiles -nostdlib ${isystem_include_flags}) string(REPLACE ";" " " CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS}") diff --git a/cmake/compiler/gcc/target.cmake b/cmake/compiler/gcc/target.cmake index 5b1e5db1218..7e8ffc48173 100644 --- a/cmake/compiler/gcc/target.cmake +++ b/cmake/compiler/gcc/target.cmake @@ -109,8 +109,7 @@ get_filename_component(LIBGCC_DIR ${LIBGCC_FILE_NAME} DIRECTORY) assert_exists(LIBGCC_DIR) -LIST(APPEND LIB_INCLUDE_DIR "-L\"${LIBGCC_DIR}\"") -LIST(APPEND TOOLCHAIN_LIBS gcc) +set_linker_property(PROPERTY lib_include_dir "-L\"${LIBGCC_DIR}\"") # For CMake to be able to test if a compiler flag is supported by the # toolchain we need to give CMake the necessary flags to compile and diff --git a/cmake/linker/armlink/linker_flags.cmake b/cmake/linker/armlink/linker_flags.cmake deleted file mode 100644 index b0f93a7b9e7..00000000000 --- a/cmake/linker/armlink/linker_flags.cmake +++ /dev/null @@ -1,6 +0,0 @@ -# The ARMClang linker, armlink, requires a dedicated linking signature in -# order for Zephyr to control the map file. - -set(CMAKE_C_LINK_EXECUTABLE " -o ") -set(CMAKE_CXX_LINK_EXECUTABLE " -o ") -set(CMAKE_ASM_LINK_EXECUTABLE " -o ") diff --git a/cmake/linker/armlink/linker_libraries.cmake b/cmake/linker/armlink/linker_libraries.cmake new file mode 100644 index 00000000000..8374e7c3cd2 --- /dev/null +++ b/cmake/linker/armlink/linker_libraries.cmake @@ -0,0 +1,8 @@ +# Copyright (c) 2024 Nordic Semiconductor +# +# SPDX-License-Identifier: Apache-2.0 + +# Per default armclang (Arm Compiler 6) doesn't need explicit C library linking +# so we only need to set link order linking in case a custom C library is linked +# in, such as picolibc. +set_property(TARGET linker APPEND PROPERTY link_order_library "c;rt") diff --git a/cmake/linker/armlink/target.cmake b/cmake/linker/armlink/target.cmake index 9aa32ad0e6f..b2e1e867f90 100644 --- a/cmake/linker/armlink/target.cmake +++ b/cmake/linker/armlink/target.cmake @@ -108,5 +108,23 @@ function(toolchain_ld_link_elf) ) endfunction(toolchain_ld_link_elf) +# This function will generate the correct CMAKE_C_LINK_EXECUTABLE / CMAKE_CXX_LINK_EXECUTABLE +# rule to ensure that standard c and runtime libraries are correctly placed +# and the end of link invocation and doesn't appear in the middle of the link +# command invocation. +macro(toolchain_linker_finalize) + set(zephyr_std_libs) + get_property(link_order TARGET linker PROPERTY link_order_library) + foreach(lib ${link_order}) + get_property(link_flag TARGET linker PROPERTY ${lib}_library) + set(zephyr_std_libs "${zephyr_std_libs} ${link_flag}") + endforeach() + + set(common_link " ${zephyr_std_libs} -o ") + set(CMAKE_C_LINK_EXECUTABLE " ${common_link}") + set(CMAKE_CXX_LINK_EXECUTABLE " ${common_link}") + set(CMAKE_ASM_LINK_EXECUTABLE " ${common_link}") +endmacro() + include(${ZEPHYR_BASE}/cmake/linker/ld/target_relocation.cmake) include(${ZEPHYR_BASE}/cmake/linker/ld/target_configure.cmake) diff --git a/cmake/linker/ld/linker_flags.cmake b/cmake/linker/ld/linker_flags.cmake index 49bba260d3a..5063ddb46fb 100644 --- a/cmake/linker/ld/linker_flags.cmake +++ b/cmake/linker/ld/linker_flags.cmake @@ -7,10 +7,6 @@ check_set_linker_property(TARGET linker PROPERTY base ${LINKERFLAGPREFIX},--build-id=none ) -if(NOT CONFIG_MINIMAL_LIBCPP AND NOT CONFIG_NATIVE_LIBRARY AND NOT CONFIG_EXTERNAL_MODULE_LIBCPP) - set_property(TARGET linker PROPERTY cpp_base -lstdc++) -endif() - check_set_linker_property(TARGET linker PROPERTY baremetal -nostdlib -static diff --git a/cmake/linker/ld/linker_libraries.cmake b/cmake/linker/ld/linker_libraries.cmake new file mode 100644 index 00000000000..1305d682ab5 --- /dev/null +++ b/cmake/linker/ld/linker_libraries.cmake @@ -0,0 +1,38 @@ +# Copyright (c) 2024 Nordic Semiconductor +# +# SPDX-License-Identifier: Apache-2.0 + +# Do not specify default link libraries when targeting host (native build). +if(NOT CONFIG_NATIVE_BUILD) + set_linker_property(NO_CREATE PROPERTY c_library "-lc") + set_linker_property(NO_CREATE PROPERTY rt_library "-lgcc") + set_linker_property(NO_CREATE PROPERTY c++_library "-lstdc++") + set_linker_property(NO_CREATE PROPERTY math_library "-lm") + # Keeping default include dir empty. The linker will then select libraries + # from its default search path. The toolchain may adjust the value to a + # specific location, for example gcc infrastructure will set the value based + # on output from --print-libgcc-file-name. + set_linker_property(NO_CREATE PROPERTY lib_include_dir "") +endif() + +if(CONFIG_CPP + AND NOT CONFIG_MINIMAL_LIBCPP + AND NOT CONFIG_NATIVE_LIBRARY + # When new link principle is fully introduced, then the below condition can + # be removed, and instead the external module c++ should use: + # set_property(TARGET linker PROPERTY c++_library "") + AND NOT CONFIG_EXTERNAL_MODULE_LIBCPP +) + set_property(TARGET linker PROPERTY link_order_library "c++") +endif() + + +if(CONFIG_NEWLIB_LIBC AND CMAKE_C_COMPILER_ID STREQUAL "GNU") + # We are using c;rt;c (expands to '-lc -lgcc -lc') 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. + # Lib C depends on libgcc. e.g. libc.a(lib_a-fvwrite.o) references __aeabi_idiv + set_property(TARGET linker APPEND PROPERTY link_order_library "math;c;rt;c") +else() + set_property(TARGET linker APPEND PROPERTY link_order_library "c;rt") +endif() diff --git a/cmake/linker/ld/target.cmake b/cmake/linker/ld/target.cmake index ccf1493aa83..5e0a117c014 100644 --- a/cmake/linker/ld/target.cmake +++ b/cmake/linker/ld/target.cmake @@ -14,18 +14,6 @@ if((${CMAKE_LINKER} STREQUAL "${CROSS_COMPILE}ld.bfd") OR string(REPLACE ";" " " CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS}") endif() -if(NOT "${ZEPHYR_TOOLCHAIN_VARIANT}" STREQUAL "host") - if(CONFIG_CPP_EXCEPTIONS AND LIBGCC_DIR) - # When building with C++ Exceptions, it is important that crtbegin and crtend - # are linked at specific locations. - # The location is so important that we cannot let this be controlled by normal - # link libraries, instead we must control the link command specifically as - # part of toolchain. - set(CMAKE_CXX_LINK_EXECUTABLE - " ${LIBGCC_DIR}/crtbegin.o -o ${LIBGCC_DIR}/crtend.o") - endif() -endif() - # Run $LINKER_SCRIPT file through the C preprocessor, producing ${linker_script_gen} # NOTE: ${linker_script_gen} will be produced at build-time; not at configure-time macro(configure_linker_script linker_script_gen linker_pass_define) @@ -138,14 +126,44 @@ function(toolchain_ld_link_elf) ${LINKERFLAGPREFIX},--no-whole-archive ${NO_WHOLE_ARCHIVE_LIBS} $ - ${LIB_INCLUDE_DIR} -L${PROJECT_BINARY_DIR} - ${TOOLCHAIN_LIBS} ${TOOLCHAIN_LD_LINK_ELF_DEPENDENCIES} ) endfunction(toolchain_ld_link_elf) +# Function for finalizing link setup after Zephyr configuration has completed. +# +# This function will generate the correct CMAKE_C_LINK_EXECUTABLE / CMAKE_CXX_LINK_EXECUTABLE +# rule to ensure that standard c and runtime libraries are correctly placed +# and the end of link invocation and doesn't appear in the middle of the link +# command invocation. +macro(toolchain_linker_finalize) + get_property(zephyr_std_libs TARGET linker PROPERTY lib_include_dir) + get_property(link_order TARGET linker PROPERTY link_order_library) + foreach(lib ${link_order}) + get_property(link_flag TARGET linker PROPERTY ${lib}_library) + list(APPEND zephyr_std_libs "${link_flag}") + endforeach() + string(REPLACE ";" " " zephyr_std_libs "${zephyr_std_libs}") + + set(link_libraries " -o ${zephyr_std_libs}") + set(common_link " ${link_libraries}") + + set(CMAKE_ASM_LINK_EXECUTABLE " ${common_link}") + set(CMAKE_C_LINK_EXECUTABLE " ${common_link}") + + set(cpp_link "${common_link}") + if(NOT "${ZEPHYR_TOOLCHAIN_VARIANT}" STREQUAL "host") + if(CONFIG_CPP_EXCEPTIONS AND LIBGCC_DIR) + # When building with C++ Exceptions, it is important that crtbegin and crtend + # are linked at specific locations. + set(cpp_link " ${LIBGCC_DIR}/crtbegin.o ${link_libraries} ${LIBGCC_DIR}/crtend.o") + endif() + endif() + set(CMAKE_CXX_LINK_EXECUTABLE " ${cpp_link}") +endmacro() + # Load toolchain_ld-family macros include(${ZEPHYR_BASE}/cmake/linker/${LINKER}/target_relocation.cmake) include(${ZEPHYR_BASE}/cmake/linker/${LINKER}/target_configure.cmake) diff --git a/cmake/linker/linker_libraries_template.cmake b/cmake/linker/linker_libraries_template.cmake new file mode 100644 index 00000000000..481ee5c473e --- /dev/null +++ b/cmake/linker/linker_libraries_template.cmake @@ -0,0 +1,16 @@ +# Copyright (c) 2024 Nordic Semiconductor +# +# SPDX-License-Identifier: Apache-2.0 + +# Linker flags for fixed linking with standard libraries, such as the C and runtime libraries. +# It is the responsibility of the linker infrastructure to use those properties to specify the +# correct placement of those libraries for correct link order. +# For example, GCC usually has the order: -lc -lgcc +# It is also possible to define extra libraries of the form `_library`, and then include +# Fixed library search path can be defined in the `lib_include_dir` property if needed. +# in the link_order_property. +# Usage example: +# set_linker_property(PROPERTY lib_include_dir "-L/path/to/libs") +# set_linker_property(PROPERTY c_library "-lc") +# set_linker_property(PROPERTY rt_library "-lgcc") +# set_linker_property(PROPERTY link_order_library "c;rt") diff --git a/cmake/linker/lld/linker_flags.cmake b/cmake/linker/lld/linker_flags.cmake index f6e873ad631..f11139aa1e2 100644 --- a/cmake/linker/lld/linker_flags.cmake +++ b/cmake/linker/lld/linker_flags.cmake @@ -1,4 +1,6 @@ # Copyright (c) 2022 Google LLC +# Copyright (c) 2024 Nordic Semiconductor +# # SPDX-License-Identifier: Apache-2.0 # Since lld is a drop in replacement for ld, we can just use ld's flags as a base @@ -6,7 +8,7 @@ include(${ZEPHYR_BASE}/cmake/linker/ld/linker_flags.cmake OPTIONAL) if(NOT CONFIG_MINIMAL_LIBCPP AND NOT CONFIG_NATIVE_LIBRARY AND NOT CONFIG_EXTERNAL_MODULE_LIBCPP) - set_property(TARGET linker PROPERTY cpp_base -lc++ ${LINKERFLAGPREFIX},-z,norelro) + set_property(TARGET linker PROPERTY cpp_base ${LINKERFLAGPREFIX},-z,norelro) endif() # Force LLVM to use built-in lld linker diff --git a/cmake/linker/lld/linker_libraries.cmake b/cmake/linker/lld/linker_libraries.cmake new file mode 100644 index 00000000000..2347898ad64 --- /dev/null +++ b/cmake/linker/lld/linker_libraries.cmake @@ -0,0 +1,21 @@ +# Copyright (c) 2024 Nordic Semiconductor +# +# SPDX-License-Identifier: Apache-2.0 + +set_linker_property(NO_CREATE TARGET linker PROPERTY c_library "-lc") +# Default per standard, will be populated by clang/target.cmake based on clang output. +set_linker_property(NO_CREATE TARGET linker PROPERTY rt_library "") +set_linker_property(TARGET linker PROPERTY c++_library "-lc++;-lc++abi") + +if(CONFIG_CPP + AND NOT CONFIG_MINIMAL_LIBCPP + AND NOT CONFIG_NATIVE_LIBRARY + # When new link principle is fully introduced, then the below condition can + # be removed, and instead the external module c++ should use: + # set_property(TARGET linker PROPERTY c++_library "") + AND NOT CONFIG_EXTERNAL_MODULE_LIBCPP +) + set_property(TARGET linker PROPERTY link_order_library "c++") +endif() + +set_property(TARGET linker APPEND PROPERTY link_order_library "c;rt") diff --git a/cmake/linker/lld/target.cmake b/cmake/linker/lld/target.cmake index 9ce3313334f..b6b96525e70 100644 --- a/cmake/linker/lld/target.cmake +++ b/cmake/linker/lld/target.cmake @@ -101,14 +101,32 @@ function(toolchain_ld_link_elf) ${LINKERFLAGPREFIX},--no-whole-archive ${NO_WHOLE_ARCHIVE_LIBS} $ - ${LIB_INCLUDE_DIR} -L${PROJECT_BINARY_DIR} - ${TOOLCHAIN_LIBS} ${TOOLCHAIN_LD_LINK_ELF_DEPENDENCIES} ) endfunction(toolchain_ld_link_elf) +# Function for finalizing link setup after Zephyr configuration has completed. +# +# This function will generate the correct CMAKE_C_LINK_EXECUTABLE / CMAKE_CXX_LINK_EXECUTABLE +# signature to ensure that standard c and runtime libraries are correctly placed +# and the end of link invocation and doesn't appear in the middle of the link +# command invocation. +macro(toolchain_linker_finalize) + get_property(zephyr_std_libs TARGET linker PROPERTY lib_include_dir) + get_property(link_order TARGET linker PROPERTY link_order_library) + foreach(lib ${link_order}) + get_property(link_flag TARGET linker PROPERTY ${lib}_library) + list(APPEND zephyr_std_libs "${link_flag}") + endforeach() + string(REPLACE ";" " " zephyr_std_libs "${zephyr_std_libs}") + + set(common_link " -o ${zephyr_std_libs}") + set(CMAKE_ASM_LINK_EXECUTABLE " ${common_link}") + set(CMAKE_C_LINK_EXECUTABLE " ${common_link}") + set(CMAKE_CXX_LINK_EXECUTABLE " ${common_link}") +endmacro() # Load toolchain_ld-family macros include(${ZEPHYR_BASE}/cmake/linker/ld/target_relocation.cmake) diff --git a/cmake/linker/target_template.cmake b/cmake/linker/target_template.cmake new file mode 100644 index 00000000000..efa27de6fb4 --- /dev/null +++ b/cmake/linker/target_template.cmake @@ -0,0 +1,13 @@ +# SPDX-License-Identifier: Apache-2.0 +# +# Copyright (c) 2024, Nordic Semiconductor ASA + +# Template file for optional Zephyr linker macros. +# +# This file will define optional linker macros for toolchains that are not +# defining these macros themselves. + +if(NOT COMMAND toolchain_linker_finalize) + macro(toolchain_linker_finalize) + endmacro() +endif() diff --git a/cmake/linker/xt-ld/target.cmake b/cmake/linker/xt-ld/target.cmake index 4f8e4fcfbdb..3546881cc71 100644 --- a/cmake/linker/xt-ld/target.cmake +++ b/cmake/linker/xt-ld/target.cmake @@ -129,7 +129,6 @@ function(toolchain_ld_link_elf) ${LINKERFLAGPREFIX},--no-whole-archive ${NO_WHOLE_ARCHIVE_LIBS} $ - ${LIB_INCLUDE_DIR} -L${PROJECT_BINARY_DIR} ${TOOLCHAIN_LIBS} @@ -137,6 +136,27 @@ function(toolchain_ld_link_elf) ) endfunction(toolchain_ld_link_elf) +# Function for finalizing link setup after Zephyr configuration has completed. +# +# This function will generate the correct CMAKE_C_LINK_EXECUTABLE / CMAKE_CXX_LINK_EXECUTABLE +# rule to ensure that standard c and runtime libraries are correctly placed +# and the end of link invocation and doesn't appear in the middle of the link +# command invocation. +macro(toolchain_linker_finalize) + get_property(zephyr_std_libs TARGET linker PROPERTY lib_include_dir) + get_property(link_order TARGET linker PROPERTY link_order_library) + foreach(lib ${link_order}) + get_property(link_flag TARGET linker PROPERTY ${lib}_library) + list(APPEND zephyr_std_libs "${link_flag}") + endforeach() + string(REPLACE ";" " " zephyr_std_libs "${zephyr_std_libs}") + + set(common_link " -o ${zephyr_std_libs}") + set(CMAKE_ASM_LINK_EXECUTABLE " ${common_link}") + set(CMAKE_C_LINK_EXECUTABLE " ${common_link}") + set(CMAKE_CXX_LINK_EXECUTABLE " ${common_link}") +endmacro() + # xt-ld is Xtensa's own version of binutils' ld. # So we can reuse most of the ld configurations. include(${ZEPHYR_BASE}/cmake/linker/ld/target_relocation.cmake) diff --git a/cmake/modules/FindTargetTools.cmake b/cmake/modules/FindTargetTools.cmake index a1fa4bf5c67..e35f577d697 100644 --- a/cmake/modules/FindTargetTools.cmake +++ b/cmake/modules/FindTargetTools.cmake @@ -105,5 +105,7 @@ include(${TOOLCHAIN_ROOT}/cmake/linker/${LINKER}/target.cmake OPTIONAL) include(${ZEPHYR_BASE}/cmake/bintools/bintools_template.cmake) include(${TOOLCHAIN_ROOT}/cmake/bintools/${BINTOOLS}/target.cmake OPTIONAL) +include(${TOOLCHAIN_ROOT}/cmake/linker/target_template.cmake) + set(TargetTools_FOUND TRUE) set(TARGETTOOLS_FOUND TRUE) diff --git a/cmake/modules/extensions.cmake b/cmake/modules/extensions.cmake index 4d8422a3ced..8d38f1abf3a 100644 --- a/cmake/modules/extensions.cmake +++ b/cmake/modules/extensions.cmake @@ -2409,6 +2409,39 @@ function(toolchain_parse_make_rule input_file include_files) set(${include_files} ${result} PARENT_SCOPE) endfunction() +# 'set_linker_property' is a function that sets the property for the linker +# property target used for toolchain abstraction. +# +# This function is similar in nature to the CMake set_property function, but +# with some additional extension flags for improved behavioral control. +# +# NO_CREATE: Flag to indicate that the property should only be set if not already +# defined with a value. +# APPEND: Flag indicated that the property should be appended to the existing +# value list for the property. +# TARGET: Name of target on which to add the property (commonly: linker) +# PROPERTY: Name of property with the value(s) following immediately after +# property name +function(set_linker_property) + set(options APPEND NO_CREATE) + set(single_args TARGET) + set(multi_args PROPERTY) + cmake_parse_arguments(LINKER_PROPERTY "${options}" "${single_args}" "${multi_args}" ${ARGN}) + + if(LINKER_PROPERTY_APPEND) + set(APPEND "APPEND") + endif() + + if(LINKER_PROPERTY_NO_CREATE) + list(GET LINKER_PROPERTY_PROPERTY 0 property_name) + get_target_property(var ${LINKER_PROPERTY_TARGET} ${property_name}) + if(NOT "${var}" STREQUAL "var-NOTFOUND") + return() + endif() + endif() + set_property(TARGET ${LINKER_PROPERTY_TARGET} ${APPEND} PROPERTY ${LINKER_PROPERTY_PROPERTY}) +endfunction() + # 'check_set_linker_property' is a function that check the provided linker # flag and only set the linker property if the check succeeds # diff --git a/cmake/target_toolchain_flags.cmake b/cmake/target_toolchain_flags.cmake index 1df7e5eddc6..716cc8f55e7 100644 --- a/cmake/target_toolchain_flags.cmake +++ b/cmake/target_toolchain_flags.cmake @@ -35,8 +35,10 @@ include(${CMAKE_CURRENT_LIST_DIR}/compiler/compiler_features.cmake) # a new toolchain. include(${CMAKE_CURRENT_LIST_DIR}/compiler/compiler_flags_template.cmake) include(${CMAKE_CURRENT_LIST_DIR}/linker/linker_flags_template.cmake) +include(${CMAKE_CURRENT_LIST_DIR}/linker/linker_libraries_template.cmake) # Configure the toolchain flags based on what toolchain technology is used # (gcc, host-gcc etc.) include(${TOOLCHAIN_ROOT}/cmake/compiler/${COMPILER}/compiler_flags.cmake OPTIONAL) include(${TOOLCHAIN_ROOT}/cmake/linker/${LINKER}/linker_flags.cmake OPTIONAL) +include(${TOOLCHAIN_ROOT}/cmake/linker/${LINKER}/linker_libraries.cmake OPTIONAL) diff --git a/cmake/toolchain/llvm/generic.cmake b/cmake/toolchain/llvm/generic.cmake index 0b138c2868c..45474b7df30 100644 --- a/cmake/toolchain/llvm/generic.cmake +++ b/cmake/toolchain/llvm/generic.cmake @@ -19,4 +19,4 @@ set(BINTOOLS llvm) set(TOOLCHAIN_HAS_NEWLIB OFF CACHE BOOL "True if toolchain supports newlib") -message(STATUS "Found toolchain: host (clang/ld)") +message(STATUS "Found toolchain: llvm (clang/ld)") diff --git a/lib/libc/newlib/CMakeLists.txt b/lib/libc/newlib/CMakeLists.txt index de39b8ce213..d3dc448ecca 100644 --- a/lib/libc/newlib/CMakeLists.txt +++ b/lib/libc/newlib/CMakeLists.txt @@ -34,40 +34,12 @@ zephyr_compile_definitions(_ANSI_SOURCE) zephyr_compile_definitions(__LINUX_ERRNO_EXTENSIONS__) if(CMAKE_C_COMPILER_ID STREQUAL "GNU") - # 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( - m - "${linker_wrapper_string}${CMAKE_LINK_LIBRARY_FLAG}c" ${LIBC_LIBRARY_DIR_FLAG} # NB: Optional $<$:-u_printf_float> $<$:-u_scanf_float> - # Lib C depends on libgcc. e.g. libc.a(lib_a-fvwrite.o) references __aeabi_idiv - "${linker_wrapper_string}${CMAKE_LINK_LIBRARY_FLAG}gcc" ) endif() -zephyr_link_libraries(c) if(CONFIG_NEWLIB_LIBC_NANO) zephyr_link_libraries( diff --git a/lib/libc/picolibc/CMakeLists.txt b/lib/libc/picolibc/CMakeLists.txt index 87fb0d9d8ec..fcb4f9f2b57 100644 --- a/lib/libc/picolibc/CMakeLists.txt +++ b/lib/libc/picolibc/CMakeLists.txt @@ -17,7 +17,7 @@ if(NOT CONFIG_PICOLIBC_USE_MODULE) # Zephyr build (via the __ZEPHYR__ macro) to expose the Zephyr C API zephyr_compile_options(--specs=picolibc.specs) - zephyr_libc_link_libraries(--specs=picolibc.specs c -lgcc) + zephyr_libc_link_libraries(--specs=picolibc.specs) if(CONFIG_PICOLIBC_IO_FLOAT) zephyr_compile_definitions(PICOLIBC_DOUBLE_PRINTF_SCANF) zephyr_link_libraries(-DPICOLIBC_DOUBLE_PRINTF_SCANF)