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    get_property(current_defines GLOBAL PROPERTY PROPERTY_LINKER_SCRIPT_DEFINES)
63
64    add_custom_command(
65      OUTPUT ${linker_script_gen}
66      DEPENDS
67      ${LINKER_SCRIPT}
68      ${AUTOCONF_H}
69      ${extra_dependencies}
70      # NB: 'linker_script_dep' will use a keyword that ends 'DEPENDS'
71      ${linker_script_dep}
72      COMMAND ${CMAKE_C_COMPILER}
73      -x assembler-with-cpp
74      ${NOSYSDEF_CFLAG}
75      -MD -MF ${linker_script_gen}.dep -MT ${linker_script_gen}
76      -D_LINKER
77      -D_ASMLANGUAGE
78      -imacros ${AUTOCONF_H}
79      ${current_includes}
80      ${current_defines}
81      ${template_script_defines}
82      -E ${LINKER_SCRIPT}
83      -P # Prevent generation of debug `#line' directives.
84      -o ${linker_script_gen}
85      VERBATIM
86      WORKING_DIRECTORY ${PROJECT_BINARY_DIR}
87      COMMAND_EXPAND_LISTS
88    )
89  endif()
90endmacro()
91
92# Force symbols to be entered in the output file as undefined symbols
93function(toolchain_ld_force_undefined_symbols)
94  foreach(symbol ${ARGN})
95    zephyr_link_libraries(${LINKERFLAGPREFIX},-u,${symbol})
96  endforeach()
97endfunction()
98
99# Link a target to given libraries with toolchain-specific argument order
100#
101# Usage:
102#   toolchain_ld_link_elf(
103#     TARGET_ELF             <target_elf>
104#     OUTPUT_MAP             <output_map_file_of_target>
105#     LIBRARIES_PRE_SCRIPT   [libraries_pre_script]
106#     LINKER_SCRIPT          <linker_script>
107#     LIBRARIES_POST_SCRIPT  [libraries_post_script]
108#     DEPENDENCIES           [dependencies]
109#   )
110function(toolchain_ld_link_elf)
111  cmake_parse_arguments(
112    TOOLCHAIN_LD_LINK_ELF                                     # prefix of output variables
113    ""                                                        # list of names of the boolean arguments
114    "TARGET_ELF;OUTPUT_MAP;LINKER_SCRIPT"                     # list of names of scalar arguments
115    "LIBRARIES_PRE_SCRIPT;LIBRARIES_POST_SCRIPT;DEPENDENCIES" # list of names of list arguments
116    ${ARGN}                                                   # input args to parse
117  )
118
119  target_link_libraries(
120    ${TOOLCHAIN_LD_LINK_ELF_TARGET_ELF}
121    ${TOOLCHAIN_LD_LINK_ELF_LIBRARIES_PRE_SCRIPT}
122    ${use_linker}
123    ${TOPT}
124    ${TOOLCHAIN_LD_LINK_ELF_LINKER_SCRIPT}
125    ${TOOLCHAIN_LD_LINK_ELF_LIBRARIES_POST_SCRIPT}
126
127    ${LINKERFLAGPREFIX},-Map=${TOOLCHAIN_LD_LINK_ELF_OUTPUT_MAP}
128    ${LINKERFLAGPREFIX},--whole-archive
129    ${ZEPHYR_LIBS_PROPERTY}
130    ${LINKERFLAGPREFIX},--no-whole-archive
131    kernel
132    $<TARGET_OBJECTS:${OFFSETS_LIB}>
133    ${LIB_INCLUDE_DIR}
134    -L${PROJECT_BINARY_DIR}
135    ${TOOLCHAIN_LIBS}
136
137    ${TOOLCHAIN_LD_LINK_ELF_DEPENDENCIES}
138  )
139endfunction(toolchain_ld_link_elf)
140
141# xt-ld is Xtensa's own version of binutils' ld.
142# So we can reuse most of the ld configurations.
143include(${ZEPHYR_BASE}/cmake/linker/${LINKER}/target_base.cmake)
144include(${ZEPHYR_BASE}/cmake/linker/ld/target_baremetal.cmake)
145include(${ZEPHYR_BASE}/cmake/linker/ld/target_cpp.cmake)
146include(${ZEPHYR_BASE}/cmake/linker/ld/target_relocation.cmake)
147include(${ZEPHYR_BASE}/cmake/linker/ld/target_configure.cmake)
148