from https://discourse.cmake.org/t/external-project-dependency/8862
Downloads nRF5 SDK and builds static library libsystem_nrf54.a
from https://discourse.cmake.org/t/external-project-dependency/8862
Downloads nRF5 SDK and builds static library libsystem_nrf54.a
cmake_minimum_required(VERSION 3.14...3.27) | |
if(CMAKE_SOURCE_DIR STREQUAL CMAKE_BINARY_DIR) | |
message(FATAL_ERROR "please use out-of-source build | |
cmake -Bbuild") | |
endif() | |
project(otherSource LANGUAGES C) | |
set(NRF_SDK_NAME nRF5_SDK_17.1.0_ddde560) | |
if(NOT DEFINED FETCHCONTENT_QUIET) | |
set(FETCHCONTENT_QUIET FALSE) | |
endif() | |
set(CMAKE_TLS_VERIFY true) | |
# placeholders | |
set(BOARD_TARGET NRF52805_XXAA) | |
include(FetchContent) | |
# https://www.nordicsemi.com/Products/Development-software/nRF5-SDK/Download | |
set(NRF_SDK_DOWNLOAD_URL | |
https://www.nordicsemi.com/-/media/Software-and-other-downloads/SDKs/nRF5/Binaries/${NRF_SDK_NAME}.zip | |
) | |
# setting hash avoid redownload of big archive on each CMake configure, | |
# and provides a way to check if the archive is corrupted | |
set(NRF_SDK_DOWNLOAD_SHA256 5bfe38e744c39fd7f30e10077ba12df306ef91f368894795d6a3e7a62dc68061) | |
FetchContent_Declare(nrf5_sdk | |
URL ${NRF_SDK_DOWNLOAD_URL} | |
URL_HASH SHA256=${NRF_SDK_DOWNLOAD_SHA256} | |
TLS_VERIFY ${CMAKE_TLS_VERIFY} | |
INACTIVITY_TIMEOUT 60 | |
) | |
FetchContent_Populate(nrf5_sdk) | |
# auto-ignore build dir | |
file(GENERATE OUTPUT .gitignore CONTENT "*") | |
# main program | |
add_library(system_nrf54 ${nrf5_sdk_SOURCE_DIR}/modules/nrfx/mdk/system_nrf52.c) | |
target_include_directories(system_nrf54 PRIVATE ${nrf5_sdk_SOURCE_DIR}/components/toolchain/cmsis/include) | |
target_compile_definitions(system_nrf54 PRIVATE ${BOARD_TARGET}) |
A few comments about this:
FETCHCONTENT_QUIET
and FETCHCONTENT_UPDATES_DISCONNECTED
should never be hard-coded by the project. These are meant to be developer controls. The defaults should normally be appropriate and safe.FetchContent_Populate()
, especially without first checking if the dependency has already been populated. Call FetchContent_MakeAvailable()
instead.SOURCE_DIR
or BINARY_DIR
options in the call to FetchContent_Declare()
. Instead, let FetchContent put things where it wants to. Both locations will be available to you after the call to FetchContent_MakeAvailable()
in the nrf5_sdk_SOURCE_DIR
and nrf5_sdk_BINARY_DIR
variables, which are set for you automatically. By leaving these locations at their defaults, you leave open the opportunity to take advantage of any future improvements to FetchContent which may do things like caching, etc.ADDITIONAL_CLEAN_FILES
directory property. By doing so, you are removing things from under the feet of FetchContent, which uses time stamps internally to work out what steps it needs to re-execute each time CMake is re-run.INACTIVITY_TIMEOUT
would not normally need to be set. It would typically only be needed if you're dealing with a poor network connection or a badly configured server. Only add it if you find you really need it (the setting is also only supported with CMake 3.19 or later).Taking account of the above points, a more appropriate minimal demonstrator project would look something like this:
cmake_minimum_required(VERSION 3.14...3.27)
project(otherSource LANGUAGES C)
set(NRF_SDK_VERSION 17.1.0_ddde560)
set(NRF_SDK_SHA256 5bfe38e744c39fd7f30e10077ba12df306ef91f368894795d6a3e7a62dc68061)
# https://www.nordicsemi.com/Products/Development-software/nRF5-SDK/Download
# setting the hash avoids redownloading a big archive on each CMake configure,
# and provides a way to check if the archive is corrupted
include(FetchContent)
FetchContent_Declare(nrf5_sdk
URL https://www.nordicsemi.com/-/media/Software-and-other-downloads/SDKs/nRF5/Binaries/nRF5_SDK_${NRF_SDK_VERSION}.zip
URL_HASH SHA256=${NRF_SDK_SHA256}
TLS_VERIFY true
)
FetchContent_MakeAvailable(nrf5_sdk)
# Example target using the dependency
add_library(system_nrf54 ${nrf5_sdk_SOURCE_DIR}/modules/nrfx/mdk/system_nrf52.c)
target_include_directories(system_nrf54 PRIVATE ${nrf5_sdk_SOURCE_DIR}/components/toolchain/cmsis/include)
target_compile_definitions(system_nrf54 PRIVATE NRF52805_XXAA) # Board target
Even the NRF_SDK_VERSION
and NRF_SDK_SHA256
variables are not needed. They are both only used once, so their values could be inlined directly in the call to FetchContent_Declare()
too. I only left them separate since they are two values that you may want to change as you update to different versions of the dependency, so having them as separate variables may make them easier to spot.
I do differ in how I use FetchContent vs. the official recommendations:
Calling FetchContent_Populate()
directly from projects will soon be deprecated, and eventually removed. See this forum post where I raised this recently. The timing of when this will occur isn't clear yet, but I'm aiming for either CMake 3.28 or 3.29 as the most likely timeframe.
Okay I just saw that on discourse as well. What would I do then to download someone else's Git project but then use my own CMake script to build all or part of it. For example, I use a few big long-time projects but their CMakeLists is like CMake 2.6 era and they don't seem to care about fixing it. So I use my own CMake script to build their project via FetchContent.
See the following from the FetchContent docs:
New in version 3.18: The SOURCE_SUBDIR option can be given in the declared details to look somewhere below the top directory instead (i.e. the same way that SOURCE_SUBDIR is used by the ExternalProject_Add() command). The path provided with SOURCE_SUBDIR must be relative and will be treated as relative to the top directory. It can also point to a directory that does not contain a CMakeLists.txt file or even to a directory that doesn't exist. This can be used to avoid adding a project that contains a CMakeLists.txt file in its top directory.
Thank you - nice!
I like the additions. This a big help.
Also, nice to leave a trail of bread crumbs for the search engine, and then find a complete answer like this.