|
|
|
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``.
|