|
|
|
|
|
|
|
|
|
|
|
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 |