Adding Generator Expressions.rst 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. Step 10: Adding Generator Expressions
  2. =====================================
  3. :manual:`Generator expressions <cmake-generator-expressions(7)>` are evaluated
  4. during build system generation to produce information specific to each build
  5. configuration.
  6. :manual:`Generator expressions <cmake-generator-expressions(7)>` are allowed in
  7. the context of many target properties, such as :prop_tgt:`LINK_LIBRARIES`,
  8. :prop_tgt:`INCLUDE_DIRECTORIES`, :prop_tgt:`COMPILE_DEFINITIONS` and others.
  9. They may also be used when using commands to populate those properties, such as
  10. :command:`target_link_libraries`, :command:`target_include_directories`,
  11. :command:`target_compile_definitions` and others.
  12. :manual:`Generator expressions <cmake-generator-expressions(7)>` may be used
  13. to enable conditional linking, conditional definitions used when compiling,
  14. conditional include directories and more. The conditions may be based on the
  15. build configuration, target properties, platform information or any other
  16. queryable information.
  17. There are different types of
  18. :manual:`generator expressions <cmake-generator-expressions(7)>` including
  19. Logical, Informational, and Output expressions.
  20. Logical expressions are used to create conditional output. The basic
  21. expressions are the ``0`` and ``1`` expressions. A ``$<0:...>`` results in the
  22. empty string, and ``<1:...>`` results in the content of ``...``. They can also
  23. be nested.
  24. A common usage of
  25. :manual:`generator expressions <cmake-generator-expressions(7)>` is to
  26. conditionally add compiler flags, such as those for language levels or
  27. warnings. A nice pattern is to associate this information to an ``INTERFACE``
  28. target allowing this information to propagate. Let's start by constructing an
  29. ``INTERFACE`` target and specifying the required C++ standard level of ``11``
  30. instead of using :variable:`CMAKE_CXX_STANDARD`.
  31. So the following code:
  32. .. literalinclude:: Step10/CMakeLists.txt
  33. :caption: CMakeLists.txt
  34. :name: CMakeLists.txt-CXX_STANDARD-variable-remove
  35. :language: cmake
  36. :start-after: project(Tutorial VERSION 1.0)
  37. :end-before: # control where the static and shared libraries are built so that on windows
  38. Would be replaced with:
  39. .. literalinclude:: Step11/CMakeLists.txt
  40. :caption: CMakeLists.txt
  41. :name: CMakeLists.txt-cxx_std-feature
  42. :language: cmake
  43. :start-after: project(Tutorial VERSION 1.0)
  44. :end-before: # add compiler warning flags just when building this project via
  45. **Note**: This upcoming section will require a change to the
  46. :command:`cmake_minimum_required` usage in the code. The Generator Expression
  47. that is about to be used was introduced in `3.15`. Update the call to require
  48. that more recent version:
  49. .. code-block:: cmake
  50. :caption: CMakeLists.txt
  51. :name: CMakeLists.txt-version-update
  52. cmake_minimum_required(VERSION 3.15)
  53. Next we add the desired compiler warning flags that we want for our project. As
  54. warning flags vary based on the compiler we use the ``COMPILE_LANG_AND_ID``
  55. generator expression to control which flags to apply given a language and a set
  56. of compiler ids as seen below:
  57. .. literalinclude:: Step11/CMakeLists.txt
  58. :caption: CMakeLists.txt
  59. :name: CMakeLists.txt-target_compile_options-genex
  60. :language: cmake
  61. :start-after: # the BUILD_INTERFACE genex
  62. :end-before: # control where the static and shared libraries are built so that on windows
  63. Looking at this we see that the warning flags are encapsulated inside a
  64. ``BUILD_INTERFACE`` condition. This is done so that consumers of our installed
  65. project will not inherit our warning flags.
  66. **Exercise**: Modify ``MathFunctions/CMakeLists.txt`` so that all targets have
  67. a :command:`target_link_libraries` call to ``tutorial_compiler_flags``.