1

An old question recently reoccurred: What is the correct way of setting CMAKE_MODULE_PATH? But this applies to pretty much any list. However there might be a difference for general text, but IMO only when that text might contain semicolons.

Precondition: That variable might be unset, empty, or set

Options:

  1. set (CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmakeModules ${CMAKE_MODULE_PATH})
  2. set (CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmakeModules" ${CMAKE_MODULE_PATH})
  3. list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmakeModules)
  4. list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmakeModules")
  5. if (NOT CMAKE_MODULE_PATH) set (CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmakeModules") else() set (CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmakeModules;${CMAKE_MODULE_PATH}") endif()

To include some reasoning:

a) 1. might fail, when there are spaces in the path so one has to use 2. to avoid this. Is this correct?
b) 3/4 looks like the better/more concise way. Again are the spaces required?
c) 5. Has (ugly) special case handling which 1-4 avoid. Is this required?

Related: cmake: when to quote variables?

But I'm still unsure, when to use quotes especially when dealing with paths and lists.

Bonus: What exactly does happen during evaluation? If all ${...} would get replaced by the value of the variable before it is passed to the function then e.g. the following would not work and requires spaces. But it does work as intended:

set(FOO_DIR "my space path")
set(CMAKE_LIST /usr)
set(CMAKE_LIST ${CMAKE_LIST} ${FOO_DIR}/foo)
oder: list(APPEND CMAKE_LIST ${FOO_DIR}/foo)

This also applies to calls to other functions. E.g.:

set_target_properties(MYTARGET PROPERTIES
  IMPORTED_LOCATION ${FOO_DIR}/foo
)

Question is: Why? Where in the standard is this specified?

Flamefire
  • 5,313
  • 3
  • 35
  • 70
  • I think this question could be generalized for "any possibly empty or unset variables with lists". But normally, in a "general question" possibilities are described in the answers, not in the question post. Don't you think to rework your question? It could be great like https://stackoverflow.com/questions/1712227/how-to-get-the-number-of-elements-in-a-list-in-python. – Tsyvarev Mar 22 '18 at 08:41
  • Added a bit and also the bonus question which should help for reasoning about what happens and what the right approach is. – Flamefire Mar 22 '18 at 09:04
  • technically 1,2 prepend value while 3,4 append value to the list. could matter sometime (i.e. find first...). – Mizux Mar 22 '18 at 20:13
  • Yes, you can do 1,2 appending too so it doesn't matter. Just wanted to show the method – Flamefire Mar 23 '18 at 07:44

2 Answers2

2

Both set and list are valid for append a value to a list:

list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmakeModules)

or

set (CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/cmakeModules)

The first form (with 'list') is preferred, as it is shorter and doesn't duplicate the variable's name.


Resulted list is not affected by quoting appended value. That is, quotes in such cases are just a matter of taste.

NOTE 1: Quoting doesn't affect only for specific cases (set and list commands). In other cases quoting could be crucial.

NOTE 2: If current path contains semicolon (;) , it will be wrongly treated either quoted or unquoted.


Why quotes are meaningless here

Assuming variable A contains semicolon(s), like

set(A "a/b;c/d")

treatements of

 ${A}/cmakeModules

and

 "${A}/cmakeModules"

are different when passed to the function: the first case is treated as two parameters, but the second - as single parameter. You may view that difference in message() calls:

# give: a/bc/d/cmakeModules
message(STATUS ${A}/cmakeModules)
# give: a/b;c/d/cmakeModules
message(STATUS "${A}/cmakeModules")

But both these treatments give the same effect in list command:

set(B "m") # Initial value
# Either command below sets B to 3(!) values: m;a/b;c/d/cmakeModules
list(APPEND B ${A}/cmakeModules)
list(APPEND B "${A}/cmakeModules")

It could be treated as "CMake variables contains flatten lists".

Tsyvarev
  • 60,011
  • 17
  • 110
  • 153
1

a) True

b) False. And yes, I prefer this way too.

c) False

arrowd
  • 33,231
  • 8
  • 79
  • 110