diff options
Diffstat (limited to 'Help/guide/tutorial')
58 files changed, 1207 insertions, 572 deletions
diff --git a/Help/guide/tutorial/A Basic Starting Point.rst b/Help/guide/tutorial/A Basic Starting Point.rst index cf1ec01..3dac68a 100644 --- a/Help/guide/tutorial/A Basic Starting Point.rst +++ b/Help/guide/tutorial/A Basic Starting Point.rst @@ -1,34 +1,81 @@ Step 1: A Basic Starting Point ============================== -The most basic project is an executable built from source code files. -For simple projects, a three line ``CMakeLists.txt`` file is all that is -required. This will be the starting point for our tutorial. Create a -``CMakeLists.txt`` file in the ``Step1`` directory that looks like: - -.. code-block:: cmake - :caption: CMakeLists.txt - :name: CMakeLists.txt-start - - cmake_minimum_required(VERSION 3.10) +Where do I start with CMake? This step will provide an introduction to some of +CMake's basic syntax, commands, and variables. As these concepts are +introduced, we will work through three exercises and create a simple CMake +project. + +Each exercise in this step will start with some background information. Then, a +goal and list of helpful resources are provided. Each file in the +``Files to Edit`` section is in the ``Step1`` directory and contains one or +more ``TODO`` comments. Each ``TODO`` represents a line or two of code to +change or add. The ``TODO`` s are intended to be completed in numerical order, +first complete ``TODO 1`` then ``TODO 2``, etc. The ``Getting Started`` +section will give some helpful hints and guide you through the exercise. Then +the ``Build and Run`` section will walk step-by-step through how to build and +test the exercise. Finally, at the end of each exercise the intended solution +is discussed. + +Also note that each step in the tutorial builds on the next. So, for example, +the starting code for ``Step2`` is the complete solution to ``Step1``. + +Exercise 1 - Building a Basic Project +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The most basic CMake project is an executable built from a single source code +file. For simple projects like this, a ``CMakeLists.txt`` file with three +commands is all that is required. + +**Note:** Although upper, lower and mixed case commands are supported by CMake, +lower case commands are preferred and will be used throughout the tutorial. + +Any project's top most CMakeLists.txt must start by specifying a minimum CMake +version using the :command:`cmake_minimum_required` command. This establishes +policy settings and ensures that the following CMake functions are run with a +compatible version of CMake. + +To start a project, we use the :command:`project` command to set the project +name. This call is required with every project and should be called soon after +:command:`cmake_minimum_required`. As we will see later, this command can +also be used to specify other project level information such as the language +or version number. + +Finally, the :command:`add_executable` command tells CMake to create an +executable using the specified source code files. + +Goal +---- + +Understand how to create a simple CMake project. + +Helpful Resources +----------------- + +* :command:`add_executable` +* :command:`cmake_minimum_required` +* :command:`project` + +Files to Edit +------------- - # set the project name - project(Tutorial) +* ``CMakeLists.txt`` - # add the executable - add_executable(Tutorial tutorial.cxx) +Getting Started +---------------- +The source code for ``tutorial.cxx`` is provided in the +``Help/guide/tutorial/Step1`` directory and can be used to compute the square +root of a number. This file does not need to be edited in this step. -Note that this example uses lower case commands in the ``CMakeLists.txt`` file. -Upper, lower, and mixed case commands are supported by CMake. The source -code for ``tutorial.cxx`` is provided in the ``Step1`` directory and can be -used to compute the square root of a number. +In the same directory is a ``CMakeLists.txt`` file which you will complete. +Start with ``TODO 1`` and work through ``TODO 3``. Build and Run ------------- -That's all that is needed - we can build and run our project now! First, run -the :manual:`cmake <cmake(1)>` executable or the +Once ``TODO 1`` through ``TODO 3`` have been completed, we are ready to build +and run our project! First, 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. @@ -40,8 +87,9 @@ build directory: mkdir Step1_build -Next, navigate to the build directory and run CMake to configure the project -and generate a native build system: +Next, navigate to that build directory and run +:manual:`cmake <cmake(1)>` to configure the project and generate a native build +system: .. code-block:: console @@ -62,114 +110,352 @@ Finally, try to use the newly built ``Tutorial`` with these commands: Tutorial 10 Tutorial +Solution +-------- -Adding a Version Number and Configured Header File --------------------------------------------------- +As mentioned above, a three line ``CMakeLists.txt`` is all that we need to get +up and running. The first line is to use :command:`cmake_minimum_required` to +set the CMake version as follows: -The first feature we will add is to provide our executable and project with a -version number. While we could do this exclusively in the source code, using -``CMakeLists.txt`` provides more flexibility. +.. raw:: html -First, modify the ``CMakeLists.txt`` file to use the :command:`project` command -to set the project name and version number. + <details><summary>TODO 1: Click to show/hide answer</summary> .. literalinclude:: Step2/CMakeLists.txt - :caption: CMakeLists.txt - :name: CMakeLists.txt-project-VERSION + :caption: TODO 1: CMakeLists.txt + :name: CMakeLists.txt-cmake_minimum_required :language: cmake - :end-before: # specify the C++ standard + :end-before: # set the project name and version -Then, configure a header file to pass the version number to the source -code: +.. raw:: html -.. literalinclude:: Step2/CMakeLists.txt - :caption: CMakeLists.txt - :name: CMakeLists.txt-configure_file - :language: cmake - :start-after: # to the source code - :end-before: # add the executable + </details> + +The next step to make a basic project is to use the :command:`project` +command as follows to set the project name: + +.. raw:: html + + <details><summary>TODO 2: Click to show/hide answer</summary> + +.. code-block:: cmake + :caption: TODO 2: CMakeLists.txt + :name: CMakeLists.txt-project + + project(Tutorial) + +.. raw:: html -Since the configured file will be written into the binary tree, we -must add that directory to the list of paths to search for include -files. Add the following lines to the end of the ``CMakeLists.txt`` file: + </details> + +The last command to call for a basic project is +:command:`add_executable`. We call it as follows: + +.. raw:: html + + <details><summary>TODO 3: Click to show/hide answer</summary> .. literalinclude:: Step2/CMakeLists.txt - :caption: CMakeLists.txt - :name: CMakeLists.txt-target_include_directories + :caption: TODO 3: CMakeLists.txt + :name: CMakeLists.txt-add_executable :language: cmake - :start-after: # so that we will find TutorialConfig.h + :start-after: # add the executable + :end-before: # TODO 9: -Using your favorite editor, create ``TutorialConfig.h.in`` in the source -directory with the following contents: +.. raw:: html -.. literalinclude:: Step2/TutorialConfig.h.in - :caption: TutorialConfig.h.in - :name: TutorialConfig.h.in - :language: c++ + </details> -When CMake configures this header file the values for -``@Tutorial_VERSION_MAJOR@`` and ``@Tutorial_VERSION_MINOR@`` will be -replaced. +Exercise 2 - Specifying the C++ Standard +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Next modify ``tutorial.cxx`` to include the configured header file, -``TutorialConfig.h``. +CMake has some special variables that are either created behind the scenes or +have meaning to CMake when set by project code. Many of these variables start +with ``CMAKE_``. Avoid this naming convention when creating variables for your +projects. Two of these special user settable variables are +:variable:`CMAKE_CXX_STANDARD` and :variable:`CMAKE_CXX_STANDARD_REQUIRED`. +These may be used together to specify the C++ standard needed to build the +project. -Finally, let's print out the executable name and version number by updating -``tutorial.cxx`` as follows: +Goal +---- -.. literalinclude:: Step2/tutorial.cxx - :caption: tutorial.cxx - :name: tutorial.cxx-print-version - :language: c++ - :start-after: { - :end-before: // convert input to double +Add a feature that requires C++11. + +Helpful Resources +----------------- + +* :variable:`CMAKE_CXX_STANDARD` +* :variable:`CMAKE_CXX_STANDARD_REQUIRED` +* :command:`set` + +Files to Edit +------------- -Specify the C++ Standard -------------------------- +* ``CMakeLists.txt`` +* ``tutorial.cxx`` -Next let's add some C++11 features to our project by replacing ``atof`` with -``std::stod`` in ``tutorial.cxx``. At the same time, remove -``#include <cstdlib>``. +Getting Started +--------------- + +Continue editing files in the ``Step1`` directory. Start with ``TODO 4`` and +complete through ``TODO 6``. + +First, edit ``tutorial.cxx`` by adding a feature that requires C++11. Then +update ``CMakeLists.txt`` to require C++11. + +Build and Run +------------- + +Let's build our project again. Since we already created a build directory and +ran CMake for Exercise 1, we can skip to the build step: + +.. code-block:: console + + cd Step1_build + cmake --build . + +Now we can try to use the newly built ``Tutorial`` with same commands as +before: + +.. code-block:: console + + Tutorial 4294967296 + Tutorial 10 + Tutorial + +Solution +-------- + +We start by adding some C++11 features to our project by replacing +``atof`` with ``std::stod`` in ``tutorial.cxx``. This looks like +the following: + +.. raw:: html + + <details><summary>TODO 4: Click to show/hide answer</summary> .. literalinclude:: Step2/tutorial.cxx - :caption: tutorial.cxx + :caption: TODO 4: tutorial.cxx :name: tutorial.cxx-cxx11 :language: c++ :start-after: // convert input to double - :end-before: // calculate square root + :end-before: // TODO 12: + +.. raw:: html + + </details> + +To complete ``TODO 5``, simply remove ``#include <cstdlib>``. We will need to explicitly state in the CMake code that it should use the -correct flags. The easiest way to enable support for a specific C++ standard -in CMake is by using the :variable:`CMAKE_CXX_STANDARD` variable. For this -tutorial, set the :variable:`CMAKE_CXX_STANDARD` variable in the -``CMakeLists.txt`` file to ``11`` and :variable:`CMAKE_CXX_STANDARD_REQUIRED` -to ``True``. Make sure to add the ``CMAKE_CXX_STANDARD`` declarations above the -call to ``add_executable``. +correct flags. One way to enable support for a specific C++ standard in CMake +is by using the :variable:`CMAKE_CXX_STANDARD` variable. For this tutorial, set +the :variable:`CMAKE_CXX_STANDARD` variable in the ``CMakeLists.txt`` file to +``11`` and :variable:`CMAKE_CXX_STANDARD_REQUIRED` to ``True``. Make sure to +add the :variable:`CMAKE_CXX_STANDARD` declarations above the call to +:command:`add_executable`. + +.. raw:: html + + <details><summary>TODO 6: Click to show/hide answer</summary> .. literalinclude:: Step2/CMakeLists.txt - :caption: CMakeLists.txt + :caption: TODO 6: CMakeLists.txt :name: CMakeLists.txt-CXX_STANDARD :language: cmake - :end-before: # configure a header file to pass some of the CMake settings + :start-after: # specify the C++ standard + :end-before: # TODO 7: + +.. raw:: html -Rebuild -------- + </details> -Let's build our project again. We already created a build directory and ran -CMake, so we can skip to the build step: +Exercise 3 - Adding a Version Number and Configured Header File +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Sometimes it may be useful to have a variable that is defined in your +``CMakelists.txt`` file also be available in your source code. In this case, we +would like to print the project version. + +One way to accomplish this is by using a configured header file. We create an +input file with one or more variables to replace. These variables have special +syntax which looks like ``@VAR@``. +Then, we use the :command:`configure_file` command to copy the input file to a +given output file and replace these variables with the current value of ``VAR`` +in the ``CMakelists.txt`` file. + +While we could edit the version directly in the source code, using this +feature is preferred since it creates a single source of truth and avoids +duplication. + +Goal +---- + +Define and report the project's version number. + +Helpful Resources +----------------- + +* :variable:`<PROJECT-NAME>_VERSION_MAJOR` +* :variable:`<PROJECT-NAME>_VERSION_MINOR` +* :command:`configure_file` +* :command:`target_include_directories` + +Files to Edit +------------- + +* ``CMakeLists.txt`` +* ``tutorial.cxx`` + +Getting Started +--------------- + +Continue to edit files from ``Step1``. Start on ``TODO 7`` and complete through +``TODO 12``. In this exercise, we start by adding a project version number in +``CMakeLists.txt``. In that same file, use :command:`configure_file` to copy a +given input file to an output file and substitute some variable values in the +input file content. + +Next, create an input header file ``TutorialConfig.h.in`` defining version +numbers which will accept variables passed from :command:`configure_file`. + +Finally, update ``tutorial.cxx`` to print out its version number. + +Build and Run +------------- + +Let's build our project again. As before, we already created a build directory +and ran CMake so we can skip to the build step: .. code-block:: console cd Step1_build cmake --build . -Now we can try to use the newly built ``Tutorial`` with same commands as before: +Verify that the version number is now reported when running the executable +without any arguments. -.. code-block:: console +Solution +-------- - Tutorial 4294967296 - Tutorial 10 - Tutorial +In this exercise, we improve our executable by printing a version number. +While we could do this exclusively in the source code, using ``CMakeLists.txt`` +lets us maintain a single source of data for the version number. + +First, we modify the ``CMakeLists.txt`` file to use the +:command:`project` command to set both the project name and version number. +When the :command:`project` command is called, CMake defines +``Tutorial_VERSION_MAJOR`` and ``Tutorial_VERSION_MINOR`` behind the scenes. + +.. raw:: html + + <details><summary>TODO 7: Click to show/hide answer</summary> + +.. literalinclude:: Step2/CMakeLists.txt + :caption: TODO 7: CMakeLists.txt + :name: CMakeLists.txt-project-VERSION + :language: cmake + :start-after: # set the project name and version + :end-before: # specify the C++ standard + +.. raw:: html + + </details> + +Then we used :command:`configure_file` to copy the input file with the +specified CMake variables replaced: + +.. raw:: html + + <details><summary>TODO 8: Click to show/hide answer</summary> + +.. literalinclude:: Step2/CMakeLists.txt + :caption: TODO 8: CMakeLists.txt + :name: CMakeLists.txt-configure_file + :language: cmake + :start-after: # to the source code + :end-before: # TODO 8: + +.. raw:: html + + </details> + +Since the configured file will be written into the project binary +directory, we must add that directory to the list of paths to search for +include files. + +**Note:** Throughout this tutorial, we will refer to the project build and +the project binary directory interchangeably. These are the same and are not +meant to refer to a `bin/` directory. + +We used :command:`target_include_directories` to specify +where the executable target should look for include files. + +.. raw:: html + + <details><summary>TODO 9: Click to show/hide answer</summary> + +.. literalinclude:: Step2/CMakeLists.txt + :caption: TODO 9: CMakeLists.txt + :name: CMakeLists.txt-target_include_directories + :language: cmake + :start-after: # so that we will find TutorialConfig.h + +.. raw:: html + + </details> + +``TutorialConfig.h.in`` is the input header file to be configured. +When :command:`configure_file` is called from our ``CMakeLists.txt``, the +values for ``@Tutorial_VERSION_MAJOR@`` and ``@Tutorial_VERSION_MINOR@`` will +be replaced with the corresponding version numbers from the project in +``TutorialConfig.h``. + +.. raw:: html + + <details><summary>TODO 10: Click to show/hide answer</summary> + +.. literalinclude:: Step2/TutorialConfig.h.in + :caption: TODO 10: TutorialConfig.h.in + :name: TutorialConfig.h.in + :language: c++ + :end-before: // TODO 13: + +.. raw:: html + + </details> + +Next, we need to modify ``tutorial.cxx`` to include the configured header file, +``TutorialConfig.h``. + +.. raw:: html + + <details><summary>TODO 11: Click to show/hide answer</summary> + +.. code-block:: c++ + :caption: TODO 11: tutorial.cxx + + #include "TutorialConfig.h" + +.. raw:: html + + </details> + +Finally, we print out the executable name and version number by updating +``tutorial.cxx`` as follows: + +.. raw:: html + + <details><summary>TODO 12: Click to show/hide answer</summary> + +.. literalinclude:: Step2/tutorial.cxx + :caption: TODO 12 : tutorial.cxx + :name: tutorial.cxx-print-version + :language: c++ + :start-after: { + :end-before: // convert input to double + +.. raw:: html -Check that the version number is now reported when running the executable without -any arguments. + </details> diff --git a/Help/guide/tutorial/Adding Generator Expressions.rst b/Help/guide/tutorial/Adding Generator Expressions.rst index 7fcc97f..0efce8d 100644 --- a/Help/guide/tutorial/Adding Generator Expressions.rst +++ b/Help/guide/tutorial/Adding Generator Expressions.rst @@ -1,4 +1,4 @@ -Step 10: Adding Generator Expressions +Step 4: Adding Generator Expressions ===================================== :manual:`Generator expressions <cmake-generator-expressions(7)>` are evaluated @@ -37,16 +37,16 @@ instead of using :variable:`CMAKE_CXX_STANDARD`. So the following code: -.. literalinclude:: Step10/CMakeLists.txt +.. literalinclude:: Step4/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 + :end-before: # should we use our own math functions Would be replaced with: -.. literalinclude:: Step11/CMakeLists.txt +.. literalinclude:: Step5/CMakeLists.txt :caption: CMakeLists.txt :name: CMakeLists.txt-cxx_std-feature :language: cmake @@ -69,12 +69,12 @@ 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 +.. literalinclude:: Step5/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 + :end-before: # should we use our own math functions 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 diff --git a/Help/guide/tutorial/Adding Support for a Testing Dashboard.rst b/Help/guide/tutorial/Adding Support for a Testing Dashboard.rst index c6e0fd0..45d5976 100644 --- a/Help/guide/tutorial/Adding Support for a Testing Dashboard.rst +++ b/Help/guide/tutorial/Adding Support for a Testing Dashboard.rst @@ -1,4 +1,4 @@ -Step 8: Adding Support for a Testing Dashboard +Step 6: Adding Support for a Testing Dashboard ============================================== Adding support for submitting our test results to a dashboard is simple. We @@ -9,21 +9,21 @@ we include the :module:`CTest` module in our top-level ``CMakeLists.txt``. Replace: -.. code-block:: cmake +.. literalinclude:: Step6/CMakeLists.txt :caption: CMakeLists.txt :name: CMakeLists.txt-enable_testing-remove - - # enable testing - enable_testing() + :language: cmake + :start-after: # enable testing + :end-before: # does the application run With: -.. code-block:: cmake +.. literalinclude:: Step7/CMakeLists.txt :caption: CMakeLists.txt :name: CMakeLists.txt-include-CTest - - # enable dashboard scripting - include(CTest) + :language: cmake + :start-after: # enable testing + :end-before: # does the application run The :module:`CTest` module will automatically call ``enable_testing()``, so we can remove it from our CMake files. @@ -46,7 +46,7 @@ downloaded from the ``Settings`` page of the project on the CDash instance that will host and display the test results. Once downloaded from CDash, the file should not be modified locally. -.. literalinclude:: Step9/CTestConfig.cmake +.. literalinclude:: Step7/CTestConfig.cmake :caption: CTestConfig.cmake :name: CTestConfig.cmake :language: cmake diff --git a/Help/guide/tutorial/Adding System Introspection.rst b/Help/guide/tutorial/Adding System Introspection.rst index 8db0cb8..4f3e808 100644 --- a/Help/guide/tutorial/Adding System Introspection.rst +++ b/Help/guide/tutorial/Adding System Introspection.rst @@ -1,4 +1,4 @@ -Step 5: Adding System Introspection +Step 7: Adding System Introspection =================================== Let us consider adding some code to our project that depends on features the @@ -15,7 +15,7 @@ these functions using the :module:`CheckCXXSourceCompiles` module in Add the checks for ``log`` and ``exp`` to ``MathFunctions/CMakeLists.txt``, after the call to :command:`target_include_directories`: -.. literalinclude:: Step6/MathFunctions/CMakeLists.txt +.. literalinclude:: Step8/MathFunctions/CMakeLists.txt :caption: MathFunctions/CMakeLists.txt :name: MathFunctions/CMakeLists.txt-check_cxx_source_compiles :language: cmake @@ -25,7 +25,7 @@ after the call to :command:`target_include_directories`: If available, use :command:`target_compile_definitions` to specify ``HAVE_LOG`` and ``HAVE_EXP`` as ``PRIVATE`` compile definitions. -.. literalinclude:: Step6/MathFunctions/CMakeLists.txt +.. literalinclude:: Step8/MathFunctions/CMakeLists.txt :caption: MathFunctions/CMakeLists.txt :name: MathFunctions/CMakeLists.txt-target_compile_definitions :language: cmake @@ -37,7 +37,7 @@ compute the square root in the ``mysqrt`` function. Add the following code to the ``mysqrt`` function in ``MathFunctions/mysqrt.cxx`` (don't forget the ``#endif`` before returning the result!): -.. literalinclude:: Step6/MathFunctions/mysqrt.cxx +.. literalinclude:: Step8/MathFunctions/mysqrt.cxx :caption: MathFunctions/mysqrt.cxx :name: MathFunctions/mysqrt.cxx-ifdef :language: c++ @@ -46,7 +46,7 @@ the ``mysqrt`` function in ``MathFunctions/mysqrt.cxx`` (don't forget the We will also need to modify ``mysqrt.cxx`` to include ``cmath``. -.. literalinclude:: Step6/MathFunctions/mysqrt.cxx +.. literalinclude:: Step8/MathFunctions/mysqrt.cxx :caption: MathFunctions/mysqrt.cxx :name: MathFunctions/mysqrt.cxx-include-cmath :language: c++ diff --git a/Help/guide/tutorial/Adding Usage Requirements for a Library.rst b/Help/guide/tutorial/Adding Usage Requirements for a Library.rst index a8e914e..b521896 100644 --- a/Help/guide/tutorial/Adding Usage Requirements for a Library.rst +++ b/Help/guide/tutorial/Adding Usage Requirements for a Library.rst @@ -1,52 +1,142 @@ Step 3: Adding Usage Requirements for a Library =============================================== -Usage requirements allow for far better control over a library or executable's -link and include line while also giving more control over the transitive -property of targets inside CMake. The primary commands that leverage usage -requirements are: - - - :command:`target_compile_definitions` - - :command:`target_compile_options` - - :command:`target_include_directories` - - :command:`target_link_libraries` - -Let's refactor our code from :guide:`tutorial/Adding a Library` to use the -modern CMake approach of usage requirements. We first state that anybody -linking to ``MathFunctions`` needs to include the current source directory, -while ``MathFunctions`` itself doesn't. So this can become an ``INTERFACE`` -usage requirement. - -Remember ``INTERFACE`` means things that consumers require but the producer -doesn't. Add the following lines to the end of -``MathFunctions/CMakeLists.txt``: +Exercise 1 - Adding Usage Requirements for a Library +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Usage requirements allow for far better control over a library or +executable's link and include line while also giving more control over the +transitive property of targets inside CMake. The primary commands that +leverage usage requirements are: + +* :command:`target_compile_definitions` +* :command:`target_compile_options` +* :command:`target_include_directories` +* :command:`target_link_libraries` + +Goal +---- + +Add usage requirements for a library. + +Helpful Materials +----------------- + +* :command:`target_include_directories` +* :variable:`CMAKE_CURRENT_SOURCE_DIR` + +Files to Edit +------------- + +* ``MathFunctions/CMakeLists.txt`` +* ``CMakeLists.txt`` + +Getting Started +--------------- + +In this exercise, we will refactor our code from +:guide:`tutorial/Adding a Library` to use the modern CMake approach. We will +let our library define its own usage requirements so they are passed +transitively to other targets as necessary. In this case, ``MathFunctions`` +will specify any needed include directories itself. Then, the consuming target +``Tutorial`` simply needs to link to ``MathFunctions`` and not worry about +any additional include directories. + +The starting source code is provided in the ``Step3`` directory. In this +exercise, complete ``TODO 1`` through ``TODO 3``. + +First, add a call to :command:`target_include_directories` in +``MathFunctions/CMakeLists``. Remember that +:variable:`CMAKE_CURRENT_SOURCE_DIR` is the path to the source directory +currently being processed. + +Then, update (and simplify!) the call to +:command:`target_include_directories` in the top-level ``CMakeLists.txt``. + +Build and Run +------------- + +Make a new directory called ``Step3_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 Step3_build + cd Step3_build + cmake ../Step3 + cmake --build . + +Next, use the newly built ``Tutorial`` and verify that it is working as +expected. + +Solution +-------- + +Let's update the code from the previous step to use the modern CMake +approach of usage requirements. + +We want to state that anybody linking to ``MathFunctions`` needs to include +the current source directory, while ``MathFunctions`` itself doesn't. This +can be expressed with an ``INTERFACE`` usage requirement. Remember +``INTERFACE`` means things that consumers require but the producer doesn't. + +At the end of ``MathFunctions/CMakeLists.txt``, use +:command:`target_include_directories` with the ``INTERFACE`` keyword, as +follows: + +.. raw:: html + + <details><summary>TODO 1: Click to show/hide answer</summary> .. literalinclude:: Step4/MathFunctions/CMakeLists.txt - :caption: MathFunctions/CMakeLists.txt + :caption: TODO 1: MathFunctions/CMakeLists.txt :name: MathFunctions/CMakeLists.txt-target_include_directories-INTERFACE :language: cmake :start-after: # to find MathFunctions.h -Now that we've specified usage requirements for ``MathFunctions`` we can safely -remove our uses of the ``EXTRA_INCLUDES`` variable from the top-level +.. raw:: html + + </details> + +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: +.. raw:: html + + <details><summary>TODO 2: Click to show/hide answer</summary> + .. literalinclude:: Step4/CMakeLists.txt - :caption: CMakeLists.txt + :caption: TODO 2: CMakeLists.txt :name: CMakeLists.txt-remove-EXTRA_INCLUDES :language: cmake :start-after: # add the MathFunctions library :end-before: # add the executable +.. raw:: html + + </details> + And here: +.. raw:: html + + <details><summary>TODO 3: Click to show/hide answer</summary> + .. literalinclude:: Step4/CMakeLists.txt - :caption: CMakeLists.txt + :caption: TODO 3: CMakeLists.txt :name: CMakeLists.txt-target_include_directories-remove-EXTRA_INCLUDES :language: cmake :start-after: # so that we will find TutorialConfig.h -Once this is done, 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. +.. 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. diff --git a/Help/guide/tutorial/Adding a Custom Command and Generated File.rst b/Help/guide/tutorial/Adding a Custom Command and Generated File.rst index 70c6695..343979e 100644 --- a/Help/guide/tutorial/Adding a Custom Command and Generated File.rst +++ b/Help/guide/tutorial/Adding a Custom Command and Generated File.rst @@ -1,4 +1,4 @@ -Step 6: Adding a Custom Command and Generated File +Step 8: Adding a Custom Command and Generated File ================================================== Suppose, for the purpose of this tutorial, we decide that we never want to use @@ -26,7 +26,7 @@ accomplish this. First, at the top of ``MathFunctions/CMakeLists.txt``, the executable for ``MakeTable`` is added as any other executable would be added. -.. literalinclude:: Step7/MathFunctions/CMakeLists.txt +.. literalinclude:: Step9/MathFunctions/CMakeLists.txt :caption: MathFunctions/CMakeLists.txt :name: MathFunctions/CMakeLists.txt-add_executable-MakeTable :language: cmake @@ -36,7 +36,7 @@ First, at the top of ``MathFunctions/CMakeLists.txt``, the executable for Then we add a custom command that specifies how to produce ``Table.h`` by running MakeTable. -.. literalinclude:: Step7/MathFunctions/CMakeLists.txt +.. literalinclude:: Step9/MathFunctions/CMakeLists.txt :caption: MathFunctions/CMakeLists.txt :name: MathFunctions/CMakeLists.txt-add_custom_command-Table.h :language: cmake @@ -47,7 +47,7 @@ Next we have to let CMake know that ``mysqrt.cxx`` depends on the generated file ``Table.h``. This is done by adding the generated ``Table.h`` to the list of sources for the library MathFunctions. -.. literalinclude:: Step7/MathFunctions/CMakeLists.txt +.. literalinclude:: Step9/MathFunctions/CMakeLists.txt :caption: MathFunctions/CMakeLists.txt :name: MathFunctions/CMakeLists.txt-add_library-Table.h :language: cmake @@ -57,7 +57,7 @@ of sources for the library MathFunctions. We also have to add the current binary directory to the list of include directories so that ``Table.h`` can be found and included by ``mysqrt.cxx``. -.. literalinclude:: Step7/MathFunctions/CMakeLists.txt +.. literalinclude:: Step9/MathFunctions/CMakeLists.txt :caption: MathFunctions/CMakeLists.txt :name: MathFunctions/CMakeLists.txt-target_include_directories-Table.h :language: cmake @@ -67,7 +67,7 @@ directories so that ``Table.h`` can be found and included by ``mysqrt.cxx``. Now let's use the generated table. First, modify ``mysqrt.cxx`` to include ``Table.h``. Next, we can rewrite the ``mysqrt`` function to use the table: -.. literalinclude:: Step7/MathFunctions/mysqrt.cxx +.. literalinclude:: Step9/MathFunctions/mysqrt.cxx :caption: MathFunctions/mysqrt.cxx :name: MathFunctions/mysqrt.cxx :language: c++ diff --git a/Help/guide/tutorial/Adding a Library.rst b/Help/guide/tutorial/Adding a Library.rst index 71755be..46a8909 100644 --- a/Help/guide/tutorial/Adding a Library.rst +++ b/Help/guide/tutorial/Adding a Library.rst @@ -1,136 +1,458 @@ Step 2: Adding a Library ======================== -Now we will add a library to our project. This library will contain our own +At this point, we have seen how to create a basic project using CMake. In this +step, we will learn how to create and use a library in our project. We will +also see how to make the use of our library optional. + +Exercise 1 - Creating a Library +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +To add a library in CMake, use the :command:`add_library` command and specify +which source files should make up the library. + +Rather than placing all of the source files in one directory, we can organize +our project with one or more subdirectories. In this case, we will create a +subdirectory specifically for our library. Here, we can add a new +``CMakeLists.txt`` file and one or more source files. In the top level +``CMakeLists.txt`` file, we will use the :command:`add_subdirectory` command +to add the subdirectory to the build. + +Once the library is created, it is connected to our executable target with +:command:`target_include_directories` and :command:`target_link_libraries`. + +Goal +---- + +Add and use a library. + +Helpful Resources +----------------- + +* :command:`add_library` +* :command:`add_subdirectory` +* :command:`target_include_directories` +* :command:`target_link_libraries` +* :variable:`PROJECT_SOURCE_DIR` + +Files to Edit +------------- + +* ``CMakeLists.txt`` +* ``tutorial.cxx`` +* ``MathFunctions/CMakeLists.txt`` + +Getting Started +--------------- + +In this exercise, we will add a library to our project that contains our own implementation for computing the square root of a number. The executable can then use this library instead of the standard square root function provided by the compiler. -For this tutorial we will put the library into a subdirectory -called ``MathFunctions``. This directory already contains a header file, -``MathFunctions.h``, and a source file ``mysqrt.cxx``. The source file has one -function called ``mysqrt`` that provides similar functionality to the -compiler's ``sqrt`` function. +For this tutorial we will put the library into a subdirectory called +``MathFunctions``. This directory already contains a header file, +``MathFunctions.h``, and a source file ``mysqrt.cxx``. We will not need to +modify either of these files. The source file has one function called +``mysqrt`` that provides similar functionality to the compiler's ``sqrt`` +function. + +From the ``Help/guide/tutorial/Step2`` directory, start with ``TODO 1`` and +complete through ``TODO 6``. + +First, fill in the one line ``CMakeLists.txt`` in the ``MathFunctions`` +subdirectory. + +Next, edit the top level ``CMakeLists.txt``. + +Finally, use the newly created ``MathFunctions`` library in ``tutorial.cxx`` + +Build and Run +------------- + +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. + +Below is a refresher of what that looks like from the command line: + +.. code-block:: console + + mkdir Step2_build + cd Step2_build + cmake ../Step2 + cmake --build . + +Try to use the newly built ``Tutorial`` and ensure that it is still +producing accurate square root values. + +Solution +-------- + +In the ``CMakeLists.txt`` file in the ``MathFunctions`` directory, we create +a library target called ``MathFunctions`` with :command:`add_library`. The +source file for the library is passed as an argument to +:command:`add_library`. This looks like the following line: -Add the following one line ``CMakeLists.txt`` file to the ``MathFunctions`` -directory: +.. raw:: html + + <details><summary>TODO 1: Click to show/hide answer</summary> .. literalinclude:: Step3/MathFunctions/CMakeLists.txt - :caption: MathFunctions/CMakeLists.txt - :name: MathFunctions/CMakeLists.txt + :caption: TODO 1: MathFunctions/CMakeLists.txt + :name: MathFunctions/CMakeLists.txt-add_library :language: cmake + :end-before: # TODO 1 + +.. raw:: html + + </details> To make use of the new library we will add an :command:`add_subdirectory` call in the top-level ``CMakeLists.txt`` file so that the library will get -built. We add the new library to the executable, and add ``MathFunctions`` as -an include directory so that the ``MathFunctions.h`` header file can be found. -The last few lines of the top-level ``CMakeLists.txt`` file should now look -like: +built. + +.. raw:: html + + <details><summary>TODO 2: Click to show/hide answer</summary> + +.. code-block:: cmake + :caption: TODO 2: CMakeLists.txt + :name: CMakeLists.txt-add_subdirectory + + add_subdirectory(MathFunctions) + +.. raw:: html + + </details> + +Next, the new library target is linked to the executable target using +:command:`target_link_libraries`. + +.. raw:: html + + <details><summary>TODO 3: Click to show/hide answer</summary> + +.. code-block:: cmake + :caption: TODO 3: CMakeLists.txt + :name: CMakeLists.txt-target_link_libraries + + target_link_libraries(Tutorial PUBLIC MathFunctions) + +.. raw:: html + + </details> + +Finally we need to specify the library's header file location. Modify +:command:`target_include_directories` to add the ``MathFunctions`` subdirectory +as an include directory so that the ``MathFunctions.h`` header file can be +found. + +.. raw:: html + + <details><summary>TODO 4: Click to show/hide answer</summary> .. code-block:: cmake - :caption: CMakeLists.txt - :name: CMakeLists.txt-add_subdirectory + :caption: TODO 4: CMakeLists.txt + :name: CMakeLists.txt-target_include_directories-step2 + + target_include_directories(Tutorial PUBLIC + "${PROJECT_BINARY_DIR}" + "${PROJECT_SOURCE_DIR}/MathFunctions" + ) + +.. raw:: html + + </details> + +Now let's use our library. In ``tutorial.cxx``, include ``MathFunctions.h``: + +.. raw:: html + + <details><summary>TODO 5: Click to show/hide answer</summary> - # add the MathFunctions library - add_subdirectory(MathFunctions) +.. code-block:: c++ + :caption: TODO 5 : tutorial.cxx + :name: tutorial.cxx-include_MathFunctions.h - # add the executable - add_executable(Tutorial tutorial.cxx) + #include "MathFunctions.h" - target_link_libraries(Tutorial PUBLIC MathFunctions) +.. raw:: html - # add the binary tree to the search path for include files - # so that we will find TutorialConfig.h - target_include_directories(Tutorial PUBLIC - "${PROJECT_BINARY_DIR}" - "${PROJECT_SOURCE_DIR}/MathFunctions" - ) + </details> -Now let us make the ``MathFunctions`` library optional. While for the tutorial +Lastly, replace ``sqrt`` with our library function ``mysqrt``. + +.. raw:: html + + <details><summary>TODO 6: Click to show/hide answer</summary> + +.. code-block:: c++ + :caption: TODO 6 : tutorial.cxx + :name: tutorial.cxx-call_mysqrt + + const double outputValue = mysqrt(inputValue); + +.. raw:: html + + </details> + +Exercise 2 - Making Our Library Optional +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Now let us make the MathFunctions library optional. While for the tutorial there really isn't any need to do so, for larger projects this is a common -occurrence. The first step is to add an option to the top-level -``CMakeLists.txt`` file. +occurrence. + +CMake can do this using the :command:`option` command. This gives users a +variable which they can change when configuring their cmake build. This +setting will be stored in the cache so that the user does not need to set +the value each time they run CMake on a build directory. + +Goal +---- + +Add the option to build without ``MathFunctions``. + + +Helpful Resources +----------------- + +* :command:`if` +* :command:`list` +* :command:`option` +* :command:`cmakedefine <configure_file>` + +Files to Edit +------------- + +* ``CMakeLists.txt`` +* ``tutorial.cxx`` +* ``TutorialConfig.h.in`` + +Getting Started +--------------- + +Start with the resulting files from Exercise 1. Complete ``TODO 7`` through +``TODO 13``. + +First create a variable ``MY_MATH`` using the :command:`option` command +in the top-level ``CMakeLists.txt`` file. In that same file, use that option +to determine whether to build and use the ``MathFunctions`` library. + +Then, update ``tutorial.cxx`` and ``TutorialConfig.h.in`` to use ``MY_MATH``. + +Build and Run +------------- + +Since we have our build directory already configured from Exercise 1, we can +rebuild by simply calling the following: + +.. code-block:: console + + cd ../Step2_build + cmake --build . + +Next, run the ``Tutorial`` executable on a few numbers to verify that it's +still correct. + +Now let's update the value of ``USE_MYMATH`` to ``OFF``. The easiest way is to +use the :manual:`cmake-gui <cmake-gui(1)>` or :manual:`ccmake <ccmake(1)>` +if you're in the terminal. Or, alternatively, if you want to change the +option from the command-line, try: + +.. code-block:: console + + cmake ../Step2 -DUSE_MYMATH=OFF + +Now, rebuild the code with the following: + +.. code-block:: console + + cmake --build . + +Then, run the executable again to ensure that it still works with +``USE_MYMATH`` set to ``OFF``. Which function gives better results, ``sqrt`` +or ``mysqrt``? + +Solution +-------- + +The first step is to add an option to the top-level ``CMakeLists.txt`` file. +This option will be displayed in the :manual:`cmake-gui <cmake-gui(1)>` and +:manual:`ccmake <ccmake(1)>` with a default value of ``ON`` that can be +changed by the user. + +.. raw:: html + + <details><summary>TODO 7: Click to show/hide answer</summary> .. literalinclude:: Step3/CMakeLists.txt - :caption: CMakeLists.txt + :caption: TODO 7: CMakeLists.txt :name: CMakeLists.txt-option :language: cmake :start-after: # should we use our own math functions - :end-before: # add the MathFunctions library + :end-before: # configure a header file to pass some of the CMake settings -This option will be displayed in the :manual:`cmake-gui <cmake-gui(1)>` and -:manual:`ccmake <ccmake(1)>` -with a default value of ``ON`` that can be changed by the user. This setting -will be stored in the cache so that the user does not need to set the value -each time they run CMake on a build directory. - -The next change is to make building and linking the ``MathFunctions`` library -conditional. To do this, we will create an ``if`` statement which checks the -value of the option. Inside the ``if`` block, put the -:command:`add_subdirectory` command from above with some additional list -commands to store information needed to link to the library and add the -subdirectory as an include directory in the ``Tutorial`` target. -The end of the top-level ``CMakeLists.txt`` file will now look like the -following: +.. raw:: html + + </details> + +Next, make building and linking the ``MathFunctions`` library +conditional. + +Start by creating a :command:`list` of the optional library targets for our +project. At the moment, it is just ``MathFunctions``. Let's name our list +``EXTRA_LIBS``. + +Similarly, we need to make a :command:`list` for the optional includes which +we will call ``EXTRA_INCLUDES``. In this list, we will ``APPEND`` the path of +the header file needed for our library. + +Next, create an :command:`if` statement which checks the value of +``USE_MYMATH``. Inside the :command:`if` block, put the +:command:`add_subdirectory` command from Exercise 1 with the additional +:command:`list` commands. + +When ``MY_MATH`` is ``ON``, the lists will be generated and will be added to +our project. When ``MY_MATH`` is ``OFF``, the lists stay empty. With this +strategy, we allow users to toggle ``MY_MATH`` to manipulate what library is +used in the build. + +The top-level CMakeLists.txt file will now look like the following: + +.. raw:: html + + <details><summary>TODO 8: Click to show/hide answer</summary> .. literalinclude:: Step3/CMakeLists.txt - :caption: CMakeLists.txt - :name: CMakeLists.txt-target_link_libraries-EXTRA_LIBS + :caption: TODO 8: CMakeLists.txt + :name: CMakeLists.txt-USE_MYMATH :language: cmake :start-after: # add the MathFunctions library + :end-before: # add the executable + +.. raw:: html + + </details> -Note the use of the variable ``EXTRA_LIBS`` to collect up any optional -libraries to later be linked into the executable. The variable -``EXTRA_INCLUDES`` is used similarly for optional header files. This is a -classic approach when dealing with many optional components, we will cover -the modern approach in the next step. +Now that we have these two lists, we need to update +:command:`target_link_libraries` and :command:`target_include_directories` to +use them. Changing them is fairly straightforward. + +For :command:`target_link_libraries`, we replace the written out +library names with ``EXTRA_LIBS``. This looks like the following: + +.. raw:: html + + <details><summary>TODO 9: Click to show/hide answer</summary> + +.. literalinclude:: Step3/CMakeLists.txt + :caption: TODO 9: CMakeLists.txt + :name: CMakeLists.txt-target_link_libraries-EXTRA_LIBS + :language: cmake + :start-after: add_executable(Tutorial tutorial.cxx) + :end-before: # TODO 3 + +.. raw:: html + + </details> + +Then, we do the same thing with :command:`target_include_directories` and +``EXTRA_INCLUDES``. + +.. raw:: html + + <details><summary>TODO 10: Click to show/hide answer</summary> + +.. literalinclude:: Step3/CMakeLists.txt + :caption: TODO 10 : CMakeLists.txt + :name: CMakeLists.txt-target_link_libraries-EXTRA_INCLUDES + :language: cmake + :start-after: # so that we will find TutorialConfig.h + +.. raw:: html + + </details> + +Note that this is a classic approach when dealing with many components. We +will cover the modern approach in the Step 3 of the tutorial. The corresponding changes to the source code are fairly straightforward. -First, in ``tutorial.cxx``, include the ``MathFunctions.h`` header if we -need it: +First, in ``tutorial.cxx``, we include the ``MathFunctions.h`` header if +``MY_MATH`` is defined. + +.. raw:: html + + <details><summary>TODO 11: Click to show/hide answer</summary> .. literalinclude:: Step3/tutorial.cxx - :caption: tutorial.cxx + :caption: TODO 11 : tutorial.cxx :name: tutorial.cxx-ifdef-include :language: c++ :start-after: // should we include the MathFunctions header :end-before: int main -Then, in the same file, make ``USE_MYMATH`` control which square root +.. raw:: html + + </details> + +Then, in the same file, we make ``USE_MYMATH`` control which square root function is used: +.. raw:: html + + <details><summary>TODO 12: Click to show/hide answer</summary> + .. literalinclude:: Step3/tutorial.cxx - :caption: tutorial.cxx + :caption: TODO 12 : tutorial.cxx :name: tutorial.cxx-ifdef-const :language: c++ :start-after: // which square root function should we use? :end-before: std::cout << "The square root of +.. raw:: html + + </details> + Since the source code now requires ``USE_MYMATH`` we can add it to ``TutorialConfig.h.in`` with the following line: +.. raw:: html + + <details><summary>TODO 13: Click to show/hide answer</summary> + .. literalinclude:: Step3/TutorialConfig.h.in - :caption: TutorialConfig.h.in + :caption: TODO 13 : TutorialConfig.h.in :name: TutorialConfig.h.in-cmakedefine :language: c++ :lines: 4 -**Exercise**: Why is it important that we configure ``TutorialConfig.h.in`` +.. raw:: html + + </details> + +With these changes, our library is now completely optional to whoever is +building and using it. + +Bonus Question +-------------- + +Why is it important that we configure ``TutorialConfig.h.in`` after the option for ``USE_MYMATH``? What would happen if we inverted the two? -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. Then run the built Tutorial executable. +Answer +------ -Now let's update the value of ``USE_MYMATH``. The easiest way is to use the -:manual:`cmake-gui <cmake-gui(1)>` or :manual:`ccmake <ccmake(1)>` if you're -in the terminal. Or, alternatively, if you want to change the option from the -command-line, try: +.. raw:: html -.. code-block:: console + <details><summary>Click to show/hide answer</summary> - cmake ../Step2 -DUSE_MYMATH=OFF +We configure after because ``TutorialConfig.h.in`` uses the value of +``USE_MYMATH``. If we configure the file before +calling :command:`option`, we won't be using the expected value of +``USE_MYMATH``. -Rebuild and run the tutorial again. +.. raw:: html -Which function gives better results, ``sqrt`` or ``mysqrt``? + </details> diff --git a/Help/guide/tutorial/Complete/CMakeLists.txt b/Help/guide/tutorial/Complete/CMakeLists.txt index 41baf64..3cdaaae 100644 --- a/Help/guide/tutorial/Complete/CMakeLists.txt +++ b/Help/guide/tutorial/Complete/CMakeLists.txt @@ -41,7 +41,7 @@ add_subdirectory(MathFunctions) add_executable(Tutorial tutorial.cxx) set_target_properties(Tutorial PROPERTIES DEBUG_POSTFIX ${CMAKE_DEBUG_POSTFIX}) -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 @@ -84,6 +84,7 @@ do_test(Tutorial 25 "25 is 5") do_test(Tutorial -25 "-25 is (-nan|nan|0)") do_test(Tutorial 0.0001 "0.0001 is 0.01") +# setup installer include(InstallRequiredSystemLibraries) set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/License.txt") set(CPACK_PACKAGE_VERSION_MAJOR "${Tutorial_VERSION_MAJOR}") diff --git a/Help/guide/tutorial/Complete/License.txt b/Help/guide/tutorial/Complete/License.txt index c62d00b..85760e5 100644 --- a/Help/guide/tutorial/Complete/License.txt +++ b/Help/guide/tutorial/Complete/License.txt @@ -1,2 +1,2 @@ This is the open source License.txt file introduced in -CMake/Tutorial/Step7... +CMake/Tutorial/Step9... diff --git a/Help/guide/tutorial/Installing and Testing.rst b/Help/guide/tutorial/Installing and Testing.rst index 394c986..8daf5aa 100644 --- a/Help/guide/tutorial/Installing and Testing.rst +++ b/Help/guide/tutorial/Installing and Testing.rst @@ -1,4 +1,4 @@ -Step 4: Installing and Testing +Step 5: Installing and Testing ============================== Now we can start adding install rules and testing support to our project. @@ -12,7 +12,7 @@ executable and configured header. So to the end of ``MathFunctions/CMakeLists.txt`` we add: -.. literalinclude:: Step5/MathFunctions/CMakeLists.txt +.. literalinclude:: Step6/MathFunctions/CMakeLists.txt :caption: MathFunctions/CMakeLists.txt :name: MathFunctions/CMakeLists.txt-install-TARGETS :language: cmake @@ -20,7 +20,7 @@ So to the end of ``MathFunctions/CMakeLists.txt`` we add: And to the end of the top-level ``CMakeLists.txt`` we add: -.. literalinclude:: Step5/CMakeLists.txt +.. literalinclude:: Step6/CMakeLists.txt :caption: CMakeLists.txt :name: CMakeLists.txt-install-TARGETS :language: cmake @@ -65,7 +65,7 @@ Next let's test our application. At the end of the top-level ``CMakeLists.txt`` file we can enable testing and then add a number of basic tests to verify that the application is working correctly. -.. literalinclude:: Step5/CMakeLists.txt +.. literalinclude:: Step6/CMakeLists.txt :caption: CMakeLists.txt :name: CMakeLists.txt-enable_testing :language: cmake diff --git a/Help/guide/tutorial/Packaging Debug and Release.rst b/Help/guide/tutorial/Packaging Debug and Release.rst index 91b46a7..fc2050e 100644 --- a/Help/guide/tutorial/Packaging Debug and Release.rst +++ b/Help/guide/tutorial/Packaging Debug and Release.rst @@ -10,8 +10,8 @@ possible, however, to setup CPack to bundle multiple build directories and construct a package that contains multiple configurations of the same project. First, we want to ensure that the debug and release builds use different names -for the executables and libraries that will be installed. Let's use `d` as the -postfix for the debug executable and libraries. +for the libraries that will be installed. Let's use `d` as the +postfix for the debug libraries. Set :variable:`CMAKE_DEBUG_POSTFIX` near the beginning of the top-level ``CMakeLists.txt`` file: @@ -44,7 +44,7 @@ Let's also add version numbering to the ``MathFunctions`` library. In :end-before: # install rules From the ``Step12`` directory, create ``debug`` and ``release`` -subbdirectories. The layout will look like: +subdirectories. The layout will look like: .. code-block:: none diff --git a/Help/guide/tutorial/Packaging an Installer.rst b/Help/guide/tutorial/Packaging an Installer.rst index 0ee5db2..11a1952 100644 --- a/Help/guide/tutorial/Packaging an Installer.rst +++ b/Help/guide/tutorial/Packaging an Installer.rst @@ -1,4 +1,4 @@ -Step 7: Packaging an Installer +Step 9: Packaging an Installer ============================== Next suppose that we want to distribute our project to other people so that @@ -11,7 +11,7 @@ installations and package management features. To accomplish this we will use CPack to create platform specific installers. Specifically we need to add a few lines to the bottom of our top-level ``CMakeLists.txt`` file. -.. literalinclude:: Step8/CMakeLists.txt +.. literalinclude:: Step10/CMakeLists.txt :caption: CMakeLists.txt :name: CMakeLists.txt-include-CPack :language: cmake @@ -38,15 +38,15 @@ binary directory run: cpack -To specify the generator, use the ``-G`` option. For multi-config builds, use -``-C`` to specify the configuration. For example: +To specify the generator, use the :option:`-G <cpack -G>` option. For multi-config builds, +use :option:`-C <cpack -C>` to specify the configuration. For example: .. code-block:: console cpack -G ZIP -C Debug For a list of available generators, see :manual:`cpack-generators(7)` or call -``cpack --help``. An :cpack_gen:`archive generator <CPack Archive Generator>` +:option:`cpack --help`. An :cpack_gen:`archive generator <CPack Archive Generator>` like ZIP creates a compressed archive of all *installed* files. To create an archive of the *full* source tree you would type: diff --git a/Help/guide/tutorial/Selecting Static or Shared Libraries.rst b/Help/guide/tutorial/Selecting Static or Shared Libraries.rst index 2d5f70e..1c49c23 100644 --- a/Help/guide/tutorial/Selecting Static or Shared Libraries.rst +++ b/Help/guide/tutorial/Selecting Static or Shared Libraries.rst @@ -1,5 +1,5 @@ -Step 9: Selecting Static or Shared Libraries -============================================ +Step 10: Selecting Static or Shared Libraries +============================================= In this section we will show how the :variable:`BUILD_SHARED_LIBS` variable can be used to control the default behavior of :command:`add_library`, @@ -19,7 +19,7 @@ library. The first step is to update the starting section of the top-level ``CMakeLists.txt`` to look like: -.. literalinclude:: Step10/CMakeLists.txt +.. literalinclude:: Step11/CMakeLists.txt :caption: CMakeLists.txt :name: CMakeLists.txt-option-BUILD_SHARED_LIBS :language: cmake @@ -33,7 +33,7 @@ explicitly require that SqrtLibrary is built statically. The end result is that ``MathFunctions/CMakeLists.txt`` should look like: -.. literalinclude:: Step10/MathFunctions/CMakeLists.txt +.. literalinclude:: Step11/MathFunctions/CMakeLists.txt :caption: MathFunctions/CMakeLists.txt :name: MathFunctions/CMakeLists.txt-add_library-STATIC :language: cmake @@ -42,7 +42,7 @@ The end result is that ``MathFunctions/CMakeLists.txt`` should look like: Next, update ``MathFunctions/mysqrt.cxx`` to use the ``mathfunctions`` and ``detail`` namespaces: -.. literalinclude:: Step10/MathFunctions/mysqrt.cxx +.. literalinclude:: Step11/MathFunctions/mysqrt.cxx :caption: MathFunctions/mysqrt.cxx :name: MathFunctions/mysqrt.cxx-namespace :language: c++ @@ -56,7 +56,7 @@ uses ``USE_MYMATH``: Finally, update ``MathFunctions/MathFunctions.h`` to use dll export defines: -.. literalinclude:: Step10/MathFunctions/MathFunctions.h +.. literalinclude:: Step11/MathFunctions/MathFunctions.h :caption: MathFunctions/MathFunctions.h :name: MathFunctions/MathFunctions.h :language: c++ @@ -67,7 +67,7 @@ library that has position independent code. The solution to this is to explicitly set the :prop_tgt:`POSITION_INDEPENDENT_CODE` target property of SqrtLibrary to be ``True`` no matter the build type. -.. literalinclude:: Step10/MathFunctions/CMakeLists.txt +.. literalinclude:: Step11/MathFunctions/CMakeLists.txt :caption: MathFunctions/CMakeLists.txt :name: MathFunctions/CMakeLists.txt-POSITION_INDEPENDENT_CODE :language: cmake diff --git a/Help/guide/tutorial/Step1/CMakeLists.txt b/Help/guide/tutorial/Step1/CMakeLists.txt new file mode 100644 index 0000000..282951a --- /dev/null +++ b/Help/guide/tutorial/Step1/CMakeLists.txt @@ -0,0 +1,16 @@ +# TODO 1: Set the minimum required version of CMake to be 3.10 + +# TODO 2: Create a project named Tutorial + +# TODO 7: Set the project version number as 1.0 in the above project command + +# TODO 6: Set the variable CMAKE_CXX_STANDARD to 11 +# and the variable CMAKE_CXX_REQUIRED_STANDARD to True + +# TODO 8: Use configure_file to configure and copy TutorialConfig.h.in to +# TutorialConfig.h + +# TODO 3: Add an executable called Tutorial to the project +# Hint: Be sure to specify the source file as tutorial.cxx + +# TODO 9: Use target_include_directories to include ${PROJECT_BINARY_DIR} diff --git a/Help/guide/tutorial/Step1/TutorialConfig.h.in b/Help/guide/tutorial/Step1/TutorialConfig.h.in new file mode 100644 index 0000000..990bfbd --- /dev/null +++ b/Help/guide/tutorial/Step1/TutorialConfig.h.in @@ -0,0 +1,2 @@ +// the configured options and settings for Tutorial +// TODO 10: Define Tutorial_VERSION_MAJOR and Tutorial_VERSION_MINOR diff --git a/Help/guide/tutorial/Step1/tutorial.cxx b/Help/guide/tutorial/Step1/tutorial.cxx index 08323bf..64d0916 100644 --- a/Help/guide/tutorial/Step1/tutorial.cxx +++ b/Help/guide/tutorial/Step1/tutorial.cxx @@ -1,17 +1,22 @@ // A simple program that computes the square root of a number #include <cmath> -#include <cstdlib> +#include <cstdlib> // TODO 5: Remove this line #include <iostream> #include <string> +// TODO 11: Include TutorialConfig.h + int main(int argc, char* argv[]) { if (argc < 2) { + // TODO 12: Create a print statement using Tutorial_VERSION_MAJOR + // and Tutorial_VERSION_MINOR std::cout << "Usage: " << argv[0] << " number" << std::endl; return 1; } // convert input to double + // TODO 4: Replace atof(argv[1]) with std::stod(argv[1]) const double inputValue = atof(argv[1]); // calculate square root diff --git a/Help/guide/tutorial/Step10/CMakeLists.txt b/Help/guide/tutorial/Step10/CMakeLists.txt index 55dc409..5c661aa 100644 --- a/Help/guide/tutorial/Step10/CMakeLists.txt +++ b/Help/guide/tutorial/Step10/CMakeLists.txt @@ -1,29 +1,37 @@ -cmake_minimum_required(VERSION 3.10) +cmake_minimum_required(VERSION 3.15) # set the project name and version project(Tutorial VERSION 1.0) # 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) -# control where the static and shared libraries are built so that on windows -# we don't need to tinker with the path to run the executable -set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}") -set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}") -set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}") +# add compiler warning flags just when building this project via +# the BUILD_INTERFACE genex +set(gcc_like_cxx "$<COMPILE_LANG_AND_ID:CXX,ARMClang,AppleClang,Clang,GNU,LCC>") +set(msvc_cxx "$<COMPILE_LANG_AND_ID:CXX,MSVC>") +target_compile_options(tutorial_compiler_flags INTERFACE + "$<${gcc_like_cxx}:$<BUILD_INTERFACE:-Wall;-Wextra;-Wshadow;-Wformat=2;-Wunused>>" + "$<${msvc_cxx}:$<BUILD_INTERFACE:-W3>>" +) -option(BUILD_SHARED_LIBS "Build using shared libraries" ON) +# should we use our own math functions +option(USE_MYMATH "Use tutorial provided math implementation" ON) -# configure a header file to pass the version number only +# configure a header file to pass some of the CMake settings +# to the source code configure_file(TutorialConfig.h.in TutorialConfig.h) # add the MathFunctions library -add_subdirectory(MathFunctions) +if(USE_MYMATH) + add_subdirectory(MathFunctions) + list(APPEND EXTRA_LIBS MathFunctions) +endif() # add the executable add_executable(Tutorial tutorial.cxx) -target_link_libraries(Tutorial PUBLIC MathFunctions) +target_link_libraries(Tutorial PUBLIC ${EXTRA_LIBS} tutorial_compiler_flags) # add the binary tree to the search path for include files # so that we will find TutorialConfig.h @@ -66,6 +74,7 @@ do_test(Tutorial 25 "25 is 5") do_test(Tutorial -25 "-25 is (-nan|nan|0)") do_test(Tutorial 0.0001 "0.0001 is 0.01") +# setup installer include(InstallRequiredSystemLibraries) set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/License.txt") set(CPACK_PACKAGE_VERSION_MAJOR "${Tutorial_VERSION_MAJOR}") diff --git a/Help/guide/tutorial/Step10/License.txt b/Help/guide/tutorial/Step10/License.txt index c62d00b..85760e5 100644 --- a/Help/guide/tutorial/Step10/License.txt +++ b/Help/guide/tutorial/Step10/License.txt @@ -1,2 +1,2 @@ This is the open source License.txt file introduced in -CMake/Tutorial/Step7... +CMake/Tutorial/Step9... diff --git a/Help/guide/tutorial/Step10/MathFunctions/CMakeLists.txt b/Help/guide/tutorial/Step10/MathFunctions/CMakeLists.txt index 0bfe20c..746f966 100644 --- a/Help/guide/tutorial/Step10/MathFunctions/CMakeLists.txt +++ b/Help/guide/tutorial/Step10/MathFunctions/CMakeLists.txt @@ -1,55 +1,30 @@ -# add the library that runs -add_library(MathFunctions MathFunctions.cxx) +# first we add the executable that generates the table +add_executable(MakeTable MakeTable.cxx) + +# add the command to generate the source code +add_custom_command( + OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/Table.h + COMMAND MakeTable ${CMAKE_CURRENT_BINARY_DIR}/Table.h + DEPENDS MakeTable + ) + +# add the main library +add_library(MathFunctions + mysqrt.cxx + ${CMAKE_CURRENT_BINARY_DIR}/Table.h + ) # state that anybody linking to us needs to include the current source dir # to find MathFunctions.h, while we don't. +# state that we depend on our binary dir to find Table.h target_include_directories(MathFunctions - INTERFACE ${CMAKE_CURRENT_SOURCE_DIR} - ) + INTERFACE ${CMAKE_CURRENT_SOURCE_DIR} + PRIVATE ${CMAKE_CURRENT_BINARY_DIR} + ) -# should we use our own math functions -option(USE_MYMATH "Use tutorial provided math implementation" ON) -if(USE_MYMATH) - - target_compile_definitions(MathFunctions PRIVATE "USE_MYMATH") - - # first we add the executable that generates the table - add_executable(MakeTable MakeTable.cxx) - - # add the command to generate the source code - add_custom_command( - OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/Table.h - COMMAND MakeTable ${CMAKE_CURRENT_BINARY_DIR}/Table.h - DEPENDS MakeTable - ) - - # library that just does sqrt - add_library(SqrtLibrary STATIC - mysqrt.cxx - ${CMAKE_CURRENT_BINARY_DIR}/Table.h - ) - - # state that we depend on our binary dir to find Table.h - target_include_directories(SqrtLibrary PRIVATE - ${CMAKE_CURRENT_BINARY_DIR} - ) - - # state that SqrtLibrary need PIC when the default is shared libraries - set_target_properties(SqrtLibrary PROPERTIES - POSITION_INDEPENDENT_CODE ${BUILD_SHARED_LIBS} - ) - - target_link_libraries(MathFunctions PRIVATE SqrtLibrary) -endif() - -# define the symbol stating we are using the declspec(dllexport) when -# building on windows -target_compile_definitions(MathFunctions PRIVATE "EXPORTING_MYMATH") +target_link_libraries(MathFunctions tutorial_compiler_flags) # install rules -set(installable_libs MathFunctions) -if(TARGET SqrtLibrary) - list(APPEND installable_libs SqrtLibrary) -endif() +set(installable_libs MathFunctions tutorial_compiler_flags) install(TARGETS ${installable_libs} DESTINATION lib) install(FILES MathFunctions.h DESTINATION include) diff --git a/Help/guide/tutorial/Step10/MathFunctions/MathFunctions.h b/Help/guide/tutorial/Step10/MathFunctions/MathFunctions.h index 3fb547b..cd36bcc 100644 --- a/Help/guide/tutorial/Step10/MathFunctions/MathFunctions.h +++ b/Help/guide/tutorial/Step10/MathFunctions/MathFunctions.h @@ -1,14 +1 @@ - -#if defined(_WIN32) -# if defined(EXPORTING_MYMATH) -# define DECLSPEC __declspec(dllexport) -# else -# define DECLSPEC __declspec(dllimport) -# endif -#else // non windows -# define DECLSPEC -#endif - -namespace mathfunctions { -double DECLSPEC sqrt(double x); -} +double mysqrt(double x); diff --git a/Help/guide/tutorial/Step10/MathFunctions/mysqrt.cxx b/Help/guide/tutorial/Step10/MathFunctions/mysqrt.cxx index 8153f18..7d80ee9 100644 --- a/Help/guide/tutorial/Step10/MathFunctions/mysqrt.cxx +++ b/Help/guide/tutorial/Step10/MathFunctions/mysqrt.cxx @@ -5,8 +5,6 @@ // include the generated table #include "Table.h" -namespace mathfunctions { -namespace detail { // a hack square root calculation using simple operations double mysqrt(double x) { @@ -33,5 +31,3 @@ double mysqrt(double x) return result; } -} -} diff --git a/Help/guide/tutorial/Step10/TutorialConfig.h.in b/Help/guide/tutorial/Step10/TutorialConfig.h.in index 7e4d7fa..e23f521 100644 --- a/Help/guide/tutorial/Step10/TutorialConfig.h.in +++ b/Help/guide/tutorial/Step10/TutorialConfig.h.in @@ -1,3 +1,4 @@ // the configured options and settings for Tutorial #define Tutorial_VERSION_MAJOR @Tutorial_VERSION_MAJOR@ #define Tutorial_VERSION_MINOR @Tutorial_VERSION_MINOR@ +#cmakedefine USE_MYMATH diff --git a/Help/guide/tutorial/Step10/tutorial.cxx b/Help/guide/tutorial/Step10/tutorial.cxx index 37a0333..b3c6a4f 100644 --- a/Help/guide/tutorial/Step10/tutorial.cxx +++ b/Help/guide/tutorial/Step10/tutorial.cxx @@ -1,11 +1,15 @@ // A simple program that computes the square root of a number +#include <cmath> #include <iostream> -#include <sstream> #include <string> -#include "MathFunctions.h" #include "TutorialConfig.h" +// should we include the MathFunctions header? +#ifdef USE_MYMATH +# include "MathFunctions.h" +#endif + int main(int argc, char* argv[]) { if (argc < 2) { @@ -19,7 +23,12 @@ int main(int argc, char* argv[]) // convert input to double const double inputValue = std::stod(argv[1]); - const double outputValue = mathfunctions::sqrt(inputValue); + // which square root function should we use? +#ifdef USE_MYMATH + const double outputValue = mysqrt(inputValue); +#else + const double outputValue = sqrt(inputValue); +#endif std::cout << "The square root of " << inputValue << " is " << outputValue << std::endl; diff --git a/Help/guide/tutorial/Step11/CMakeLists.txt b/Help/guide/tutorial/Step11/CMakeLists.txt index 1044748..046bfc9 100644 --- a/Help/guide/tutorial/Step11/CMakeLists.txt +++ b/Help/guide/tutorial/Step11/CMakeLists.txt @@ -3,6 +3,7 @@ cmake_minimum_required(VERSION 3.15) # set the project name and version project(Tutorial VERSION 1.0) +# specify the C++ standard add_library(tutorial_compiler_flags INTERFACE) target_compile_features(tutorial_compiler_flags INTERFACE cxx_std_11) @@ -31,7 +32,7 @@ add_subdirectory(MathFunctions) # add the executable add_executable(Tutorial tutorial.cxx) -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 @@ -46,7 +47,7 @@ install(FILES "${PROJECT_BINARY_DIR}/TutorialConfig.h" ) # enable testing -enable_testing() +include(CTest) # does the application run add_test(NAME Runs COMMAND Tutorial 25) @@ -74,6 +75,7 @@ do_test(Tutorial 25 "25 is 5") do_test(Tutorial -25 "-25 is (-nan|nan|0)") do_test(Tutorial 0.0001 "0.0001 is 0.01") +# setup installer include(InstallRequiredSystemLibraries) set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/License.txt") set(CPACK_PACKAGE_VERSION_MAJOR "${Tutorial_VERSION_MAJOR}") diff --git a/Help/guide/tutorial/Step11/License.txt b/Help/guide/tutorial/Step11/License.txt index c62d00b..85760e5 100644 --- a/Help/guide/tutorial/Step11/License.txt +++ b/Help/guide/tutorial/Step11/License.txt @@ -1,2 +1,2 @@ This is the open source License.txt file introduced in -CMake/Tutorial/Step7... +CMake/Tutorial/Step9... diff --git a/Help/guide/tutorial/Step11/MathFunctions/CMakeLists.txt b/Help/guide/tutorial/Step11/MathFunctions/CMakeLists.txt index 0d287ca..0e86a12 100644 --- a/Help/guide/tutorial/Step11/MathFunctions/CMakeLists.txt +++ b/Help/guide/tutorial/Step11/MathFunctions/CMakeLists.txt @@ -47,7 +47,7 @@ endif() target_link_libraries(MathFunctions PUBLIC tutorial_compiler_flags) # define the symbol stating we are using the declspec(dllexport) when -#building on windows +# building on windows target_compile_definitions(MathFunctions PRIVATE "EXPORTING_MYMATH") # install rules diff --git a/Help/guide/tutorial/Step11/tutorial.cxx b/Help/guide/tutorial/Step11/tutorial.cxx index a4f44d5..37a0333 100644 --- a/Help/guide/tutorial/Step11/tutorial.cxx +++ b/Help/guide/tutorial/Step11/tutorial.cxx @@ -1,5 +1,6 @@ // A simple program that computes the square root of a number #include <iostream> +#include <sstream> #include <string> #include "MathFunctions.h" diff --git a/Help/guide/tutorial/Step12/CMakeLists.txt b/Help/guide/tutorial/Step12/CMakeLists.txt index 63f9643..220ed4b 100644 --- a/Help/guide/tutorial/Step12/CMakeLists.txt +++ b/Help/guide/tutorial/Step12/CMakeLists.txt @@ -37,7 +37,7 @@ add_subdirectory(MathFunctions) # add the executable add_executable(Tutorial tutorial.cxx) -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 @@ -80,6 +80,7 @@ do_test(Tutorial 25 "25 is 5") do_test(Tutorial -25 "-25 is (-nan|nan|0)") do_test(Tutorial 0.0001 "0.0001 is 0.01") +# setup installer include(InstallRequiredSystemLibraries) set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/License.txt") set(CPACK_PACKAGE_VERSION_MAJOR "${Tutorial_VERSION_MAJOR}") diff --git a/Help/guide/tutorial/Step12/License.txt b/Help/guide/tutorial/Step12/License.txt index c62d00b..85760e5 100644 --- a/Help/guide/tutorial/Step12/License.txt +++ b/Help/guide/tutorial/Step12/License.txt @@ -1,2 +1,2 @@ This is the open source License.txt file introduced in -CMake/Tutorial/Step7... +CMake/Tutorial/Step9... diff --git a/Help/guide/tutorial/Step2/CMakeLists.txt b/Help/guide/tutorial/Step2/CMakeLists.txt index 7aa59e9..2f7d56e 100644 --- a/Help/guide/tutorial/Step2/CMakeLists.txt +++ b/Help/guide/tutorial/Step2/CMakeLists.txt @@ -7,13 +7,36 @@ project(Tutorial VERSION 1.0) set(CMAKE_CXX_STANDARD 11) set(CMAKE_CXX_STANDARD_REQUIRED True) +# TODO 7: Create a variable MY_MATH using option and set default to ON + # configure a header file to pass some of the CMake settings # to the source code configure_file(TutorialConfig.h.in TutorialConfig.h) +# TODO 8: Use list() and APPEND to create a list of optional libraries +# called EXTRA_LIBS and a list of optional include directories called +# EXTRA_INCLUDES. Add the MathFunctions library and source directory to +# the appropriate lists. +# +# Only call add_subdirectory and only add MathFunctions specific values +# to EXTRA_LIBS and EXTRA_INCLUDES if USE_MYMATH is true. + +# TODO 2: Use add_subdirectory() to add MathFunctions to this project + # add the executable add_executable(Tutorial tutorial.cxx) +# TODO 9: Use EXTRA_LIBS instead of the MathFunctions specific values +# in target_link_libraries. + +# TODO 3: Use target_link_libraries to link the library to our executable + +# TODO 4: Add MathFunctions to Tutorial's target_include_directories() +# Hint: ${PROJECT_SOURCE_DIR} is a path to the project source. AKA This folder! + +# TODO 10: Use EXTRA_INCLUDES instead of the MathFunctions specific values +# in target_include_directories. + # add the binary tree to the search path for include files # so that we will find TutorialConfig.h target_include_directories(Tutorial PUBLIC diff --git a/Help/guide/tutorial/Step2/MathFunctions/CMakeLists.txt b/Help/guide/tutorial/Step2/MathFunctions/CMakeLists.txt new file mode 100644 index 0000000..b7779b7 --- /dev/null +++ b/Help/guide/tutorial/Step2/MathFunctions/CMakeLists.txt @@ -0,0 +1,2 @@ +# TODO 1: Add a library called MathFunctions +# Hint: You will need the add_library command diff --git a/Help/guide/tutorial/Step2/TutorialConfig.h.in b/Help/guide/tutorial/Step2/TutorialConfig.h.in index 7e4d7fa..adb4c55 100644 --- a/Help/guide/tutorial/Step2/TutorialConfig.h.in +++ b/Help/guide/tutorial/Step2/TutorialConfig.h.in @@ -1,3 +1,5 @@ // the configured options and settings for Tutorial #define Tutorial_VERSION_MAJOR @Tutorial_VERSION_MAJOR@ #define Tutorial_VERSION_MINOR @Tutorial_VERSION_MINOR@ + +// TODO 13: use cmakedefine to define MY_MATH diff --git a/Help/guide/tutorial/Step2/tutorial.cxx b/Help/guide/tutorial/Step2/tutorial.cxx index 53b0810..f83aa7e 100644 --- a/Help/guide/tutorial/Step2/tutorial.cxx +++ b/Help/guide/tutorial/Step2/tutorial.cxx @@ -5,6 +5,10 @@ #include "TutorialConfig.h" +// TODO 11: Only include MathFunctions if MY_MATH is defined + +// TODO 5: Include MathFunctions.h + int main(int argc, char* argv[]) { if (argc < 2) { @@ -18,6 +22,10 @@ int main(int argc, char* argv[]) // convert input to double const double inputValue = std::stod(argv[1]); + // TODO 12: Use mysqrt if MY_MATH is defined and sqrt otherwise + + // TODO 6: Replace sqrt with mysqrt + // calculate square root const double outputValue = sqrt(inputValue); std::cout << "The square root of " << inputValue << " is " << outputValue diff --git a/Help/guide/tutorial/Step3/CMakeLists.txt b/Help/guide/tutorial/Step3/CMakeLists.txt index 1c12816..007770a 100644 --- a/Help/guide/tutorial/Step3/CMakeLists.txt +++ b/Help/guide/tutorial/Step3/CMakeLists.txt @@ -14,6 +14,8 @@ option(USE_MYMATH "Use tutorial provided math implementation" ON) # to the source code configure_file(TutorialConfig.h.in TutorialConfig.h) +# TODO 2: Remove EXTRA_INCLUDES list + # add the MathFunctions library if(USE_MYMATH) add_subdirectory(MathFunctions) @@ -26,6 +28,8 @@ add_executable(Tutorial tutorial.cxx) target_link_libraries(Tutorial PUBLIC ${EXTRA_LIBS}) +# TODO 3: Remove use of EXTRA_INCLUDES + # add the binary tree to the search path for include files # so that we will find TutorialConfig.h target_include_directories(Tutorial PUBLIC diff --git a/Help/guide/tutorial/Step3/MathFunctions/CMakeLists.txt b/Help/guide/tutorial/Step3/MathFunctions/CMakeLists.txt index 8b443a6..7bf05e0 100644 --- a/Help/guide/tutorial/Step3/MathFunctions/CMakeLists.txt +++ b/Help/guide/tutorial/Step3/MathFunctions/CMakeLists.txt @@ -1 +1,5 @@ add_library(MathFunctions mysqrt.cxx) + +# TODO 1: State that anybody linking to MathFunctions needs to include the +# current source directory, while MathFunctions itself doesn't. +# Hint: Use target_include_directories with the INTERFACE keyword diff --git a/Help/guide/tutorial/Step5/CMakeLists.txt b/Help/guide/tutorial/Step5/CMakeLists.txt index 82d00c8..4003c21 100644 --- a/Help/guide/tutorial/Step5/CMakeLists.txt +++ b/Help/guide/tutorial/Step5/CMakeLists.txt @@ -1,11 +1,20 @@ -cmake_minimum_required(VERSION 3.10) +cmake_minimum_required(VERSION 3.15) # set the project name and version project(Tutorial VERSION 1.0) # 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) + +# add compiler warning flags just when building this project via +# the BUILD_INTERFACE genex +set(gcc_like_cxx "$<COMPILE_LANG_AND_ID:CXX,ARMClang,AppleClang,Clang,GNU,LCC>") +set(msvc_cxx "$<COMPILE_LANG_AND_ID:CXX,MSVC>") +target_compile_options(tutorial_compiler_flags INTERFACE + "$<${gcc_like_cxx}:$<BUILD_INTERFACE:-Wall;-Wextra;-Wshadow;-Wformat=2;-Wunused>>" + "$<${msvc_cxx}:$<BUILD_INTERFACE:-W3>>" +) # should we use our own math functions option(USE_MYMATH "Use tutorial provided math implementation" ON) @@ -22,45 +31,10 @@ endif() # add the executable add_executable(Tutorial tutorial.cxx) -target_link_libraries(Tutorial PUBLIC ${EXTRA_LIBS}) +target_link_libraries(Tutorial PUBLIC ${EXTRA_LIBS} tutorial_compiler_flags) # add the binary tree to the search path for include files # so that we will find TutorialConfig.h target_include_directories(Tutorial PUBLIC "${PROJECT_BINARY_DIR}" ) - -# add the install targets -install(TARGETS Tutorial DESTINATION bin) -install(FILES "${PROJECT_BINARY_DIR}/TutorialConfig.h" - DESTINATION include - ) - -# enable testing -enable_testing() - -# does the application run -add_test(NAME Runs COMMAND Tutorial 25) - -# does the usage message work? -add_test(NAME Usage COMMAND Tutorial) -set_tests_properties(Usage - PROPERTIES PASS_REGULAR_EXPRESSION "Usage:.*number" - ) - -# define a function to simplify adding tests -function(do_test target arg result) - add_test(NAME Comp${arg} COMMAND ${target} ${arg}) - set_tests_properties(Comp${arg} - PROPERTIES PASS_REGULAR_EXPRESSION ${result} - ) -endfunction() - -# do a bunch of result based tests -do_test(Tutorial 4 "4 is 2") -do_test(Tutorial 9 "9 is 3") -do_test(Tutorial 5 "5 is 2.236") -do_test(Tutorial 7 "7 is 2.645") -do_test(Tutorial 25 "25 is 5") -do_test(Tutorial -25 "-25 is (-nan|nan|0)") -do_test(Tutorial 0.0001 "0.0001 is 0.01") diff --git a/Help/guide/tutorial/Step5/MathFunctions/CMakeLists.txt b/Help/guide/tutorial/Step5/MathFunctions/CMakeLists.txt index b12f27d..e02f211 100644 --- a/Help/guide/tutorial/Step5/MathFunctions/CMakeLists.txt +++ b/Help/guide/tutorial/Step5/MathFunctions/CMakeLists.txt @@ -6,6 +6,4 @@ target_include_directories(MathFunctions INTERFACE ${CMAKE_CURRENT_SOURCE_DIR} ) -# install rules -install(TARGETS MathFunctions DESTINATION lib) -install(FILES MathFunctions.h DESTINATION include) +target_link_libraries(MathFunctions tutorial_compiler_flags) diff --git a/Help/guide/tutorial/Step6/CMakeLists.txt b/Help/guide/tutorial/Step6/CMakeLists.txt index 82d00c8..da9e852 100644 --- a/Help/guide/tutorial/Step6/CMakeLists.txt +++ b/Help/guide/tutorial/Step6/CMakeLists.txt @@ -1,11 +1,20 @@ -cmake_minimum_required(VERSION 3.10) +cmake_minimum_required(VERSION 3.15) # set the project name and version project(Tutorial VERSION 1.0) # 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) + +# add compiler warning flags just when building this project via +# the BUILD_INTERFACE genex +set(gcc_like_cxx "$<COMPILE_LANG_AND_ID:CXX,ARMClang,AppleClang,Clang,GNU,LCC>") +set(msvc_cxx "$<COMPILE_LANG_AND_ID:CXX,MSVC>") +target_compile_options(tutorial_compiler_flags INTERFACE + "$<${gcc_like_cxx}:$<BUILD_INTERFACE:-Wall;-Wextra;-Wshadow;-Wformat=2;-Wunused>>" + "$<${msvc_cxx}:$<BUILD_INTERFACE:-W3>>" +) # should we use our own math functions option(USE_MYMATH "Use tutorial provided math implementation" ON) @@ -22,7 +31,7 @@ endif() # add the executable add_executable(Tutorial tutorial.cxx) -target_link_libraries(Tutorial PUBLIC ${EXTRA_LIBS}) +target_link_libraries(Tutorial PUBLIC ${EXTRA_LIBS} tutorial_compiler_flags) # add the binary tree to the search path for include files # so that we will find TutorialConfig.h diff --git a/Help/guide/tutorial/Step6/CTestConfig.cmake b/Help/guide/tutorial/Step6/CTestConfig.cmake new file mode 100644 index 0000000..73efdb1 --- /dev/null +++ b/Help/guide/tutorial/Step6/CTestConfig.cmake @@ -0,0 +1,7 @@ +set(CTEST_PROJECT_NAME "CMakeTutorial") +set(CTEST_NIGHTLY_START_TIME "00:00:00 EST") + +set(CTEST_DROP_METHOD "http") +set(CTEST_DROP_SITE "my.cdash.org") +set(CTEST_DROP_LOCATION "/submit.php?project=CMakeTutorial") +set(CTEST_DROP_SITE_CDASH TRUE) diff --git a/Help/guide/tutorial/Step6/MathFunctions/CMakeLists.txt b/Help/guide/tutorial/Step6/MathFunctions/CMakeLists.txt index 42e098a..226099a 100644 --- a/Help/guide/tutorial/Step6/MathFunctions/CMakeLists.txt +++ b/Help/guide/tutorial/Step6/MathFunctions/CMakeLists.txt @@ -6,29 +6,9 @@ target_include_directories(MathFunctions INTERFACE ${CMAKE_CURRENT_SOURCE_DIR} ) -# does this system provide the log and exp functions? -include(CheckCXXSourceCompiles) -check_cxx_source_compiles(" - #include <cmath> - int main() { - std::log(1.0); - return 0; - } -" HAVE_LOG) -check_cxx_source_compiles(" - #include <cmath> - int main() { - std::exp(1.0); - return 0; - } -" HAVE_EXP) - -# add compile definitions -if(HAVE_LOG AND HAVE_EXP) - target_compile_definitions(MathFunctions - PRIVATE "HAVE_LOG" "HAVE_EXP") -endif() +target_link_libraries(MathFunctions tutorial_compiler_flags) # install rules -install(TARGETS MathFunctions DESTINATION lib) +set(installable_libs MathFunctions tutorial_compiler_flags) +install(TARGETS ${installable_libs} DESTINATION lib) install(FILES MathFunctions.h DESTINATION include) diff --git a/Help/guide/tutorial/Step6/MathFunctions/MakeTable.cxx b/Help/guide/tutorial/Step6/MathFunctions/MakeTable.cxx deleted file mode 100644 index ee58556..0000000 --- a/Help/guide/tutorial/Step6/MathFunctions/MakeTable.cxx +++ /dev/null @@ -1,25 +0,0 @@ -// A simple program that builds a sqrt table -#include <cmath> -#include <fstream> -#include <iostream> - -int main(int argc, char* argv[]) -{ - // make sure we have enough arguments - if (argc < 2) { - return 1; - } - - std::ofstream fout(argv[1], std::ios_base::out); - const bool fileOpen = fout.is_open(); - if (fileOpen) { - fout << "double sqrtTable[] = {" << std::endl; - for (int i = 0; i < 10; ++i) { - fout << sqrt(static_cast<double>(i)) << "," << std::endl; - } - // close the table with a zero - fout << "0};" << std::endl; - fout.close(); - } - return fileOpen ? 0 : 1; // return 0 if wrote the file -} diff --git a/Help/guide/tutorial/Step6/MathFunctions/mysqrt.cxx b/Help/guide/tutorial/Step6/MathFunctions/mysqrt.cxx index 7eecd26..abe767d 100644 --- a/Help/guide/tutorial/Step6/MathFunctions/mysqrt.cxx +++ b/Help/guide/tutorial/Step6/MathFunctions/mysqrt.cxx @@ -1,4 +1,3 @@ -#include <cmath> #include <iostream> #include "MathFunctions.h" @@ -10,12 +9,6 @@ double mysqrt(double x) return 0; } - // if we have both log and exp then use them -#if defined(HAVE_LOG) && defined(HAVE_EXP) - double result = std::exp(std::log(x) * 0.5); - std::cout << "Computing sqrt of " << x << " to be " << result - << " using log and exp" << std::endl; -#else double result = x; // do ten iterations @@ -27,6 +20,5 @@ double mysqrt(double x) result = result + 0.5 * delta / result; std::cout << "Computing sqrt of " << x << " to be " << result << std::endl; } -#endif return result; } diff --git a/Help/guide/tutorial/Step7/CMakeLists.txt b/Help/guide/tutorial/Step7/CMakeLists.txt index 82d00c8..d26a90c 100644 --- a/Help/guide/tutorial/Step7/CMakeLists.txt +++ b/Help/guide/tutorial/Step7/CMakeLists.txt @@ -1,11 +1,20 @@ -cmake_minimum_required(VERSION 3.10) +cmake_minimum_required(VERSION 3.15) # set the project name and version project(Tutorial VERSION 1.0) # 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) + +# add compiler warning flags just when building this project via +# the BUILD_INTERFACE genex +set(gcc_like_cxx "$<COMPILE_LANG_AND_ID:CXX,ARMClang,AppleClang,Clang,GNU,LCC>") +set(msvc_cxx "$<COMPILE_LANG_AND_ID:CXX,MSVC>") +target_compile_options(tutorial_compiler_flags INTERFACE + "$<${gcc_like_cxx}:$<BUILD_INTERFACE:-Wall;-Wextra;-Wshadow;-Wformat=2;-Wunused>>" + "$<${msvc_cxx}:$<BUILD_INTERFACE:-W3>>" +) # should we use our own math functions option(USE_MYMATH "Use tutorial provided math implementation" ON) @@ -22,7 +31,7 @@ endif() # add the executable add_executable(Tutorial tutorial.cxx) -target_link_libraries(Tutorial PUBLIC ${EXTRA_LIBS}) +target_link_libraries(Tutorial PUBLIC ${EXTRA_LIBS} tutorial_compiler_flags) # add the binary tree to the search path for include files # so that we will find TutorialConfig.h @@ -37,7 +46,7 @@ install(FILES "${PROJECT_BINARY_DIR}/TutorialConfig.h" ) # enable testing -enable_testing() +include(CTest) # does the application run add_test(NAME Runs COMMAND Tutorial 25) diff --git a/Help/guide/tutorial/Step7/CTestConfig.cmake b/Help/guide/tutorial/Step7/CTestConfig.cmake new file mode 100644 index 0000000..73efdb1 --- /dev/null +++ b/Help/guide/tutorial/Step7/CTestConfig.cmake @@ -0,0 +1,7 @@ +set(CTEST_PROJECT_NAME "CMakeTutorial") +set(CTEST_NIGHTLY_START_TIME "00:00:00 EST") + +set(CTEST_DROP_METHOD "http") +set(CTEST_DROP_SITE "my.cdash.org") +set(CTEST_DROP_LOCATION "/submit.php?project=CMakeTutorial") +set(CTEST_DROP_SITE_CDASH TRUE) diff --git a/Help/guide/tutorial/Step7/License.txt b/Help/guide/tutorial/Step7/License.txt deleted file mode 100644 index c62d00b..0000000 --- a/Help/guide/tutorial/Step7/License.txt +++ /dev/null @@ -1,2 +0,0 @@ -This is the open source License.txt file introduced in -CMake/Tutorial/Step7... diff --git a/Help/guide/tutorial/Step7/MathFunctions/CMakeLists.txt b/Help/guide/tutorial/Step7/MathFunctions/CMakeLists.txt index 9ede4b3..226099a 100644 --- a/Help/guide/tutorial/Step7/MathFunctions/CMakeLists.txt +++ b/Help/guide/tutorial/Step7/MathFunctions/CMakeLists.txt @@ -1,29 +1,14 @@ -# first we add the executable that generates the table -add_executable(MakeTable MakeTable.cxx) - -# add the command to generate the source code -add_custom_command( - OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/Table.h - COMMAND MakeTable ${CMAKE_CURRENT_BINARY_DIR}/Table.h - DEPENDS MakeTable - ) - -# add the main library -add_library(MathFunctions - mysqrt.cxx - ${CMAKE_CURRENT_BINARY_DIR}/Table.h - ) +add_library(MathFunctions mysqrt.cxx) # state that anybody linking to us needs to include the current source dir # to find MathFunctions.h, while we don't. -# state that we depend on Tutorial_BINARY_DIR but consumers don't, as the -# TutorialConfig.h include is an implementation detail -# state that we depend on our binary dir to find Table.h target_include_directories(MathFunctions INTERFACE ${CMAKE_CURRENT_SOURCE_DIR} - PRIVATE ${CMAKE_CURRENT_BINARY_DIR} ) +target_link_libraries(MathFunctions tutorial_compiler_flags) + # install rules -install(TARGETS MathFunctions DESTINATION lib) +set(installable_libs MathFunctions tutorial_compiler_flags) +install(TARGETS ${installable_libs} DESTINATION lib) install(FILES MathFunctions.h DESTINATION include) diff --git a/Help/guide/tutorial/Step7/MathFunctions/MakeTable.cxx b/Help/guide/tutorial/Step7/MathFunctions/MakeTable.cxx deleted file mode 100644 index ee58556..0000000 --- a/Help/guide/tutorial/Step7/MathFunctions/MakeTable.cxx +++ /dev/null @@ -1,25 +0,0 @@ -// A simple program that builds a sqrt table -#include <cmath> -#include <fstream> -#include <iostream> - -int main(int argc, char* argv[]) -{ - // make sure we have enough arguments - if (argc < 2) { - return 1; - } - - std::ofstream fout(argv[1], std::ios_base::out); - const bool fileOpen = fout.is_open(); - if (fileOpen) { - fout << "double sqrtTable[] = {" << std::endl; - for (int i = 0; i < 10; ++i) { - fout << sqrt(static_cast<double>(i)) << "," << std::endl; - } - // close the table with a zero - fout << "0};" << std::endl; - fout.close(); - } - return fileOpen ? 0 : 1; // return 0 if wrote the file -} diff --git a/Help/guide/tutorial/Step7/MathFunctions/mysqrt.cxx b/Help/guide/tutorial/Step7/MathFunctions/mysqrt.cxx index 7d80ee9..abe767d 100644 --- a/Help/guide/tutorial/Step7/MathFunctions/mysqrt.cxx +++ b/Help/guide/tutorial/Step7/MathFunctions/mysqrt.cxx @@ -2,9 +2,6 @@ #include "MathFunctions.h" -// include the generated table -#include "Table.h" - // a hack square root calculation using simple operations double mysqrt(double x) { @@ -12,12 +9,7 @@ double mysqrt(double x) return 0; } - // use the table to help find an initial value double result = x; - if (x >= 1 && x < 10) { - std::cout << "Use the table to help find an initial value " << std::endl; - result = sqrtTable[static_cast<int>(x)]; - } // do ten iterations for (int i = 0; i < 10; ++i) { @@ -28,6 +20,5 @@ double mysqrt(double x) result = result + 0.5 * delta / result; std::cout << "Computing sqrt of " << x << " to be " << result << std::endl; } - return result; } diff --git a/Help/guide/tutorial/Step8/CMakeLists.txt b/Help/guide/tutorial/Step8/CMakeLists.txt index 4c78b94..cb87281 100644 --- a/Help/guide/tutorial/Step8/CMakeLists.txt +++ b/Help/guide/tutorial/Step8/CMakeLists.txt @@ -1,11 +1,21 @@ -cmake_minimum_required(VERSION 3.10) +cmake_minimum_required(VERSION 3.15) # set the project name and version project(Tutorial VERSION 1.0) # 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) + +# add compiler warning flags just when building this project via +# the BUILD_INTERFACE genex +set(gcc_like_cxx "$<COMPILE_LANG_AND_ID:CXX,ARMClang,AppleClang,Clang,GNU,LCC>") +set(msvc_cxx "$<COMPILE_LANG_AND_ID:CXX,MSVC>") +target_compile_options(tutorial_compiler_flags INTERFACE + "$<${gcc_like_cxx}:$<BUILD_INTERFACE:-Wall;-Wextra;-Wshadow;-Wformat=2;-Wunused>>" + "$<${msvc_cxx}:$<BUILD_INTERFACE:-W3>>" +) + # should we use our own math functions option(USE_MYMATH "Use tutorial provided math implementation" ON) @@ -22,7 +32,7 @@ endif() # add the executable add_executable(Tutorial tutorial.cxx) -target_link_libraries(Tutorial PUBLIC ${EXTRA_LIBS}) +target_link_libraries(Tutorial PUBLIC ${EXTRA_LIBS} tutorial_compiler_flags) # add the binary tree to the search path for include files # so that we will find TutorialConfig.h @@ -37,7 +47,7 @@ install(FILES "${PROJECT_BINARY_DIR}/TutorialConfig.h" ) # enable testing -enable_testing() +include(CTest) # does the application run add_test(NAME Runs COMMAND Tutorial 25) @@ -64,11 +74,3 @@ do_test(Tutorial 7 "7 is 2.645") do_test(Tutorial 25 "25 is 5") do_test(Tutorial -25 "-25 is (-nan|nan|0)") do_test(Tutorial 0.0001 "0.0001 is 0.01") - -# setup installer -include(InstallRequiredSystemLibraries) -set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/License.txt") -set(CPACK_PACKAGE_VERSION_MAJOR "${Tutorial_VERSION_MAJOR}") -set(CPACK_PACKAGE_VERSION_MINOR "${Tutorial_VERSION_MINOR}") -set(CPACK_SOURCE_GENERATOR "TGZ") -include(CPack) diff --git a/Help/guide/tutorial/Step8/License.txt b/Help/guide/tutorial/Step8/License.txt deleted file mode 100644 index c62d00b..0000000 --- a/Help/guide/tutorial/Step8/License.txt +++ /dev/null @@ -1,2 +0,0 @@ -This is the open source License.txt file introduced in -CMake/Tutorial/Step7... diff --git a/Help/guide/tutorial/Step8/MathFunctions/CMakeLists.txt b/Help/guide/tutorial/Step8/MathFunctions/CMakeLists.txt index 9ede4b3..a832003 100644 --- a/Help/guide/tutorial/Step8/MathFunctions/CMakeLists.txt +++ b/Help/guide/tutorial/Step8/MathFunctions/CMakeLists.txt @@ -1,29 +1,37 @@ -# first we add the executable that generates the table -add_executable(MakeTable MakeTable.cxx) - -# add the command to generate the source code -add_custom_command( - OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/Table.h - COMMAND MakeTable ${CMAKE_CURRENT_BINARY_DIR}/Table.h - DEPENDS MakeTable - ) - -# add the main library -add_library(MathFunctions - mysqrt.cxx - ${CMAKE_CURRENT_BINARY_DIR}/Table.h - ) +add_library(MathFunctions mysqrt.cxx) # state that anybody linking to us needs to include the current source dir # to find MathFunctions.h, while we don't. -# state that we depend on Tutorial_BINARY_DIR but consumers don't, as the -# TutorialConfig.h include is an implementation detail -# state that we depend on our binary dir to find Table.h target_include_directories(MathFunctions INTERFACE ${CMAKE_CURRENT_SOURCE_DIR} - PRIVATE ${CMAKE_CURRENT_BINARY_DIR} ) +target_link_libraries(MathFunctions tutorial_compiler_flags) + +# does this system provide the log and exp functions? +include(CheckCXXSourceCompiles) +check_cxx_source_compiles(" + #include <cmath> + int main() { + std::log(1.0); + return 0; + } +" HAVE_LOG) +check_cxx_source_compiles(" + #include <cmath> + int main() { + std::exp(1.0); + return 0; + } +" HAVE_EXP) + +# add compile definitions +if(HAVE_LOG AND HAVE_EXP) + target_compile_definitions(MathFunctions + PRIVATE "HAVE_LOG" "HAVE_EXP") +endif() + # install rules -install(TARGETS MathFunctions DESTINATION lib) +set(installable_libs MathFunctions tutorial_compiler_flags) +install(TARGETS ${installable_libs} DESTINATION lib) install(FILES MathFunctions.h DESTINATION include) diff --git a/Help/guide/tutorial/Step8/MathFunctions/mysqrt.cxx b/Help/guide/tutorial/Step8/MathFunctions/mysqrt.cxx index 7d80ee9..7eecd26 100644 --- a/Help/guide/tutorial/Step8/MathFunctions/mysqrt.cxx +++ b/Help/guide/tutorial/Step8/MathFunctions/mysqrt.cxx @@ -1,10 +1,8 @@ +#include <cmath> #include <iostream> #include "MathFunctions.h" -// include the generated table -#include "Table.h" - // a hack square root calculation using simple operations double mysqrt(double x) { @@ -12,12 +10,13 @@ double mysqrt(double x) return 0; } - // use the table to help find an initial value + // if we have both log and exp then use them +#if defined(HAVE_LOG) && defined(HAVE_EXP) + double result = std::exp(std::log(x) * 0.5); + std::cout << "Computing sqrt of " << x << " to be " << result + << " using log and exp" << std::endl; +#else double result = x; - if (x >= 1 && x < 10) { - std::cout << "Use the table to help find an initial value " << std::endl; - result = sqrtTable[static_cast<int>(x)]; - } // do ten iterations for (int i = 0; i < 10; ++i) { @@ -28,6 +27,6 @@ double mysqrt(double x) result = result + 0.5 * delta / result; std::cout << "Computing sqrt of " << x << " to be " << result << std::endl; } - +#endif return result; } diff --git a/Help/guide/tutorial/Step9/CMakeLists.txt b/Help/guide/tutorial/Step9/CMakeLists.txt index 6bae26e..d26a90c 100644 --- a/Help/guide/tutorial/Step9/CMakeLists.txt +++ b/Help/guide/tutorial/Step9/CMakeLists.txt @@ -1,11 +1,20 @@ -cmake_minimum_required(VERSION 3.10) +cmake_minimum_required(VERSION 3.15) # set the project name and version project(Tutorial VERSION 1.0) # 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) + +# add compiler warning flags just when building this project via +# the BUILD_INTERFACE genex +set(gcc_like_cxx "$<COMPILE_LANG_AND_ID:CXX,ARMClang,AppleClang,Clang,GNU,LCC>") +set(msvc_cxx "$<COMPILE_LANG_AND_ID:CXX,MSVC>") +target_compile_options(tutorial_compiler_flags INTERFACE + "$<${gcc_like_cxx}:$<BUILD_INTERFACE:-Wall;-Wextra;-Wshadow;-Wformat=2;-Wunused>>" + "$<${msvc_cxx}:$<BUILD_INTERFACE:-W3>>" +) # should we use our own math functions option(USE_MYMATH "Use tutorial provided math implementation" ON) @@ -22,7 +31,7 @@ endif() # add the executable add_executable(Tutorial tutorial.cxx) -target_link_libraries(Tutorial PUBLIC ${EXTRA_LIBS}) +target_link_libraries(Tutorial PUBLIC ${EXTRA_LIBS} tutorial_compiler_flags) # add the binary tree to the search path for include files # so that we will find TutorialConfig.h @@ -64,10 +73,3 @@ do_test(Tutorial 7 "7 is 2.645") do_test(Tutorial 25 "25 is 5") do_test(Tutorial -25 "-25 is (-nan|nan|0)") do_test(Tutorial 0.0001 "0.0001 is 0.01") - -include(InstallRequiredSystemLibraries) -set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/License.txt") -set(CPACK_PACKAGE_VERSION_MAJOR "${Tutorial_VERSION_MAJOR}") -set(CPACK_PACKAGE_VERSION_MINOR "${Tutorial_VERSION_MINOR}") -set(CPACK_SOURCE_GENERATOR "TGZ") -include(CPack) diff --git a/Help/guide/tutorial/Step9/License.txt b/Help/guide/tutorial/Step9/License.txt index c62d00b..85760e5 100644 --- a/Help/guide/tutorial/Step9/License.txt +++ b/Help/guide/tutorial/Step9/License.txt @@ -1,2 +1,2 @@ This is the open source License.txt file introduced in -CMake/Tutorial/Step7... +CMake/Tutorial/Step9... diff --git a/Help/guide/tutorial/Step9/MathFunctions/CMakeLists.txt b/Help/guide/tutorial/Step9/MathFunctions/CMakeLists.txt index 50f0701..8a08157 100644 --- a/Help/guide/tutorial/Step9/MathFunctions/CMakeLists.txt +++ b/Help/guide/tutorial/Step9/MathFunctions/CMakeLists.txt @@ -16,12 +16,17 @@ add_library(MathFunctions # state that anybody linking to us needs to include the current source dir # to find MathFunctions.h, while we don't. +# state that we depend on Tutorial_BINARY_DIR but consumers don't, as the +# TutorialConfig.h include is an implementation detail # state that we depend on our binary dir to find Table.h target_include_directories(MathFunctions INTERFACE ${CMAKE_CURRENT_SOURCE_DIR} PRIVATE ${CMAKE_CURRENT_BINARY_DIR} ) +target_link_libraries(MathFunctions tutorial_compiler_flags) + # install rules -install(TARGETS MathFunctions DESTINATION lib) +set(installable_libs MathFunctions tutorial_compiler_flags) +install(TARGETS ${installable_libs} DESTINATION lib) install(FILES MathFunctions.h DESTINATION include) diff --git a/Help/guide/tutorial/Step9/MathFunctions/MathFunctions.cxx b/Help/guide/tutorial/Step9/MathFunctions/MathFunctions.cxx deleted file mode 100644 index 0145300..0000000 --- a/Help/guide/tutorial/Step9/MathFunctions/MathFunctions.cxx +++ /dev/null @@ -1,19 +0,0 @@ - -#include "MathFunctions.h" - -#include <cmath> - -#ifdef USE_MYMATH -# include "mysqrt.h" -#endif - -namespace mathfunctions { -double sqrt(double x) -{ -#ifdef USE_MYMATH - return detail::mysqrt(x); -#else - return std::sqrt(x); -#endif -} -} diff --git a/Help/guide/tutorial/Step9/MathFunctions/mysqrt.h b/Help/guide/tutorial/Step9/MathFunctions/mysqrt.h deleted file mode 100644 index e1c42ef..0000000 --- a/Help/guide/tutorial/Step9/MathFunctions/mysqrt.h +++ /dev/null @@ -1,6 +0,0 @@ - -namespace mathfunctions { -namespace detail { -double mysqrt(double x); -} -} diff --git a/Help/guide/tutorial/index.rst b/Help/guide/tutorial/index.rst index 09553cb..1ab0009 100644 --- a/Help/guide/tutorial/index.rst +++ b/Help/guide/tutorial/index.rst @@ -24,13 +24,13 @@ provides the complete solution for the previous step. A Basic Starting Point Adding a Library Adding Usage Requirements for a Library + Adding Generator Expressions Installing and Testing + Adding Support for a Testing Dashboard Adding System Introspection Adding a Custom Command and Generated File Packaging an Installer - Adding Support for a Testing Dashboard Selecting Static or Shared Libraries - Adding Generator Expressions Adding Export Configuration Packaging Debug and Release |