Adding a Library.rst 4.7 KB

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