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