1# SPDX-License-Identifier: Apache-2.0
2set_property(TARGET linker PROPERTY devices_start_symbol "__device_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 ${CROSS_COMPILE}ld.bfd ${LD_SEARCH_PATH})
11if(NOT CMAKE_LINKER)
12  find_program(CMAKE_LINKER ${CROSS_COMPILE}ld ${LD_SEARCH_PATH})
13endif()
14
15set_ifndef(LINKERFLAGPREFIX -Wl)
16
17if(NOT "${ZEPHYR_TOOLCHAIN_VARIANT}" STREQUAL "host")
18  if(CONFIG_EXCEPTIONS)
19    # When building with C++ Exceptions, it is important that crtbegin and crtend
20    # are linked at specific locations.
21    # The location is so important that we cannot let this be controlled by normal
22    # link libraries, instead we must control the link command specifically as
23    # part of toolchain.
24    set(CMAKE_CXX_LINK_EXECUTABLE
25        "<CMAKE_CXX_COMPILER> <FLAGS> <CMAKE_CXX_LINK_FLAGS> <LINK_FLAGS> ${LIBGCC_DIR}/crtbegin.o <OBJECTS> -o <TARGET> <LINK_LIBRARIES> ${LIBGCC_DIR}/crtend.o")
26  endif()
27endif()
28
29# Run $LINKER_SCRIPT file through the C preprocessor, producing ${linker_script_gen}
30# NOTE: ${linker_script_gen} will be produced at build-time; not at configure-time
31macro(configure_linker_script linker_script_gen linker_pass_define)
32  set(extra_dependencies ${ARGN})
33
34  if(CONFIG_CMAKE_LINKER_GENERATOR)
35    if("${linker_pass_define}" STREQUAL "-DLINKER_ZEPHYR_PREBUILT")
36      set(PASS 1)
37    elseif("${linker_pass_define}" STREQUAL "-DLINKER_ZEPHYR_FINAL;-DLINKER_PASS2")
38      set(PASS 2)
39    endif()
40
41    add_custom_command(
42      OUTPUT ${linker_script_gen}
43      COMMAND ${CMAKE_COMMAND}
44        -DPASS=${PASS}
45        -DFORMAT="$<TARGET_PROPERTY:linker,FORMAT>"
46        -DENTRY="$<TARGET_PROPERTY:linker,ENTRY>"
47        -DMEMORY_REGIONS="$<TARGET_PROPERTY:linker,MEMORY_REGIONS>"
48        -DGROUPS="$<TARGET_PROPERTY:linker,GROUPS>"
49        -DSECTIONS="$<TARGET_PROPERTY:linker,SECTIONS>"
50        -DSECTION_SETTINGS="$<TARGET_PROPERTY:linker,SECTION_SETTINGS>"
51        -DSYMBOLS="$<TARGET_PROPERTY:linker,SYMBOLS>"
52        -DOUT_FILE=${CMAKE_CURRENT_BINARY_DIR}/${linker_script_gen}
53        -P ${ZEPHYR_BASE}/cmake/linker/ld/ld_script.cmake
54      )
55  else()
56    # Different generators deal with depfiles differently.
57    if(CMAKE_GENERATOR STREQUAL "Unix Makefiles")
58      # Note that the IMPLICIT_DEPENDS option is currently supported only
59      # for Makefile generators and will be ignored by other generators.
60      set(linker_script_dep IMPLICIT_DEPENDS C ${LINKER_SCRIPT})
61    elseif(CMAKE_GENERATOR STREQUAL "Ninja")
62      # Using DEPFILE with other generators than Ninja is an error.
63      set(linker_script_dep DEPFILE ${PROJECT_BINARY_DIR}/${linker_script_gen}.dep)
64    else()
65      # TODO: How would the linker script dependencies work for non-linker
66      # script generators.
67      message(STATUS "Warning; this generator is not well supported. The
68    Linker script may not be regenerated when it should.")
69      set(linker_script_dep "")
70    endif()
71
72    zephyr_get_include_directories_for_lang(C current_includes)
73    get_filename_component(base_name ${CMAKE_CURRENT_BINARY_DIR} NAME)
74    get_property(current_defines GLOBAL PROPERTY PROPERTY_LINKER_SCRIPT_DEFINES)
75
76    add_custom_command(
77      OUTPUT ${linker_script_gen}
78      DEPENDS
79      ${LINKER_SCRIPT}
80      ${AUTOCONF_H}
81      ${extra_dependencies}
82      # NB: 'linker_script_dep' will use a keyword that ends 'DEPENDS'
83      ${linker_script_dep}
84      COMMAND ${CMAKE_C_COMPILER}
85      -x assembler-with-cpp
86      ${NOSYSDEF_CFLAG}
87      -MD -MF ${linker_script_gen}.dep -MT ${base_name}/${linker_script_gen}
88      -D_LINKER
89      -D_ASMLANGUAGE
90      -imacros ${AUTOCONF_H}
91      ${current_includes}
92      ${current_defines}
93      ${linker_pass_define}
94      -E ${LINKER_SCRIPT}
95      -P # Prevent generation of debug `#line' directives.
96      -o ${linker_script_gen}
97      VERBATIM
98      WORKING_DIRECTORY ${PROJECT_BINARY_DIR}
99      COMMAND_EXPAND_LISTS
100    )
101  endif()
102endmacro()
103
104# Force symbols to be entered in the output file as undefined symbols
105function(toolchain_ld_force_undefined_symbols)
106  foreach(symbol ${ARGN})
107    zephyr_link_libraries(${LINKERFLAGPREFIX},-u,${symbol})
108  endforeach()
109endfunction()
110
111# Link a target to given libraries with toolchain-specific argument order
112#
113# Usage:
114#   toolchain_ld_link_elf(
115#     TARGET_ELF             <target_elf>
116#     OUTPUT_MAP             <output_map_file_of_target>
117#     LIBRARIES_PRE_SCRIPT   [libraries_pre_script]
118#     LINKER_SCRIPT          <linker_script>
119#     LIBRARIES_POST_SCRIPT  [libraries_post_script]
120#     DEPENDENCIES           [dependencies]
121#   )
122function(toolchain_ld_link_elf)
123  cmake_parse_arguments(
124    TOOLCHAIN_LD_LINK_ELF                                     # prefix of output variables
125    ""                                                        # list of names of the boolean arguments
126    "TARGET_ELF;OUTPUT_MAP;LINKER_SCRIPT"                     # list of names of scalar arguments
127    "LIBRARIES_PRE_SCRIPT;LIBRARIES_POST_SCRIPT;DEPENDENCIES" # list of names of list arguments
128    ${ARGN}                                                   # input args to parse
129  )
130
131  if(${CMAKE_LINKER} STREQUAL "${CROSS_COMPILE}ld.bfd")
132    # ld.bfd was found so let's explicitly use that for linking, see #32237
133    set(use_linker "-fuse-ld=bfd")
134  endif()
135
136  target_link_libraries(
137    ${TOOLCHAIN_LD_LINK_ELF_TARGET_ELF}
138    ${TOOLCHAIN_LD_LINK_ELF_LIBRARIES_PRE_SCRIPT}
139    ${use_linker}
140    ${TOPT}
141    ${TOOLCHAIN_LD_LINK_ELF_LINKER_SCRIPT}
142    ${TOOLCHAIN_LD_LINK_ELF_LIBRARIES_POST_SCRIPT}
143
144    ${LINKERFLAGPREFIX},-Map=${TOOLCHAIN_LD_LINK_ELF_OUTPUT_MAP}
145    ${LINKERFLAGPREFIX},--whole-archive
146    ${ZEPHYR_LIBS_PROPERTY}
147    ${LINKERFLAGPREFIX},--no-whole-archive
148    kernel
149    $<TARGET_OBJECTS:${OFFSETS_LIB}>
150    ${LIB_INCLUDE_DIR}
151    -L${PROJECT_BINARY_DIR}
152    ${TOOLCHAIN_LIBS}
153
154    ${TOOLCHAIN_LD_LINK_ELF_DEPENDENCIES}
155  )
156endfunction(toolchain_ld_link_elf)
157
158# Load toolchain_ld-family macros
159include(${ZEPHYR_BASE}/cmake/linker/${LINKER}/target_base.cmake)
160include(${ZEPHYR_BASE}/cmake/linker/${LINKER}/target_baremetal.cmake)
161include(${ZEPHYR_BASE}/cmake/linker/${LINKER}/target_cpp.cmake)
162include(${ZEPHYR_BASE}/cmake/linker/${LINKER}/target_relocation.cmake)
163include(${ZEPHYR_BASE}/cmake/linker/${LINKER}/target_configure.cmake)
164