| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384 |
- Step 10: Adding Generator Expressions
- =====================================
- :manual:`Generator expressions <cmake-generator-expressions(7)>` are evaluated
- during build system generation to produce information specific to each build
- configuration.
- :manual:`Generator expressions <cmake-generator-expressions(7)>` are allowed in
- the context of many target properties, such as :prop_tgt:`LINK_LIBRARIES`,
- :prop_tgt:`INCLUDE_DIRECTORIES`, :prop_tgt:`COMPILE_DEFINITIONS` and others.
- They may also be used when using commands to populate those properties, such as
- :command:`target_link_libraries`, :command:`target_include_directories`,
- :command:`target_compile_definitions` and others.
- :manual:`Generator expressions <cmake-generator-expressions(7)>` may be used
- to enable conditional linking, conditional definitions used when compiling,
- conditional include directories and more. The conditions may be based on the
- build configuration, target properties, platform information or any other
- queryable information.
- There are different types of
- :manual:`generator expressions <cmake-generator-expressions(7)>` including
- Logical, Informational, and Output expressions.
- Logical expressions are used to create conditional output. The basic
- expressions are the ``0`` and ``1`` expressions. A ``$<0:...>`` results in the
- empty string, and ``<1:...>`` results in the content of ``...``. They can also
- be nested.
- A common usage of
- :manual:`generator expressions <cmake-generator-expressions(7)>` is to
- conditionally add compiler flags, such as those for language levels or
- warnings. A nice pattern is to associate this information to an ``INTERFACE``
- target allowing this information to propagate. Let's start by constructing an
- ``INTERFACE`` target and specifying the required C++ standard level of ``11``
- instead of using :variable:`CMAKE_CXX_STANDARD`.
- So the following code:
- .. literalinclude:: Step10/CMakeLists.txt
- :caption: CMakeLists.txt
- :name: CMakeLists.txt-CXX_STANDARD-variable-remove
- :language: cmake
- :start-after: project(Tutorial VERSION 1.0)
- :end-before: # control where the static and shared libraries are built so that on windows
- Would be replaced with:
- .. literalinclude:: Step11/CMakeLists.txt
- :caption: CMakeLists.txt
- :name: CMakeLists.txt-cxx_std-feature
- :language: cmake
- :start-after: project(Tutorial VERSION 1.0)
- :end-before: # add compiler warning flags just when building this project via
- **Note**: This upcoming section will require a change to the
- :command:`cmake_minimum_required` usage in the code. The Generator Expression
- that is about to be used was introduced in `3.15`. Update the call to require
- that more recent version:
- .. code-block:: cmake
- :caption: CMakeLists.txt
- :name: CMakeLists.txt-version-update
- cmake_minimum_required(VERSION 3.15)
- Next we add the desired compiler warning flags that we want for our project. As
- warning flags vary based on the compiler we use the ``COMPILE_LANG_AND_ID``
- generator expression to control which flags to apply given a language and a set
- of compiler ids as seen below:
- .. literalinclude:: Step11/CMakeLists.txt
- :caption: CMakeLists.txt
- :name: CMakeLists.txt-target_compile_options-genex
- :language: cmake
- :start-after: # the BUILD_INTERFACE genex
- :end-before: # control where the static and shared libraries are built so that on windows
- Looking at this we see that the warning flags are encapsulated inside a
- ``BUILD_INTERFACE`` condition. This is done so that consumers of our installed
- project will not inherit our warning flags.
- **Exercise**: Modify ``MathFunctions/CMakeLists.txt`` so that all targets have
- a :command:`target_link_libraries` call to ``tutorial_compiler_flags``.
|