Configure-Time Actions
This page details LIBRA usage and actions when you invoke CMake on the cmdline. It is coupled to, but distinct from, project-local.cmake: How To Hook Into LIBRA.
Target Configuration
LIBRA will apply all of its magic (compile options, analysis config, etc.) to
all targets in LIBRA_TARGETS. By default, this contains only
the PROJECT_NAME target (i.e., the target has the same name as the
project–Principle of Least Surprise). If you want to include multiple targets
it is recommended to use libra_add_library(),
libra_add_executable(), to have LIBRA handle multiple targets.
You can also use LIBRA_GLOBAL_C_FLAGS,
LIBRA_GLOBAL_CXX_FLAGS to apply compiler configuration to all
targets, though this will affect ALL Cmake targets, which is generally a bad
idea.
File Discovery
All files under
src/ending in:.c.cpp
are globbed as source files (see Repository/Code Structure Requirements for repository layout requirements) so that if you add a new source file, rename a source file, etc., you just need to re-run cmake. This means you don’t have to MANUALLY specify all the files in the cmake project. Woo-hoo!
Note
See Using cmake Globbing for rationale on why globs are used, contrary to common cmake guidance.
All files under
tests/ending in a specified pattern are recursively globbed as unit test files which will be compiled into executable unit tests at build time ifLIBRA_TESTSis enabled. See Variables more details on this configuration item. Same for integration tests.All files under
tests/ending in a specified pattern are recursively globbed as the test harness for unit/integration tests. All test harness files will be compiled into static libraries at build time and all test targets link against them ifLIBRA_TESTSis enabled.
Note
The difference between unit tests and integration tests is purely semantic, and exists solely to help organize your tests. LIBRA treats both types of tests equivalently.
The rest of the page details variables available for fine-tuning the cmake
configuration process; thus, these variables are indended to be set on the
command line via -D, as they enable/disable LIBRA features, instead of
configuring a feature. However, most can be put in your
project-local.cmake if you want to–see project-local.cmake: How To Hook Into LIBRA for
details about restrictions.
Important
Unless specified otherwise, all knobs only apply to the current
project and/or target; i.e., no CMAKE_XXX global variables
are set. This helps to prevent untended cascades of build options
which might cause issues.
Knobs For Configuring LIBRA/CMake
- LIBRA_DEPS_PREFIX
- Default:
$HOME/.local/system
- Type:
STRING
The location where cmake should search for other locally installed libraries (e.g.,
$HOME/.local). VERY useful to separate out 3rd party headers which you want to suppress all warnings for by treating them as system headers when you can’t/don’t want to install things as root.Only available if
LIBRA_DRIVER=SELF. Cannot be set inproject-local.cmake.
- LIBRA_DRIVER
- Default:
SELF
- Type:
STRING
The primary user-visible driver to LIBRA, if any. Possible values are:
SELF- LIBRA itself is the driver/main way users interact with the build system; for all intents and purposes, LIBRA IS the build system. It also handles packaging duties, to the extent that cmake supports packaging.CONAN- CONAN is the primary driver of the build system. It sets up the environment and handles all packaging tasks. LIBRA only has to run the actual builds.
- LIBRA_SUMMARY
- Default:
YES
- Type:
BOOL
Show a configuration summary after the configuration step finishes.
Knobs For Supporting SW Engineering
See also the individual docs pages for each compiler, which describe how these knobs are realized for each supported compiler.
- LIBRA_DOCS
- Default:
NO
- Type:
BOOL
Enable documentation build via
make apidoc.
- LIBRA_CODE_COV
- Default:
NO
- Type:
BOOL
Build in runtime code-coverage instrumentation for report generation and coverage checking. See Actions For Supporting SW Engineering for specifics.
- LIBRA_CODE_COV_NATIVE
- Default:
YES
- Type:
BOOL
Direct compilers to build in coverage instrumentation in their “native” format. E.g., clang will using LLVM format, and GCC will use GNU format. If false, all compilers will use GNU format. The created targets will reflect which format is selected.
- LIBRA_SAN
- Default:
NONE
- Type:
STRING
Build in runtime checking of code using any compiler. When passed, the value should be a comma-separated list of sanitizer groups to enable:
MSAN- Memory checking/sanitization. To use this, you may needliblsaninstalled, compatible with your compiler.ASAN- Address sanitization. To use this, you will needlibasaninstalled, compatible with your compiler.SSAN- Aggressive stack checking.UBSAN- Undefined behavior checks.TSAN- Multithreading checks. To use this, you will needlibtsaninstalled, compatible with your compiler.NONE- None of the above.
Note
The first 4 can generally be stacked together without issue. Depending on compiler; the thread sanitizer is incompatible with some other sanitizer groups.
- LIBRA_ANALYSIS
- Default:
NO
- Type:
BOOL
Enable static analysis targets for checkers, formatters, etc. See Build Time Actions for the targets enabled (assuming the necessary executables are found).
- LIBRA_OPT_REPORT
- Default:
NO
- Type:
BOOL
Enable compiler-generated reports for optimizations performed, as well as suggestions for further optimizations.
- LIBRA_FORTIFY
- Default:
NONE. Any non-None value also sets
LIBRA_LTO=YES.- Type:
STRING
Build in compiler support/runtime checking of code for heightened security. Which options get passed to compiler/linker AND which groups are supported is obviously compiler dependent.
Important
When enabling things using this variable, you probably will have to compile everything with the same settings to avoid getting linker errors.
When passed, the value should be a comma-separated list of groups to enable:
STACK- Fortify the stack: add stack protector, etc.SOURCE- Fortify source code via_FORTIFY_SOURCE=2.FORMAT- Fortify against formatting attacks.ALL- All of the above.NONE- None of the above.
Added in version 0.8.3.
- LIBRA_TESTS
- Default:
NO
- Type:
BOOL
Enable building of tests via:
make unit-tests(unit tests only)make integration-tests(integration tests only)make regression-tests(regression tests only)make tests(all tests)
Knobs For Configuring Builds
- LIBRA_FPC
- Default:
INHERIT
- Type:
STRING
Enable Function Precondition Checking (FPC): checking function parameters/global state before executing a function, for functions which a library/application has defined conditions for. LIBRA does not define how precondition checking is implemented for a given library/application using it, only a simple declarative interface for specifying what type of checking is desired at build time; a library application can choose how to interpret the specification. This flexibility and simplicity is part of what makes LIBRA a very useful build process front-end across different projects.
FPC is, generally speaking, mostly used in C, and is very helpful for debugging, but can slow things down in production builds. Possible values for this option are:
NONE- Checking compiled out.RETURN- If at least one precondition is not met, return without executing the function. Do not abort() the program.ABORT- If at least one precondition is not met, abort() the program.INHERIT- FPC configuration should be inherited from a parent project which exposes it. This is the default because it prevents cluttering compiler commands with #defines for projects which don’t use it.
- LIBRA_FPC_EXPORT
- Default:
NO
- Type:
BOOL
Make
LIBRA_FPCvisible to downstream projects; it is private by default. This allows you to create an arbitrary dependency graph w.r.t which projects define their own FPC vs. which inherit it from elsewhere.
- LIBRA_C_STANDARD
- Default:
Autodetected to the latest C standard supported by
CMAKE_C_COMPILER. RespectsCMAKE_C_STANDARD, if set/overridden.- Type:
STRING
Added in version 0.8.4.
- LIBRA_CXX_STANDARD
- Default:
Autodetected to the latest C++ standard supported by
CMAKE_CXX_COMPILER. RespectsCMAKE_CXX_STANDARD, if set/overridden.- Type:
STRING
Added in version 0.8.4.
- LIBRA_GLOBAL_C_FLAGS
- Default:
NO
- Type:
BOOL
Specify that the total set of C flags (diagnostic, sanitizer, optimization, defines, etc.) which are automatically set for
PROJECT_NAMEshould be applied globally viaCMAKE_C_FLAGS_<build type>to all C files.Use with care, as applying said flags to external dependencies built alongside your code can cause a cascade of unintended errors. That said, for well-behaved dependencies, this can be a nice way of ensuring uniformity of build options when building from source.
Changed in version 0.9.14: When disabled, the
target_compile_options()andtarget_compile_definitions()set by LIBRA are PRIVATE not PUBLIC.
- LIBRA_GLOBAL_CXX_FLAGS
- Default:
NO
- Type:
BOOL
Specify that the total set of C++ flags (diagnostic, sanitizer, optimization, defines, etc.) which are automatically set for
PROJECT_NAMEshould be applied globally viaCMAKE_CXX_FLAGS_<build type>to all C++ files.Use with care, as applying said flags to external dependencies built alongside your code can cause a cascade of unintended errors. That said, for well-behaved dependencies, this can be a nice way of ensuring uniformity of build options when building from source.
Changed in version 0.9.14: When disabled, the
target_compile_options()andtarget_compile_definitions()set by LIBRA are PRIVATE, not PUBLIC.
- LIBRA_ERL
- Default:
INHERIT
- Type:
STRING
Specify Event Reporting Level (ERL). LIBRA does not prescribe a given event reporting framework (e.g., log4ccx, log4c, spdlog) which must be used. Instead, it provides a simple declarative interface for specifying the desired result of framework configuration at the highest level. Possible values of this option are:
ALL- Event reporting is compiled in fully and linked with; that is, all possible events of all levels are present in the compiled binary, and whether an encountered event is emitted is dependent on the level and scope of the event (which may be configured at runtime).FATAL- Compile out event reporting EXCEPT FATAL events.ERROR- Compile out event reporting EXCEPT [FATAL, ERROR] events.WARN- Compile out event reporting EXCEPT [FATAL, ERROR, WARN] events.INFO- Compile out event reporting EXCEPT [FATAL, ERROR, WARN, INFO] events.DEBUG- Compile out event reporting EXCEPT [FATAL, ERROR, WARN, INFO, DEBUG] events.TRACE- Same asALL.NONE- All event reporting compiled out.INHERIT- Event reporting configuration should be inherited from a parent project which exposes it. This is the default because it prevents cluttering compiler commands with #defines for projects which don’t use it.
- LIBRA_ERL_EXPORT
- Default:
NO
- Type:
BOOL
Make
LIBRA_ERLvisible to downstream projects; it is private by default. This allows you to create an arbitrary dependency graph w.r.t which projects define their own ERL vs. which inherit it from elsewhere.
- LIBRA_PGO
- Default:
NONE
- Type:
STRING
Generate a PGO build for the selected compiler, if supported. Possible values for this option are:
NONEGEN- Input stage. Generally, you would do something like:cmake -DLIBRA_PGO=GEN .. make ./bin/my_application # Run with representative workload
If you’re using clang, you would then have to do something like:
llvm-profdata merge -o default.profdata default*.profraw
USE- Final stage (after executing theGENbuild to get profiling info and running):cmake -DLIBRA_PGO=USE .. make
The optimized binary in will be tuned based on the runtime behavior observed in when running with PGO instrumentation compiled in.
Requires LIBRA_PGO to be set to GEN or USE.
- LIBRA_VALGRIND_COMPAT
- Default:
NO
- Type:
BOOL
Disable compiler instructions in 64-bit code so that programs will run under valgrind reliably.
- LIBRA_LTO
- Default:
NO
- Type:
BOOL
Enable Link-Time Optimization (LTO), also known as Interprocedural optimization (IPO). Compiler-independent.
Changed in version 0.8.3: This is automatically enabled by
LIBRA_FORTIFY != NONE.
- LIBRA_STDLIB
- Default:
UNDEFINED; use compiler built-in default.
- Type:
STRING
Enable using the standard library and/or select which standard library to use. You would only turn this off for bare-metal builds (e.g., bootstraps). Valid values are:
NONE- Don’t use the stdlib at all. Defines__nostdlib__macro for all source files.CXX- Use libc++, if the compiler supports it.STDCXX- Use libstdc++, if the compiler supports it.
- LIBRA_DEBUG_INFO
- Default:
YES
- Type:
BOOL
Enable generation of debug symbols independent of whatever the default is with a given cmake build type.
Added in version 0.8.4.
Changed in version 0.9.36: Renamed to
LIBRA_DEBUG_INFO, and default to on.
- LIBRA_NATIVE_OPT
- Default:
NO
- Type:
BOOL
Enable compiler optimizations native to the current machine. This will likely make code compiled in this way only runnable on the current machine. Not recommended for use with docker/CI pipelines.
Added in version 0.9.15.
- LIBRA_USE_COMPDB
- default:
NO
- type:
BOOL
Tell LIBRA that all analysis tools should use a compilation database, rather than the default of extracting the necessary includes, #defines, etc. from the target itself. See Static Analysis for more details about this decision.
For best results, if you are using any of the clang-based analysis targets, set the compiler to clang and then set
LIBRA_USE_COMPDB. If you are using e.g., gcc as the compiler, clang-based analysis may still work, but generate some spurious warnings about a compilation database not being found/used.Added in version 0.9.36.