45

I'm trying for long time to understand the benefit of generator expressions such as $<xxx:yy> in CMake, when and how to use them. Can anybody explain it clearly with some examples. Many thank in advance

Mauri
  • 1,185
  • 1
  • 13
  • 21
  • `Can anybody explain it clearly` - too broad. Should someone repeat [CMake documentation](https://cmake.org/cmake/help/v3.9/manual/cmake-generator-expressions.7.html)? Or other manual? Otherwise, explain **what exactly** you don't understand, e.g. which expression, or which example. – Tsyvarev Sep 13 '17 at 20:52
  • 3
    @Tsyvarev I added the documentation of the part, that I didn't understand – Mauri Sep 13 '17 at 21:07
  • 6
    `$` is nearly a half of all usage of generator expressions. Its meaning in short: if generator expression `xxx` is evaluated to TRUE (as boolean), then value of generator expression `yy` is used. Otherwise, empty string is used. Usefullness of this kind of expression is: when value of the left generator expressions depends on configuration option, and build system supports multiconfiguration (e.g. Visual Studio), then such expression cannot be rewritten with `if`, as concrete configuration isn't known at this stage. – Tsyvarev Sep 13 '17 at 21:56

1 Answers1

43

CMake does first parse the CMakeLists.txt files in your project - named "Configuration Phase" - and then it generates your build environment - named "Generation Phase".

So basically the generator expressions are for everything only the generator could know:

  • The name and path of target outputs (mainly when cross-compiling and in multi-configuration environments)
  • Or more generally any target property that the generator evaluates to mingle together the compiler/linker calls

Here are examples where I use generator expressions in my project:

  1. Copying files next to the executable (in multi-configuration environments you can't just use variables like CMAKE_CURRENT_BINARY_DIR)

    add_custom_command(
        TARGET library1 
        POST_BUILD
        COMMAND ${CMAKE_COMMAND} -E copy
            "$<TARGET_FILE:library1>"
            "$<TARGET_FILE_DIR:mainProject>/$<TARGET_FILE_NAME:library1>"
    )
    

    CMake post-build-event: copy compiled libraries

    add_custom_command(
        TARGET myBinary 
        POST_BUILD
            COMMAND ${CMAKE_COMMAND} -E copy  
                         "${CMAKE_CURRENT_SOURCE_DIR}/myTest.txt" 
                         "$<TARGET_FILE_DIR:myBinary>/myTest.txt"
    )
    

    how do I add external test files to a cmake project

  2. Differentiate e.g. DEBUG or RELEASE configurations

    add_compile_options("$<$<CONFIG:DEBUG>:/MDd>")
    

    For Cmake, can you modify the release/debug compiler flags with `add_compiler_flags()` command?

    Modern way to set compiler flags in cross-platform cmake project

  3. With the TARGET_PROPERTY generator expression you could do a lot of things e.g.

    file(GENERATE 
        OUTPUT "includes.txt" 
        CONTENT "$<TARGET_PROPERTY:motor,INCLUDE_DIRECTORIES>\n"
    )
    

    CMake doesn't pick up INTERFACE_INCLUDE_DIRECTORIES of linked library

Florian
  • 39,996
  • 9
  • 133
  • 149
  • 2
    In 1 you're saying that "in multi-configuration environments you can't just use variables like `CMAKE_CURRENT_BINARY_DIR`", why? – Shlomo Gottlieb Apr 30 '22 at 11:33