1# SPDX-License-Identifier: Apache-2.0 2set_property(TARGET linker PROPERTY devices_start_symbol "_device_list_start") 3 4find_package(GnuLd REQUIRED) 5set(CMAKE_LINKER ${GNULD_LINKER}) 6 7set_ifndef(LINKERFLAGPREFIX -Wl) 8 9if(NOT "${ZEPHYR_TOOLCHAIN_VARIANT}" STREQUAL "host") 10 if(CONFIG_CPP_EXCEPTIONS AND LIBGCC_DIR) 11 # When building with C++ Exceptions, it is important that crtbegin and crtend 12 # are linked at specific locations. 13 # The location is so important that we cannot let this be controlled by normal 14 # link libraries, instead we must control the link command specifically as 15 # part of toolchain. 16 set(CMAKE_CXX_LINK_EXECUTABLE 17 "<CMAKE_CXX_COMPILER> <FLAGS> <CMAKE_CXX_LINK_FLAGS> <LINK_FLAGS> ${LIBGCC_DIR}/crtbegin.o <OBJECTS> -o <TARGET> <LINK_LIBRARIES> ${LIBGCC_DIR}/crtend.o") 18 endif() 19endif() 20 21# Run $LINKER_SCRIPT file through the C preprocessor, producing ${linker_script_gen} 22# NOTE: ${linker_script_gen} will be produced at build-time; not at configure-time 23macro(configure_linker_script linker_script_gen linker_pass_define) 24 set(extra_dependencies ${ARGN}) 25 26 if(CONFIG_CMAKE_LINKER_GENERATOR) 27 add_custom_command( 28 OUTPUT ${linker_script_gen} 29 COMMAND ${CMAKE_COMMAND} 30 -DPASS="${linker_pass_define}" 31 -DFORMAT="$<TARGET_PROPERTY:linker,FORMAT>" 32 -DENTRY="$<TARGET_PROPERTY:linker,ENTRY>" 33 -DMEMORY_REGIONS="$<TARGET_PROPERTY:linker,MEMORY_REGIONS>" 34 -DGROUPS="$<TARGET_PROPERTY:linker,GROUPS>" 35 -DSECTIONS="$<TARGET_PROPERTY:linker,SECTIONS>" 36 -DSECTION_SETTINGS="$<TARGET_PROPERTY:linker,SECTION_SETTINGS>" 37 -DSYMBOLS="$<TARGET_PROPERTY:linker,SYMBOLS>" 38 -DOUT_FILE=${CMAKE_CURRENT_BINARY_DIR}/${linker_script_gen} 39 -P ${ZEPHYR_BASE}/cmake/linker/ld/ld_script.cmake 40 ) 41 else() 42 set(template_script_defines ${linker_pass_define}) 43 list(TRANSFORM template_script_defines PREPEND "-D") 44 45 # Only Ninja and Makefile generators support DEPFILE. 46 if((CMAKE_GENERATOR STREQUAL "Ninja") 47 OR (CMAKE_GENERATOR MATCHES "Makefiles") 48 ) 49 set(linker_script_dep DEPFILE ${PROJECT_BINARY_DIR}/${linker_script_gen}.dep) 50 else() 51 # TODO: How would the linker script dependencies work for non-linker 52 # script generators. 53 message(STATUS "Warning; this generator is not well supported. The 54 Linker script may not be regenerated when it should.") 55 set(linker_script_dep "") 56 endif() 57 58 zephyr_get_include_directories_for_lang(C current_includes) 59 get_property(current_defines GLOBAL PROPERTY PROPERTY_LINKER_SCRIPT_DEFINES) 60 if(DEFINED SOC_LINKER_SCRIPT) 61 cmake_path(GET SOC_LINKER_SCRIPT PARENT_PATH soc_linker_script_includes) 62 set(soc_linker_script_includes -I${soc_linker_script_includes}) 63 endif() 64 65 add_custom_command( 66 OUTPUT ${linker_script_gen} 67 DEPENDS 68 ${LINKER_SCRIPT} 69 ${AUTOCONF_H} 70 ${extra_dependencies} 71 # NB: 'linker_script_dep' will use a keyword that ends 'DEPENDS' 72 ${linker_script_dep} 73 COMMAND ${CMAKE_C_COMPILER} 74 -x assembler-with-cpp 75 ${NOSYSDEF_CFLAG} 76 -MD -MF ${linker_script_gen}.dep -MT ${linker_script_gen} 77 -D_LINKER 78 -D_ASMLANGUAGE 79 -imacros ${AUTOCONF_H} 80 ${current_includes} 81 ${soc_linker_script_includes} 82 ${current_defines} 83 ${template_script_defines} 84 -E ${LINKER_SCRIPT} 85 -P # Prevent generation of debug `#line' directives. 86 -o ${linker_script_gen} 87 VERBATIM 88 WORKING_DIRECTORY ${PROJECT_BINARY_DIR} 89 COMMAND_EXPAND_LISTS 90 ) 91 endif() 92endmacro() 93 94# Force symbols to be entered in the output file as undefined symbols 95function(toolchain_ld_force_undefined_symbols) 96 foreach(symbol ${ARGN}) 97 zephyr_link_libraries(${LINKERFLAGPREFIX},-u,${symbol}) 98 endforeach() 99endfunction() 100 101# Link a target to given libraries with toolchain-specific argument order 102# 103# Usage: 104# toolchain_ld_link_elf( 105# TARGET_ELF <target_elf> 106# OUTPUT_MAP <output_map_file_of_target> 107# LIBRARIES_PRE_SCRIPT [libraries_pre_script] 108# LINKER_SCRIPT <linker_script> 109# LIBRARIES_POST_SCRIPT [libraries_post_script] 110# DEPENDENCIES [dependencies] 111# ) 112function(toolchain_ld_link_elf) 113 cmake_parse_arguments( 114 TOOLCHAIN_LD_LINK_ELF # prefix of output variables 115 "" # list of names of the boolean arguments 116 "TARGET_ELF;OUTPUT_MAP;LINKER_SCRIPT" # list of names of scalar arguments 117 "LIBRARIES_PRE_SCRIPT;LIBRARIES_POST_SCRIPT;DEPENDENCIES" # list of names of list arguments 118 ${ARGN} # input args to parse 119 ) 120 121 if((${CMAKE_LINKER} STREQUAL "${CROSS_COMPILE}ld.bfd") OR 122 ${GNULD_LINKER_IS_BFD}) 123 # ld.bfd was found so let's explicitly use that for linking, see #32237 124 set(use_linker "-fuse-ld=bfd") 125 endif() 126 127 target_link_libraries( 128 ${TOOLCHAIN_LD_LINK_ELF_TARGET_ELF} 129 ${TOOLCHAIN_LD_LINK_ELF_LIBRARIES_PRE_SCRIPT} 130 ${use_linker} 131 ${TOPT} 132 ${TOOLCHAIN_LD_LINK_ELF_LINKER_SCRIPT} 133 ${TOOLCHAIN_LD_LINK_ELF_LIBRARIES_POST_SCRIPT} 134 135 ${LINKERFLAGPREFIX},-Map=${TOOLCHAIN_LD_LINK_ELF_OUTPUT_MAP} 136 ${LINKERFLAGPREFIX},--whole-archive 137 ${WHOLE_ARCHIVE_LIBS} 138 ${LINKERFLAGPREFIX},--no-whole-archive 139 ${NO_WHOLE_ARCHIVE_LIBS} 140 $<TARGET_OBJECTS:${OFFSETS_LIB}> 141 ${LIB_INCLUDE_DIR} 142 -L${PROJECT_BINARY_DIR} 143 ${TOOLCHAIN_LIBS} 144 145 ${TOOLCHAIN_LD_LINK_ELF_DEPENDENCIES} 146 ) 147endfunction(toolchain_ld_link_elf) 148 149# Load toolchain_ld-family macros 150include(${ZEPHYR_BASE}/cmake/linker/${LINKER}/target_base.cmake) 151include(${ZEPHYR_BASE}/cmake/linker/${LINKER}/target_baremetal.cmake) 152include(${ZEPHYR_BASE}/cmake/linker/${LINKER}/target_cpp.cmake) 153include(${ZEPHYR_BASE}/cmake/linker/${LINKER}/target_relocation.cmake) 154include(${ZEPHYR_BASE}/cmake/linker/${LINKER}/target_configure.cmake) 155