How to prepend all filenames on the list with common path?

How can I prepend all filenames on the list with a common path prefix automatically? For instance having a list of files in CMakeLists.txt:

SET(SRC_FILES foo1.cpp foo2.cpp)

I'd like to get a list that is equivalent to this:

${CMAKE_CURRENT_SOURCE_DIR}/foo1.cpp ${CMAKE_CURRENT_SOURCE_DIR}/foo2.cpp

I need this to use filenames in a PARENT_SCOPE context, e.g.

SET(FILES_TO_TRANSLATE ${FILES_TO_TRANSLATE} ${SRC_FILES} PARENT_SCOPE)

so, that a CMakeFiles.txt in another directory can still find these files.

In essence, I'd expect something like this (pseudo-code):

SET(FILES_TO_TRANSLATE PREPEND_ALL_NAMES(${CMAKE_CURRENT_SOURCE_DIR} ${SRC_FILES}) PARENT_SCOPE)

Is this is easily doable, or do I have to user "foreach" loop to create new list of files?


Solution 1:

CMake 3.12 added list transformers - one of these transformers is PREPEND. Thus, the following can be used inline to prepend all entries in a list:

list(TRANSFORM FILES_TO_TRANSLATE PREPEND ${CMAKE_CURRENT_SOURCE_DIR})

...where FILES_TO_TRANSLATE is the variable name of the list.

More information can be found in the CMake documentation.

Solution 2:

Following function may be what you want.

FUNCTION(PREPEND var prefix)
   SET(listVar "")
   FOREACH(f ${ARGN})
      LIST(APPEND listVar "${prefix}/${f}")
   ENDFOREACH(f)
   SET(${var} "${listVar}" PARENT_SCOPE)
ENDFUNCTION(PREPEND)

To use it,

PREPEND(FILES_TO_TRANSLATE ${CMAKE_CURRENT_SOURCE_DIR} ${SRC_FILES})

Solution 3:

string(REGEX REPLACE "([^;]+)" "ANYPREFIX/\\1.cpp" outputlist "${inputlist}")

Replace ANYPREFIX with any prefix and '.cpp' with any suffix you need.

Solution 4:

You need to use a foreach loop. But if you use that in several parts of your project, you might want to create a function or a macro.

Solution 5:

As an improvement to Ding-Yi Chen's answer, if you still need to support pre-3.12 CMake as I do, you can use following code:

function(list_transform_prepend var prefix)
    set(temp "")
    foreach(f ${${var}})
        list(APPEND temp "${prefix}${f}")
    endforeach()
    set(${var} "${temp}" PARENT_SCOPE)
endfunction()

Advantage of this solution is, that interface is closer to one is CMake 3.12 list(TRANSFORM ...) and the change is done in-place.

Used like this

list_transform_prepend(FILES_TO_TRANSLATE "${CMAKE_CURRENT_SOURCE_DIR}/")