External project dependency

Greetings,

CMake version in use: 3.24, but would be nice to work on 3.16 as well.

I cannot seem to get CMake to recognize a dependency based on an external project.
The goal is to download Nordic Semiconductor’s SDK and use it as source files.

set(NRF_SDK_VERSION     17.1.0_ddde560)
set(NRF_SDK_NAME        nRF5_SDK_${NRF_SDK_VERSION})

# Nordic nRF5 SDK downloads into external/${NRF_SDK_NAME}
include(ExternalProject)

set(NRF_SDK_DOWNLOAD_URL
    https://www.nordicsemi.com/-/media/Software-and-other-downloads/SDKs/nRF5/Binaries/${NRF_SDK_NAME}.zip
)
set(NRF_SDK_SOURCE_DIR  ${CMAKE_SOURCE_DIR}/external/${NRF_SDK_NAME})
set(NRF_SDK_BINARY_DIR  ${CMAKE_BINARY_DIR}/nrf_sdk)

ExternalProject_Add(nRF5_SDK
    URL                 ${NRF_SDK_DOWNLOAD_URL}
    SOURCE_DIR          ${NRF_SDK_SOURCE_DIR}
    BINARY_DIR          ${NRF_SDK_BINARY_DIR}
    CONFIGURE_COMMAND   ""
    BUILD_COMMAND       ""
    INSTALL_COMMAND     ""
    TEST_COMMAND        ""
)

That all goes well. It downloads their SDK into the external/${NRF_SDK_NAME} directory.

I have a library that I want to build with their sources and my own sources:

set(LIBRARY_NAME board)

# For CMake 3.13 compatibility, create an intermediate object library first,
# and use its object list to create the static library. This allows the
# $<TARGET_OBJECTS:${LIBRARY_NAME}_objects> to be accessed.
# For CMake 3.15 and later, $<TARGET_OBJECTS:${LIBRARY_NAME}> can be accessed
# without the intermediate  $<TARGET_OBJECTS:${LIBRARY_NAME}_objects>.
add_library(${LIBRARY_NAME}_objects OBJECT)
target_sources(${LIBRARY_NAME}_objects
    PRIVATE
    # some source files

    external/${NRF_SDK_NAME}/modules/nrfx/mdk/system_nrf52.c
)

add_library(${LIBRARY_NAME} STATIC)

target_sources(${LIBRARY_NAME}
    PRIVATE
    $<TARGET_OBJECTS:${LIBRARY_NAME}_objects>
)

add_dependencies(${LIBRARY_NAME}_objects nRF5_SDK)
  • The build fails, because the system_nrf52.c file has not been downloaded (yet).
  • If I comment out the line containing system_nrf52.c, then the download works, and the link fails due to missing symbols.
  • Remove the comment # char, and the build succeeds, since the missing symbols are in that file.

I get no errors related to the add_dependencies(${LIBRARY_NAME}_objects nRF5_SDK) line, but it does not appear to be doing to task intended.

The method you’re using here should use FetchContent instead of externalProject.

That is, if you do not wish to build someone else’s project using their build system, and just wish to use their individual source files, then the way to do that is via FetchContent which will make their source files available at configure time.

2 Likes

Thanks, that worked.
Here is what I wound up with:

set(NRF_SDK_VERSION     17.1.0_ddde560)
set(NRF_SDK_NAME        nRF5_SDK_${NRF_SDK_VERSION})

# Nordic nRF5 SDK downloads into board/${TARGET}/external/${NRF_SDK_NAME}
include(FetchContent)
set(NRF_SDK_DOWNLOAD_URL
    https://www.nordicsemi.com/-/media/Software-and-other-downloads/SDKs/nRF5/Binaries/${NRF_SDK_NAME}.zip
)
set(NRF_SDK_SOURCE_DIR  ${BOARD_PATH}/external/${NRF_SDK_NAME})
set(NRF_SDK_BINARY_DIR  ${CMAKE_BINARY_DIR}/${BOARD_TARGET}/nrf_sdk)

FetchContent_Declare(nrf5_sdk
   URL                  ${NRF_SDK_DOWNLOAD_URL}
   BINARY_DIR           ${NRF_SDK_BINARY_DIR}
   SOURCE_DIR           ${BOARD_PATH}/external/${NRF_SDK_NAME}
   CONFIGURE_COMMAND    ""
   BUILD_COMMAND        ""
   INSTALL_COMMAND      ""
   TEST_COMMAND         ""
)

FetchContent_GetProperties(nrf5_sdk)
if(NOT nrf5_sdk_POPULATED)
    set(FETCHCONTENT_QUIET FALSE)
    FetchContent_Populate(nrf5_sdk)
endif()

# When the 'clean' target is used, removes the downloaded zip file, and associated
# built tags, from the build directory.
set_directory_properties(PROPERTIES ADDITIONAL_CLEAN_FILES ${NRF_SDK_BINARY_DIR})
set_directory_properties(PROPERTIES ADDITIONAL_CLEAN_FILES ${NRF_SDK_SOURCE_DIR})

Great: here is a minimal working example of your script: CMake FetchContent specific source files from other project with current project · GitHub

I left some comments and more simplified example in the gist linked above.