Search code examples
c++cmakeexternal-project

Is there an easy way of skip download_step if folder exists, in cmake ExternalProject_Add


I need the ExternalProject_Add in CMakeLists.txt to skip download_step for git downloads if there is already a folder with the repo cloned, like the update_step if you provide a GIT_TAG, but don't want to write a custom DOWNLOAD_COMMAND. Basically just need the project to build fully offline if the dependencies where added manually to the folder project.

For example:

ExternalProject_Add(civ
  SOURCE_DIR            ${PROJECT_SOURCE_DIR}/test
  BUILD_COMMAND         ${MAKE_EXE}
  BINARY_DIR            "./bin"
  INSTALL_COMMAND       ""
  GIT_REPOSITORY        "https://github.com/test/test"
  GIT_TAG               "v1.0"
  LOG_DOWNLOAD          on
  CMAKE_ARGS
    "-DTuberosumTools_DIR=${TUBEROSUMTOOLS_DIR}"
)

this, deletes test folder and clones it again every time the project is builded for the first time(if i manually delete build folder), i can build after that totally offline, but really need to use it offline always. Already tried to set a cache variable like:

set(FRESH_DOWNLOAD off CACHE BOOL "download a fresh copy of all dependencies")

include(ExternalProject)
ExternalProject_Add(civ
  SOURCE_DIR            ${PROJECT_SOURCE_DIR}/test
  BUILD_COMMAND         ${MAKE_EXE}
  BINARY_DIR            "./bin"
  INSTALL_COMMAND       ""
  GIT_REPOSITORY        "https://github.com/test/test"
  GIT_TAG               "v1.0"
  if(NOT FRESH_DOWNLOAD)
    DOWNLOAD_COMMAND      ""
  endif()
  CMAKE_ARGS
    "-DTuberosumTools_DIR=${TUBEROSUMTOOLS_DIR}"
)

to completly disable download unless indicated, but the if inside the call to ExternalProject_Add(), obviusly does not work, and using the if outside introduces extra code a little harder to mantain, and its ugly.

Any simple alternative is valid, thanks in advance.


Solution

  • When call a function or macro, CMake allows to substitute a variable, which contains several parameters at once. That is, you may conditionally define a variable which is responsible for DOWNLOAD step:

    set(FRESH_DOWNLOAD off CACHE BOOL "download a fresh copy of all dependencies")
    
    include(ExternalProject)
    if (NOT FRESH_DOWNLOAD)
        # Define the variable to disable DOWNLOAD step
        set(civ_DOWNLOAD DOWNLOAD_COMMAND      "")
    else()
        # Define an empty variable.
        # This actually can be omitted since absent variable is treated as empty.
        set(civ_DOWNLOAD)
    endif()
    
    ExternalProject_Add(civ
      SOURCE_DIR            ${PROJECT_SOURCE_DIR}/test
      BUILD_COMMAND         ${MAKE_EXE}
      BINARY_DIR            "./bin"
      INSTALL_COMMAND       ""
      GIT_REPOSITORY        "https://github.com/test/test"
      GIT_TAG               "v1.0"
      ${civ_DOWNLOAD} # IMPORTANT: Do not use double quotes here.
      CMAKE_ARGS
        "-DTuberosumTools_DIR=${TUBEROSUMTOOLS_DIR}"
    )