Recently, we wanted to pass a new cached value to an external project in CMake
via the CMAKE_ARGS
variable.
CMAKE_ARGS
holds various types of arguments. From which, the arguments in the form -Dname:type=value
are passed to the CMake
command line and cannot be changed by the user.
We found two ways to add a new argument pair to the CMAKE_ARGS
of the external project.
The first method uses the set
function:
set(CMAKE_ARGS "${CMAKE_ARGS} -D${CACHE_VAR}${CACHE_VAR_TYPE}=\"${${CACHE_VAR}}\"")
where basically we create a new string that starts with the existing value of CMAKE_ARGS
and then we append to its end the new pair.
The second method uses the list
function:
list(APPEND CMAKE_ARGS "-D${CACHE_VAR}${CACHE_VAR_TYPE}=${${CACHE_VAR}}")
that treats CMAKE_ARGS
as a list and it appends to its end the new pair.
To verify by hand that they were equivalent we did the following small test with success
#Copy the original value of ${CMAKE_ARGS} set(CMAKE_ARGS_ORIGINAL ${CMAKE_ARGS}) #Define the Name, Type and Value for the new argument pairs set(CACHE_VAR_P_NAME PRODUCTS_DIR) set(CACHE_VAR_P_TYPE string) set(CACHE_VAR_P_VALUE "someplace/with spaces") set(CACHE_VAR_C_NAME CLIENTS_DIR) set(CACHE_VAR_C_TYPE string) set(CACHE_VAR_C_VALUE "another/place") #Print the original value of ${CMAKE_ARGS} MESSAGE(STATUS "CMAKE_ARGS: '" ${CMAKE_ARGS} "'") #Append the two pairs to ${CMAKE_ARGS} using set set(CMAKE_ARGS "${CMAKE_ARGS} -D${CACHE_VAR_P_NAME}:${CACHE_VAR_P_TYPE}=\"${CACHE_VAR_P_VALUE}\"") set(CMAKE_ARGS "${CMAKE_ARGS} -D${CACHE_VAR_C_NAME}:${CACHE_VAR_C_TYPE}=\"${CACHE_VAR_C_VALUE}\"") #Print the modified value of ${CMAKE_ARGS} MESSAGE(STATUS "CMAKE_ARGS: '" ${CMAKE_ARGS} "'") #Reset ${CMAKE_ARGS} to its original value set(CMAKE_ARGS ${CMAKE_ARGS_ORIGINAL}) #Print the original value of ${CMAKE_ARGS} for verification MESSAGE( STATUS "CMAKE_ARGS: '" ${CMAKE_ARGS} "'") #Append the two pairs to ${CMAKE_ARGS} using list list(APPEND CMAKE_ARGS "-D${CACHE_VAR_P_NAME}:${CACHE_VAR_P_TYPE}=\"${CACHE_VAR_P_VALUE}\"") list(APPEND CMAKE_ARGS "-D${CACHE_VAR_C_NAME}:${CACHE_VAR_C_TYPE}=\"${CACHE_VAR_C_VALUE}\"") #Print the modified value of ${CMAKE_ARGS} #Notice that here we surrounded ${CMAKE_ARGS} with quotes so that it is printed as list of delimiter separated values #Between each element the character ';' will be added because ${CMAKE_ARGS} is surrounded with quotes MESSAGE(STATUS "CMAKE_ARGS: '" "${CMAKE_ARGS}" "'")
Which resulted in the following output
-- CMAKE_ARGS: '' -- CMAKE_ARGS: ' -DPRODUCTS_DIR:string="someplace/with spaces" -DCLIENTS_DIR:string="another/place"' -- CMAKE_ARGS: '' -- CMAKE_ARGS: '-DPRODUCTS_DIR:string="someplace/with spaces";-DCLIENTS_DIR:string="another/place"'
From the output we can see that the two options treat the variable in a different way as using set just created a huge string containing both pairs while list created a list of two elements.
Both methods seem to work properly but we chose the list method for our external project.
The CMakeLists.txt
file that we used to include the external project using custom CMAKE_ARGS
resulted as follows:
cmake_minimum_required (VERSION 3.2.2) include (ExternalProject) set (TARGET c-banana-eat-banana) project (${TARGET} C) set (BANANA_ROOT ${CMAKE_CURRENT_BINARY_DIR} CACHE INTERNAL "") #Add custom CMake arguments to be passed to the CMake command line of the external project list(APPEND CMAKE_ARGS "-DARTIFACTS_DIR:string=\"${LIBRARIES_DIR}/${TARGET}\"") ExternalProject_Add (${TARGET} URL ${CMAKE_CURRENT_SOURCE_DIR}/${TARGET}.zip URL URL_HASH MD5=34734a678729967f426931d913326112 CMAKE_ARGS "${CMAKE_ARGS}" BUILD_IN_SOURCE 1)