diff options
Diffstat (limited to 'Help/guide/tutorial/Adding a Library.rst')
| -rw-r--r-- | Help/guide/tutorial/Adding a Library.rst | 135 | 
1 files changed, 135 insertions, 0 deletions
diff --git a/Help/guide/tutorial/Adding a Library.rst b/Help/guide/tutorial/Adding a Library.rst new file mode 100644 index 0000000..ed03448 --- /dev/null +++ b/Help/guide/tutorial/Adding a Library.rst @@ -0,0 +1,135 @@ +Step 2: Adding a Library +======================== + +Now we will add a library to our project. This library will contain 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. + +Add the following one line ``CMakeLists.txt`` file to the ``MathFunctions`` +directory: + +.. literalinclude:: Step3/MathFunctions/CMakeLists.txt +  :caption: MathFunctions/CMakeLists.txt +  :name: MathFunctions/CMakeLists.txt +  :language: cmake + +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 ``mysqrt.h`` header file can be found. The +last few lines of the top-level ``CMakeLists.txt`` file should now look like: + +.. code-block:: cmake +        :caption: CMakeLists.txt +        :name: CMakeLists.txt-add_subdirectory + +        # add the MathFunctions library +        add_subdirectory(MathFunctions) + +        # add the executable +        add_executable(Tutorial tutorial.cxx) + +        target_link_libraries(Tutorial PUBLIC MathFunctions) + +        # 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" +                                  ) + +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. + +.. literalinclude:: Step3/CMakeLists.txt +  :caption: CMakeLists.txt +  :name: CMakeLists.txt-option +  :language: cmake +  :start-after: # should we use our own math functions +  :end-before: # add the MathFunctions library + +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: + +.. literalinclude:: Step3/CMakeLists.txt +  :caption: CMakeLists.txt +  :name: CMakeLists.txt-target_link_libraries-EXTRA_LIBS +  :language: cmake +  :start-after: # add the MathFunctions library + +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. + +The corresponding changes to the source code are fairly straightforward. +First, in ``tutorial.cxx``, include the ``MathFunctions.h`` header if we +need it: + +.. literalinclude:: Step3/tutorial.cxx +  :caption: 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 +function is used: + +.. literalinclude:: Step3/tutorial.cxx +  :caption: 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 + +Since the source code now requires ``USE_MYMATH`` we can add it to +``TutorialConfig.h.in`` with the following line: + +.. literalinclude:: Step3/TutorialConfig.h.in +  :caption: TutorialConfig.h.in +  :name: TutorialConfig.h.in-cmakedefine +  :language: c++ +  :lines: 4 + +**Exercise**: 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. + +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: + +.. code-block:: console + +  cmake ../Step2 -DUSE_MYMATH=OFF + +Rebuild and run the tutorial again. + +Which function gives better results, ``sqrt`` or ``mysqrt``?  | 
