CMake Generators#

Yanga uses a modular system of CMake Generators to create the build files for a project. Each generator is a Python class responsible for producing a specific set of CMake commands and targets. They are configured per platform in the yanga.yaml file, allowing for different build pipelines for different targets (e.g., one for building an executable, another for running tests).

Below is an overview of the main CMake generators available in Yanga.

CreateExecutableCMakeGenerator#

This generator is responsible for creating a single executable for a specific variant. It compiles all components of the variant as object libraries and then links them together into one executable file.

Use Case: Building the final application for a product variant.

Configuration:

platforms:
  - name: my_executable_platform
    generators:
      - step: CreateExecutableCMakeGenerator
        module: yanga.cmake.create_executable
        config:
          # If true, all include directories are added globally.
          # If false, includes are handled on a per-component basis.
          use_global_includes: true

GTestCMakeGenerator#

This generator facilitates unit testing using the Google Test framework. For each testable component, it builds a separate test executable. It also includes a powerful auto-mocking feature that uses clanguru to generate mocks for dependencies, isolating the component under test.

Use Case: Running unit tests and generating coverage reports for individual components.

Configuration:

platforms:
  - name: test_platform
    generators:
      - step: GTestCMakeGenerator
        module: yanga.cmake.gtest
        config:
          # Enable/disable auto-mocking for all components.
          # This can be overridden in each component's 'testing' section.
          mocking:
            enabled: true
            strict: false # If true, clanguru parsing errors are fatal.
            exclude_symbol_patterns: ["_*"] # Symbols to exclude from mocking.

CppCheckCMakeGenerator#

This generator integrates cppcheck, a static analysis tool for C/C++ code. It creates targets to run cppcheck on a per-component basis and for the entire variant. The results are generated as XML and then converted to Markdown for inclusion in reports.

Use Case: Performing static code analysis to find bugs and improve code quality.

Configuration:

This generator is typically added as a step without specific configuration.

platforms:
  - name: analysis_platform
    generators:
      - step: CppCheckCMakeGenerator
        module: yanga.cmake.cppcheck

ReportCMakeGenerator#

This generator orchestrates the creation of comprehensive HTML reports for both individual components and the entire variant. It uses Sphinx to collect and render various artifacts generated by other steps, such as:

  • User-provided documentation (e.g., Markdown files).

  • Source code documentation (component sources or generated by the auto-mocker).

  • Static analysis reports (from CppCheckCMakeGenerator).

  • Test and coverage reports (from GTestCMakeGenerator).

Use Case: Generating detailed documentation and quality assurance reports.

Configuration:

This generator is typically added as a step without specific configuration.

platforms:
  - name: report_platform
    generators:
      # It is recommended to run this generator after all other generators
      # that produce reports (e.g., GTest, CppCheck).
      - step: ReportCMakeGenerator
        module: yanga.cmake.reports

Auto-emitted targets#

Some targets are emitted by Yanga unconditionally — they do not need to be configured per platform in yanga.yaml.

<component>_clean#

For every component in the variant, Yanga emits a custom target that removes the component’s outputs without touching the rest of the variant:

cmake --build <variant_build_dir> --target <component>_clean

The target carries no DEPENDS, so invoking it never triggers a build. It removes:

  1. The per-component output namespace — ${CMAKE_BUILD_DIR}/<component>/. This is where generators (gtest, cppcheck, reports, …) write artifacts produced by tools cmake/ninja does not track (gcovr, sphinx-build, cmake -E copy_directory, …).

  2. CMake-derived outputs of tagged targets — for every add_library / add_executable whose generator passed component_name=<component>, the target removes the intermediate dir ${CMAKE_BUILD_DIR}/CMakeFiles/<target>.dir/ (object files, depfiles, link inputs) and, for executables, the runtime artifact $<TARGET_FILE:<target>>.

If you write a custom CMake generator that emits per-component add_library or add_executable, pass component_name=component.name so its outputs are picked up. Anything written outside both the per-component dir and a tagged cmake target’s own outputs is invisible to this target.

Variant-level add_library / add_executable outputs (e.g. the variant executable ${PROJECT_NAME}) are owned by the buildsystem’s own clean target, not by <component>_clean.

For a full wipe of the variant build directory (e.g. configure is broken after a variant rename or schema change) use yanga run --pristine, which removes the build dir from outside cmake before re-invoking the pipeline.