API#

LIBRA API Conventions#

  • All public API functions/macros start with libra_; anything else is non-API and can change at any time.

  • All public API variables start with LIBRA_; anything else is non-API and can change at any time.

  • All private API functions/macros start with _libra_. They should never be used outside of LIBRA itself.

  • All private API variables start with _LIBRA_. They should never be used outside of LIBRA itself. Private API variables are ones which have some semantic significance beyond just a temp variable for calculations.

LIBRA Private API#

Analysis#

_libra_register_code_checkers#

Registers all code-checking analysis tools (distinct from documentation checking analysis tools). Currently this is:

  • cppcheck. Operates on sources and stubs.

  • clang-tidy. Operates on sources, headers, and stubs.

  • clang-check. Operates on sources and stubs.

Param TARGET:

The name of the target {sources,headers,stubs} are attached to.

Param SRCS:

Source files for checkers to check.

Param HEADERS:

Header files for checkers to check.

Param STUBS:

Stub C/C++ files which include a single header for checkers to check. Used to check headers which aren’t included in any source file and thus don’t have compdb entries.

_libra_register_code_fixers#

Registers all code-fixing analysis tools. Currently this is:

  • clang-tidy

  • clang-check

Fixing is limited to source files because fixing with raw header files and/or stubs is not very reliable.

Param TARGET:

The name of the target {sources,headers,stubs} are attached to.

Param SRCS:

Source files for checkers to check.

_libra_header_needs_stub#

Determine if a header file in the project needs a stub created for it so that analysis works reliably with a compilation database. A header needs a stub if it isn’t included in any source file in the project.

This is done by checking through every source file to see if a given header appears in it relative to a given interface include directory.

Param HEADER:

The header to check the status of.

Param PARENT:

The parent interface include directory to check against.

Param RET:

Name of variable in parent scope to set with yes/no.

_libra_prune_stale_stubs#

Remove stub files from STUB_DIR that no longer correspond to any header in the current project.

Called before _libra_generate_header_stubs so that stubs for removed or renamed headers don’t accumulate across reconfigures. Relies on the same naming convention used by _libra_generate_header_stubs to reconstruct the expected stub filename from each header path.

This approach was chosen over nuking the stub directory on every configure for a few reasons:

  • The unconditional delete violates incremental build principles. CMake’s configure step is supposed to be idempotent and cheap for unchanged inputs. Unconditionally deleting and regenerating all stubs means every cmake configure run with LIBRA_ANALYSIS=YES invalidates all stub object files, forcing a full stub recompile before any analysis can run — even if zero headers changed. For a project with hundreds of public headers this becomes a meaningful tax on every analysis run.

  • The IS_NEWER_THAN mechanism already exists for a reason: to avoid unnecessary regeneration. The unconditional delete defeats it entirely, making it dead code in practice.

  • This approach composes better with –fresh. A –fresh configure already wipes the binary directory entirely, so stale stubs are cleaned up naturally. The unconditional delete is redundant in the –fresh case and harmful in the incremental case.

Param TARGET:

The CMake target whose public headers define the expected stub set.

Param STUB_DIR:

Directory containing existing stubs to prune.

_libra_generate_header_stubs#

Generate stub .cpp files for standalone header analysis.

Each stub contains a single #include of its corresponding header, expressed as a path relative to the include directory it was found under. This ensures the header is analyzed with the same include path form as real consumers would use, and that any missing self-containment or include-order bugs are caught as real errors rather than papered over.

Stubs are written to STUB_DIR and only regenerated if the header is newer than the existing stub, avoiding spurious rebuilds.

Only headers under the target’s INTERFACE_INCLUDE_DIRECTORIES are stubbed, which is correct: those are the headers that form the public API and must be self-contained. Private/internal headers that are not exposed via INTERFACE_INCLUDE_DIRECTORIES are intentionally excluded.

Param TARGET:

The CMake target whose public headers are stubbed.

Param STUB_DIR:

Directory under which stub .cpp files are written. Typically ${CMAKE_BINARY_DIR}/libra_header_stubs.

Param STUBS_VAR:

Name of the variable in caller’s scope that receives the list of generated stub file paths.

_libra_normalize_includes#

Normalize a list of includes for the purposes of stub file generation.

  • Strip BUILD_INTERFACE genex, since we only want the actual dir

  • Ignore INSTALL_INTERFACE dirs

After the above, remove duplicates.

_libra_find_code_analyzers#

Finds acceptable versions of all analysis tools libra uses for analyze code.

Currently this is:

  • clang-tidy

  • clang-check

  • cppcheck

_libra_find_apidoc_analyzers#

Finds acceptable versions of all analysis tools libra uses for analyze documentation.

Currently this is:

  • clang

  • doxygen

Formatting#

_libra_find_formatting_tools#

Finds acceptable versions of all formatting tools LIBRA uses.

Currently this is:

  • clang-format

  • cmake-format

Documentation#

_libra_apidoc_configure_doxygen#

Configures doxygen. If docs/Doxyfile.in doesn’t exist, nothing is done. If it does exist, then the parameter targets are created.

Param APIDOC_TARGET:

Target to generate API docs with doxygen.

Param APIDOC_CHECK_TARGET:

Parent target to check API documentation for all configured source files. All warnings from doxygen are treated as errors, which can be a little pedantic.

_libra_apidoc_register_clang#

Configures clang for API doc checking. Uses a fixeddb unconditionally, since we need very little actual syntax checking for the code to check the docs.

_libra_sphinxdoc_configure#

Configures sphinx. If docs/conf.py doesn’t exist, nothing is done. Checks if LIBRA_SPHINXDOC_COMMAND works. If it works, then the sphinx target is created.

Param SPHINXDOC_TARGET:

Target to generate docs with sphinx.

Param APIDOC_TARGET:

Target to generate API docs. If it exists, the the sphinx target will depend on it.