|  |  | @@ -0,0 +1,214 @@ | 
		
	
		
			
			|  |  |  | How Do I Use ``dds`` in a CMake Project? | 
		
	
		
			
			|  |  |  | ######################################## | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | .. highlight:: cmake | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | If you have a CMake project and you wish to pull your dependencies via ``dds``, | 
		
	
		
			
			|  |  |  | you're in luck: Such a process is explicitly supported. Here's the recommended | 
		
	
		
			
			|  |  |  | approach: | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | #. Download `PMM`_ and place and commit `the PMM script <pmm.cmake>`_ into your | 
		
	
		
			
			|  |  |  | CMake project. [#f1]_ | 
		
	
		
			
			|  |  |  | #. In your ``CMakeLists.txt``, ``include()`` ``pmm.cmake``. | 
		
	
		
			
			|  |  |  | #. Call ``pmm(DDS)`` and list your dependencies. | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | Below, we'll walk through this in more detail. | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | .. note:: | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | You don't even have to have ``dds`` downloaded and present on your system to | 
		
	
		
			
			|  |  |  | use ``dds`` in PMM! Read on... | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | Using PMM | 
		
	
		
			
			|  |  |  | ********* | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | `PMM`_ is the *Package Manager Manager* for CMake, and is designed to offer | 
		
	
		
			
			|  |  |  | greater integration between a CMake build and an external package management | 
		
	
		
			
			|  |  |  | tool. `PMM`_ supports Conan, vcpkg, and, of course, ``dds``. | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | .. seealso:: | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | Refer to the ``README.md`` file in `the PMM repo <PMM>`_ for information on | 
		
	
		
			
			|  |  |  | how to use PMM. | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | Getting PMM | 
		
	
		
			
			|  |  |  | =========== | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | To use PMM, you need to download one only file and commit it to your project: | 
		
	
		
			
			|  |  |  | `pmm.cmake`_, the entrypoint for PMM [#f1]_. It is not significant where the | 
		
	
		
			
			|  |  |  | ``pmm.cmake`` script is placed, but it should be noted for inclusion. | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | ``pmm.cmake`` should be committed to the project because it contains version | 
		
	
		
			
			|  |  |  | pinning settings for PMM and can be customized on a per-project basis to alter | 
		
	
		
			
			|  |  |  | its behavior for a particular project's needs. | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | Including PMM | 
		
	
		
			
			|  |  |  | ============= | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | Suppose I have downloaded and committed `pmm.cmake`_ into the ``tools/`` | 
		
	
		
			
			|  |  |  | subdirectory of my CMake project. To use it in CMake, I first need to | 
		
	
		
			
			|  |  |  | ``include()`` the script. The simplest way is to simply ``include()`` the file | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | .. code-block:: | 
		
	
		
			
			|  |  |  | :caption: CMakeLists.txt | 
		
	
		
			
			|  |  |  | :emphasize-lines: 4 | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | cmake_minimum_required(VERSION 3.12) | 
		
	
		
			
			|  |  |  | project(MyApplication VERSION 2.1.3) | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | include(tools/pmm.cmake) | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | The ``include()`` command should specify the path to ``pmm.cmake``, including | 
		
	
		
			
			|  |  |  | the file extension, relative to the directory that contains the CMake script | 
		
	
		
			
			|  |  |  | that contains the ``include()`` command. | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | Running PMM | 
		
	
		
			
			|  |  |  | =========== | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | Simply ``include()``-ing PMM won't do much, because we need to actually *invoke | 
		
	
		
			
			|  |  |  | it*. | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | PMM's main CMake command is ``pmm()``. It takes a variety of options and | 
		
	
		
			
			|  |  |  | arguments for the package managers it supports, but we'll only focus on ``dds`` | 
		
	
		
			
			|  |  |  | for now. | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | The basic signature of the ``pmm(DDS)`` command looks like this:: | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | pmm(DDS [DEP_FILES [filepaths...]] | 
		
	
		
			
			|  |  |  | [DEPENDS [dependencies...]] | 
		
	
		
			
			|  |  |  | [TOOLCHAIN file-or-id]) | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | The most straightforward usage is to use only the ``DEPENDS`` argument. For | 
		
	
		
			
			|  |  |  | example, if we want to import `{fmt} <https://fmt.dev>`_:: | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | pmm(DDS DEPENDS "fmt^7.0.3") | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | When CMake executes the ``pmm(DDS ...)`` line above, PMM will download the | 
		
	
		
			
			|  |  |  | appropriate ``dds`` executable for your platform, generate | 
		
	
		
			
			|  |  |  | :doc:`a dds toolchain </guide/toolchains>` based on the CMake environment, and | 
		
	
		
			
			|  |  |  | then invoke ``dds build-deps`` to build the dependencies that were listed in the | 
		
	
		
			
			|  |  |  | ``pmm()`` invocation. The results from ``build-deps`` are then imported into | 
		
	
		
			
			|  |  |  | CMake as ``IMPORTED`` targets that can be used by the containing CMake project. | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | .. seealso:: | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | For more in-depth discussion on ``dds build-deps``, refer to | 
		
	
		
			
			|  |  |  | :doc:`/guide/build-deps`. | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | .. note:: | 
		
	
		
			
			|  |  |  | The ``_deps`` directory and generated CMake imports file will be placed in | 
		
	
		
			
			|  |  |  | the CMake build directory, out of the way of the rest of the project. | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | .. note:: | 
		
	
		
			
			|  |  |  | The version of ``dds`` that PMM downloads depends on the version of PMM | 
		
	
		
			
			|  |  |  | that is in use. | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | Using the ``IMPORTED`` Targets | 
		
	
		
			
			|  |  |  | ============================== | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | Like with ``dds``, CMake wants us to explicitly declare how our build targets | 
		
	
		
			
			|  |  |  | *use* other libraries. After ``pmm(DDS)`` executes, there will be ``IMPORTED`` | 
		
	
		
			
			|  |  |  | targets that can be linked against. | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | In ``dds`` (and in libman), a library is identified by a combination of | 
		
	
		
			
			|  |  |  | *namespace* and *name*, joined together with a slash ``/`` character. This | 
		
	
		
			
			|  |  |  | *qualified name* of a library is decided by the original package author or | 
		
	
		
			
			|  |  |  | maintainer, and should be documented. In the case of ``fmt``, the only library | 
		
	
		
			
			|  |  |  | is ``fmt/fmt``. | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | When ``pmm(DDS)`` imports a library, it creates a qualified name using a | 
		
	
		
			
			|  |  |  | double-colon "``::``" instead of a slash. As such, our ``fmt/fmt`` is imported | 
		
	
		
			
			|  |  |  | in CMake as ``fmt::fmt``. We can link against it as we would with any other | 
		
	
		
			
			|  |  |  | target:: | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | add_executable(my-application app.cpp) | 
		
	
		
			
			|  |  |  | target_link_libraries(my-application PRIVATE fmt::fmt) | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | This will allow us to use **{fmt}** in our CMake project as an external | 
		
	
		
			
			|  |  |  | dependency. | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | In all, this is our final ``CMakeLists.txt``: | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | .. code-block:: | 
		
	
		
			
			|  |  |  | :caption: ``CMakeLists.txt`` | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | cmake_minimum_required(VERSION 3.12) | 
		
	
		
			
			|  |  |  | project(MYApplication VERSION 2.1.3) | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | include(tools/pmm.cmake) | 
		
	
		
			
			|  |  |  | pmm(DDS DEPENDS fmt^7.0.3) | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | add_executable(my-application app.cpp) | 
		
	
		
			
			|  |  |  | target_link_libraries(my-application PRIVATE fmt::fmt) | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | Changing Compile Options | 
		
	
		
			
			|  |  |  | ************************ | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | ``dds`` supports setting compilation options using | 
		
	
		
			
			|  |  |  | :doc:`toolchains </guide/toolchains>`. PMM supports specifying a toolchain using | 
		
	
		
			
			|  |  |  | the ``TOOLCHAIN`` argument:: | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | pmm(DDS DEPENDS fmt^7.0.3 TOOLCHAIN my-toolchain.json5) | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | Of course, writing a separate toolchain file just for your dependencies can be | 
		
	
		
			
			|  |  |  | tedious. For this reason, PMM will write a toolchain file on-the-fly when it | 
		
	
		
			
			|  |  |  | executes ``dds``. The generated toolchain is created based on the current CMake | 
		
	
		
			
			|  |  |  | settings when ``pmm()`` was executed. | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | To add compile options, simply ``add_compile_options``:: | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | add_compile_options(-fsanitize=address) | 
		
	
		
			
			|  |  |  | pmm(DDS ...) | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | The above will cause all ``dds``-built dependencies to compile with | 
		
	
		
			
			|  |  |  | ``-fsanitize=address`` as a command-line option. | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | The following CMake variables and directory properties are used to generate the | 
		
	
		
			
			|  |  |  | ``dds`` toolchain: | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | ``COMPILE_OPTIONS`` | 
		
	
		
			
			|  |  |  | Adds additional compiler options. Should be provided by | 
		
	
		
			
			|  |  |  | ``add_compile_options``. | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | ``COMPILE_DEFINITIONS`` | 
		
	
		
			
			|  |  |  | Add preprocessor definitions. Should be provided by | 
		
	
		
			
			|  |  |  | ``add_compile_definitions`` | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | ``CXX_STANDARD`` | 
		
	
		
			
			|  |  |  | Control the ``cxx_version`` in the toolchian | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | ``CMAKE_MSVC_RUNTIME_LIBRARY`` | 
		
	
		
			
			|  |  |  | Sets the ``runtime`` option. This option has limited support for generator | 
		
	
		
			
			|  |  |  | expressions. | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | ``CMAKE_C_FLAGS`` and ``CMAKE_CXX_FLAGS``, and their per-config variants | 
		
	
		
			
			|  |  |  | Set the basic compile flags for the respective file sypes | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | ``CXX_COMPILE_LAUNCHER`` | 
		
	
		
			
			|  |  |  | Allow providing a compiler launcher, e.g. ``ccache``. | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | .. note:: | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | Calls to ``add_compile_options``, ``add_compile_definitions``, or other CMake | 
		
	
		
			
			|  |  |  | settings should appear *before* calling ``pmm(DDS)``, since the toolchain file | 
		
	
		
			
			|  |  |  | is generated and dependencies are built at that point. | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | ``add_link_options`` has no effect on the ``dds`` toolchain, as ``dds`` does | 
		
	
		
			
			|  |  |  | not generate any runtime binaries. | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | .. rubric:: Footnotes | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | .. [#f1] | 
		
	
		
			
			|  |  |  | Do not use ``file(DOWNLOAD)`` to "automatically" obtain `pmm.cmake`_. The | 
		
	
		
			
			|  |  |  | ``pmm.cmake`` script is already built to do this for the rest of PMM. The | 
		
	
		
			
			|  |  |  | `pmm.cmake`_ script itself is very small and is *designed* to be copy-pasted | 
		
	
		
			
			|  |  |  | and committed into other projects. | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | .. _PMM: https://github.com/vector-of-bool/pmm | 
		
	
		
			
			|  |  |  | .. _pmm.cmake: https://github.com/vector-of-bool/pmm/raw/master/pmm.cmake |