Merge topic 'tutorial-iface-order'

c6a426198a Tutorial: Move Step4-Ex1 to Step3-Ex2

Acked-by: Kitware Robot <kwrobot@kitware.com>
Merge-request: !8417
This commit is contained in:
Brad King
2023-05-01 15:37:33 +00:00
committed by Kitware Robot
7 changed files with 225 additions and 200 deletions
@@ -27,168 +27,7 @@ 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.
Exercise 1 - Setting the C++ Standard with Interface Libraries
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Before we use :manual:`generator expressions <cmake-generator-expressions(7)>`
let's refactor our existing code to use an ``INTERFACE`` library. We will
use that library in the next step to demonstrate a common use for
:manual:`generator expressions <cmake-generator-expressions(7)>`.
Goal
----
Add an ``INTERFACE`` library target to specify the required C++ standard.
Helpful Resources
-----------------
* :command:`add_library`
* :command:`target_compile_features`
* :command:`target_link_libraries`
Files to Edit
-------------
* ``CMakeLists.txt``
* ``MathFunctions/CMakeLists.txt``
Getting Started
---------------
In this exercise, we will refactor our code to use an ``INTERFACE`` library to
specify the C++ standard.
The starting source code is provided in the ``Step4`` directory. In this
exercise, complete ``TODO 1`` through ``TODO 3``.
Start by editing the top level ``CMakeLists.txt`` file. Construct an
``INTERFACE`` library target called ``tutorial_compiler_flags`` and
specify ``cxx_std_11`` as a target compiler feature.
Modify ``CMakeLists.txt`` and ``MathFunctions/CMakeLists.txt`` so that all
targets have a :command:`target_link_libraries` call to
``tutorial_compiler_flags``.
Build and Run
-------------
Make a new directory called ``Step4_build``, run the :manual:`cmake <cmake(1)>`
executable or the :manual:`cmake-gui <cmake-gui(1)>` to configure the project
and then build it with your chosen build tool or by using ``cmake --build .``
from the build directory.
Here's a refresher of what that looks like from the command line:
.. code-block:: console
mkdir Step4_build
cd Step4_build
cmake ../Step4
cmake --build .
Next, use the newly built ``Tutorial`` and verify that it is working as
expected.
Solution
--------
Let's update our code from the previous step to use interface libraries
to set our C++ requirements.
To start, we need to remove the two :command:`set` calls on the variables
:variable:`CMAKE_CXX_STANDARD` and :variable:`CMAKE_CXX_STANDARD_REQUIRED`.
The specific lines to remove are as follows:
.. literalinclude:: Step4/CMakeLists.txt
:caption: CMakeLists.txt
:name: CMakeLists.txt-CXX_STANDARD-variable-remove
:language: cmake
:start-after: # specify the C++ standard
:end-before: # TODO 6: Create helper variables
Next, we need to create an interface library, ``tutorial_compiler_flags``. And
then use :command:`target_compile_features` to add the compiler feature
``cxx_std_11``.
.. raw:: html
<details><summary>TODO 1: Click to show/hide answer</summary>
.. literalinclude:: Step5/CMakeLists.txt
:caption: TODO 1: CMakeLists.txt
:name: CMakeLists.txt-cxx_std-feature
:language: cmake
:start-after: # specify the C++ standard
:end-before: # add compiler warning flags just
.. raw:: html
</details>
Finally, with our interface library set up, we need to link our
executable ``Target``, our ``MathFunctions`` library, and our ``SqrtLibrary``
library to our new
``tutorial_compiler_flags`` library. Respectively, the code will look like
this:
.. raw:: html
<details><summary>TODO 2: Click to show/hide answer</summary>
.. literalinclude:: Step5/CMakeLists.txt
:caption: TODO 2: CMakeLists.txt
:name: CMakeLists.txt-target_link_libraries-step4
:language: cmake
:start-after: add_executable(Tutorial tutorial.cxx)
:end-before: # add the binary tree to the search path for include file
.. raw:: html
</details>
this:
.. raw:: html
<details><summary>TODO 3: Click to show/hide answer</summary>
.. literalinclude:: Step5/MathFunctions/CMakeLists.txt
:caption: TODO 3: MathFunctions/CMakeLists.txt
:name: MathFunctions-CMakeLists.txt-target_link_libraries-step4
:language: cmake
:start-after: # link our compiler flags interface library
:end-before: target_link_libraries(MathFunctions
.. raw:: html
</details>
and this:
.. raw:: html
<details><summary>TODO 4: Click to show/hide answer</summary>
.. literalinclude:: Step5/MathFunctions/CMakeLists.txt
:caption: TODO 4: MathFunctions/CMakeLists.txt
:name: MathFunctions-SqrtLibrary-target_link_libraries-step4
:language: cmake
:start-after: target_link_libraries(SqrtLibrary
:end-before: endif()
.. raw:: html
</details>
With this, all of our code still requires C++ 11 to build. Notice
though that with this method, it gives us the ability to be specific about
which targets get specific requirements. In addition, we create a single
source of truth in our interface library.
Exercise 2 - Adding Compiler Warning Flags with Generator Expressions
Exercise 1 - Adding Compiler Warning Flags with Generator Expressions
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
A common usage of
@@ -218,8 +57,8 @@ Files to Edit
Getting Started
---------------
Start with the resulting files from Exercise 1. Complete ``TODO 5`` through
``TODO 8``.
Open the file ``Step4/CMakeLists.txt`` and complete ``TODO 1`` through
``TODO 4``.
First, in the top level ``CMakeLists.txt`` file, we need to set the
:command:`cmake_minimum_required` to ``3.15``. In this exercise we are going
@@ -233,12 +72,16 @@ given a language and a set of compiler ids.
Build and Run
-------------
Since we have our build directory already configured from Exercise 1, simply
rebuild our code by calling the following:
Make a new directory called ``Step4_build``, run the :manual:`cmake <cmake(1)>`
executable or the :manual:`cmake-gui <cmake-gui(1)>` to configure the project
and then build it with your chosen build tool or by using ``cmake --build .``
from the build directory.
.. code-block:: console
mkdir Step4_build
cd Step4_build
cmake ../Step4
cmake --build .
Solution
@@ -249,10 +92,10 @@ version ``3.15``:
.. raw:: html
<details><summary>TODO 5: Click to show/hide answer</summary>
<details><summary>TODO 1: Click to show/hide answer</summary>
.. literalinclude:: Step5/CMakeLists.txt
:caption: TODO 5: CMakeLists.txt
:caption: TODO 1: CMakeLists.txt
:name: MathFunctions-CMakeLists.txt-minimum-required-step4
:language: cmake
:end-before: # set the project name and version
@@ -268,10 +111,10 @@ variables ``gcc_like_cxx`` and ``msvc_cxx`` as follows:
.. raw:: html
<details><summary>TODO 6: Click to show/hide answer</summary>
<details><summary>TODO 2: Click to show/hide answer</summary>
.. literalinclude:: Step5/CMakeLists.txt
:caption: TODO 6: CMakeLists.txt
:caption: TODO 2: CMakeLists.txt
:name: CMakeLists.txt-compile_lang_and_id
:language: cmake
:start-after: # the BUILD_INTERFACE genex
@@ -289,10 +132,10 @@ interface library.
.. raw:: html
<details><summary>TODO 7: Click to show/hide answer</summary>
<details><summary>TODO 3: Click to show/hide answer</summary>
.. code-block:: cmake
:caption: TODO 7: CMakeLists.txt
:caption: TODO 3: CMakeLists.txt
:name: CMakeLists.txt-compile_flags
target_compile_options(tutorial_compiler_flags INTERFACE
@@ -311,10 +154,10 @@ condition. The resulting full code looks like the following:
.. raw:: html
<details><summary>TODO 8: Click to show/hide answer</summary>
<details><summary>TODO 4: Click to show/hide answer</summary>
.. literalinclude:: Step5/CMakeLists.txt
:caption: TODO 8: CMakeLists.txt
:caption: TODO 4: CMakeLists.txt
:name: CMakeLists.txt-target_compile_options-genex
:language: cmake
:start-after: set(msvc_cxx "$<COMPILE_LANG_AND_ID:CXX,MSVC>")
@@ -100,7 +100,7 @@ follows:
:name: MathFunctions/CMakeLists.txt-target_include_directories-INTERFACE
:language: cmake
:start-after: # to find MathFunctions.h
:end-before: option
:end-before: # should we use our own
.. raw:: html
@@ -108,24 +108,26 @@ follows:
Now that we've specified usage requirements for ``MathFunctions`` we can
safely remove our uses of the ``EXTRA_INCLUDES`` variable from the top-level
``CMakeLists.txt``, here:
``CMakeLists.txt``.
Remove this line:
.. raw:: html
<details><summary>TODO 2: Click to show/hide answer</summary>
.. literalinclude:: Step4/CMakeLists.txt
.. literalinclude:: Step3/CMakeLists.txt
:caption: TODO 2: CMakeLists.txt
:name: CMakeLists.txt-remove-EXTRA_INCLUDES
:language: cmake
:start-after: # add the MathFunctions library
:end-before: # TODO 2: Link to tutorial_compiler_flags
:start-after: add_subdirectory(MathFunctions)
:end-before: # add the executable
.. raw:: html
</details>
And here:
And the lines:
.. raw:: html
@@ -141,7 +143,181 @@ And here:
</details>
The remaining code looks like:
.. raw:: html
<details><summary>Click to show/hide the resulting code</summary>
.. literalinclude:: Step4/CMakeLists.txt
:caption: Remaining code after removing EXTRA_INCLUDES
:name: CMakeLists.txt-after-removing-EXTRA_INCLUDES
:language: cmake
:start-after: add_subdirectory(MathFunctions)
.. raw:: html
</details>
Notice that with this technique, the only thing our executable target does to
use our library is call :command:`target_link_libraries` with the name
of the library target. In larger projects, the classic method of specifying
library dependencies manually becomes very complicated very quickly.
Exercise 2 - Setting the C++ Standard with Interface Libraries
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Now that we have switched our code to a more modern approach, let's demonstrate
a modern technique to set properties to multiple targets.
Let's refactor our existing code to use an ``INTERFACE`` library. We will
use that library in the next step to demonstrate a common use for
:manual:`generator expressions <cmake-generator-expressions(7)>`.
Goal
----
Add an ``INTERFACE`` library target to specify the required C++ standard.
Helpful Resources
-----------------
* :command:`add_library`
* :command:`target_compile_features`
* :command:`target_link_libraries`
Files to Edit
-------------
* ``CMakeLists.txt``
* ``MathFunctions/CMakeLists.txt``
Getting Started
---------------
In this exercise, we will refactor our code to use an ``INTERFACE`` library to
specify the C++ standard.
Start this exercise from what we left at the end of Step3 exercise 1. You will
have to complete ``TODO 4`` through ``TODO 7``.
Start by editing the top level ``CMakeLists.txt`` file. Construct an
``INTERFACE`` library target called ``tutorial_compiler_flags`` and
specify ``cxx_std_11`` as a target compiler feature.
Modify ``CMakeLists.txt`` and ``MathFunctions/CMakeLists.txt`` so that all
targets have a :command:`target_link_libraries` call to
``tutorial_compiler_flags``.
Build and Run
-------------
Since we have our build directory already configured from Exercise 1, simply
rebuild our code by calling the following:
.. code-block:: console
cd Step3_build
cmake --build .
Next, use the newly built ``Tutorial`` and verify that it is working as
expected.
Solution
--------
Let's update our code from the previous step to use interface libraries
to set our C++ requirements.
To start, we need to remove the two :command:`set` calls on the variables
:variable:`CMAKE_CXX_STANDARD` and :variable:`CMAKE_CXX_STANDARD_REQUIRED`.
The specific lines to remove are as follows:
.. literalinclude:: Step3/CMakeLists.txt
:caption: CMakeLists.txt
:name: CMakeLists.txt-CXX_STANDARD-variable-remove
:language: cmake
:start-after: # specify the C++ standard
:end-before: # configure a header file
Next, we need to create an interface library, ``tutorial_compiler_flags``. And
then use :command:`target_compile_features` to add the compiler feature
``cxx_std_11``.
.. raw:: html
<details><summary>TODO 4: Click to show/hide answer</summary>
.. literalinclude:: Step4/CMakeLists.txt
:caption: TODO 4: CMakeLists.txt
:name: CMakeLists.txt-cxx_std-feature
:language: cmake
:start-after: # specify the C++ standard
:end-before: # TODO 2: Create helper
.. raw:: html
</details>
Finally, with our interface library set up, we need to link our
executable ``Target``, our ``MathFunctions`` library, and our ``SqrtLibrary``
library to our new
``tutorial_compiler_flags`` library. Respectively, the code will look like
this:
.. raw:: html
<details><summary>TODO 5: Click to show/hide answer</summary>
.. literalinclude:: Step4/CMakeLists.txt
:caption: TODO 5: CMakeLists.txt
:name: CMakeLists.txt-target_link_libraries-step4
:language: cmake
:start-after: add_executable(Tutorial tutorial.cxx)
:end-before: # add the binary tree to the search path for include file
.. raw:: html
</details>
this:
.. raw:: html
<details><summary>TODO 6: Click to show/hide answer</summary>
.. literalinclude:: Step4/MathFunctions/CMakeLists.txt
:caption: TODO 6: MathFunctions/CMakeLists.txt
:name: MathFunctions-CMakeLists.txt-target_link_libraries-step4
:language: cmake
:start-after: # link our compiler flags interface library
:end-before: target_link_libraries(MathFunctions
.. raw:: html
</details>
and this:
.. raw:: html
<details><summary>TODO 7: Click to show/hide answer</summary>
.. literalinclude:: Step4/MathFunctions/CMakeLists.txt
:caption: TODO 7: MathFunctions/CMakeLists.txt
:name: MathFunctions-SqrtLibrary-target_link_libraries-step4
:language: cmake
:start-after: target_link_libraries(SqrtLibrary
:end-before: endif()
.. raw:: html
</details>
With this, all of our code still requires C++ 11 to build. Notice
though that with this method, it gives us the ability to be specific about
which targets get specific requirements. In addition, we create a single
source of truth in our interface library.
+3 -2
View File
@@ -409,7 +409,7 @@ that has sources ``mysqrt.cxx``.
:name: MathFunctions/CMakeLists.txt-add_library-SqrtLibrary
:language: cmake
:start-after: # library that just does sqrt
:end-before: target_link_libraries(MathFunctions
:end-before: # TODO 7: Link
.. raw:: html
@@ -426,7 +426,8 @@ enabled.
:caption: TODO 13 : MathFunctions/CMakeLists.txt
:name: MathFunctions/CMakeLists.txt-target_link_libraries-SqrtLibrary
:language: cmake
:lines: 16-18
:start-after: to tutorial_compiler_flags
:end-before: endif()
.. raw:: html
+8
View File
@@ -3,6 +3,12 @@ cmake_minimum_required(VERSION 3.10)
# set the project name and version
project(Tutorial VERSION 1.0)
# TODO 4: Replace the following code by:
# * Creating an interface library called tutorial_compiler_flags
# Hint: use add_library() with the INTERFACE signature
# * Add compiler feature cxx_std_11 to tutorial_compiler_flags
# Hint: Use target_compile_features()
# specify the C++ standard
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED True)
@@ -20,6 +26,8 @@ list(APPEND EXTRA_INCLUDES "${PROJECT_SOURCE_DIR}/MathFunctions")
# add the executable
add_executable(Tutorial tutorial.cxx)
# TODO 5: Link Tutorial to tutorial_compiler_flags
target_link_libraries(Tutorial PUBLIC MathFunctions)
# TODO 3: Remove use of EXTRA_INCLUDES
@@ -14,5 +14,9 @@ if (USE_MYMATH)
mysqrt.cxx
)
# TODO 7: Link SqrtLibrary to tutorial_compiler_flags
target_link_libraries(MathFunctions PUBLIC SqrtLibrary)
endif()
# TODO 6: Link MathFunctions to tutorial_compiler_flags
+7 -15
View File
@@ -1,33 +1,27 @@
# TODO 5: Update the minimum required version to 3.15
# TODO 1: Update the minimum required version to 3.15
cmake_minimum_required(VERSION 3.10)
# set the project name and version
project(Tutorial VERSION 1.0)
# TODO 1: Replace the following code by:
# * Creating an interface library called tutorial_compiler_flags
# Hint: use add_library() with the INTERFACE signature
# * Add compiler feature cxx_std_11 to tutorial_compiler_flags
# Hint: Use target_compile_features()
# specify the C++ standard
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED True)
add_library(tutorial_compiler_flags INTERFACE)
target_compile_features(tutorial_compiler_flags INTERFACE cxx_std_11)
# TODO 6: Create helper variables to determine which compiler we are using:
# TODO 2: Create helper variables to determine which compiler we are using:
# * Create a new variable gcc_like_cxx that is true if we are using CXX and
# any of the following compilers: ARMClang, AppleClang, Clang, GNU, LCC
# * Create a new variable msvc_cxx that is true if we are using CXX and MSVC
# Hint: Use set() and COMPILE_LANG_AND_ID
# TODO 7: Add warning flag compile options to the interface library
# TODO 3: Add warning flag compile options to the interface library
# tutorial_compiler_flags.
# * For gcc_like_cxx, add flags -Wall;-Wextra;-Wshadow;-Wformat=2;-Wunused
# * For msvc_cxx, add flags -W3
# Hint: Use target_compile_options()
# TODO 8: With nested generator expressions, only use the flags for the
# TODO 4: With nested generator expressions, only use the flags for the
# build-tree
# Hint: Use BUILD_INTERFACE
@@ -41,9 +35,7 @@ add_subdirectory(MathFunctions)
# add the executable
add_executable(Tutorial tutorial.cxx)
# TODO 2: Link to tutorial_compiler_flags
target_link_libraries(Tutorial PUBLIC MathFunctions)
target_link_libraries(Tutorial PUBLIC MathFunctions tutorial_compiler_flags)
# add the binary tree to the search path for include files
# so that we will find TutorialConfig.h
@@ -17,9 +17,10 @@ if (USE_MYMATH)
mysqrt.cxx
)
# TODO 4: Link to tutorial_compiler_flags
# link our compiler flags interface library
target_link_libraries(SqrtLibrary PUBLIC tutorial_compiler_flags)
target_link_libraries(MathFunctions PUBLIC SqrtLibrary)
endif()
# TODO 3: Link to tutorial_compiler_flags
# link our compiler flags interface library
target_link_libraries(MathFunctions PUBLIC tutorial_compiler_flags)