Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

doc: User guide #5

Merged
merged 13 commits into from
Dec 21, 2023
20 changes: 18 additions & 2 deletions docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
"breathe",
"sphinx.ext.intersphinx",
"sphinx_tippy",
"sphinx.ext.todo",
]

templates_path = []
Expand All @@ -29,20 +30,35 @@
"tasklist",
"colon_fence",
]
myst_heading_anchors = 3

intersphinx_mapping = {
"cmake": ("https://cmake.org/cmake/help/latest", None),
"sphinx": ("https://www.sphinx-doc.org/en/master", None),
"rtd": ("https://docs.readthedocs.io/en/stable", None),
"tmt": ("https://tmt.readthedocs.io/en/stable", None),
"sphinx-tippy": ("https://sphinx-tippy.readthedocs.io/en/latest", None),
"sphinx-hoverxref": ("https://sphinx-hoverxref.readthedocs.io/en/latest", None),
}

tippy_rtd_urls = [
## Only works with RTD hosted intersphinx
# Only works with RTD hosted intersphinx
# "https://cmake.org/cmake/help/latest",
# "https://www.sphinx-doc.org/en/master",
"https://www.sphinx-doc.org/en/master",
"https://docs.readthedocs.io/en/stable",
"https://tmt.readthedocs.io/en/stable",
"https://sphinx-tippy.readthedocs.io/en/latest",
"https://sphinx-hoverxref.readthedocs.io/en/latest",
]

copybutton_exclude = ".linenos, .gp, .go"

linkcheck_ignore = [
# pkgs.org gives 402 Client Error: Payment Required
r"https://pkgs.org",
]
linkcheck_anchors_ignore_for_url = [
r"https://gitlab.kitware.com/.*",
]

todo_include_todos = True
9 changes: 9 additions & 0 deletions docs/guides/developer.md → docs/guides/developer/index.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,14 @@
# Developer guide

```{toctree}
: maxdepth: 2
: titlesonly: true
: hidden: true
: glob: true

who-is-the-developer
```

This is a developer's guide intended to explain many of the paradigms used in
this template project

Expand Down
11 changes: 11 additions & 0 deletions docs/guides/developer/who-is-the-developer.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Who is the developer?

In the context of this guide, the developer is someone who:
- is looking to expand the build system to add more options, expand the project
dependencies
- a project developer who is looking at implementing this template project
- a CMake enthusiast looking for a common standard for their design. (Feel free
to interact in the template [issue page] if you have any comments)
- a non-CMake build-system enthusiast. There is no discrimination here :)

[issue page]: https://github.com/LecrisUT/CMake-Template/issues
88 changes: 81 additions & 7 deletions docs/guides/index.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,85 @@
# Guides

```{toctree}
---
maxdepth: 2
titlesonly: true
caption: Guides
glob: true
---
*
: maxdepth: 2
: titlesonly: true

user/index
developer/index
```

## What are these guides?

In this template project, you will find a [user guide] and a [developer guide]
intended to answer common questions that either a [user] or a [developer] would
have when encountering a project that uses this template.

Feel free to reference and/or [include] these guides or sections of it in your
documentation.

[user]: user/who-is-the-user.md
[developer]: developer/who-is-the-developer.md
[user guide]: user/index.md
[developer guide]: developer/index.md
[include]: #including-these-guides-in-your-downstream-project

## Including these guides in your downstream project

The best way to include these guides is if your project uses a
[sphinx backend][rtd-sphinx] for your documentation. There you can simply link
to it using [inter-sphinx]. For example, include the following configurations
to your `docs/conf.py` file:

```{code-block} python
: caption: docs/conf.py
: emphasize-lines: 5

extensions = [
"sphinx.ext.intersphinx",
]
intersphinx_mapping = {
"template-guide": ("https://lecrisut-cmake-template.readthedocs.io/en/latest/", None),
}
```

:::{note}
If you want to have the links pop-up like in this documentation, use either
[`sphinx-tippy`] or [`sphinx-hoverxref`]. The latter produces better results,
however it does [not yet support Markdown documents][sphinx-hoverxref-issue].
:::

Then, you can use it in your documentation files as follows:

::::{tab-set}
:::{tab-item} Markdown
```{code-block} markdown
: caption: docs/example.md
: emphasize-lines: 4

Refer to the [following guide][template-user-guide] for a basic how-to interact
with a CMake project...

[template-user-guide]: inv:template-user-guide:std:doc#guides/user/index
```
:::
:::{tab-item} reStructuredText
```{code-block} rst
: caption: docs/example.rst
: emphasize-lines: 1

Refer to the :external+template-user-guide:std:doc:`following guide<template-user-guide>`
for a basic how-to interact with a CMake project...
```
:::
:::{tab-item} (Result)
Refer to the [following guide][user guide] for a basic how-to interact with a
CMake project...
:::
::::

[rtd-sphinx]: inv:rtd:std:doc#intro/getting-started-with-sphinx
[//]: # (TODO: Fix the intersphinx link)
[inter-sphinx]: https://www.sphinx-doc.org/en/master/usage/quickstart.html#intersphinx
[`sphinx-tippy`]: inv:sphinx-tippy#index
[`sphinx-hoverxref`]: inv:sphinx-hoverxref#index
[sphinx-hoverxref-issue]: https://github.com/readthedocs/sphinx-hoverxref/issues/250
6 changes: 0 additions & 6 deletions docs/guides/user.md

This file was deleted.

39 changes: 39 additions & 0 deletions docs/guides/user/build.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# Building the project

:::{admonition} Tl;dr
```console
$ cmake --build ./build-dir
```
:::

At this point the build process is more-or-less up to the actual project, and
you simply run the build as shown above. Here are also a few tips:

## Using presets

If you have used a [`configurePreset`] in the previous section, you may not be
aware of the build directory. Often times, the project also provides a
`buildPreset` with the same name, so you can simply run:
```console
$ cmake --build --preset default
```

You can find a list of them using:
```console
$ cmake --list-preset=build
```

## Running in parallel

Use the [`-j`] option, either by itself (the build system decides) or pass
`$(nproc)` as its value.

```console
$ cmake --build ./build-dir -j
```

Alternatively, set the [`CMAKE_BUILD_PARALLEL_LEVEL`] environment variable.

[`-j`]: inv:cmake:std:cmdoption#cmake--build.--parallel
[`configurePreset`]: configure/index.md#cmake-presets
[`CMAKE_BUILD_PARALLEL_LEVEL`]: inv:cmake:cmake:envvar#envvar:CMAKE_BUILD_PARALLEL_LEVEL
129 changes: 129 additions & 0 deletions docs/guides/user/configure/import.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
# Importing dependencies

This section covers both how to import a project in another CMake project
([importing]), and how a user can control where a project is found ([finding]).

## Importing dependencies in a CMake project

:::{admonition} Tl;dr
```cmake
include(FetchContent)
FetchContent_Declare(awesome-project
GIT_REPOSITORY https://github.com/user/awesome-project
GIT_TAG main
FIND_PACKAGE_ARGS CONFIG
)
FetchContent_MakeAvailable(awesome-project)
```
:::

The best way to consume a project is within CMake, using the
[`FetchContent`/`find_package` integration]. This will run [`find_package`]
first to try and import the system installed [packaged] version, and if none is
available it will git clone the [source] project and include it as
[`add_subdirectory`]. See the [configuration] section on how to configure the
included project.

From there, navigate the dependency's top-level `CMakeLists.txt` to find the
available targets you can use.

If you need to overwrite the upstream project's options, simply add the
[`option`] before the [`FetchContent_MakeAvailable`] call, e.g.:
```cmake
option(PROJECT2_TESTS "Project1: Override" OFF)

FetchContent_MakeAvailable(Project2)
```

### Making a dependency optional

Currently, the only clear design for supporting optional dependencies is by
avoiding [`FetchContent`] and using [`find_package`] only:

```cmake
find_package(awesome-project)
```

See the [controlling] section on how to disable or make it a required
dependency.

:::{todo}
Make the optional dependency work with [`FetchContent`]. Currently, there is no
clear way how to combine [`find_package`] and [`FetchContent`] fallthrough.
Key part is the interaction with [`CMAKE_REQUIRE_FIND_PACKAGE_<PackageName>`]
and [`CMAKE_DISABLE_FIND_PACKAGE_<PackageName>`].
:::

## How dependencies are found

Here we assume that all projects in the chain use the modern [importing]
approach to define their dependencies.

### Default behavior

By default, the project will first try to find the [`<PackageName>Config.cmake`]
file from the system installed [packaged], and if that fails, it would either
use [`FetchContent`] to download the [source] project if it is a required
dependency, or simply disable the feature if it is an [optional dependency].

### Controlling how dependencies are imported

| Option | Effect | Notes |
|:--------------------------------------------:|:-------------------------------------------------------|:-------------------------------------------------------------------------------------------|
| [`CMAKE_PREFIX_PATH`] | Where to look for system installed package | |
| [`<PackageName>_ROOT`] | Where to look for system installed package | It can happen that this is not enforced |
| [`FETCHCONTENT_TRY_FIND_PACKAGE_MODE`] | If `NEVER`, will use downloaded version | |
| [`FETCHCONTENT_SOURCE_DIR_<PACKAGENAME>`] | Path to package source to use (instead of downloading) | Takes precedence of any other option |
| [`CMAKE_REQUIRE_FIND_PACKAGE_<PackageName>`] | Make optional dependency required | If dependency is already required via `FetchContent`, it ensure the system package is used |
| [`CMAKE_DISABLE_FIND_PACKAGE_<PackageName>`] | Disable finding system installed package | |

Here `<PackageName>` is the case-sensitive name of the dependency, and
`<PACKAGENAME>` is the equivalent uppercase name.

:::{caution}
[`CMAKE_REQUIRE_FIND_PACKAGE_<PackageName>`] and
[`CMAKE_DISABLE_FIND_PACKAGE_<PackageName>`] options propagate to other
dependencies in the chain. Normally this would not be an issue, unless a project
uses [`Find<PackageName>.cmake`] and do not take this into account [^1].
:::

### Troubleshooting the dependency search

:::{admonition} Tl;dr
```console
$ cmake -b ./build --debug-find-pkg=<PackageName>
```
:::

The most comprehensive way of finding out how a dependency has been searched is
to use the [`--debug-find-pkg`] option. This does not cover the
[`Find<PackageName>.cmake`], where the find process is non-standard.

[importing]: #importing-dependencies-in-a-cmake-project
[finding]: #how-dependencies-are-found
[controlling]: #controlling-how-dependencies-are-imported
[optional dependency]: #making-a-dependency-optional

[packaged]: ../download.md#packaged-version
[source]: ../download.md#source-project
[configuration]: options.md#upstream-project-options

[`FetchContent`]: inv:cmake:cmake:module#module:FetchContent
[`find_package`]: inv:cmake:cmake:command#command:find_package
[`FetchContent`/`find_package` integration]: inv:cmake:std:label#fetchcontent-find_package-integration-examples
[`add_subdirectory`]: inv:cmake:cmake:command#command:add_subdirectory

[`CMAKE_PREFIX_PATH`]: inv:cmake:cmake:variable#variable:CMAKE_PREFIX_PATH
[`<PackageName>_ROOT`]: inv:cmake:cmake:variable#variable:<PackageName>_ROOT
[`FETCHCONTENT_TRY_FIND_PACKAGE_MODE`]: inv:cmake:cmake:variable#variable:FETCHCONTENT_TRY_FIND_PACKAGE_MODE
[`FETCHCONTENT_SOURCE_DIR_<PACKAGENAME>`]: inv:cmake:cmake:variable#variable:FETCHCONTENT_SOURCE_DIR_<uppercaseName>
[`CMAKE_REQUIRE_FIND_PACKAGE_<PackageName>`]: inv:cmake:cmake:variable#variable:CMAKE_REQUIRE_FIND_PACKAGE_<PackageName>
[`CMAKE_DISABLE_FIND_PACKAGE_<PackageName>`]: inv:cmake:cmake:variable#variable:CMAKE_DISABLE_FIND_PACKAGE_<PackageName>

[`FetchContent_MakeAvailable`]: inv:cmake:cmake:command#command:fetchcontent_makeavailable
[`option`]: inv:cmake:cmake:command#command:option
[`<PackageName>Config.cmake`]: <inv:cmake:std:label#full signature>
[`Find<PackageName>.cmake`]: <inv:cmake:std:label#find modules>
[`--debug-find-pkg`]: inv:cmake:std:cmdoption#cmake.--debug-find-pkg

[^1]: <https://gitlab.kitware.com/cmake/cmake/-/merge_requests/8951#note_1442376>
Loading
Loading