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

Cmake

Cmake Problem Overview


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?

Cmake Solutions


Solution 1 - Cmake

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 - Cmake

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 - Cmake

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

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

Solution 4 - Cmake

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 - Cmake

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}/")

Solution 6 - Cmake

I assume that you want an absolute filename as you are prepending ${CMAKE_CURRENT_SOURCE_DIR}. If you are using FILE(GLOB <VAR> <PATTER>), all the files will have an absolute path already:

file(GLOB_RECURSE SOURCE_FILES src/*.cpp)

See the comments CMake in documentation on why not to use GLOB to add source files.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionPawel StolowskiView Question on Stackoverflow
Solution 1 - Cmakecode-gsView Answer on Stackoverflow
Solution 2 - CmakeDing-Yi ChenView Answer on Stackoverflow
Solution 3 - Cmakegena2xView Answer on Stackoverflow
Solution 4 - CmaketiburView Answer on Stackoverflow
Solution 5 - CmakeDominik WójtView Answer on Stackoverflow
Solution 6 - CmakesradomskiView Answer on Stackoverflow