1if (NOT TARGET pico_standard_link)
2    pico_add_library(pico_standard_link)
3
4    target_sources(pico_standard_link INTERFACE
5        ${CMAKE_CURRENT_LIST_DIR}/crt0.S
6        ${CMAKE_CURRENT_LIST_DIR}/new_delete.cpp
7        ${CMAKE_CURRENT_LIST_DIR}/binary_info.c
8    )
9
10    pico_add_map_output(pico_standard_link)
11
12    # todo revisit when we do Clang
13    if (CMAKE_C_COMPILER_ID STREQUAL "Clang")
14        target_link_options(pico_standard_link INTERFACE "LINKER:-nostdlib")
15    endif ()
16
17    pico_mirrored_target_link_libraries(pico_standard_link INTERFACE hardware_regs pico_bootrom pico_binary_info)
18    target_link_libraries(pico_standard_link INTERFACE pico_cxx_options  boot_stage2_headers)
19
20    function(pico_add_link_depend TARGET dependency)
21        get_target_property(target_type ${TARGET} TYPE)
22        if (${target_type} STREQUAL "INTERFACE_LIBRARY")
23            set(PROP "INTERFACE_LINK_DEPENDS")
24        else()
25            set(PROP "LINK_DEPENDS")
26        endif()
27        get_target_property(_LINK_DEPENDS ${TARGET} ${PROP})
28        if (NOT _LINK_DEPENDS)
29            set(_LINK_DEPENDS ${dependency})
30        else()
31            list(APPEND _LINK_DEPENDS ${dependency})
32        endif()
33        set_target_properties(${TARGET} PROPERTIES ${PROP} "${_LINK_DEPENDS}")
34    endfunction()
35
36    # need this because cmake does not appear to have a way to override an INTERFACE variable
37    function(pico_set_linker_script TARGET LDSCRIPT)
38        set_target_properties(${TARGET} PROPERTIES PICO_TARGET_LINKER_SCRIPT ${LDSCRIPT})
39        pico_add_link_depend(${TARGET} ${LDSCRIPT})
40    endfunction()
41
42    function(pico_set_binary_type TARGET TYPE)
43        set_target_properties(${TARGET} PROPERTIES PICO_TARGET_BINARY_TYPE ${TYPE})
44    endfunction()
45
46    if (PICO_NO_FLASH)
47        set(PICO_DEFAULT_BINARY_TYPE no_flash)
48    elseif (PICO_USE_BLOCKED_RAM)
49        set(PICO_DEFAULT_BINARY_TYPE blocked_ram)
50    elseif (PICO_COPY_TO_RAM)
51        set(PICO_DEFAULT_BINARY_TYPE copy_to_ram)
52    else()
53        set(PICO_DEFAULT_BINARY_TYPE default)
54    endif()
55
56    # LINKER script will be PICO_TARGET_LINKER_SCRIPT if set on target, or ${CMAKE_CURRENT_LIST_DIR}/memmap_foo.ld
57    # if PICO_TARGET_BINARY_TYPE is set to foo on the target, otherwise ${CMAKE_CURRENT_LIST_DIR}/memmap_${PICO_DEFAULT_BINARY_TYPE).ld
58    target_link_options(pico_standard_link INTERFACE
59            "LINKER:--script=$<IF:$<BOOL:$<TARGET_PROPERTY:PICO_TARGET_LINKER_SCRIPT>>,$<TARGET_PROPERTY:PICO_TARGET_LINKER_SCRIPT>,${CMAKE_CURRENT_LIST_DIR}/memmap_$<IF:$<STREQUAL:$<TARGET_PROPERTY:PICO_TARGET_BINARY_TYPE>,>,${PICO_DEFAULT_BINARY_TYPE},$<TARGET_PROPERTY:PICO_TARGET_BINARY_TYPE>>.ld>"
60    )
61
62    # PICO_NO_FLASH will be set based on PICO_TARGET_BUILD_TYPE target property being equal to no_flash if set, otherwise to the value of the PICO_NO_FLASH cmake variable unless PICO_TARGET_TYPE is set to something else
63    # PICO_BUILD_DEFINE: PICO_NO_FLASH, whether this is a 'no_flash' build, type=bool, default=0, but dependent on CMake options, group=pico_standard_link
64    target_compile_definitions(pico_standard_link INTERFACE PICO_NO_FLASH=$<IF:$<STREQUAL:$<TARGET_PROPERTY:PICO_TARGET_BINARY_TYPE>,no_flash>,1,$<AND:$<BOOL:${PICO_NO_FLASH}>,$<STREQUAL:,$<TARGET_PROPERTY:PICO_TARGET_BINARY_TYPE>>>>)
65    # PICO_USE_BLOCKED_RAM will be set based on PICO_TARGET_BUILD_TYPE target property being equal to use_blocked_ram if set, otherwise to the value of the PICO_USE_BLOCKED_RAM cmake variable unless PICO_TARGET_TYPE is set to something else
66    # PICO_BUILD_DEFINE: PICO_USE_BLOCKED_RAM, whether this is a 'blocked_ram' build, type=bool, default=0, but dependent on CMake options, group=pico_standard_link
67    target_compile_definitions(pico_standard_link INTERFACE PICO_USE_BLOCKED_RAM=$<IF:$<STREQUAL:$<TARGET_PROPERTY:PICO_TARGET_BINARY_TYPE>,use_blocked_ram>,1,$<AND:$<BOOL:${PICO_USE_BLOCKED_RAM}>,$<STREQUAL:,$<TARGET_PROPERTY:PICO_TARGET_BINARY_TYPE>>>>)
68    # PICO_COPY_TO_RAM will be set based on PICO_TARGET_BUILD_TYPE target property being equal to copy_to_ram if set, otherwise to the value of the PICO_COPY_TO_RAM cmake variable unless PICO_TARGET_TYPE is set to something else
69    # PICO_BUILD_DEFINE: PICO_COPY_TO_RAM, whether this is a 'copy_to_ram' build, type=bool, default=0, but dependent on CMake options, group=pico_standard_link
70    target_compile_definitions(pico_standard_link INTERFACE PICO_COPY_TO_RAM=$<IF:$<STREQUAL:$<TARGET_PROPERTY:PICO_TARGET_BINARY_TYPE>,copy_to_ram>,1,$<AND:$<BOOL:${PICO_COPY_TO_RAM}>,$<STREQUAL:,$<TARGET_PROPERTY:PICO_TARGET_BINARY_TYPE>>>>)
71
72    target_compile_definitions(pico_standard_link INTERFACE PICO_CMAKE_BUILD_TYPE="${CMAKE_BUILD_TYPE}")
73    if (PICO_DEOPTIMIZED_DEBUG AND "${CMAKE_BUILD_TYPE}" STREQUAL "Debug")
74        target_compile_definitions(pico_standard_link INTERFACE PICO_DEOPTIMIZED_DEBUG=1)
75    endif()
76
77    # todo revisit/recall reasoning for why not -nostartfiles always?
78    # -nostartfiles will be added if PICO_NO_FLASH would be defined to 1
79    target_link_options(pico_standard_link INTERFACE $<$<IF:$<STREQUAL:$<TARGET_PROPERTY:PICO_TARGET_BINARY_TYPE>,no_flash>,1,$<AND:$<BOOL:${PICO_NO_FLASH}>,$<STREQUAL:,$<TARGET_PROPERTY:PICO_TARGET_BINARY_TYPE>>>>:-nostartfiles>)
80    # boot_stage2 will be linked if PICO_NO_FLASH would be defined to 0
81    target_link_libraries(pico_standard_link INTERFACE $<$<NOT:$<IF:$<STREQUAL:$<TARGET_PROPERTY:PICO_TARGET_BINARY_TYPE>,no_flash>,1,$<AND:$<BOOL:${PICO_NO_FLASH}>,$<STREQUAL:,$<TARGET_PROPERTY:PICO_TARGET_BINARY_TYPE>>>>>:$<IF:$<BOOL:$<TARGET_PROPERTY:PICO_TARGET_BOOT_STAGE2>>,$<TARGET_PROPERTY:PICO_TARGET_BOOT_STAGE2>,bs2_default>_library>)
82
83    # PICO_CMAKE_CONFIG: PICO_USE_DEFAULT_MAX_PAGE_SIZE, Don't shrink linker max page to 4096, type=bool, default=0, advanced=true, group=pico_standard_link
84    if (NOT PICO_USE_DEFAULT_MAX_PAGE_SIZE)
85        target_link_options(pico_standard_link INTERFACE "LINKER:-z,max-page-size=4096")
86    endif()
87    # done in compiler now
88    #target_link_options(pico_standard_link INTERFACE "LINKER:--build-id=none")
89
90    # this line occasionally useful for debugging ... todo maybe make a PICO_ var
91    # target_compile_options(pico_standard_link INTERFACE --save-temps) #debugging only
92
93    # PICO_CMAKE_CONFIG: PICO_NO_GC_SECTIONS, Disable -ffunction-sections -fdata-sections and --gc-sections, type=bool, default=0, advanced=true, group=pico_standard_link
94    if (NOT PICO_NO_GC_SECTIONS)
95        target_compile_options(pico_standard_link INTERFACE -ffunction-sections -fdata-sections)
96        target_link_options(pico_standard_link INTERFACE "LINKER:--gc-sections")
97    endif()
98
99    if ("${CMAKE_C_COMPILER_ID}" STREQUAL "GNU")
100        # Ignore warnings about rwx segments introduced in binutils 2.39
101        execute_process(COMMAND ${CMAKE_C_COMPILER} -print-prog-name=ld RESULT_VARIABLE RUN_C_RESULT OUTPUT_VARIABLE FULL_LD_PATH
102            OUTPUT_STRIP_TRAILING_WHITESPACE)
103        if (${RUN_C_RESULT} EQUAL 0)
104            execute_process(COMMAND ${FULL_LD_PATH} --help RESULT_VARIABLE RUN_LD_RESULT OUTPUT_VARIABLE LD_HELP_OUTPUT
105                OUTPUT_STRIP_TRAILING_WHITESPACE)
106            if (${RUN_LD_RESULT} EQUAL 0)
107                    set(RWX_WARNING "no-warn-rwx-segments")
108                    string(FIND "${LD_HELP_OUTPUT}" "${RWX_WARNING}" LD_RWX_WARNING_SUPPORTED)
109                    if (${LD_RWX_WARNING_SUPPORTED} GREATER -1)
110                        target_link_options(pico_standard_link INTERFACE "LINKER:--${RWX_WARNING}")
111                    endif()
112            endif()
113        endif()
114    endif()
115endif()
116