Build instructions#

Last Updated on 2024-01-29

The project uses CMake as a build system and defines presets in the CmakePrests.json file that describe the most commonly used configuration, build and test settings. While you can still use the traditional way of invoking cmake commands in a build directory, we recommend that you understand and embrace the cmake presets way, which simplifies the command lines required to invoke cmake and integrates nicely with the most commonly used IDEs.

Build targets#

The project defines a number of targets that can be used to build specific artifacts or groups of related artifacts.

all:

build all primary targets of the project. That includes all library and executable targets defined using the asap_add_library and asap_add_executable commands. Each of these targets may also be built individually. Tests are usually excluded from the `all` target unless they have been added with the POST_BUILD option.

build-all-tests:

build all tests added using the asap_add_test or asap_add_test_runner commands.

build-all-post-build-tests:

build all tests added using the asap_add_test or asap_add_test_runner commands and with the option POST_BUILD. Such tests are also built as part of the `all` target.

do-all-tests:

builds and runs all tests added using the asap_add_test or asap_add_test_runner commands, including unit tests and integration tests.

do-all-unit-tests:

builds and runs all tests added using the asap_add_test or asap_add_test_runner commands with the option UNIT_TEST.

do-all-integration-tests:

builds and runs all tests added using the asap_add_test or asap_add_test_runner commands with the option INTEGRATION_TEST.

dox:

build doxygen documentation. This target is only available when doxygen and its dependencies (such as graphviz) have been properly detected and were found.

sphinx:

build sphinx documentation. This target is only available when sphinx and its dependencies have been properly detected and were found. A complete documentation also requires doxygen documentation to have been built prior to building the sphinx manual. Such dependency is not enforced in the targets graph to make it faster to build sphinx docs without rebuilding doxygen docs each time.

The following targets are only defined when code coverage tools have been detected on the system. Such tools depend on the compiler being used (clang or gcc, MSVC is not supported).

ccov-all:

run all tests to collect code coverage statistics and produce a consolidated report in HTML for all the source files included in coverage collection.

ccov-xxxtargetxxx:

where xxxtargetxxx refers to a specific executable target in the project. Run the executable with code coverage collection enabled and produce a html report just for that target. This can be used to run code coverage analysis just for a specific test.

ccov-clean:

clean intermediary files generated for code coverage analysis.

The following targets are only defined if the clang-format tool has been properly detected and found on the system.

clang-format:

Shows which files are affected by clang-format.

check-clang-format:

Errors if files are affected by clang-format (for CI integration).

fix-clang-format:

Applies clang-format to all affected files.

The following targets are only defined if the cmake-format tool has been properly detected and found on the system.

cmake-format:

Shows which files are affected by cmake-format.

check-cmake-format:

Errors if files are affected by cmake-format (for CI integration).

fix-cmake-format:

Applies cmake-format to all affected files.

The following targets combine the above two categories of targets.

format:

Shows which files are affected by cmake-format or clang-format.

check-format:

Errors if files are affected by cmake-format or clang-format (for CI integration).

fix-format:

Applies cmake-format or clang-format to all affected files.

The following target are only defined if the compiler is clang, the clang-tidy tool has been properly detected and found on the system.

clang-tidy-all:

lints all C++ source code files in the project using clang-tidy.

clang-tidy-all-check:

lints all C++ source code files in the project using clang-tidy and exits with a non-zero exit-code if any warnings were generated.

clang-tidy-diff:

formats only changed C++ source code files in the project using clang-format.

clang-tidy-diff-check:

lints only changed C++ source code files in the project using clang-tidy and exits with a non-zero exit-code if any warnings were generated.

Note

Targets for running clang-tidy on a specific target in the project are also defined. For example to run it on the asap_common module, use clang-tidy-asp_common.

CMake Presets#

CMake supports two files, CMakePresets.json and CMakeUserPresets.json, that allow users to specify common configure options and share them with others.

CMakePresets.json and CMakeUserPresets.json live in the project’s root directory. They both have exactly the same format. CMakePresets.json is meant to save project-wide builds, while CMakeUserPresets.json is meant for developers to save their own local builds. CMakePresets.json may be checked into a version control system, and CMakeUserPresets.json should NOT be checked in.

For a complete description of the format refer to the cmake-presets documentation.

This project defines presets in a hierarchical way and uses ‘mixins’ to add specific aspects of the build configuration such as debug/release, code coverage, etc. Once you understand the format of the presets files, it’s easy to understand the logic and the reasoning behind how asap presets are defined.

  1{
  2  "version": 3,
  3  "cmakeMinimumRequired": {
  4    "major": 3,
  5    "minor": 20,
  6    "patch": 0
  7  },
  8  "configurePresets": [
  9    {
 10      "name": "base",
 11      "description": "Base preset",
 12      "hidden": true,
 13      "generator": "Ninja",
 14      "binaryDir": "${sourceDir}/out/build/${presetName}",
 15      "installDir": "${sourceDir}/out/install/${presetName}",
 16      "environment": {
 17        "CMAKE_EXPORT_COMPILE_COMMANDS": "ON"
 18      },
 19      "cacheVariables": {
 20        "CPM_SOURCE_CACHE": "~/.cache/CPM",
 21        "USE_CCACHE": "ON",
 22        "ASAP_BUILD_TESTS": "ON",
 23        "ASAP_BUILD_EXAMPLES": "ON"
 24      }
 25    },
 26    {
 27      "name": "debug",
 28      "description": "Debug build",
 29      "hidden": true,
 30      "cacheVariables": {
 31        "CMAKE_BUILD_TYPE": "Debug"
 32      }
 33    },
 34    {
 35      "name": "release",
 36      "description": "Release build",
 37      "hidden": true,
 38      "cacheVariables": {
 39        "CMAKE_BUILD_TYPE": "Release",
 40        "ASAP_BUILD_EXAMPLES": "OFF"
 41      }
 42    },
 43    {
 44      "name": "x64",
 45      "description": "64bit build (on windows)",
 46      "hidden": true,
 47      "architecture": {
 48        "value": "x64",
 49        "strategy": "external"
 50      },
 51      "condition": {
 52        "type": "equals",
 53        "lhs": "${hostSystemName}",
 54        "rhs": "Windows"
 55      }
 56    },
 57    {
 58      "name": "code-coverage",
 59      "description": "Add code coverage to the build",
 60      "hidden": true,
 61      "cacheVariables": {
 62        "CODE_COVERAGE": "ON"
 63      },
 64      "condition": {
 65        "type": "inList",
 66        "string": "${hostSystemName}",
 67        "list": [
 68          "Linux",
 69          "Darwin"
 70        ]
 71      }
 72    },
 73    {
 74      "name": "compiler-clang",
 75      "hidden": true,
 76      "description": "Use clang as the C/C++ compiler",
 77      "cacheVariables": {
 78        "CMAKE_C_COMPILER": "/usr/bin/clang",
 79        "CMAKE_CXX_COMPILER": "/usr/bin/clang++"
 80      },
 81      "condition": {
 82        "type": "inList",
 83        "string": "${hostSystemName}",
 84        "list": [
 85          "Linux",
 86          "Darwin"
 87        ]
 88      }
 89    },
 90    {
 91      "name": "compiler-gcc",
 92      "hidden": true,
 93      "description": "Use GCC as the C/C++ compiler",
 94      "cacheVariables": {
 95        "CMAKE_C_COMPILER": "/usr/bin/gcc",
 96        "CMAKE_CXX_COMPILER": "/usr/bin/g++"
 97      },
 98      "condition": {
 99        "type": "inList",
100        "string": "${hostSystemName}",
101        "list": [
102          "Linux",
103          "Darwin"
104        ]
105      }
106    },
107    {
108      "name": "dev-windows",
109      "description": "Default build in a dev environment",
110      "inherits": [
111        "base",
112        "debug",
113        "x64"
114      ],
115      "environment": {
116        "caexcludepath": "${sourceDir}/third_party;${sourceDir}/out;$env{userprofile}/.cache/CPM"
117      }
118    },
119    {
120      "name": "dev-linux",
121      "description": "Default build in a dev environment",
122      "inherits": [
123        "base",
124        "debug",
125        "compiler-clang",
126        "code-coverage"
127      ],
128      "vendor": {
129        "jetbrains.com/clion": {
130          "toolchain": "LinuxWSL"
131        }
132      }
133    },
134    {
135      "name": "dev-mac",
136      "description": "Default build in a dev environment",
137      "inherits": [
138        "base",
139        "debug",
140        "compiler-clang",
141        "code-coverage"
142      ],
143      "condition": {
144        "type": "equals",
145        "lhs": "${hostSystemName}",
146        "rhs": "Darwin"
147      }
148    },
149    {
150      "name": "dev-clang",
151      "description": "Basic build in a dev environment using clang",
152      "inherits": [
153        "base",
154        "debug",
155        "compiler-clang",
156        "code-coverage"
157      ],
158      "vendor": {
159        "jetbrains.com/clion": {
160          "toolchain": "LinuxWSL"
161        }
162      }
163    },
164    {
165      "name": "dev-gcc",
166      "description": "Basic build in a dev environment using clang",
167      "inherits": [
168        "base",
169        "debug",
170        "compiler-gcc",
171        "code-coverage"
172      ],
173      "vendor": {
174        "jetbrains.com/clion": {
175          "toolchain": "LinuxWSL"
176        }
177      }
178    },
179    {
180      "name": "dev-valgrind",
181      "description": "Builds targets with valgrind profiles added",
182      "inherits": [
183        "base",
184        "debug",
185        "compiler-clang"
186      ],
187      "cacheVariables": {
188        "CODE_COVERAGE": "OFF",
189        "ASAP_WITH_VALGRIND": "ON"
190      },
191      "condition": {
192        "type": "inList",
193        "string": "${hostSystemName}",
194        "list": [
195          "Linux",
196          "Darwin"
197        ]
198      },
199      "vendor": {
200        "jetbrains.com/clion": {
201          "toolchain": "LinuxWSL"
202        }
203      }
204    },
205    {
206      "name": "dev-sanitizers",
207      "description": "Builds targets with Google ASAN and UBSAN sanitizers added",
208      "inherits": [
209        "base",
210        "debug",
211        "compiler-clang"
212      ],
213      "cacheVariables": {
214        "CODE_COVERAGE": "OFF",
215        "ASAP_WITH_GOOGLE_ASAN": "ON",
216        "ASAP_WITH_GOOGLE_UBSAN": "ON"
217      },
218      "condition": {
219        "type": "inList",
220        "string": "${hostSystemName}",
221        "list": [
222          "Linux",
223          "Darwin"
224        ]
225      },
226      "vendor": {
227        "jetbrains.com/clion": {
228          "toolchain": "LinuxWSL"
229        }
230      }
231    },
232    {
233      "name": "dev-sanitizers-thread",
234      "description": "Builds targets with Google thread sanitizer added",
235      "inherits": [
236        "base",
237        "debug",
238        "compiler-clang"
239      ],
240      "cacheVariables": {
241        "ASAP_WITH_GOOGLE_TSAN": "ON"
242      },
243      "condition": {
244        "type": "inList",
245        "string": "${hostSystemName}",
246        "list": [
247          "Linux",
248          "Darwin"
249        ]
250      },
251      "vendor": {
252        "jetbrains.com/clion": {
253          "toolchain": "LinuxWSL"
254        }
255      }
256    },
257    {
258      "name": "rel-windows",
259      "description": "Default build in a dev environment",
260      "inherits": [
261        "base",
262        "release",
263        "x64"
264      ]
265    },
266    {
267      "name": "rel-linux",
268      "description": "Default build in a dev environment",
269      "inherits": [
270        "base",
271        "release",
272        "compiler-clang"
273      ],
274      "vendor": {
275        "jetbrains.com/clion": {
276          "toolchain": "LinuxWSL"
277        }
278      }
279    },
280    {
281      "name": "rel-mac",
282      "description": "Default build in a dev environment",
283      "inherits": [
284        "base",
285        "release",
286        "compiler-clang"
287      ],
288      "condition": {
289        "type": "equals",
290        "lhs": "${hostSystemName}",
291        "rhs": "Darwin"
292      }
293    }
294  ],
295  "buildPresets": [
296    {
297      "name": "dev-base",
298      "hidden": true,
299      "jobs": 4,
300      "verbose": false
301    },
302    {
303      "name": "dev-windows",
304      "configurePreset": "dev-windows",
305      "inherits": [
306        "dev-base"
307      ]
308    },
309    {
310      "name": "dev-clang",
311      "configurePreset": "dev-clang",
312      "inherits": [
313        "dev-base"
314      ]
315    },
316    {
317      "name": "dev-linux",
318      "configurePreset": "dev-linux",
319      "inherits": [
320        "dev-clang"
321      ]
322    },
323    {
324      "name": "dev-mac",
325      "configurePreset": "dev-mac",
326      "inherits": [
327        "dev-clang"
328      ]
329    },
330    {
331      "name": "dev-gcc",
332      "configurePreset": "dev-gcc",
333      "inherits": [
334        "dev-base"
335      ]
336    },
337    {
338      "name": "dev-valgrind",
339      "configurePreset": "dev-valgrind",
340      "inherits": [
341        "dev-base"
342      ]
343    },
344    {
345      "name": "dev-sanitizers",
346      "configurePreset": "dev-sanitizers",
347      "inherits": [
348        "dev-base"
349      ]
350    },
351    {
352      "name": "dev-sanitizers-thread",
353      "configurePreset": "dev-sanitizers-thread",
354      "inherits": [
355        "dev-base"
356      ]
357    },
358    {
359      "name": "rel-base",
360      "hidden": true,
361      "jobs": 4,
362      "cleanFirst": true,
363      "verbose": true
364    },
365    {
366      "name": "rel-windows",
367      "configurePreset": "rel-windows",
368      "inherits": [
369        "rel-base"
370      ]
371    },
372    {
373      "name": "rel-linux",
374      "configurePreset": "rel-linux",
375      "inherits": [
376        "rel-base"
377      ]
378    },
379    {
380      "name": "rel-mac",
381      "configurePreset": "rel-mac",
382      "inherits": [
383        "rel-base"
384      ]
385    }
386  ],
387  "testPresets": [
388    {
389      "name": "test-base",
390      "description": "Enable output on failure",
391      "hidden": true,
392      "output": {
393        "outputOnFailure": true
394      }
395    },
396    {
397      "name": "dev-test-windows",
398      "inherits": "test-base",
399      "configurePreset": "dev-windows"
400    },
401    {
402      "name": "rel-test-windows",
403      "inherits": "test-base",
404      "configurePreset": "rel-windows"
405    },
406    {
407      "name": "dev-test-linux",
408      "inherits": "test-base",
409      "configurePreset": "dev-linux"
410    },
411    {
412      "name": "rel-test-linux",
413      "inherits": "test-base",
414      "configurePreset": "rel-linux"
415    },
416    {
417      "name": "dev-test-mac",
418      "inherits": "test-base",
419      "configurePreset": "dev-mac"
420    },
421    {
422      "name": "rel-test-mac",
423      "inherits": "test-base",
424      "configurePreset": "rel-mac"
425    },
426    {
427      "name": "dev-test-clang",
428      "inherits": "test-base",
429      "configurePreset": "dev-clang"
430    },
431    {
432      "name": "dev-test-gcc",
433      "inherits": "test-base",
434      "configurePreset": "dev-gcc"
435    }
436  ]
437}

Integration in IDEs#

Refer to the relevant documentation of the IDE you are using to understand how cmake presets are integrated in the IDE and how you can select the right preset for configure, build and test phases.

Command-line build with presets#

Note

All output goes into the out directory under the project root.

All commands should be run from the project root.

Configure#

$ cmake --preset=dev-linux

Build#

$ cmake --build --preset=dev-linux

$ cmake --build --preset=dev-linux --target=dox

Test#

$ cmake --build --preset=dev-linux --target=test

$ cmake --build --preset=dev-linux --target=do-all-tests

Run tests with code coverage collection enabled:

$ cmake --build --preset=dev-linux --target=ccov-all

Run tests with sanitizers enabled:

$ cmake --preset=dev-sanitizers
$ cmake --build --preset=dev-sanitizers --target=do-all-tests

Run tests with valgrind enabled (output reports are in out/build/dev-valgrind/profiling):

$ cmake --preset=dev-valgrind
$ cmake --build --preset=dev-valgrind --target=do-all-valgrind