Line data Source code
1 0 : \cond NEVER
2 : Distributed under the MIT License.
3 : See LICENSE.txt for details.
4 : \endcond
5 : # Build System - CMake {#spectre_build_system}
6 :
7 : \tableofcontents
8 :
9 : SpECTRE uses [CMake](https://cmake.org/) for the build system. In this
10 : guide we'll outline how to configure SpECTRE and
11 : describe some [commonly used CMake flags](#common_cmake_flags).
12 : We'll also go over how to
13 : [add new source files](#adding_source_files),
14 : [libraries](#adding_libraries),
15 : [unit tests](#adding_unit_tests), [executables](#adding_executables), and
16 : [external dependencies](#adding_external_dependencies).
17 :
18 : # Configuring
19 :
20 : The command to configure SpECTRE will look like this
21 :
22 : ```
23 : cmake -D FLAG1=OPT1 ... -D FLAGN=OPTN <SPECTRE_ROOT>
24 : ```
25 :
26 : where `FLAG{1..N}` are CMake flags that are detailed in the section on
27 : [commonly used CMake flags](#common_cmake_flags).
28 :
29 : CMake will look in your `$PATH` environment variable for all of the
30 : [build dependencies](installation.html#build_dependencies) and will use the
31 : first one it finds that satisfies the requirements. However, if a dependency is
32 : not in your `$PATH`, there are multiple versions of a dependency, or you just
33 : want to customize your configuration, you'll have to tell CMake which dependency
34 : you want to use and where it is using CMake flags. To that end, even though the
35 : [commonly used CMake flags](#common_cmake_flags) section has a more detailed
36 : list of the flags available, the following list has the *most common* CMake
37 : flags you'll need to customize your configuration (e.g. compilers, charm, build
38 : type, and library types):
39 :
40 : - CMAKE_C_COMPILER
41 : - CMAKE_CXX_COMPILER
42 : - CMAKE_Fortran_COMPILER
43 : - CHARM_ROOT
44 : - CMAKE_BUILD_TYPE
45 : - BUILD_SHARED_LIBS
46 :
47 : \note If you are on a cluster, take a look at the
48 : [installation on clusters](installation_on_clusters.html)
49 : instructions. If you are on a cluster we support, we will already have an
50 : environment setup and an easy way for you to configure the build without having
51 : to specify flags yourself.
52 :
53 : ## Configuring with CMake presets {#cmake_presets}
54 :
55 : Instead of passing flags on the command line every time, you can use
56 : [CMake presets](https://cmake.org/cmake/help/latest/manual/cmake-presets.7.html)
57 : to capture a configuration once and select it with `cmake --preset <name>`. The
58 : build directory of a preset defaults to `build-<name>` in the source tree.
59 :
60 : We provide a few standard presets that you can reuse on any machine:
61 :
62 : - `debug`: a `Debug` build (`-O0`, all `ASSERT`s and sanity checks enabled),
63 : used while actively developing and debugging.
64 : - `release-debug`: a `Release` build with `SPECTRE_DEBUG=ON`, so it keeps the
65 : `ASSERT`s and sanity checks but is optimized. **This is the preferred default
66 : for most runs**: the checks catch subtle bugs that only surface in long
67 : simulations and cost very little performance.
68 : - `release`: a fully optimized `Release` build with no debug checks. Use this
69 : only when full performance is absolutely necessary.
70 :
71 : These presets are assembled from building blocks defined in
72 : `support/Environments/Presets.json`: `debug-flags`, `release-flags` and
73 : `release-debug-flags`. You can combine these build-type flags with your own
74 : machine-specific configuration that supplies the compilers and dependency paths.
75 :
76 : - **On a personal machine**, create a `CMakeUserPresets.json` file in the source
77 : root (this file is git-ignored). Define a preset with your local compiler
78 : settings and dependency paths (e.g. name it `local`), then add
79 : `debug`/`release`/`release-debug` presets that combine `local` with the
80 : build-type flags. CMake reads `CMakeUserPresets.json` automatically, so `cmake
81 : --preset release-debug` will use your configuration. Here's an example
82 : `CMakeUserPresets.json`:
83 : ```json
84 : {
85 : "version": 7,
86 : "configurePresets": [
87 : {
88 : "name": "local",
89 : "inherits": "base",
90 : "hidden": true,
91 : "generator": "Ninja",
92 : "cacheVariables": {
93 : "CMAKE_C_COMPILER": "clang",
94 : "CMAKE_CXX_COMPILER": "clang++",
95 : "CMAKE_Fortran_COMPILER": "gfortran",
96 : "MEMORY_ALLOCATOR": "SYSTEM"
97 : }
98 : },
99 : {
100 : "name": "debug",
101 : "inherits": ["local", "debug-flags"]
102 : },
103 : {
104 : "name": "release",
105 : "inherits": ["local", "release-flags"]
106 : },
107 : {
108 : "name": "release-debug",
109 : "inherits": ["local", "release-debug-flags"]
110 : }
111 : ]
112 : }
113 : ```
114 : - **On a supercomputer**, we supply preset files on supported machines. To use
115 : the correct preset file, set the `SPECTRE_MACHINE` environment variable
116 : (supported machines are listed in support/Environments/). Then, `cmake
117 : --preset release-debug` works just the same as on a personal machine (it pulls
118 : the correct presets through `CMakePresets.json` in the repository root). Use
119 : the environment shell scripts in support/Environments/ to load
120 : modules and set `SPECTRE_MACHINE`.
121 : - **In git worktrees**, `CMakeUserPresets.json` is symlinked from the main
122 : checkout by a git hook, see `USE_GIT_HOOKS` below.
123 :
124 : ## Commonly Used CMake flags {#common_cmake_flags}
125 : The following are common flags used to control building SpECTRE with CMake (in
126 : alphabetical order):
127 : - ASAN
128 : - Whether or not to turn on the address sanitizer compile flags
129 : (`-fsanitize=address`) (default is `OFF`)
130 : - BLAZE_USE_ALWAYS_INLINE
131 : - Force Blaze inlining (default is `ON`)
132 : - If disabled or if the platform is unable to 100% guarantee inlining,
133 : falls back to `BLAZE_USE_STRONG_INLINE` (see below)
134 : - Forced inlining reduces function call overhead, and so generally reduces
135 : runtime. However, it does increase compile time and compile memory usage. It
136 : is also easier to use a debugger when forced inlining is disabled. If you
137 : are encountering debugger messages like `function inlined`, then forced
138 : inlining should be disabled.
139 : - BLAZE_USE_STRONG_INLINE
140 : - Increase the likelihood of Blaze inlining (default is `ON`)
141 : - Strong inlining reduces function call overhead, and so generally reduces
142 : runtime. However, it does increase compile time and compile memory usage. It
143 : is also easier to use a debugger when strong inlining is disabled. If you
144 : are encountering debugger messages like `function inlined`, then strong
145 : inlining should be disabled.
146 : - BOOTSTRAP_PY_DEPS and BOOTSTRAP_PY_DEV_DEPS
147 : - Install missing Python dependencies into the build directory, as listed in
148 : `support/Python/requirements.txt` and `support/Python/dev_requirements.txt`,
149 : respectively. This is an alternative to creating a Python environment and
150 : installing the packages yourself. If you run into problems with packages
151 : like h5py, numpy or scipy you can/should still install them yourself to make
152 : sure they use the correct HDF5, BLAS, etc.
153 : (default is `OFF`)
154 : - BUILD_DOCS
155 : - Enable building documentation. (default is `ON`)
156 : - BUILD_PYTHON_BINDINGS
157 : - Build python libraries to call SpECTRE C++ code from python
158 : (default is `ON`)
159 : - BUILD_SHARED_LIBS
160 : - Whether shared libraries are built instead of static libraries
161 : (default is `OFF`)
162 : - BUILD_TESTING
163 : - Enable building tests. (default is `ON`)
164 : - CHARM_ROOT
165 : - The path to the build directory of `Charm++`
166 : - CHARM_TRACE_PROJECTIONS
167 : - Enables tracing with Charm++ projections. Specifically, enables the link
168 : flag `-tracemode projections`. (default is `OFF`)
169 : - CHARM_TRACE_SUMMARY
170 : - Enables trace summaries with Charm++ projections. Specifically, enables
171 : the link flag `-tracemode summary`. (default is `OFF`)
172 : - CMAKE_BUILD_TYPE
173 : - Sets the build type. Common options:
174 : - `Debug` (the default if the flag is not specified): sets flags
175 : that trigger additional error checking
176 : - `Release`
177 : - CMAKE_C_COMPILER
178 : - The `C` compiler used (defaults to whatever is determined by
179 : `CMake/Modules/CMakeDetermineCCompiler.cmake`, usually `cc`)
180 : - CMAKE_C_FLAGS
181 : - Additional flags passed to the `C` compiler.
182 : - CMAKE_CXX_COMPILER
183 : - The `C++` compiler used (defaults to whatever is determined by
184 : `CMake/Modules/CMakeDetermineCXXCompiler.cmake`, usually `c++`)
185 : - CMAKE_CXX_FLAGS
186 : - Additional flags passed to the `C++` compiler.
187 : - CMAKE_Fortran_COMPILER
188 : - The `Fortran` compiler used (defaults to whatever is determined by
189 : `CMake/Modules/CMakeDetermineFortranCompiler.cmake`)
190 : - CMAKE_Fortran_FLAGS
191 : - Additional flags passed to the `Fortran` compiler.
192 : - CMAKE_INSTALL_PREFIX
193 : - Location where the `install` target copies executables, libraries, etc. Make
194 : sure to set this variable before you `install`, or a default location such
195 : as `/usr/local` is used.
196 : - CMAKE_RUNTIME_OUTPUT_DIRECTORY
197 : - Sets the directory where the library and executables are placed.
198 : By default libraries end up in `<BUILD_DIR>/lib` and executables
199 : in `<BUILD_DIR>/bin`.
200 : - COVERAGE
201 : - Enable code coverage with GCOV and LCOV (default `OFF`)
202 : - DEBUG_SYMBOLS
203 : - Whether or not to use debug symbols (default is `ON`)
204 : - Disabling debug symbols will reduce compile time and total size of the build
205 : directory.
206 : - DOCS_ONLY
207 : - Build _only_ documentation (default is `OFF`). Requires `BUILD_DOCS=ON`.
208 : - ENABLE_OPENMP
209 : - Enable OpenMP parallelization in some parts of the code, such as Python
210 : bindings and interpolating volume data files. Note that simulations do not
211 : typically use OpenMP parallelization, so this flag only applies to tools.
212 : - ENABLE_PARAVIEW
213 : - Try to find ParaView to enable 3D rendering tools (default is `OFF`)
214 : - ENABLE_PROFILING
215 : - Enables various options to make profiling SpECTRE easier
216 : (default is `OFF`)
217 : - ENABLE_PYTHON
218 : - Enables Python. (default is `ON`)
219 : - Set to `OFF` for a minimal build on systems without a recent Python
220 : installation. Warning: Many things will not work!!
221 : - Note: Even when disabled, a minimal Python installation
222 : (Python ≥ 2.7) is still required.
223 : - BUILD_PYTHON_BINDINGS, BUILD_TESTING, BUILD_DOCS should be `OFF`.
224 : - ENABLE_WARNINGS
225 : - Whether or not warning flags are enabled (default is `ON`)
226 : - FUKA_ROOT
227 : - Set to a path to a [FUKA](https://bitbucket.org/fukaws/fuka) installation to
228 : enable loading FUKA initial data into SpECTRE. Can be the FUKA repository
229 : root or the directory where `libkadath.a` was installed. Also requires FFTW
230 : to be installed (see FUKA docs on dependencies).
231 : - GSL_STATIC
232 : - If set, then the GNU Scientific Library is statically linked.
233 : - KEEP_FRAME_POINTER
234 : - Whether to keep the frame pointer. Needed for profiling or other cases
235 : where you need to be able to figure out what the call stack is.
236 : (default is `OFF`)
237 : - MACHINE
238 : - Select a machine that we know how to run on, such as a particular
239 : supercomputer. A file named MACHINE.yaml must exist in support/Machines and
240 : a submit script template named MACHINE.sh must exist in
241 : support/SubmitScripts.
242 : - MEMORY_ALLOCATOR
243 : - Set which memory allocator to use. If there are unexplained segfaults or
244 : other memory issues, it would be worth setting `MEMORY_ALLOCATOR=SYSTEM` to
245 : see if that resolves the issue. It could be the case that different
246 : third-party libraries accidentally end up using different allocators, which
247 : is undefined behavior and will result in complete chaos.
248 : (default is `JEMALLOC`)
249 : - PY_DEV_MODE
250 : - Enable development mode for the Python package, meaning that Python files
251 : are symlinked rather than copied to the build directory. Allows to edit and
252 : test Python code much easier, in particular when it uses compiled Python
253 : bindings, but doesn't replace CMake placeholders in the Python code such as
254 : the project version. (default is `OFF`)
255 : - SPEC_ROOT
256 : - Set to a path to a SpEC installation (the SpEC repository root) to link in
257 : SpEC libraries. In particular, the SpEC::Exporter library is linked in and
258 : enables loading SpEC data into SpECTRE. See \ref installation for details.
259 : - SPECTRE_AUTODIFF
260 : - Enable automatic differentation (default is `OFF`). This is required for
261 : computing Hessians.
262 : - SPECTRE_DEBUG
263 : - Defines `SPECTRE_DEBUG` macro to enable `ASSERT`s and other debug
264 : checks so they can be used in Release builds. That is, you get sanity checks
265 : and compiler optimizations. You cannot disable the checks in Debug builds,
266 : so this option has no effect in Debug builds.
267 : (default is `OFF` in release)
268 : - SPECTRE_DEBUG_Og
269 : - Compile Debug builds with `-Og` instead of the default `-O0`.
270 : `-Og` is specifically designed to preserve debuggability while enabling
271 : optimizations that do not interfere with source-level debugging.
272 : Has no effect when `SPECTRE_OPTIMIZE_SIZE=ON` (which uses `-Oz`).
273 : (default is `ON`)
274 : - SPECTRE_NAN_INIT
275 : - Defines `SPECTRE_NAN_INIT` macro to initialize memory to NaN in various
276 : places to catch use of uninitialized values.
277 : (default is the value of `SPECTRE_DEBUG`, or `ON` in Debug builds)
278 : - SPECTRE_OPTIMIZE_SIZE
279 : - Optimize for executable size instead of speed (adds the `-Oz` compiler
280 : flag). The default is `OFF`, unless on Apple Silicon machines, where the
281 : default is `ON`. This is because of a bug in macOS on Apple Silicon, which
282 : means executables larger than 2GB in size cannot run. Disabling this option
283 : on Apple Silicon can improve debugging tests (which are small enough so the
284 : bug does not affect them).
285 : - SPECTRE_FETCH_MISSING_DEPS
286 : - Download missing dependencies and build them alongside the SpECTRE source.
287 : (default is `OFF`)
288 : - SPECTRE_Fortran_STATIC_LIBS (default: `OFF`)
289 : - Use static version of `libgfortran` and `libquadmath`.
290 : - SPECTRE_INPUT_FILE_TEST_MIN_PRIORITY
291 : - Minimum priority of input file tests to run. Possible values are: `low` (not
292 : usually run on CI), `normal` (run at least once on CI), `high` (run always
293 : on CI). (default is `normal`)
294 : - SPECTRE_KOKKOS (default: `OFF`)
295 : - Enable Kokkos support. You must have Kokkos installed and detectable.
296 : - SPECTRE_LTO
297 : - Enable link-time optimization if the compiler supports it.
298 : - SPECTRE_LTO_CORES
299 : - Specifies the number of cores to use for parallelizing LTO. Must be a
300 : positive integer or "auto". This is only available when `SPECTRE_LTO=ON` and
301 : the compiler supports LTO.
302 : - SPECTRE_TEST_RUNNER
303 : - Run test executables through a wrapper. This might be `charmrun`, for
304 : example. (default is to not use one)
305 : - SPECTRE_TEST_TIMEOUT_FACTOR (and specific overrides
306 : SPECTRE_X_TEST_TIMEOUT_FACTOR for X one of UNIT, STANDALONE, INPUT_FILE, or
307 : PYTHON)
308 : - Multiply the timeout for the respective set of tests by this factor (default
309 : is `1`).
310 : - This is useful to run tests on slower machines.
311 : - SPECTRE_USE_ALWAYS_INLINE
312 : - Force SpECTRE inlining (default is `ON`)
313 : - Forced inlining reduces function call overhead, and so generally reduces
314 : runtime. However, it does increase compile time and compile memory usage. It
315 : is also easier to use a debugger when forced inlining is disabled. If you
316 : are encountering debugger messages like `function inlined`, then forced
317 : inlining should be disabled.
318 : - STRIP_SYMBOLS
319 : - Whether or not to strip all symbols (default is `OFF`)
320 : - If enabled strips all extraneous symbols from libraries and executables,
321 : further reducing the size of them.
322 : - STUB_EXECUTABLE_OBJECT_FILES
323 : - Replace object files from executables after linking with empty stubs
324 : (default is `OFF`)
325 : - This is useful for drastically reducing the build size in CI, but since the
326 : object files are replaced with empty stubs will generally cause linking
327 : problems if used during development.
328 : - STUB_LIBRARY_OBJECT_FILES
329 : - Replace object files from libraries after linking with empty stubs
330 : (default is `OFF`)
331 : - This is useful for drastically reducing the build size in CI, but since the
332 : object files are replaced with empty stubs will generally cause linking
333 : problems if used during development.
334 : - UBSAN_INTEGER
335 : - Whether or not to turn on the undefined behavior sanitizer
336 : [unsigned integer
337 : overflow](https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html) flag
338 : (`-fsanitize=integer`) (default is `OFF`)
339 : - UBSAN_UNDEFINED
340 : - Whether or not to turn on the undefined behavior sanitizer
341 : [undefined
342 : behavior](https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html)
343 : compile flags (`-fsanitize=undefined`) (default is `OFF`)
344 : - UNIT_TESTS_IN_TEST_EXECUTABLES
345 : - Whether to build the `unit-tests` target as part of the `test-executables`
346 : target. This is used to build only the non-unit tests in the CI build
347 : that doesn't use the PCH. (default is `ON`)
348 : - USE_CCACHE
349 : - Use ccache to cache build output so that rebuilding parts of the source tree
350 : is faster. The cache will use up space on disk, with the default being
351 : around 2-5GB. If you are performing a one time build to test something
352 : specific you should consider disabling ccache in order to avoid removing
353 : cached files that may be useful in other builds.
354 : (default is `ON`)
355 : - USE_FORMALINE
356 : - Write the source tree into HDF5 files written to disk in order to increase
357 : reproducibility of results.
358 : (default is `ON`)
359 : - USE_GIT_HOOKS
360 : - Use git hooks to perform some sanity checks so that small goofs are caught
361 : before they are committed. These checks are particularly useful because they
362 : also run automatically on \ref github_actions_guide "CI" and must pass
363 : before pull requests are merged. The hooks are shared between all git
364 : worktrees of the repository and use the tools of the last configured build.
365 : A `post-checkout` hook also symlinks git-ignored personal files such as
366 : `CMakeUserPresets.json` from the main checkout into new worktrees.
367 : (default is `ON`)
368 : - USE_LD
369 : - Override the automatically chosen linker. The options are `ld`, `gold`, and
370 : `lld`.
371 : (default is `OFF`)
372 : - USE_PCH
373 : - Whether or not to use pre-compiled headers (default is `ON`)
374 : - USE_SLEEF
375 : - Whether to use [Sleef](https://github.com/shibatch/sleef) with Blaze to
376 : vectorize addition math functions like `sin`, `cos`, and `exp`.
377 : (default is `OFF`)
378 : - \note Blaze isn't tested super thoroughly across different architectures so
379 : there's unfortunately no guarantee that Blaze+Sleef will work everywhere.
380 : - USE_XSIMD
381 : - Whether to use [xsimd](https://github.com/xtensor-stack/xsimd) with Blaze to
382 : vectorize addition math functions like `sin`, `cos`, and `exp`.
383 : Defines the macro `SPECTRE_USE_XSIMD`, which can be check to enable manual
384 : vectorization where necessary.
385 : (default is `ON`)
386 :
387 : ## CMake targets
388 :
389 : To see all possible build targets, once you configure SpECTRE run
390 :
391 : ```
392 : make list
393 : ```
394 :
395 : This will be a long list of all libraries, test executables, simulation
396 : executables, and custom build targets. The custom targets that are
397 : available to build with `make` or `ninja` are:
398 :
399 : - unit-tests
400 : - Build unit tests, which you can run with `ctest -L unit`. Available if
401 : `BUILD_TESTING` is `ON` (the default).
402 : - test-executables
403 : - Build all tests, including executables, so you can run all tests with
404 : `ctest`. Available if `BUILD_TESTING` is `ON` (the default). To compile
405 : `test-executables` you may have to reduce the number of cores you build on
406 : in parallel to avoid running out of memory.
407 : - all-pybindings
408 : - Build Python bindings. See \ref spectre_using_python for details.
409 : - cli
410 : - Same as all-pybindings
411 : - install
412 : - Install targets that have been built to the `CMAKE_INSTALL_PREFIX`. Doesn't
413 : try to build anything else.
414 :
415 : # Editing the build system
416 :
417 : \note When editing `CMakeLists.txt` files, it is conventional to
418 : indent multiline commands by two spaces (except for the first line),
419 : and to separate most commands by blank lines.
420 :
421 : ## Adding Source Files {#adding_source_files}
422 :
423 : SpECTRE organizes source files into subdirectories of `src` that are
424 : compiled into libraries. To add a new source file `FILE.cpp` to an
425 : existing library in `src/PATH/DIR`, just edit
426 : `src/PATH/DIR/CMakeLists.txt` and add `FILE.cpp` to the list of files
427 : in
428 : ```
429 : spectre_target_sources(
430 : ${LIBRARY}
431 : PRIVATE
432 : <list_of_files>
433 : )
434 : ```
435 : such that the resulting `<list_of_files>` is in alphabetical order.
436 :
437 : ## Adding Header Files {#adding_header_files}
438 :
439 : Similarly to [adding new source files](#adding_source_files), you can add a new
440 : header file `FILE.hpp` to a library by editing the `CMakeLists.txt` in that
441 : directory and adding `FILE.hpp` to the list of files in
442 : ```
443 : spectre_target_headers(
444 : ${LIBRARY}
445 : INCLUDE_DIRECTORY ${CMAKE_SOURCE_DIR}/src
446 : HEADERS
447 : <list_of_files>
448 : )
449 : ```
450 :
451 : \note Any `.tpp` files also go in this list of header files.
452 :
453 : ## Adding Libraries {#adding_libraries}
454 :
455 : To add a source file `FILE.cpp` that is compiled into a new library `LIB` in a
456 : directory `src/PATH/DIR` (either in a new directory, or in an existing
457 : directory that either does not have a `CMakeLists.txt` file, or does
458 : not create a library in the existing `CMakeLists.txt`):
459 : - Create (if necessary) a `CMakeLists.txt` file in `DIR`, with the following
460 : two lines at the top:
461 : ```
462 : # Distributed under the MIT License.
463 : # See LICENSE.txt for details.
464 : ```
465 : - In the parent directory (i.e. `src/PATH`), (if necessary) add the
466 : following line to its `CMakeLists.txt` file (if necessary, recursively
467 : do the previous step and this one until you reach a `CMakeLists.txt` that
468 : adds the appropriate subdirectory):
469 : ```
470 : add_subdirectory(DIR)
471 : ```
472 : If there are already other `add_subdirectory()` lines in the file, place
473 : the new one so that the subdirectories are in alphabetical order.
474 : - Add the line:
475 : ```
476 : set(LIBRARY LIB)
477 : ```
478 : where convention is that `LIB` = `DIR`. As library names must be
479 : unique, this is not always possible, in which case the convention is to
480 : prepend the parent directory to `DIR`.
481 : - Add the lines
482 : ```
483 : add_spectre_library(${LIBRARY})
484 :
485 : spectre_target_sources(
486 : ${LIBRARY}
487 : PRIVATE
488 : FILE.cpp
489 : )
490 :
491 : spectre_target_headers(
492 : ${LIBRARY}
493 : INCLUDE_DIRECTORY ${CMAKE_SOURCE_DIR}/src
494 : HEADERS
495 : FILE.hpp
496 : )
497 :
498 : target_link_libraries(
499 : ${LIBRARY}
500 : PUBLIC
501 : <list_of_public_libraries>
502 : PRIVATE
503 : <list_of_private_libraries>
504 : INTERFACE
505 : <list_of_interface_libraries>
506 : )
507 : ```
508 : where each `<list_of_X_libraries>` is an alphabetized list
509 : of libraries of the form
510 : ```
511 : SomeLibrary
512 : SomeOtherLibrary
513 : YetAnotherLibrary
514 : ```
515 : The libraries listed under `INTERFACE` are those included in at
516 : least one `.hpp` file in `LIB` but never used in any `.cpp` files
517 : in `LIB`. The libraries listed under `PRIVATE` are used in
518 : at least one `.cpp` file in `LIB` but not in any `.hpp` file
519 : in `LIB`. The libraries listed under `PUBLIC` are used in at
520 : least one `.hpp` file and at least one `.cpp` file in `LIB`.
521 : Note that a library counts as being used in a `.cpp` file if the
522 : corresponding `.hpp` file includes it. In other words, list a dependency
523 : as `PRIVATE` if it is needed only to compile the library, but not for
524 : including headers. List a dependency as `INTERFACE` if it is not needed
525 : to compile the library, but is needed for including headers. List a
526 : dependency as `PUBLIC` if it is needed for both.
527 :
528 : \note If your library only contains header files, you must specify `INTERFACE`
529 : like so in the `add_spectre_library(${LIBRARY} INTERFACE)` function. You should
530 : also omit the `spectre_target_sources` lines as well.
531 :
532 : ## Adding Unit Tests {#adding_unit_tests}
533 :
534 : We use the [Catch](https://github.com/philsquared/Catch) testing
535 : framework for unit tests. All unit tests are housed in `tests/Unit`
536 : with subdirectories for each subdirectory of `src`. Add the `cpp` file
537 : to the appropriate subdirectory and also to the `CMakeLists.txt` in
538 : that subdirectory. Inside the source file you can create a new test by
539 : adding a `SPECTRE_TEST_CASE("Unit.Dir.Component",
540 : "[Unit][Dir][Tag]")`. The `[Tag]` is optional and you can have more
541 : than one, but the tags should be used quite sparingly. The purpose of
542 : the tags is to be able to run all unit tests or all tests of a
543 : particular set of components, e.g. `ctest -L Data` to run all tests
544 : inside the `Data` directory. Please see \ref writing_unit_tests
545 : "writing unit tests", other unit tests and the [Catch
546 : documentation](https://github.com/philsquared/Catch) for more help on
547 : writing tests. Unit tests should take as short a time as possible,
548 : with a goal of less than two seconds. Please also limit the number of
549 : distinct cases (by using `SECTION`s).
550 :
551 : You can check the unit test coverage of your code by installing all the optional
552 : components and then running `make unit-test-coverage` (after re-running CMake).
553 : This will create the
554 : directory `BUILD_DIR/docs/html/unit-test-coverage/` which is where the coverage
555 : information is located. Open the `index.html` file in your browser and make
556 : sure that your tests are indeed checking all lines of your code. Your pull
557 : requests might not be merged until your line coverage is over 90% (we are aiming
558 : for 100% line coverage wherever possible). Unreachable lines of code can be
559 : excluded from coverage analysis by adding the inline comment `LCOV_EXCL_LINE`
560 : or a block can be excluded using `LCOV_EXCL_START` and `LCOV_EXCL_STOP`.
561 : However, this should be used extremely sparingly since unreachable code paths
562 : should be removed from the code base altogether.
563 :
564 : ## Adding Executables {#adding_executables}
565 :
566 : All general executables are found in `src/Executables`, while those
567 : for specific evolution (elliptic) systems are found in
568 : `src/Evolution/Executables` (`src/Elliptic/Executables`). See \ref
569 : dev_guide_creating_executables "how to create executables".
570 :
571 : ## Adding External Dependencies {#adding_external_dependencies}
572 :
573 : To add an external dependency, first add a `SetupDEPENDENCY.cmake`
574 : file to the `cmake` directory. If CMake
575 : does not already support `find_package` for the library you're adding
576 : you can write your own `FindDEPENDENCY.cmake` file.
577 : The `SetupDEPENDENCY.cmake` file must then be included in
578 : the root `spectre/CMakeLists.txt`. Be sure to test both that setting
579 : `LIBRARY_ROOT` works correctly for your library, and also that if the
580 : library is required that CMake fails gracefully if the library is not
581 : found.
582 :
583 : # Dependencies
584 :
585 : ## Checking Dependencies
586 :
587 : Getting dependencies of libraries correct is quite difficult. SpECTRE offers the
588 : CMake function `check_spectre_libs_dependencies`, defined in
589 : `cmake/SpectreCheckDependencies.cmake`, to check the dependencies for all
590 : libraries in the `libs` target. Individual target dependencies can be checked
591 : using the `check_target_dependencies` CMake function defined in
592 : `cmake/SpectreCheckTargetDependencies.cmake`. Please see those functions in the
593 : source tree for more details on how to use them.
594 :
595 : ## Formaline
596 :
597 : SpECTRE's implementation of Formaline is based on, but distinct in
598 : implementation from, the
599 : [original design](https://github.com/hypercott/formaline)
600 : which embeds an archive of the source tree into the executable. The original
601 : design creates a C/C++ file with a function that returns an array/vector of
602 : `char`s (a byte stream). However, this results in a very large source file (50MB
603 : or more), which is very slow to compile and ends up more than doubling the link
604 : time. Instead, SpECTRE's Formaline implementation uses the linker `ld` to
605 : encode a file into an object, which means
606 : rather than creating a large source file, we can directly encode the source tree
607 : archive into the binary at the linking stage.
608 :
609 : Most of SpECTRE's Formaline is implemented
610 : inside the `tools/WrapExecutableLinker.sh` script. Function declarations are
611 : provided in `Utilities/Formaline.hpp` and a small function that writes the
612 : source file to disk is defined in `Utilities/Formaline.cpp`. The first
613 : Formaline-related thing done in `WrapExecutableLinker.sh` is to archive
614 : everything in the source directory tracked by git. Once the archive is created
615 : we run `ld -r -b binary -o object.o src.tar.gz` (with unique names for
616 : `object.o` and `src.tar.gz` for each executable that is built to avoid name
617 : collisions) to generate an object file with the source file encoded from
618 : `_binary_src_tar_gz_start` to `_binary_src_tar_gz_end`. Next we write a C++
619 : source file that defines a function `get_archive` to convert the byte stream
620 : into a `std::vector<char>`. We also encode the output of `printenv`, the various
621 : `PATH` environment variables, and the CMake generated `BuildInfo.txt` file
622 : into the source file. Finally, the generated source file is built during the
623 : linking phase and the object file containing the source archive is linked into
624 : the executable.
625 :
626 : To further aid in reproducibility, the `printenv` output and
627 : `BuildInfo.txt` contents are written to HDF5 files as part of the
628 : `h5::Header` object. The archive of the source tree is written using the
629 : `h5::SourceArchive` object and can be extracted by running
630 : ```
631 : h5dump -d /src.tar.gz -b LE -o src.tar.gz /path/to/hdf5/file.h5
632 : ```
633 :
634 : # Using Kokkos
635 :
636 : Kokkos support is still extremely experimental, but can be enabled by passing
637 : `-D SPECTRE_KOKKOS=ON` to CMake. You must pass additional CMake flags that
638 : Kokkos will use to configure itself. For example, to enable CUDA support you
639 : must pass `-D Kokkos_ENABLE_CUDA=ON`. See the
640 : [Kokkos documentation](https://kokkos.org/kokkos-core-wiki/keywords.html) for
641 : details.
642 :
643 : ## Nvidia Compiler
644 :
645 : If you are using CUDA to compile for Nvidia GPUs but do not have the target GPU
646 : on the system you are compiling on then you must also tell CMake what CUDA
647 : architecture to use. You can do this by passing `-D CMAKE_CUDA_ARCHITECTURES=80`
648 : to CMake. You must choose the architecture that will be compatible with the GPU
649 : you plan to use. Note that this is actually called the compute capability
650 : version by Nvidia and can be viewed
651 : [here](https://developer.nvidia.com/cuda-gpus).
|