Adding a Library.rst 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. Step 2: Adding a Library
  2. ========================
  3. Now we will add a library to our project. This library will contain our own
  4. implementation for computing the square root of a number. The executable can
  5. then use this library instead of the standard square root function provided by
  6. the compiler.
  7. For this tutorial we will put the library into a subdirectory
  8. called ``MathFunctions``. This directory already contains a header file,
  9. ``MathFunctions.h``, and a source file ``mysqrt.cxx``. The source file has one
  10. function called ``mysqrt`` that provides similar functionality to the
  11. compiler's ``sqrt`` function.
  12. Add the following one line ``CMakeLists.txt`` file to the ``MathFunctions``
  13. directory:
  14. .. literalinclude:: Step3/MathFunctions/CMakeLists.txt
  15. :language: cmake
  16. To make use of the new library we will add an :command:`add_subdirectory`
  17. call in the top-level ``CMakeLists.txt`` file so that the library will get
  18. built. We add the new library to the executable, and add ``MathFunctions`` as
  19. an include directory so that the ``mysqrt.h`` header file can be found. The
  20. last few lines of the top-level ``CMakeLists.txt`` file should now look like:
  21. .. code-block:: cmake
  22. # add the MathFunctions library
  23. add_subdirectory(MathFunctions)
  24. # add the executable
  25. add_executable(Tutorial tutorial.cxx)
  26. target_link_libraries(Tutorial PUBLIC MathFunctions)
  27. # add the binary tree to the search path for include files
  28. # so that we will find TutorialConfig.h
  29. target_include_directories(Tutorial PUBLIC
  30. "${PROJECT_BINARY_DIR}"
  31. "${PROJECT_SOURCE_DIR}/MathFunctions"
  32. )
  33. Now let us make the MathFunctions library optional. While for the tutorial
  34. there really isn't any need to do so, for larger projects this is a common
  35. occurrence. The first step is to add an option to the top-level
  36. ``CMakeLists.txt`` file.
  37. .. literalinclude:: Step3/CMakeLists.txt
  38. :language: cmake
  39. :start-after: # should we use our own math functions
  40. :end-before: # add the MathFunctions library
  41. This option will be displayed in the :manual:`cmake-gui <cmake-gui(1)>` and
  42. :manual:`ccmake <ccmake(1)>`
  43. with a default value of ON that can be changed by the user. This setting will
  44. be stored in the cache so that the user does not need to set the value each
  45. time they run CMake on a build directory.
  46. The next change is to make building and linking the MathFunctions library
  47. conditional. To do this we change the end of the top-level ``CMakeLists.txt``
  48. file to look like the following:
  49. .. literalinclude:: Step3/CMakeLists.txt
  50. :language: cmake
  51. :start-after: # add the MathFunctions library
  52. Note the use of the variable ``EXTRA_LIBS`` to collect up any optional
  53. libraries to later be linked into the executable. The variable
  54. ``EXTRA_INCLUDES`` is used similarly for optional header files. This is a
  55. classic approach when dealing with many optional components, we will cover
  56. the modern approach in the next step.
  57. The corresponding changes to the source code are fairly straightforward.
  58. First, in ``tutorial.cxx``, include the ``MathFunctions.h`` header if we
  59. need it:
  60. .. literalinclude:: Step3/tutorial.cxx
  61. :language: c++
  62. :start-after: // should we include the MathFunctions header
  63. :end-before: int main
  64. Then, in the same file, make ``USE_MYMATH`` control which square root
  65. function is used:
  66. .. literalinclude:: Step3/tutorial.cxx
  67. :language: c++
  68. :start-after: // which square root function should we use?
  69. :end-before: std::cout << "The square root of
  70. Since the source code now requires ``USE_MYMATH`` we can add it to
  71. ``TutorialConfig.h.in`` with the following line:
  72. .. literalinclude:: Step3/TutorialConfig.h.in
  73. :language: c
  74. :lines: 4
  75. **Exercise**: Why is it important that we configure ``TutorialConfig.h.in``
  76. after the option for ``USE_MYMATH``? What would happen if we inverted the two?
  77. Run the :manual:`cmake <cmake(1)>` executable or the
  78. :manual:`cmake-gui <cmake-gui(1)>` to configure the project and then build it
  79. with your chosen build tool. Then run the built Tutorial executable.
  80. Now let's update the value of ``USE_MYMATH``. The easiest way is to use the
  81. :manual:`cmake-gui <cmake-gui(1)>` or :manual:`ccmake <ccmake(1)>` if you're
  82. in the terminal. Or, alternatively, if you want to change the option from the
  83. command-line, try:
  84. .. code-block:: console
  85. cmake ../Step2 -DUSE_MYMATH=OFF
  86. Rebuild and run the tutorial again.
  87. Which function gives better results, sqrt or mysqrt?