Переглянути джерело

How-to for CMake deps

default_compile_flags
vector-of-bool 3 роки тому
джерело
коміт
bbd6cc4ed6
4 змінених файлів з 229 додано та 66 видалено
  1. +1
    -1
      docs/guide/build-deps.rst
  2. +13
    -65
      docs/guide/cmake.rst
  3. +214
    -0
      docs/howto/cmake.rst
  4. +1
    -0
      docs/howto/index.rst

+ 1
- 1
docs/guide/build-deps.rst Переглянути файл

@@ -82,7 +82,7 @@ Importing an Index: CMake

This section discusses how to import ``INDEX.lmi`` into CMake, but ``dds``
also has built-in support for generating a CMake targets file. See
:doc:`cmake` and :ref:`cmake.pmm` for even simpler integration steps.
:doc:`/howto/cmake` and :doc:`cmake` for even simpler integration steps.

Supposed that we've generated a libman index and set of packages, and we want to
import them into CMake. CMake doesn't know how to do this natively, but there

+ 13
- 65
docs/guide/cmake.rst Переглянути файл

@@ -1,7 +1,7 @@
.. highlight:: cmake

Easy Mode: Using ``dds`` in a CMake Project
###########################################
Using ``dds`` in a CMake Project
################################

One of ``dds``'s primary goals is to inter-operate with other build systems
cleanly. Because of CMakes ubiquity, ``dds`` includes built-in support for
@@ -13,10 +13,11 @@ emitting files that can be imported into CMake.
section of the :doc:`build-deps` page, which will discuss how to use the
``dds build-deps`` subcommand.

.. note::
.. seealso::

We'll first look as *easy mode*, but there's also an *easiest mode* for a
one-line solution: :ref:`see below <cmake.pmm>`.
This page presents an involved and detailed process for importing
dependencies, but there's also an *easy mode* for a one-line solution. See:
:doc:`/howto/cmake`.

.. _PMM: https://github.com/vector-of-bool/PMM

@@ -66,69 +67,16 @@ with any other target::

.. _cmake.pmm:

*Easiest* Mode: PMM Support
***************************
*Easy* Mode: PMM Support
************************

`PMM`_ is the *package package manager*, and can be used to control and access
package managers from within CMake scripts. This includes controlling ``dds``.
With PMM, we can automate all of the previous steps into a single line.

Refer to the ``README.md`` file in `the PMM repo <PMM>`_ for information on how
to get PMM into your CMake project. In short, download and place the
``pmm.cmake`` file in your repository, and ``include()`` the file near the top
of your ``CMakeLists.txt``::

include(pmm.cmake)

The ``pmm()`` function also supports ``dds`` directly, and will automatically
download a prebuilt ``dds`` for the host platform and invoke ``dds build-deps``
in a single pass as part of CMake's configure process. This is especially useful
for a CI environment where you want to have a stable ``dds`` version and always
have your dependencies obtained just-in-time.

To start, pass the ``DDS`` argument to ``pmm()`` to use it::

pmm(DDS)

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

This alone won't do anything useful, because you'll need to tell it what
dependencies we want to install::

pmm(DDS DEP_FILES dependencies.json5)

You can also list your dependencies as inline strings in your CMakeLists.txt
instead of a separate file::

pmm(DDS DEPENDS neo-sqlite3^0.2.2)

This invocation will run ``build-deps`` with the build options, generate a CMake
imports file, and immediately ``include()`` it to import the generated CMake
targets. ``pmm(DDS)`` will also generate a ``dds`` :doc:`toolchain <toolchains>`
based on the current CMake build environment, ensuring that the generated
packages have matching build options to the rest of the project. Refer to the
PMM README for more details.

.. code-block::
:caption: ``CMakeLists.txt``
:linenos:
:emphasize-lines: 4,5

cmake_minimum_required(VERSION 3.15)
project(MyApplication VERSION 1.0.0)

include(pmm.cmake)
pmm(DDS DEPENDS neo-sqlite3^0.2.2)

add_executable(my-application app.cpp)
target_link_libraries(my-application PRIVATE neo::sqlite3)
For a complete rundown on using PMM to get dependencies via ``dds``, refer to
the :doc:`/howto/cmake` page.

This removes the requirement that we write a separate dependencies file, and we
no longer need to invoke ``dds build-deps`` externally, as it is all handled
by ``pmm()``.
Using PMM removes the requirement that we write a separate dependencies file,
and we no longer need to invoke ``dds build-deps`` externally, as it is all
handled by PMM.

+ 214
- 0
docs/howto/cmake.rst Переглянути файл

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

+ 1
- 0
docs/howto/index.rst Переглянути файл

@@ -8,3 +8,4 @@ These pages will discuss some common "How-do-I...?" questions.
:maxdepth: 2

deps
cmake

Завантаження…
Відмінити
Зберегти