# Should I be using types with -D options?

**URL:** https://discourse.cmake.org/t/should-i-be-using-types-with-d-options/3877
**Category:** Usage
**Created:** [August 4, 2021, 8:53pm UTC](https://discourse.cmake.org/t/should-i-be-using-types-with-d-options/3877 "2021-08-04T20:53:25Z")
**Posts on this page:** 7
**Page:** 1

<div class="post-metadata">

### Author: ![mathomp4](https://discourse.cmake.org/user_avatar/discourse.cmake.org/mathomp4/32/176_2.png) [@mathomp4](https://discourse.cmake.org/u/mathomp4)
#### Post date: [August 4, 2021, 8:53pm UTC](https://discourse.cmake.org/t/should-i-be-using-types-with-d-options/3877/1 "2021-08-04T20:53:25Z")

</div>

Just a general query for the CMake gurus on here. I’ve always done things like:

```auto
cmake .. -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=OFF ...

```

but I do see others using the more explicit typing:

```auto
cmake .. -DCMAKE_BUILD_TYPE:STRING=Release -DBUILD_SHARED_LIBS:BOOL=OFF ...

```

I guess my question is: Should I re-train my brain to do this? Am I possibly missing out on some type-checking CMake can do or the like by not doing so?

Thanks,  
Matt

---

<div class="post-metadata">

### Author: ![kyle.edwards](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/k/65b543/32.png) [@kyle.edwards](https://discourse.cmake.org/u/kyle.edwards)
#### Post date: [August 4, 2021, 8:58pm UTC](https://discourse.cmake.org/t/should-i-be-using-types-with-d-options/3877/2 "2021-08-04T20:58:09Z")

</div>

It doesn’t make a great deal of difference either way. The biggest difference the type makes is how `ccmake` and `cmake-gui` display the cache entry - giving it a type causes it to present as a more appropriate control, like a checkbox or a file input, instead of a simple text input.

---

<div class="post-metadata">

### Author: ![kyle.edwards](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/k/65b543/32.png) [@kyle.edwards](https://discourse.cmake.org/u/kyle.edwards)
#### Post date: [August 4, 2021, 8:58pm UTC](https://discourse.cmake.org/t/should-i-be-using-types-with-d-options/3877/3 "2021-08-04T20:58:42Z")

</div>

FWIW, I usually enter it without the type on the command line.

---

<div class="post-metadata">

### Author: ![ben.boeckel](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/b/ea5d25/32.png) [@ben.boeckel](https://discourse.cmake.org/u/ben.boeckel)
#### Post date: [August 4, 2021, 9:08pm UTC](https://discourse.cmake.org/t/should-i-be-using-types-with-d-options/3877/4 "2021-08-04T21:08:40Z")

</div>

Note that specifying a `PATH` type may convert the value to an absolute path on you. `FILEPATH` may have similar behaviors.

Edit: This might be more related to _not_ having a type on the command line and then finding a `set(var value CACHE PATH doc)` command later.

---

<div class="post-metadata">

### Author: ![mathomp4](https://discourse.cmake.org/user_avatar/discourse.cmake.org/mathomp4/32/176_2.png) [@mathomp4](https://discourse.cmake.org/u/mathomp4)
#### Post date: [August 4, 2021, 10:41pm UTC](https://discourse.cmake.org/t/should-i-be-using-types-with-d-options/3877/5 "2021-08-04T22:41:08Z")

</div>

I did not know this! I’ll have to experiment!

---

<div class="post-metadata">

### Author: ![mathomp4](https://discourse.cmake.org/user_avatar/discourse.cmake.org/mathomp4/32/176_2.png) [@mathomp4](https://discourse.cmake.org/u/mathomp4)
#### Post date: [August 4, 2021, 10:41pm UTC](https://discourse.cmake.org/t/should-i-be-using-types-with-d-options/3877/6 "2021-08-04T22:41:27Z")

</div>

Oh. That is interesting. I can see how that would be a Good Thing™. Thanks

---

<div class="post-metadata">

### Author: ![craig.scott](https://discourse.cmake.org/user_avatar/discourse.cmake.org/craig.scott/32/20_2.png) [@craig.scott](https://discourse.cmake.org/u/craig.scott)
#### Post date: [August 5, 2021, 10:43pm UTC](https://discourse.cmake.org/t/should-i-be-using-types-with-d-options/3877/7 "2021-08-05T22:43:21Z")

</div>

> [@kyle.edwards](#):
>
> It doesn’t make a great deal of difference either way.

Except when it does… If you don’t provide the type on the command line, it can lead to different behavior between the first and subsequent CMake runs. The situation arises because of a quirk where if the project sets a cache variable that was already set but didn’t yet have a type associated with it, this will discard any non-cache variable of the same name. Consider the following test project:

```cmake
cmake_minimum_required(VERSION 3.4)
project(var_test)

set(SOMEVAR local_value)
set(SOMEVAR cache_value CACHE STRING "")
message(STATUS "SOMEVAR = ${SOMEVAR}")

```

Consider firstly if you don’t try to set `SOMEVAR` on the command line at all. On the first CMake run, this prints `SOMEVAR = cache_value` and on subsequent runs, it prints `SOMEVAR = local_value`. On the first run, the cache variable isn’t set, so setting the variable results in clearing any non-variable of the same name. On subsequent runs, the cache variable exists and has a type, so it doesn’t touch the non-cache variable, which then still takes precedence over the cache variable when we print `${SOMEVAR}` at the end.

Now consider if you set the cache variable on the command line. If you set it without any type, like so:

```auto
cmake -D SOMEVAR=cmdline ...

```

On the first run, the cache variable doesn’t initially have a type, even though we’ve given it a value. When the project sets the cache variable, it sees the cache variable has no type, so it clears the non-cache variable (yes, this is quite surprising and probably not widely understood). On subsequent runs, the cache variable does have a type and the local variable is not cleared.

But if on the first run we _do_ provide a type like so:

```auto
cmake -D SOMEVAR:STRING=cmdline ...

```

When we reach the line that sets the cache variable, it already has a type and so the non-cache variable’s value is used even on the first run.

Now, the above all likely sounds horribly unintuitive. And you’re right. This was fixed in CMake 3.21, subject to a new policy CMP0126. If we changed the first line of our example such that the new policy is always used:

```auto
cmake_minimum_required(VERSION 3.21)

```

Now the local variable’s value is left alone and will always be used whether it is the first run or not, whether we set the cache variable on the command line or not, and whether we include the type with the variable on the command line or not. In other words, the new behavior is what people expect.

For completeness, there is a similar situation for the `option()` command, but that was fixed back in CMake 3.13 with policy CMP0077.
