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