cmake: improve Zephyr link phase
Zephyr is a bare metal build where standard libs are disabled. This means that c and runtime libraries must manually be linked in. This has generally been handled by using CMake's link libraries handling but the issue with that is both de-duplication but also library link order. Standard libraries must be linked at last location to ensure symbols are always available, however this is not optimal with target_link_libraries() because this would ultimately require every library to know the c library to link with, which is not desired. Therefore, setup standard C and runtime library linking in linker CMake files for toolchains where this is required. This commit expands the principle introduced with toolchain abstraction, see PR#24851. This means that a toolchain implementation may specify standard C, runtime, C++, etc libraries, as well as their link order. Because a property approach is used, then Zephyr modules, such as the Picolibc module can adjust such properties. An optional `zephyr_linker_finalize()` macro is called at the end of Zephyr's CMakeList process and can be used by the toolchain implementation to define the final linker invocation. This aligns the linker handling flow to the principle introduced in PR#24851 and improves the flexibility and robustness of Zephyr build system. Signed-off-by: Torsten Rasmussen <Torsten.Rasmussen@nordicsemi.no>
This commit is contained in:
parent
9fe6c5e3fb
commit
2e3873adde
21 changed files with 234 additions and 62 deletions
|
@ -2233,3 +2233,5 @@ add_subdirectory_ifdef(
|
|||
CONFIG_MAKEFILE_EXPORTS
|
||||
cmake/makefile_exports
|
||||
)
|
||||
|
||||
toolchain_linker_finalize()
|
||||
|
|
|
@ -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}")
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 "<CMAKE_LINKER> <CMAKE_C_LINK_FLAGS> <LINK_FLAGS> <LINK_LIBRARIES> <OBJECTS> -o <TARGET>")
|
||||
set(CMAKE_CXX_LINK_EXECUTABLE "<CMAKE_LINKER> <CMAKE_CXX_LINK_FLAGS> <LINK_FLAGS> <LINK_LIBRARIES> <OBJECTS> -o <TARGET>")
|
||||
set(CMAKE_ASM_LINK_EXECUTABLE "<CMAKE_LINKER> <CMAKE_ASM_LINK_FLAGS> <LINK_FLAGS> <LINK_LIBRARIES> <OBJECTS> -o <TARGET>")
|
8
cmake/linker/armlink/linker_libraries.cmake
Normal file
8
cmake/linker/armlink/linker_libraries.cmake
Normal file
|
@ -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")
|
|
@ -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 "<LINK_FLAGS> <LINK_LIBRARIES> <OBJECTS> ${zephyr_std_libs} -o <TARGET>")
|
||||
set(CMAKE_C_LINK_EXECUTABLE "<CMAKE_LINKER> <CMAKE_C_LINK_FLAGS> ${common_link}")
|
||||
set(CMAKE_CXX_LINK_EXECUTABLE "<CMAKE_LINKER> <CMAKE_CXX_LINK_FLAGS> ${common_link}")
|
||||
set(CMAKE_ASM_LINK_EXECUTABLE "<CMAKE_LINKER> <CMAKE_ASM_LINK_FLAGS> ${common_link}")
|
||||
endmacro()
|
||||
|
||||
include(${ZEPHYR_BASE}/cmake/linker/ld/target_relocation.cmake)
|
||||
include(${ZEPHYR_BASE}/cmake/linker/ld/target_configure.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
|
||||
|
|
38
cmake/linker/ld/linker_libraries.cmake
Normal file
38
cmake/linker/ld/linker_libraries.cmake
Normal file
|
@ -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 "<external_c++_lib>")
|
||||
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()
|
|
@ -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
|
||||
"<CMAKE_CXX_COMPILER> <FLAGS> <CMAKE_CXX_LINK_FLAGS> <LINK_FLAGS> ${LIBGCC_DIR}/crtbegin.o <OBJECTS> -o <TARGET> <LINK_LIBRARIES> ${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}
|
||||
$<TARGET_OBJECTS:${OFFSETS_LIB}>
|
||||
${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 "<LINK_FLAGS> <OBJECTS> -o <TARGET> <LINK_LIBRARIES> ${zephyr_std_libs}")
|
||||
set(common_link "<LINK_FLAGS> ${link_libraries}")
|
||||
|
||||
set(CMAKE_ASM_LINK_EXECUTABLE "<CMAKE_ASM_COMPILER> <FLAGS> <CMAKE_ASM_LINK_FLAGS> ${common_link}")
|
||||
set(CMAKE_C_LINK_EXECUTABLE "<CMAKE_C_COMPILER> <FLAGS> <CMAKE_C_LINK_FLAGS> ${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 "<LINK_FLAGS> ${LIBGCC_DIR}/crtbegin.o ${link_libraries} ${LIBGCC_DIR}/crtend.o")
|
||||
endif()
|
||||
endif()
|
||||
set(CMAKE_CXX_LINK_EXECUTABLE "<CMAKE_CXX_COMPILER> <FLAGS> <CMAKE_CXX_LINK_FLAGS> ${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)
|
||||
|
|
16
cmake/linker/linker_libraries_template.cmake
Normal file
16
cmake/linker/linker_libraries_template.cmake
Normal file
|
@ -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 `<name>_library`, and then include
|
||||
# Fixed library search path can be defined in the `lib_include_dir` property if needed.
|
||||
# <name> 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")
|
|
@ -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
|
||||
|
|
21
cmake/linker/lld/linker_libraries.cmake
Normal file
21
cmake/linker/lld/linker_libraries.cmake
Normal file
|
@ -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 "<external_c++_lib>")
|
||||
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")
|
|
@ -101,14 +101,32 @@ function(toolchain_ld_link_elf)
|
|||
${LINKERFLAGPREFIX},--no-whole-archive
|
||||
${NO_WHOLE_ARCHIVE_LIBS}
|
||||
$<TARGET_OBJECTS:${OFFSETS_LIB}>
|
||||
${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 "<LINK_FLAGS> <OBJECTS> -o <TARGET> <LINK_LIBRARIES> ${zephyr_std_libs}")
|
||||
set(CMAKE_ASM_LINK_EXECUTABLE "<CMAKE_ASM_COMPILER> <FLAGS> <CMAKE_ASM_LINK_FLAGS> ${common_link}")
|
||||
set(CMAKE_C_LINK_EXECUTABLE "<CMAKE_C_COMPILER> <FLAGS> <CMAKE_C_LINK_FLAGS> ${common_link}")
|
||||
set(CMAKE_CXX_LINK_EXECUTABLE "<CMAKE_CXX_COMPILER> <FLAGS> <CMAKE_CXX_LINK_FLAGS> ${common_link}")
|
||||
endmacro()
|
||||
|
||||
# Load toolchain_ld-family macros
|
||||
include(${ZEPHYR_BASE}/cmake/linker/ld/target_relocation.cmake)
|
||||
|
|
13
cmake/linker/target_template.cmake
Normal file
13
cmake/linker/target_template.cmake
Normal file
|
@ -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()
|
|
@ -129,7 +129,6 @@ function(toolchain_ld_link_elf)
|
|||
${LINKERFLAGPREFIX},--no-whole-archive
|
||||
${NO_WHOLE_ARCHIVE_LIBS}
|
||||
$<TARGET_OBJECTS:${OFFSETS_LIB}>
|
||||
${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 "<LINK_FLAGS> <OBJECTS> -o <TARGET> <LINK_LIBRARIES> ${zephyr_std_libs}")
|
||||
set(CMAKE_ASM_LINK_EXECUTABLE "<CMAKE_ASM_COMPILER> <FLAGS> <CMAKE_ASM_LINK_FLAGS> ${common_link}")
|
||||
set(CMAKE_C_LINK_EXECUTABLE "<CMAKE_C_COMPILER> <FLAGS> <CMAKE_C_LINK_FLAGS> ${common_link}")
|
||||
set(CMAKE_CXX_LINK_EXECUTABLE "<CMAKE_CXX_COMPILER> <FLAGS> <CMAKE_CXX_LINK_FLAGS> ${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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
#
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)")
|
||||
|
|
|
@ -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
|
||||
$<$<BOOL:${CONFIG_NEWLIB_LIBC_FLOAT_PRINTF}>:-u_printf_float>
|
||||
$<$<BOOL:${CONFIG_NEWLIB_LIBC_FLOAT_SCANF}>:-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(
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue