1# SPDX-License-Identifier: Apache-2.0
2
3set_property(TARGET linker PROPERTY devices_start_symbol "Image$$device$$Base")
4
5find_program(CMAKE_LINKER ${CROSS_COMPILE}armlink PATHS ${TOOLCHAIN_HOME} NO_DEFAULT_PATH)
6
7add_custom_target(armlink)
8
9function(toolchain_ld_force_undefined_symbols)
10  foreach(symbol ${ARGN})
11    zephyr_link_libraries(--undefined=${symbol})
12  endforeach()
13endfunction()
14
15macro(configure_linker_script linker_script_gen linker_pass_define)
16  set(STEERING_FILE)
17  set(STEERING_C)
18  set(STEERING_FILE_ARG)
19  set(STEERING_C_ARG)
20  set(linker_pass_define_list ${linker_pass_define})
21  set(cmake_linker_script_settings
22      ${PROJECT_BINARY_DIR}/include/generated/ld_script_settings_${linker_pass_define}.cmake
23  )
24
25  if("LINKER_ZEPHYR_FINAL" IN_LIST linker_pass_define_list)
26    set(STEERING_FILE ${CMAKE_CURRENT_BINARY_DIR}/armlink_symbol_steering.steer)
27    set(STEERING_C ${CMAKE_CURRENT_BINARY_DIR}/armlink_symbol_steering.c)
28    set(STEERING_FILE_ARG "-DSTEERING_FILE=${STEERING_FILE}")
29    set(STEERING_C_ARG "-DSTEERING_C=${STEERING_C}")
30  endif()
31
32  file(GENERATE OUTPUT ${cmake_linker_script_settings} CONTENT
33       "set(FORMAT \"$<TARGET_PROPERTY:linker,FORMAT>\" CACHE INTERNAL \"\")\n
34        set(ENTRY \"$<TARGET_PROPERTY:linker,ENTRY>\" CACHE INTERNAL \"\")\n
35        set(MEMORY_REGIONS \"$<TARGET_PROPERTY:linker,MEMORY_REGIONS>\" CACHE INTERNAL \"\")\n
36        set(GROUPS \"$<TARGET_PROPERTY:linker,GROUPS>\" CACHE INTERNAL \"\")\n
37        set(SECTIONS \"$<TARGET_PROPERTY:linker,SECTIONS>\" CACHE INTERNAL \"\")\n
38        set(SECTION_SETTINGS \"$<TARGET_PROPERTY:linker,SECTION_SETTINGS>\" CACHE INTERNAL \"\")\n
39        set(SYMBOLS \"$<TARGET_PROPERTY:linker,SYMBOLS>\" CACHE INTERNAL \"\")\n
40       "
41    )
42  add_custom_command(
43    OUTPUT ${linker_script_gen}
44           ${STEERING_FILE}
45           ${STEERING_C}
46    COMMAND ${CMAKE_COMMAND}
47      -C ${DEVICE_API_LINKER_SECTIONS_CMAKE}
48      -C ${cmake_linker_script_settings}
49      -DPASS="${linker_pass_define}"
50      ${STEERING_FILE_ARG}
51      ${STEERING_C_ARG}
52      -DOUT_FILE=${CMAKE_CURRENT_BINARY_DIR}/${linker_script_gen}
53      -P ${ZEPHYR_BASE}/cmake/linker/armlink/scatter_script.cmake
54    DEPENDS ${DEVICE_API_LD_TARGET}
55  )
56
57  if("LINKER_ZEPHYR_FINAL" IN_LIST linker_pass_define_list)
58    add_library(armlink_steering OBJECT ${STEERING_C})
59    target_link_libraries(armlink_steering PRIVATE zephyr_interface)
60  endif()
61endmacro()
62
63function(toolchain_ld_link_elf)
64  cmake_parse_arguments(
65    TOOLCHAIN_LD_LINK_ELF                                     # prefix of output variables
66    ""                                                        # list of names of the boolean arguments
67    "TARGET_ELF;OUTPUT_MAP;LINKER_SCRIPT"                     # list of names of scalar arguments
68    "LIBRARIES_PRE_SCRIPT;LIBRARIES_POST_SCRIPT;DEPENDENCIES" # list of names of list arguments
69    ${ARGN}                                                   # input args to parse
70  )
71
72  foreach(lib ${ZEPHYR_LIBS_PROPERTY})
73    if(NOT ${lib} STREQUAL arch__arm__core__cortex_m)
74      list(APPEND ZEPHYR_LIBS_OBJECTS $<TARGET_OBJECTS:${lib}>)
75      list(APPEND ZEPHYR_LIBS_OBJECTS $<TARGET_PROPERTY:${lib},LINK_LIBRARIES>)
76    endif()
77  endforeach()
78
79  target_link_libraries(
80    ${TOOLCHAIN_LD_LINK_ELF_TARGET_ELF}
81    ${TOOLCHAIN_LD_LINK_ELF_LIBRARIES_PRE_SCRIPT}
82    --scatter=${TOOLCHAIN_LD_LINK_ELF_LINKER_SCRIPT}
83    ${TOOLCHAIN_LD_LINK_ELF_LIBRARIES_POST_SCRIPT}
84    $<TARGET_OBJECTS:arch__arm__core__cortex_m>
85    --map --list=${TOOLCHAIN_LD_LINK_ELF_OUTPUT_MAP}
86    ${ZEPHYR_LIBS_OBJECTS}
87    kernel
88    $<TARGET_OBJECTS:${OFFSETS_LIB}>
89    --library_type=microlib
90    --entry=$<TARGET_PROPERTY:linker,ENTRY>
91    "--keep=\"*.o(.init_*)\""
92    "--keep=\"*.o(.device_*)\""
93    $<TARGET_OBJECTS:armlink_steering>
94    --edit=${CMAKE_CURRENT_BINARY_DIR}/armlink_symbol_steering.steer
95    # Resolving symbols using generated steering files will emit the warnings 6331 and 6332.
96    # Steering files are used because we want to be able to use `__device_end` instead of `Image$$device$$Limit`.
97    # Thus silence those two warnings.
98    --diag_suppress=6331,6332
99    # The scatter file is generated, and thus sometimes input sections are specified
100    # even though there will be no such sections found in the libraries linked.
101    --diag_suppress=6314
102    # We use empty execution sections in order to define custom symbols, such as
103    # __kernel_ram_x symbols, but nothing will go in those section, so silence
104    # the warning. Note, marking the section EMPTY causes armlink to reserve the
105    # address which in some cases leads to overlapping section errors.
106    --diag_suppress=6312
107    # Use of '.gnu.linkonce' sections. Those are used by ld, and # supported by armlink, albeit
108    # deprecated there. For current ARMClang support phase, we accept this warning, but we should
109    # look into changing to COMDAT groups.
110    --diag_suppress=6092
111    # Wildcard matching of keep sections, Those are needed for gnu ld, and thus we inherit the same
112    # keep flags and apply them to armlink. Consider adjusting keep flags per linker in future.
113    --diag_suppress=6319
114    # Match pattern for an unused section that is being removed.
115    --diag_suppress=6329
116    ${TOOLCHAIN_LIBS_OBJECTS}
117
118    ${TOOLCHAIN_LD_LINK_ELF_DEPENDENCIES}
119  )
120endfunction(toolchain_ld_link_elf)
121
122# This function will generate the correct CMAKE_C_LINK_EXECUTABLE / CMAKE_CXX_LINK_EXECUTABLE
123# rule to ensure that standard c and runtime libraries are correctly placed
124# and the end of link invocation and doesn't appear in the middle of the link
125# command invocation.
126macro(toolchain_linker_finalize)
127  set(zephyr_std_libs)
128  get_property(link_order TARGET linker PROPERTY link_order_library)
129  foreach(lib ${link_order})
130    get_property(link_flag TARGET linker PROPERTY ${lib}_library)
131    set(zephyr_std_libs "${zephyr_std_libs} ${link_flag}")
132  endforeach()
133
134  set(common_link "<LINK_FLAGS> <LINK_LIBRARIES> <OBJECTS> ${zephyr_std_libs} -o <TARGET>")
135  set(CMAKE_C_LINK_EXECUTABLE "<CMAKE_LINKER> <CMAKE_C_LINK_FLAGS> ${common_link}")
136  set(CMAKE_CXX_LINK_EXECUTABLE "<CMAKE_LINKER> <CMAKE_CXX_LINK_FLAGS> ${common_link}")
137  set(CMAKE_ASM_LINK_EXECUTABLE "<CMAKE_LINKER> <CMAKE_ASM_LINK_FLAGS> ${common_link}")
138endmacro()
139
140include(${ZEPHYR_BASE}/cmake/linker/ld/target_relocation.cmake)
141include(${ZEPHYR_BASE}/cmake/linker/ld/target_configure.cmake)
142