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