Adding Export Configuration.rst 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. Step 11: Adding Export Configuration
  2. ====================================
  3. During :guide:`tutorial/Installing and Testing` of the tutorial we added the
  4. ability for CMake to install the library and headers of the project. During
  5. :guide:`tutorial/Packaging an Installer` we added the ability to package up
  6. this information so it could be distributed to other people.
  7. The next step is to add the necessary information so that other CMake projects
  8. can use our project, be it from a build directory, a local install or when
  9. packaged.
  10. The first step is to update our :command:`install(TARGETS)` commands to not
  11. only specify a ``DESTINATION`` but also an ``EXPORT``. The ``EXPORT`` keyword
  12. generates a CMake file containing code to import all targets listed in the
  13. install command from the installation tree. So let's go ahead and explicitly
  14. ``EXPORT`` the ``MathFunctions`` library by updating the ``install`` command
  15. in ``MathFunctions/CMakeLists.txt`` to look like:
  16. .. literalinclude:: Complete/MathFunctions/CMakeLists.txt
  17. :caption: MathFunctions/CMakeLists.txt
  18. :name: MathFunctions/CMakeLists.txt-install-TARGETS-EXPORT
  19. :language: cmake
  20. :start-after: # install libs
  21. Now that we have ``MathFunctions`` being exported, we also need to explicitly
  22. install the generated ``MathFunctionsTargets.cmake`` file. This is done by
  23. adding the following to the bottom of the top-level ``CMakeLists.txt``:
  24. .. literalinclude:: Complete/CMakeLists.txt
  25. :caption: CMakeLists.txt
  26. :name: CMakeLists.txt-install-EXPORT
  27. :language: cmake
  28. :start-after: # install the configuration targets
  29. :end-before: include(CMakePackageConfigHelpers)
  30. At this point you should try and run CMake. If everything is setup properly
  31. you will see that CMake will generate an error that looks like:
  32. .. code-block:: console
  33. Target "MathFunctions" INTERFACE_INCLUDE_DIRECTORIES property contains
  34. path:
  35. "/Users/robert/Documents/CMakeClass/Tutorial/Step11/MathFunctions"
  36. which is prefixed in the source directory.
  37. CMake is telling you that during the generation of the export information
  38. it will export a path that is intrinsically tied to the current machine and
  39. will not be valid on other machines. The solution to this is to update the
  40. ``MathFunctions`` :command:`target_include_directories` to understand that it
  41. needs different ``INTERFACE`` locations when being used from within the build
  42. directory and from an install / package. This means converting the
  43. :command:`target_include_directories` call for ``MathFunctions`` to look like:
  44. .. literalinclude:: Step12/MathFunctions/CMakeLists.txt
  45. :caption: MathFunctions/CMakeLists.txt
  46. :name: MathFunctions/CMakeLists.txt-target_include_directories
  47. :language: cmake
  48. :start-after: # to find MathFunctions.h, while we don't.
  49. :end-before: # should we use our own math functions
  50. Once this has been updated, we can re-run CMake and verify that it doesn't
  51. warn anymore.
  52. At this point, we have CMake properly packaging the target information that is
  53. required but we will still need to generate a ``MathFunctionsConfig.cmake`` so
  54. that the CMake :command:`find_package` command can find our project. So let's go
  55. ahead and add a new file to the top-level of the project called
  56. ``Config.cmake.in`` with the following contents:
  57. .. literalinclude:: Step12/Config.cmake.in
  58. :caption: Config.cmake.in
  59. :name: Config.cmake.in
  60. Then, to properly configure and install that file, add the following to the
  61. bottom of the top-level ``CMakeLists.txt``:
  62. .. literalinclude:: Step12/CMakeLists.txt
  63. :caption: CMakeLists.txt
  64. :name: CMakeLists.txt-install-Config.cmake
  65. :language: cmake
  66. :start-after: # install the configuration targets
  67. :end-before: # generate the config file
  68. Next, we execute the :command:`configure_package_config_file`. This command
  69. will configure a provided file but with a few specific differences from the
  70. standard :command:`configure_file` way.
  71. To properly utilize this function, the input file should have a single line
  72. with the text ``@PACKAGE_INIT@`` in addition to the content that is desired.
  73. That variable will be replaced with a block of code which turns set values into
  74. relative paths. These values which are new can be referenced by the same name
  75. but prepended with a ``PACKAGE_`` prefix.
  76. .. literalinclude:: Step12/CMakeLists.txt
  77. :caption: CMakeLists.txt
  78. :name: CMakeLists.txt-configure-package-config.cmake
  79. :language: cmake
  80. :start-after: # install the configuration targets
  81. :end-before: # generate the version file
  82. The :command:`write_basic_package_version_file` is next. This command writes
  83. a file which is used by :command:`find_package`, documenting the version and
  84. compatibility of the desired package. Here, we use the ``Tutorial_VERSION_*``
  85. variables and say that it is compatible with ``AnyNewerVersion``, which
  86. denotes that this version or any higher one are compatible with the requested
  87. version.
  88. .. literalinclude:: Step12/CMakeLists.txt
  89. :caption: CMakeLists.txt
  90. :name: CMakeLists.txt-basic-version-file.cmake
  91. :language: cmake
  92. :start-after: # generate the version file
  93. :end-before: # install the generated configuration files
  94. Finally, set both generated files to be installed:
  95. .. literalinclude:: Step12/CMakeLists.txt
  96. :caption: CMakeLists.txt
  97. :name: CMakeLists.txt-install-configured-files.cmake
  98. :language: cmake
  99. :start-after: # install the generated configuration files
  100. :end-before: # generate the export
  101. At this point, we have generated a relocatable CMake Configuration for our
  102. project that can be used after the project has been installed or packaged. If
  103. we want our project to also be used from a build directory we only have to add
  104. the following to the bottom of the top level ``CMakeLists.txt``:
  105. .. literalinclude:: Step12/CMakeLists.txt
  106. :caption: CMakeLists.txt
  107. :name: CMakeLists.txt-export
  108. :language: cmake
  109. :start-after: # needs to be after the install(TARGETS) command
  110. With this export call we now generate a ``MathFunctionsTargets.cmake``, allowing the
  111. configured ``MathFunctionsConfig.cmake`` in the build directory to be used by
  112. other projects, without needing it to be installed.