Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

241 line
8.3KB

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