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