1cmake_policy(SET CMP0079 NEW) # allow inserting of dependencies into our INTERFACE libraries
2set(PICO_PLATFORM_CMAKE_FILE "${PICO_PLATFORM_CMAKE_FILE}" CACHE INTERNAL "")
3set(PICO_DOXYGEN_PATHS "" CACHE INTERNAL "") # generated each time
4set(PICO_DOXYGEN_EXCLUDE_PATHS "" CACHE INTERNAL "") # generated each time
5set(PICO_DOXYGEN_PRE_DEFINES "" CACHE INTERNAL "") # generated each time
6set(PICO_DOXYGEN_ENABLED_SECTIONS "" CACHE INTERNAL "") # generated each time
7
8if (NOT PICO_PLATFORM_CMAKE_DIR)
9    set(PICO_PLATFORM_CMAKE_DIR ${CMAKE_CURRENT_LIST_DIR})
10endif()
11if (NOT PICO_PLATFORM_CMAKE_FILE)
12    set(PICO_PLATFORM_CMAKE_FILE ${PICO_PLATFORM_CMAKE_DIR}/${PICO_PLATFORM}.cmake CACHE INTERNAL "")
13endif ()
14
15if (NOT EXISTS "${PICO_PLATFORM_CMAKE_FILE}")
16    message(FATAL_ERROR "${PICO_PLATFORM_CMAKE_FILE} does not exist. \
17    Either specify a valid PICO_PLATFORM (or PICO_PLATFORM_CMAKE_FILE).")
18endif ()
19
20# call add_subdirectory(subdir) unless SKIP_SUBDIR evaluates to true
21# second argument is optional path
22function(pico_add_subdirectory subdir)
23    # todo add option to disable skip flag
24    string(TOUPPER ${subdir} subdir_upper)
25    # we do not include any path part of the subdir
26    get_filename_component(subdir_upper ${subdir_upper} NAME)
27    set(replace_flag SKIP_${subdir_upper})
28    if (NOT ${replace_flag})
29        string(TOUPPER ${subdir} subdir_upper)
30        set(replace_flag SKIP_${subdir_upper})
31        if (${ARGC} GREATER 1)
32            # argv1 is the root where the subdir is relative to
33            add_subdirectory(${ARGV1}/${subdir} ${subdir})
34            # todo make this optional?
35            pico_add_doxygen(${ARGV1}/${subdir})
36        else()
37            add_subdirectory(${subdir})
38            # todo make this optional?
39            pico_add_doxygen(${subdir})
40        endif()
41    else()
42        message("Not including ${subdir} because ${replace_flag} defined.")
43    endif ()
44    pico_promote_common_scope_vars()
45endfunction()
46
47# takes dependencies after the target
48function(pico_mirrored_target_link_libraries TARGET SCOPE)
49    if (${ARGC} LESS 3)
50        message(FATAL_ERROR "expected a target, scope and at least one dependency")
51    endif()
52    if (NOT TARGET ${TARGET}_headers)
53        message(FATAL_ERROR "${TARGET} does not have headers")
54    endif()
55    # library should depend on its own header
56    target_link_libraries(${TARGET} ${SCOPE} ${TARGET}_headers)
57    foreach(DEPENDENCY IN LISTS ARGN)
58        if (DEPENDENCY MATCHES ".*_headers")
59            message(FATAL_ERROR "should not use headers with pico_mirrored_target_link_libraries")
60        endif()
61        # note, it would be nice to only add the dependency if it exists, but we do
62        # not necessarily add libraries in reverse dependency order, so we do this
63        # unconditionally, so this function should only be passed dependencies that
64        # have headers, or link will fail with a missing library -lfoo_headers
65        target_link_libraries(${TARGET}_headers ${SCOPE} ${DEPENDENCY}_headers)
66        target_link_libraries(${TARGET} ${SCOPE} ${DEPENDENCY})
67    endforeach()
68endfunction()
69
70# add a link option to wrap the given function name; i.e. -Wl:wrap=FUNCNAME for gcc
71function(pico_wrap_function TARGET FUNCNAME)
72    target_link_options(${TARGET} INTERFACE "LINKER:--wrap=${FUNCNAME}")
73endfunction()
74
75# add map file generation for the given target
76function(pico_add_map_output TARGET)
77    pico_get_runtime_output_directory(${TARGET} output_path)
78    get_target_property(target_type ${TARGET} TYPE)
79    if ("EXECUTABLE" STREQUAL "${target_type}")
80        target_link_options(${TARGET} PRIVATE "LINKER:-Map=${output_path}$<IF:$<BOOL:$<TARGET_PROPERTY:OUTPUT_NAME>>,$<TARGET_PROPERTY:OUTPUT_NAME>,$<TARGET_PROPERTY:NAME>>${CMAKE_EXECUTABLE_SUFFIX}.map")
81    else ()
82        target_link_options(${TARGET} INTERFACE "LINKER:-Map=${output_path}$<IF:$<BOOL:$<TARGET_PROPERTY:OUTPUT_NAME>>,$<TARGET_PROPERTY:OUTPUT_NAME>,$<TARGET_PROPERTY:NAME>>${CMAKE_EXECUTABLE_SUFFIX}.map")
83    endif ()
84endfunction()
85
86# create a hardware_NAME_headers target (see pico_simple_hardware_headers_target)
87# create a hardware_NAME target (see pico_simple_hardware_target)
88macro(pico_simple_hardware_target NAME)
89    pico_simple_hardware_headers_target(${NAME})
90    pico_simple_hardware_impl_target(${NAME})
91endmacro()
92
93# create an INTERFACE library named target, and define LIB_TARGET=1 (upper case) as a compile option
94# and make it dependent on a pre-existing corresponding _headers library
95# optional arg NOFLAG will skip the LIB_TARGET definition
96function(pico_add_impl_library target)
97    add_library(${target} INTERFACE)
98    string(TOUPPER ${target} TARGET_UPPER)
99    if (${ARGC} GREATER 1)
100        if (NOT "${ARGV1}" STREQUAL "NOFLAG")
101            message(FATAL_ERROR "Unknown parameter ${ARGV1}")
102        endif()
103    else()
104        target_compile_definitions(${target} INTERFACE LIB_${TARGET_UPPER}=1)
105    endif()
106    target_link_libraries(${target} INTERFACE ${target}_headers)
107endfunction()
108
109# create an INTERFACE library named target along with associated header, and define LIB_TARGET=1 (upper case) as a compile option
110# optional arg NOFLAG will skip the LIB_TARGET definition
111function(pico_add_library target)
112    add_library(${target}_headers INTERFACE)
113    pico_add_impl_library(${target} ${ARGN})
114endfunction()
115
116# create an INTERFACE library named hardware_NAME_headers INTERFACE library if it doesn't already exist,
117#        and add include/ relative to the calling directory to the includes.
118#        and hardware_structs and hardware_claim as dependencies of the library
119macro(pico_simple_hardware_headers_target NAME)
120    if (NOT TARGET hardware_${NAME}_headers)
121        add_library(hardware_${NAME}_headers INTERFACE)
122
123        target_include_directories(hardware_${NAME}_headers SYSTEM INTERFACE ${CMAKE_CURRENT_LIST_DIR}/include)
124        target_link_libraries(hardware_${NAME}_headers INTERFACE pico_base_headers)
125        if (NOT PICO_NO_HARDWARE)
126            target_link_libraries(hardware_${NAME}_headers INTERFACE hardware_structs hardware_claim_headers)
127        endif()
128    endif()
129endmacro()
130
131# create an INTERFACE library named hardware_NAME if it doesn't exist, along with a hardware_NAME_headers
132#        INTERFACE library that it depends on. The hardware_NAME_headers library add include/ relative to
133#        and pico_base_headers, and harddware_structs as a dependency of the library
134macro(pico_simple_hardware_headers_only_target NAME)
135    if (NOT TARGET hardware_${NAME})
136        # Choosing not to add LIB_HARDWARE_ defines to avoid command line bloat pending a need (they aren't
137        #   super interesting except to determine functionality as they are mostly passive accessors, however
138        #   they could be useful to determine if the header is available.
139        # pico_add_sdk_impl_library(hardware_${NAME})
140        add_library(hardware_${NAME}_headers INTERFACE)
141
142        # a headers only target should still have an explicit _headers library for consistency
143        target_include_directories(hardware_${NAME}_headers SYSTEM INTERFACE ${CMAKE_CURRENT_LIST_DIR}/include)
144        target_link_libraries(hardware_${NAME}_headers INTERFACE pico_base_headers)
145        if (NOT PICO_NO_HARDWARE)
146            target_link_libraries(hardware_${NAME}_headers INTERFACE hardware_structs)
147        endif()
148
149        add_library(hardware_${NAME} INTERFACE)
150        target_link_libraries(hardware_${NAME} INTERFACE hardware_${NAME}_headers)
151    endif()
152endmacro()
153
154# create an INTERFACE library named hardware_NAME if it doesn't exist, dependent on a pre-existing  hardware_NAME_headers
155#        INTERFACE library and pico_platform. The file NAME.c relative to the caller is added to the C sources for the hardware_NAME
156macro(pico_simple_hardware_impl_target NAME)
157    if (NOT TARGET hardware_${NAME})
158        # Choosing not to add LIB_HARDWARE_ defines to avoid command line bloat pending a need (they aren't
159        #   super interesting except to determine functionality as they are mostly passive accessors, however
160        #   they could be useful to determine if the header is available.
161        # pico_add_sdk_impl_library(hardware_${NAME})
162        add_library(hardware_${NAME} INTERFACE)
163
164        target_sources(hardware_${NAME} INTERFACE
165                ${CMAKE_CURRENT_LIST_DIR}/${NAME}.c
166                )
167
168        pico_mirrored_target_link_libraries(hardware_${NAME} INTERFACE pico_platform)
169        if (NOT PICO_NO_HARDWARE)
170            target_link_libraries(hardware_${NAME} INTERFACE hardware_claim)
171        endif()
172    endif()
173endmacro()
174
175function(pico_add_doxygen_pre_define PRE_DEFINE)
176    list(APPEND PICO_DOXYGEN_PRE_DEFINES "${PRE_DEFINE}")
177    set(PICO_DOXYGEN_PRE_DEFINES "${PICO_DOXYGEN_PRE_DEFINES}" CACHE INTERNAL "")
178endfunction()
179
180function(pico_add_doxygen_enabled_section ENABLED_SECTION)
181    list(APPEND PICO_DOXYGEN_ENABLED_SECTIONS "${ENABLED_SECTION}")
182    set(PICO_DOXYGEN_ENABLED_SECTIONS "${PICO_DOXYGEN_ENABLED_SECTIONS}" CACHE INTERNAL "")
183endfunction()
184
185function(pico_add_doxygen SOURCE_DIR)
186    if (NOT IS_ABSOLUTE "${SOURCE_DIR}")
187        get_filename_component(SOURCE_DIR "${SOURCE_DIR}" ABSOLUTE BASE_DIR ${CMAKE_CURRENT_SOURCE_DIR})
188    endif()
189    list(APPEND PICO_DOXYGEN_PATHS "${SOURCE_DIR}")
190    set(PICO_DOXYGEN_PATHS "${PICO_DOXYGEN_PATHS}" CACHE INTERNAL "")
191endfunction()
192
193function(pico_add_doxygen_exclude SOURCE_DIR)
194    if (NOT IS_ABSOLUTE "${SOURCE_DIR}")
195        get_filename_component(SOURCE_DIR "${SOURCE_DIR}" ABSOLUTE BASE_DIR ${CMAKE_CURRENT_SOURCE_DIR})
196    endif()
197    list(APPEND PICO_DOXYGEN_EXCLUDE_PATHS "${SOURCE_DIR}")
198    set(PICO_DOXYGEN_EXCLUDE_PATHS "${PICO_DOXYGEN_EXCLUDE_PATHS}" CACHE INTERNAL "")
199endfunction()
200
201include(${PICO_PLATFORM_CMAKE_FILE})
202
203pico_promote_common_scope_vars()