0

I have 2 CMake scripts:

Script1.cmake:

cmake_minimum_required(VERSION 3.15)

macro(m1)
message("[DEBUG1] " ${var1})
m2(var1)  #<====================== HERE is different
endmacro(m1)


macro(m2 var2)
message("[DEBUG2] " ${var2})
set(${var2} "set from m2")
endmacro()


m1()
message("[DEBUG3] " ${var1})

Script2.cmake:

cmake_minimum_required(VERSION 3.15)

macro(m1)
message("[DEBUG1] " ${var1})
m2("var1")  #<====================== HERE is different
endmacro(m1)


macro(m2 var2)
message("[DEBUG2] " ${var2})
set(${var2} "set from m2")
endmacro()


m1()
message("[DEBUG3] " ${var1})

I run them with cmake -P. They both give the same output:

[DEBUG1]
[DEBUG2] var1
[DEBUG3] set from m2

For [DEBUG1], I can explain it that because var1 is not defined yet. So ${var1} resolves to nothing.

But for [DEBUG2], how could it be the same to pass in var1 and "var1" ?

  • For passing "var1", I think the result is logically reasonable.

  • But for passing var1, I am actually passing some non-existing variable to macro m2. I think there should be some error because the variable is not defined yet. But actually CMake works fine. And ${var2} resolves to the name of var1.

I did some C++ programming before and I can understand pass argument by reference or pass argument by value. But it seems neither explanation fits in here. It seems there's some implicit conversion happening.

smwikipedia
  • 61,609
  • 92
  • 309
  • 482
  • 1
    CMake is one of the strangest languages in existence. In CMake, everything is a string. `var` and `"var"` are exactly the same when passed as an argument; the quotes just let you put characters like spaces in the argument. When you expand a variable with `${var}`, that's like a lookup in a hashmap for the key which is the string `var`. – Justin Jul 10 '19 at 03:22

1 Answers1

1

As @Justin said, foo(a) and foo("a") are the same thing.

But you can see the difference, when passing a list as a parameter. When you write

foo(a b c d)

this gets turned into foo("a;b;c;d"). This is what happens when you call add_executable with a list of source files, for example. The ; symbol is a special symbol used by CMake to separate list items. Moreover, CMake list() command, basically, operate on plain strings, appending or removing ; along with items themselves.

Now, if you write

foo("a b c d")

you pass a single string with space, not a list of 4 elements.

smwikipedia
  • 61,609
  • 92
  • 309
  • 482
arrowd
  • 33,231
  • 8
  • 79
  • 110
  • `foo(a b c d)` isn't turned into `foo("a;b;c;d")`. If you write `foo("a;b;c;d")`, the first argument of `foo` holds the value `a;b;c;d` and `foo` was called with one argument. In short, command arguments are the special case where there is a list-like type. For variables, everything is a string, and `set(foo a b c d)` is the same as `set(foo "a;b;c;d")` – Justin Jul 11 '19 at 00:00