Nelze vybrat více než 25 témat Téma musí začínat písmenem nebo číslem, může obsahovat pomlčky („-“) a může být dlouhé až 35 znaků.

240 lines
8.2KB

  1. .. highlight:: cmake
  2. Using ``dds`` Packages in a CMake Project
  3. #########################################
  4. One of ``dds``'s primary goals is to inter-operate with other build systems
  5. cleanly. One of ``dds``'s primary outputs is *libman* package indices. These
  6. package indices can be imported into other build systems that support the
  7. *libman* format.
  8. .. note::
  9. ``dds`` doesn't (yet) have a ready-made central repository of packages that
  10. can be downloaded. You'll need to populate the local package catalog
  11. appropriately.
  12. .. seealso:: Refer to :doc:`catalog` for information about remote packages.
  13. .. _PMM: https://github.com/vector-of-bool/PMM
  14. .. _CMakeCM: https://github.com/vector-of-bool/CMakeCM
  15. .. _lm-cmake: https://raw.githubusercontent.com/vector-of-bool/libman/develop/cmake/libman.cmake
  16. Generating a libman Index
  17. *************************
  18. Importing libman packages into a build system requires that we have a libman
  19. index generated on the filesystem. **This index is not generated globally**: It
  20. is generated on a per-build basis as part of the build setup. The index will
  21. describe in build-system-agnostic terms how to include a set of packages and
  22. libraries as part of a build.
  23. ``dds`` has first-class support for generating this index. The ``build-deps``
  24. subcommand of ``dds`` will download and build a set of dependencies, and places
  25. an ``INDEX.lmi`` file that can be used to import the built results.
  26. Declaring Dependencies
  27. ======================
  28. ``dds build-deps`` accepts a list of dependencies as commnad line arguments,
  29. but it may be useful to specify those requirements in a file.
  30. ``dds build-deps`` accepts a JSON5 file describing the dependencies of a
  31. project as well. This file is similar to a very stripped-down version of a
  32. ``dds`` :ref:`package manifest <pkgs.pkgs>`, and only includes the ``depends``
  33. key. (The presence of any other key is an error.)
  34. Here is a simple dependencies file that declares a single requirement:
  35. .. code-block:: js
  36. :caption: ``dependencies.json5``
  37. {
  38. depends: {
  39. 'neo-sqlite3': '^0.2.0',
  40. }
  41. }
  42. Building Dependencies and the Index
  43. ===================================
  44. We can invoke ``dds build-deps`` and give it the path to this file:
  45. .. code-block:: bash
  46. $ dds build-deps --deps dependencies.json5
  47. When finished, ``dds`` will write the build results into a subdirectory called
  48. ``_deps`` and generate a file named ``INDEX.lmi``. This file is ready to be
  49. imported into any build system that can understand libman files (in our case,
  50. CMake).
  51. .. note::
  52. The output directory and index filepath can be controlled with the
  53. ``--out`` and ``--lmi-path`` flags, respectively.
  54. Importing into CMake
  55. ********************
  56. We've generated a libman index and set of packages, and we want to import
  57. them into CMake. CMake doesn't know how to do this natively, but there exists a
  58. single-file module for CMake that allows CMake to import libraries from libman
  59. indices without any additional work.
  60. The module is not shipped with CMake, but is available online as a single
  61. stand-alone file. The `libman.cmake <lm-cmake_>`_ file can be downloaded and
  62. added to a project directly, or it can be obtained automatically through a
  63. CMake tool like `PMM`_ (recommended).
  64. Enabling *libman* Support in CMake via PMM
  65. ==========================================
  66. Refer to the ``README.md`` file in `the PMM repo <PMM_>`_ for information on how
  67. to get PMM into your CMake project. In short, download and place the
  68. ``pmm.cmake`` file in your repository, and ``include()`` the file near the top
  69. of your ``CMakeLists.txt``::
  70. include(pmm.cmake)
  71. Once it has been included, you can call the ``pmm()`` function. To obtain
  72. *libman*, we need to start by enabling `CMakeCM`_::
  73. pmm(CMakeCM ROLLING)
  74. .. warning::
  75. It is not recommended to use the ``ROLLING`` mode, but it is the easiest to
  76. use when getting started. For reproducible and reliable builds, you should
  77. pin your CMakeCM version using the ``FROM <url>`` argument.
  78. Enabling CMakeCM will make available all of the CMake modules available in `the
  79. CMakeCM repository <CMakeCM_>`_, which includes `libman.cmake <lm-cmake_>`_.
  80. After the call to ``pmm()``, simply ``include()`` the ``libman`` module::
  81. include(libman)
  82. That's it! The only function from the module that we will care about for now
  83. is the ``import_packages()`` function.
  84. Importing Our Dependencies' Packages
  85. ====================================
  86. To import a package from a libman tree, we need only know the *name* of the
  87. package we wish to import. In our example case above, we depend on
  88. ``neo-sqlite3``, so we simply call the libman-CMake function
  89. ``import_packages()`` with that package name::
  90. import_packages("neo-sqlite3")
  91. You'll note that we don't request any particular version of the package: All
  92. versioning resolution is handled by ``dds``. You'll also note that we don't
  93. need to specify our transitive dependencies: This is handled by the libman
  94. index that was generated by ``dds``: It will automatically ``import_packages()``
  95. any of the transitive dependencies required.
  96. Using Out Dependencies' Libraries
  97. =================================
  98. Like with ``dds``, CMake wants us to explicitly declare how our build targets
  99. *use* other libraries. When we import a package from a libman index, the
  100. import will generate CMake ``IMPORTED`` targets that can be linked against.
  101. In ``dds`` and in libman, a library is identified by a combination of
  102. *namespace* and *name*, joined together with a slash ``/`` character. This
  103. *qualified name* of a library is decided by the original package author, and
  104. should be documented. In the case of ``neo-sqlite3``, the only target is
  105. ``neo/sqlite3``.
  106. When the libman CMake module imports a library, it creates a qualified name
  107. using a double-colon "``::``" instead of a slash. As such, our ``neo/sqlite3``
  108. is imported in CMake as ``neo::sqlite3``. We can link against it as we would
  109. with any other target::
  110. add_executable(my-application app.cpp)
  111. target_link_libraries(my-application PRIVATE neo::sqlite3)
  112. Altogether, here is the final CMake file:
  113. .. code-block::
  114. :caption: ``CMakeLists.txt``
  115. :linenos:
  116. cmake_minimum_required(VERSION 3.15)
  117. project(MyApplication VERSION 1.0.0)
  118. include(pmm.cmake)
  119. pmm(CMakeCM ROLLING)
  120. include(libman)
  121. import_packages("neo-sqlite3")
  122. add_executable(my-application app.cpp)
  123. target_link_libraries(my-application PRIVATE neo::sqlite3)
  124. Additional PMM Support
  125. **********************
  126. The ``pmm()`` function also supports ``dds`` directly, similar to ``CMakeCM``
  127. mode. This will automatically download a prebuilt ``dds`` for the host platform
  128. and invoke ``dds build-deps`` in a single pass as part of CMake's configure
  129. process. This is especially useful for a CI environment where you want to have
  130. a stable ``dds`` version and always have your dependencies obtained
  131. just-in-time.
  132. To start, pass the ``DDS`` argument to ``pmm()`` to use it::
  133. pmm(DDS)
  134. ..note::
  135. The ``_deps`` directory and ``INDEX.lmi`` file will be placed in the CMake
  136. build directory, out of the way of the rest of the project.
  137. .. note::
  138. The version of ``dds`` that PMM downloads depends on the version of PMM
  139. that is in use.
  140. This alone won't do anything useful, because you'll need to tell it what
  141. dependencies we want to install::
  142. pmm(DDS DEP_FILES dependencies.json5)
  143. You can also list your dependencies as an inline string in your CMakeLists.txt
  144. instead of a separate file::
  145. pmm(DDS DEPENDS "neo-sqlite3 ^0.2.2")
  146. Since you'll probably want to be using ``libman.cmake`` at the same time, the
  147. calls for ``CMakeCM`` and ``DDS`` can simply be combined. This is how our new
  148. CMake project might look:
  149. .. code-block::
  150. :caption: ``CMakeLists.txt``
  151. :linenos:
  152. cmake_minimum_required(VERSION 3.15)
  153. project(MyApplication VERSION 1.0.0)
  154. include(pmm.cmake)
  155. pmm(CMakeCM ROLLING
  156. DDS DEPENDS "neo-sqlite3 ^0.2.2"
  157. )
  158. include(libman)
  159. import_packages("neo-sqlite3")
  160. add_executable(my-application app.cpp)
  161. target_link_libraries(my-application PRIVATE neo::sqlite3)
  162. This removes the requirement that we write a separate dependencies file, and we
  163. no longer need to invoke ``dds build-deps`` externally, as it is all handled
  164. by ``pmm``.