1# SPDX-License-Identifier: Apache-2.0
2set_property(TARGET linker PROPERTY devices_start_symbol "_device_list_start")
3
4if(DEFINED TOOLCHAIN_HOME)
5  # When Toolchain home is defined, then we are cross-compiling, so only look
6  # for linker in that path, else we are using host tools.
7  set(LD_SEARCH_PATH PATHS ${TOOLCHAIN_HOME} NO_DEFAULT_PATH)
8endif()
9
10find_program(CMAKE_LINKER xt-ld ${LD_SEARCH_PATH})
11
12set_ifndef(LINKERFLAGPREFIX -Wl)
13
14if(CONFIG_CPP_EXCEPTIONS)
15  # When building with C++ Exceptions, it is important that crtbegin and crtend
16  # are linked at specific locations.
17  # The location is so important that we cannot let this be controlled by normal
18  # link libraries, instead we must control the link command specifically as
19  # part of toolchain.
20  set(CMAKE_CXX_LINK_EXECUTABLE
21      "<CMAKE_CXX_COMPILER> <FLAGS> <CMAKE_CXX_LINK_FLAGS> <LINK_FLAGS> ${LIBGCC_DIR}/crtbegin.o <OBJECTS> -o <TARGET> <LINK_LIBRARIES> ${LIBGCC_DIR}/crtend.o")
22endif()
23
24# Run $LINKER_SCRIPT file through the C preprocessor, producing ${linker_script_gen}
25# NOTE: ${linker_script_gen} will be produced at build-time; not at configure-time
26macro(configure_linker_script linker_script_gen linker_pass_define)
27  set(extra_dependencies ${ARGN})
28
29  if(CONFIG_CMAKE_LINKER_GENERATOR)
30    add_custom_command(
31      OUTPUT ${linker_script_gen}
32      COMMAND ${CMAKE_COMMAND}
33        -DPASS="${linker_pass_define}"
34        -DFORMAT="$<TARGET_PROPERTY:linker,FORMAT>"
35        -DENTRY="$<TARGET_PROPERTY:linker,ENTRY>"
36        -DMEMORY_REGIONS="$<TARGET_PROPERTY:linker,MEMORY_REGIONS>"
37        -DGROUPS="$<TARGET_PROPERTY:linker,GROUPS>"
38        -DSECTIONS="$<TARGET_PROPERTY:linker,SECTIONS>"
39        -DSECTION_SETTINGS="$<TARGET_PROPERTY:linker,SECTION_SETTINGS>"
40        -DSYMBOLS="$<TARGET_PROPERTY:linker,SYMBOLS>"
41        -DOUT_FILE=${CMAKE_CURRENT_BINARY_DIR}/${linker_script_gen}
42        -P ${ZEPHYR_BASE}/cmake/linker/ld/ld_script.cmake
43      )
44  else()
45    set(template_script_defines ${linker_pass_define})
46    list(TRANSFORM template_script_defines PREPEND "-D")
47
48    # Only Ninja and Makefile generators support DEPFILE.
49    if((CMAKE_GENERATOR STREQUAL "Ninja")
50       OR (CMAKE_GENERATOR MATCHES "Makefiles")
51    )
52      set(linker_script_dep DEPFILE ${PROJECT_BINARY_DIR}/${linker_script_gen}.dep)
53    else()
54      # TODO: How would the linker script dependencies work for non-linker
55      # script generators.
56      message(STATUS "Warning; this generator is not well supported. The
57    Linker script may not be regenerated when it should.")
58      set(linker_script_dep "")
59    endif()
60
61    zephyr_get_include_directories_for_lang(C current_includes)
62
63    add_custom_command(
64      OUTPUT ${linker_script_gen}
65      DEPENDS
66      ${LINKER_SCRIPT}
67      ${AUTOCONF_H}
68      ${extra_dependencies}
69      # NB: 'linker_script_dep' will use a keyword that ends 'DEPENDS'
70      ${linker_script_dep}
71      COMMAND ${CMAKE_C_COMPILER}
72      -x assembler-with-cpp
73      ${NOSYSDEF_CFLAG}
74      -MD -MF ${linker_script_gen}.dep -MT ${linker_script_gen}
75      -D_LINKER
76      -D_ASMLANGUAGE
77      -D__GCC_LINKER_CMD__
78      -imacros ${AUTOCONF_H}
79      ${current_includes}
80      ${template_script_defines}
81      -E ${LINKER_SCRIPT}
82      -P # Prevent generation of debug `#line' directives.
83      -o ${linker_script_gen}
84      VERBATIM
85      WORKING_DIRECTORY ${PROJECT_BINARY_DIR}
86      COMMAND_EXPAND_LISTS
87    )
88  endif()
89endmacro()
90
91# Force symbols to be entered in the output file as undefined symbols
92function(toolchain_ld_force_undefined_symbols)
93  foreach(symbol ${ARGN})
94    zephyr_link_libraries(${LINKERFLAGPREFIX},-u,${symbol})
95  endforeach()
96endfunction()
97
98# Link a target to given libraries with toolchain-specific argument order
99#
100# Usage:
101#   toolchain_ld_link_elf(
102#     TARGET_ELF             <target_elf>
103#     OUTPUT_MAP             <output_map_file_of_target>
104#     LIBRARIES_PRE_SCRIPT   [libraries_pre_script]
105#     LINKER_SCRIPT          <linker_script>
106#     LIBRARIES_POST_SCRIPT  [libraries_post_script]
107#     DEPENDENCIES           [dependencies]
108#   )
109function(toolchain_ld_link_elf)
110  cmake_parse_arguments(
111    TOOLCHAIN_LD_LINK_ELF                                     # prefix of output variables
112    ""                                                        # list of names of the boolean arguments
113    "TARGET_ELF;OUTPUT_MAP;LINKER_SCRIPT"                     # list of names of scalar arguments
114    "LIBRARIES_PRE_SCRIPT;LIBRARIES_POST_SCRIPT;DEPENDENCIES" # list of names of list arguments
115    ${ARGN}                                                   # input args to parse
116  )
117
118  target_link_libraries(
119    ${TOOLCHAIN_LD_LINK_ELF_TARGET_ELF}
120    ${TOOLCHAIN_LD_LINK_ELF_LIBRARIES_PRE_SCRIPT}
121    ${use_linker}
122    ${TOPT}
123    ${TOOLCHAIN_LD_LINK_ELF_LINKER_SCRIPT}
124    ${TOOLCHAIN_LD_LINK_ELF_LIBRARIES_POST_SCRIPT}
125
126    ${LINKERFLAGPREFIX},-Map=${TOOLCHAIN_LD_LINK_ELF_OUTPUT_MAP}
127    ${LINKERFLAGPREFIX},--whole-archive
128    ${WHOLE_ARCHIVE_LIBS}
129    ${LINKERFLAGPREFIX},--no-whole-archive
130    ${NO_WHOLE_ARCHIVE_LIBS}
131    $<TARGET_OBJECTS:${OFFSETS_LIB}>
132    -L${PROJECT_BINARY_DIR}
133
134    ${TOOLCHAIN_LD_LINK_ELF_DEPENDENCIES}
135  )
136endfunction(toolchain_ld_link_elf)
137
138# Function for finalizing link setup after Zephyr configuration has completed.
139#
140# This function will generate the correct CMAKE_C_LINK_EXECUTABLE / CMAKE_CXX_LINK_EXECUTABLE
141# rule to ensure that standard c and runtime libraries are correctly placed
142# and the end of link invocation and doesn't appear in the middle of the link
143# command invocation.
144macro(toolchain_linker_finalize)
145  get_property(zephyr_std_libs TARGET linker PROPERTY lib_include_dir)
146  get_property(link_order TARGET linker PROPERTY link_order_library)
147  foreach(lib ${link_order})
148    get_property(link_flag TARGET linker PROPERTY ${lib}_library)
149    list(APPEND zephyr_std_libs "${link_flag}")
150  endforeach()
151  string(REPLACE ";" " " zephyr_std_libs "${zephyr_std_libs}")
152
153 set(common_link "<LINK_FLAGS> <OBJECTS> -o <TARGET> <LINK_LIBRARIES> ${zephyr_std_libs}")
154 set(CMAKE_ASM_LINK_EXECUTABLE "<CMAKE_ASM_COMPILER> <FLAGS> <CMAKE_ASM_LINK_FLAGS> ${common_link}")
155 set(CMAKE_C_LINK_EXECUTABLE   "<CMAKE_C_COMPILER> <FLAGS> <CMAKE_C_LINK_FLAGS> ${common_link}")
156 set(CMAKE_CXX_LINK_EXECUTABLE "<CMAKE_CXX_COMPILER> <FLAGS> <CMAKE_CXX_LINK_FLAGS> ${common_link}")
157endmacro()
158
159# xt-ld is Xtensa's own version of binutils' ld.
160# So we can reuse most of the ld configurations.
161include(${ZEPHYR_BASE}/cmake/linker/ld/target_relocation.cmake)
162include(${ZEPHYR_BASE}/cmake/linker/ld/target_configure.cmake)
163