# Use variables or genexes with usage requirements?

**URL:** https://discourse.cmake.org/t/use-variables-or-genexes-with-usage-requirements/2679
**Category:** Code
**Created:** [February 3, 2021, 9:13am UTC](https://discourse.cmake.org/t/use-variables-or-genexes-with-usage-requirements/2679 "2021-02-03T09:13:09Z")
**Posts on this page:** 4
**Page:** 1

<div class="post-metadata">

### Author: ![Angew](https://discourse.cmake.org/user_avatar/discourse.cmake.org/angew/32/229_2.png) [@Angew](https://discourse.cmake.org/u/Angew)
#### Post date: [February 3, 2021, 9:13am UTC](https://discourse.cmake.org/t/use-variables-or-genexes-with-usage-requirements/2679/1 "2021-02-03T09:13:09Z")

</div>

Hi all, I have a question about setting usage requirements which depend on platform or compiler. Assume I have a C++ library `Foo` such that:

- When consumers link against it on Windows, they must define `FOO_WINDOWS`.
- When the consumer is built using GCC or Clang, `-fpersmissive` must be used.

(The above macro/flag are just examples, the question holds for arbitrary macro/option usage requirements).

I want to express these as usage requirements on `Foo`. My question is, what are the [dis]advantages of using variable-conditioned settings vs. generator expressions? Basically, should I do this:

```auto
if(WIN32)
  target_compile_definitions(Foo INTERFACE FOO_WINDOWS)
endif()
if(CMAKE_CXX_COMPILER_ID MATCHES GNU|Clang)
  target_compile_options(Foo INTERFACE -fpermissive)
endif()

```

or this:

```auto
target_compile_definitions(Foo INTERFACE $<$<PLATFORM_ID:Windows>:FOO_WINDOWS>)
target_compile_options(Foo INTERFACE $<$<OR:$<CXX_COMPILER_ID:GNU>,$<CXX_COMPILER_ID:Clang>>:-fpermissive>)

```

My intuition is to use the former (variable-based) approach, since it’s easier to read and I expect it to be faster as well, as it will only be evaluated once, not once per build configuration. (This could add up if dozens of such libraries are involved, each with its own slightly different set of usage requirements).

I understand the advantage of the genex-based approach in situations such as using CUDA, where different compilers can get their hands on the same file. However, when such special cases are not involved and the buildsystem follows CMake’s normal limitation of “one platform, one toolchain”, is there any advantage to one or the other approach?

Also, does the answer change if I were not defining `Foo` as part of the build, but writing a package config file for it which could be consumed by the outside world?

---

<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: [February 3, 2021, 12:31pm UTC](https://discourse.cmake.org/t/use-variables-or-genexes-with-usage-requirements/2679/2 "2021-02-03T12:31:53Z")

</div>

For platform-specific logic, either choice works, but variables are probably clearer. For compiler-specific logic, the compiler you build with might not be the same as the one the consumer is using, so that should probably be done through generator expressions if using different compilers like that is acceptable.

---

<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: [February 3, 2021, 2:39pm UTC](https://discourse.cmake.org/t/use-variables-or-genexes-with-usage-requirements/2679/3 "2021-02-03T14:39:39Z")

</div>

I think I’d still prefer the genex approach myself. But rarely do I have platform-specific things like that in CMake (as I believe that is usually done in headers in the projects I’ve worked on). Compiler-specific things can’t be in headers and have to be in the usage interface.

---

<div class="post-metadata">

### Author: ![Angew](https://discourse.cmake.org/user_avatar/discourse.cmake.org/angew/32/229_2.png) [@Angew](https://discourse.cmake.org/u/Angew)
#### Post date: [February 8, 2021, 8:07am UTC](https://discourse.cmake.org/t/use-variables-or-genexes-with-usage-requirements/2679/4 "2021-02-08T08:07:03Z")

</div>

Thanks everyone for the answers.

> [@craig.scott](#):
>
> For compiler-specific logic, the compiler you build with might not be the same as the one the consumer is using

That is something I failed to fully consider for the package case, and is a very good point.
