56

Is there a way to concatenate strings in cmake?

I have a folder that only contains .cpp files with main methods. I thought this would be easy by just using a foreach through all src files. This is what I've got this far:

project(opengl-tutorial)
cmake_minimum_required(VERSION 2.8)

aux_source_directory(. SRC_LIST)

add_definitions(
    --std=c++11
)

foreach (src ${SRC_LIST})
    # name = ${src} + ".out"
    add_executable(${name} ${src})
    target_link_libraries(${name} GL GLU GLEW glfw)
endforeach(src ${SRC_LIST})

How can I do what's described in the comment?

sighol
  • 2,678
  • 6
  • 28
  • 34

5 Answers5

61

"${src}.out" should work fine, so you can write set(NAME "${src}.out") and use ${NAME} wherever you need to.

Nafis Zaman
  • 1,505
  • 13
  • 16
  • 27
    Just a tiny, picky correction. The topic of the question is 'How do you concatenate string in cmake'. So the dot `.` in the answer is a bit misleading. The suiting more general answer would be: `"${stringA}${stringB}"` or `"${stringA}bla"` or `"bla${stringA}"` are examples to concatenate string variables or string variables with string literals. – yau Jan 21 '17 at 10:19
24

Three typical CMake string concatenation methods

While the answer to this particular question will be best handled via set or string, there is a third possibility which is list if you want to join strings with an arbitrary character.

set()

Just combine strings like in bash

set(FILE file)
set(FILE_TXT ${FILE}.txt)
message(STATUS "FILE_TXT: ${FILE_TXT}")

string(CONCAT)

Concatenate all the input arguments together and store the result in the named output variable.

string(CONCAT [...])

string(CONCAT MULTI "xxxx" "YYYY" "xxxx")
message(STATUS "MULTI: ${MULTI}")

list(APPEND)

Appends elements to the list.

list(APPEND [ ...])

When it comes to things like compiler flags, this is the tool of choice. Lists in CMake are just semicolon separated strings and when you quote them, you get the list joined with semicolons.

list(APPEND FLAGS "-D option1")
list(APPEND FLAGS "-D option2")
list(APPEND FLAGS "-D option3")
list(JOIN FLAGS " " FLAGS)
message(STATUS "FLAGS: " ${FLAGS})
Cameron Lowell Palmer
  • 21,528
  • 7
  • 125
  • 126
6

if you just want to deal with a string value see @nonexplosive's answer.

However if you wish to have a Cmake variable in your CMakeLists.txt and set that variable to some value do use either: [string()] for Cmake 3.0+ (https://cmake.org/cmake/help/v3.0/command/string.html) or set() for Cmake 2.0+.

The reason you have two options is because older cmake doesn't support the CONCAT feature.

Example CMakeLists.txt:

cmake_minimum_required(VERSION 2.8.11)
project(Hello)
string(CONCAT x "hello" "goodbye")
set(y "hellogoodbye")
message(STATUS "DEBUG: x=${x}")
message(STATUS "DEBUG: y=${y}")

Full stdout:

-- DEBUG: x=hellogoodbye
-- DEBUG: y=hellogoodbye
-- Configuring done
-- Generating done
-- Build files have been written to: /home/_______/testing/_______
Community
  • 1
  • 1
Trevor Boyd Smith
  • 18,164
  • 32
  • 127
  • 177
  • You put the minimum required version of CMake as `2.x`, but your answer says you can't use `string(...` until CMake `3.x`. – Zak Jul 15 '19 at 17:41
3

There are 5 general methods for your question.

  1. use set()
set(MY_FLAGS "")
set(MY_FLAGS "${MY_FLAGS} -Werror=shadow")
set(MY_FLAGS "${MY_FLAGS} -Werror=return-local-addr")
  1. use list(APPEND) and replace ; with space
set(MY_FLAGS "")
list(APPEND MY_FLAGS "-Werror=shadow")
list(APPEND MY_FLAGS "-Werror=return-local-addr")
string(REPLACE ";" " " MY_FLAGS "${MY_FLAGS}")
  1. use string(CONCAT). Note: this not means "append"
set(MY_FLAGS "")
string(CONCAT MY_FLAGS "-Werror=shadow") #You get "-Werror=shadow"
string(CONCAT MY_FLAGS "-Werror=return-local-addr") #You get "-Werror=return-local-addr" instead of "-Werror=shadow -Werror=return-local-addr"
  1. use string(APPEND).
set(MY_FLAGS "")
string(APPEND MY_FLAGS " -Werror=shadow") #Notice the leading space
string(APPEND MY_FLAGS " -Werror=return-local-addr") #Notice the leading space
  1. use string(JOIN)
set(MY_FLAGS "")
string(JOIN " " MY_FLAGS "-Werror=shadow" "-Werror=return-local-addr")
ChrisZZ
  • 1,521
  • 2
  • 17
  • 24
0

This is only sort of related, but I found this answer when looking for how do you concatenate paths so that you don't get double or duplicate slashes if one ends in a slash and the other begins with one?

if SOME_VAR="/foo/" and SOME_OTHER_VAR="/bar/"

FILE(TO_CMAKE_PATH "${SOME_VAR}/${SOME_OTHER_VAR}") 

will give you /foo/bar/

if you want it to give you native path delimiters (i.e. backslashes in windows), then use TO_NATIVE_PATH instead of TO_CMAKE_PATH

xaxxon
  • 19,189
  • 5
  • 50
  • 80