Ceedling Documentation

repository·master·Indexed 21 days ago

https://github.com/throwtheswitch/ceedling

A build system and test runner for C projects optimized for embedded and enterprise environments. Ceedling integrates Unity and CMock to support Test-Driven Development (TDD) workflows. Key features include the use of mixins for injecting symbols and configurations, Partials for testing static functions and variables, and the Platform Standin technique for simulating memory-mapped hardware registers in host environments. It provides flexible test execution via the `test:all`, `test:<FileName>`, and `test:pattern[<Pattern>]` commands.

Tokens
100.5K
Snippets
319
Records
513
Agent score
72%

What's inside Ceedling

  1. Overview of Ceedling

    master

    Ceedling is a build system for C projects designed to simplify building release targets and running unit test suites. It operates using a YAML project configuration and a command-line interface.

    Key components include:

    • Unity: A unit testing framework.
    • CMock: A mocking framework.
    • Plugins: Extensions for reporting, code coverage, static analysis, and more.

    Ceedling is designed to work across various platforms, from workstations to microcontrollers, making it a popular choice for embedded systems development.

  2. Overview of Ceedling Configuration Keys

    master

    Ceedling configuration is managed via a YAML file containing top-level keys that control different aspects of the build and test process. The configuration is organized into several functional areas:

    Project & Build Structure

    • :project: Global settings including build root, default tasks, parallelism, and release build toggles.
    • :mixins: Allows loading and merging additional YAML configuration files for composable builds.
    • :test_build: Settings specific to test suite builds, such as assembly file support.
    • :release_build: Settings for production/release artifacts, including output names and file copying.
    • :environment: Defines shell environment variables (supports inline Ruby string expansion) set before tools are invoked.

    Files, Paths & Extensions

    • :paths: Defines directory search paths for source, tests, headers, support files, and libraries. Supports globs and subtractive entries.
    • :files: Provides fine-grained control to add or subtract specific files from the collections assembled by :paths.
    • :extension: Allows overriding default filename extensions for source, header, object, assembly, and executable files.

    Compilation & Linking

    • :defines: Adds -D symbols to compiler command lines. Can be applied globally, to all tests, or to specific test executables using name, substring, or regex matchers.
    • :flags: Adds flags to the preprocessor, compiler, assembler, or linker. Supports global, all-test, or matcher-based application.
    • :libraries: Configures test, release, and system libraries for linking, including search paths and flag formats.

    Frameworks

    • :unity: Configures Unity behavior via compile-time symbols and parameterized test case support.
    • :cmock: Configures CMock code generation, strict ordering, and Unity helper paths.
    • :cexception: Configures CException behavior via compile-time symbols.
    • :test_runner: Options for Unity's test runner generation script, such as additional header includes.

    Tools & Extensions

    • :tools: Full definitions for build step tools (compiler, assembler, linker, test fixture).
    • :plugins: Enables built-in or custom plugins and specifies plugin load paths.
  3. Understand Ceedling project configuration

    master

    Ceedling projects are configured using a YAML project file. This file defines the build settings, test configurations, and toolchain parameters required for your C projects.

    Key concepts for managing configuration include:

    • Project File Structure: Uses YAML with specific Ceedling-specific handling for conventions and structure.
    • Configuration Loading: You can load configurations via command line flags, environment variables, or by placing a default filename in your working directory.
    • Mixins: Allows you to merge additional configuration into your base project configuration on demand. This is useful for managing build variants, local overrides, CI settings, or toolchain differences.
    • Global Collections: Provides globally available Ruby lists of paths and files, which is useful for advanced project customization and plugin development.
  4. Access Ceedling reference documentation

    master

    The Ceedling Reference section provides a quick-lookup for all technical components of the tool. It is organized into several specialized categories for rapid scanning:

    • Command Line: Application commands and build task syntax.
    • Project Configuration: Configuration sections, project loading, and using mixins to modify configurations.
    • Test Build Directives: Macros used to affect build configurations for specific individual test files.
    • Environment Variables: A list of all environment variables recognized by Ceedling.
    • Partials Macros: Macros for function selection and static variable access used with the Partials feature.
    • Coverage Reporting: Configuration options for the GCov plugin, including advanced reports via GCovr and ReportGenerator.
    • Global Collections: Globally-accessible Ruby constants available at startup.
  5. What is Ceedling?

    master

    Ceedling is a build system for C projects, specifically designed to facilitate unit testing and release builds. It acts as a glue layer that integrates two primary open-source tools:

    1. Unity: An xUnit-style test framework.
    2. CMock: A code generation kit for function mocking and stubbing to enable interaction-based testing.

    Additionally, Ceedling supports FFF (Fake Function Framework) via a plugin as an alternative to CMock.

  6. Use globs and subtractive entries in `:paths`

    master

    Ceedling supports glob patterns to specify directory patterns without listing every path individually. Globs in :paths match directories, not files.

    Glob Operators:

    • *: Standard wildcard. /* matches all subdirectories of depth 1 below the parent.
    • **: Matches all subdirectories recursively (e.g., /**).
    • ?: Matches a single alphanumeric character.
    • [x-y]: Matches a character within a specified range.
    • {x, y, ...}: Matches any of the comma-separated patterns.

    Special Convention: If a globified path ends with /* or /**, the resulting list of directories also includes the parent directory.

    Subtractive Entries: To exclude specific directories from a collection generated by a glob, use the -: prefix. While +: can be used for visual alignment, only -: performs subtraction.

    Note: Subtraction occurs after all Mixins are merged.

    :paths:
      :source:
        - +:project/src/**    # Recursive glob
        - -:project/src/exp   # Exclude experimental code
    
      :include:
        - +:project/src/**/inc
        - -:project/src/exp/inc
  7. When to use test file preprocessing

    master

    You do not need to enable preprocessing just because your files contain #ifdef statements. You only need it if those statements affect how Ceedling discovers the structure of your tests.

    Use test file preprocessing if:

    • #include statements are generated by macros.
    • #include statements are conditionally present due to #ifdef statements.
    • Test case function signatures are generated by macros.
    • Test case function signatures are conditionally present due to #ifdef statements.

    Do NOT use test file preprocessing if:

    • Conditional directives are used inside the test case functions (e.g., choosing which assertion to run). The standard C preprocessor in your toolchain handles this during the build phase without Ceedling needing to 'see' the expanded version for discovery.
    // NOT NEEDED: The toolchain handles this during compilation
    void test_some_test_case(void) {
    #ifdef BUILD_VARIANT_A
       TEST_ASSERT_EQUALS(...);
    #endif
    }
  8. Concept: Test builds vs. Release builds in Ceedling

    master

    This project demonstrates a workflow where Test builds and Release builds are handled differently using Ceedling:

    1. Test Builds: Driven by the :defines: :test: section in project.yml. Symbols are applied per-file using matchers so that each test executable is isolated and only sees the symbols it needs to exercise its specific logic.
    2. Release Builds: Driven by the :defines: :release: section. In this pattern, the base project.yml contains no release symbols. Instead, symbols are supplied externally at build time via mixins. This allows you to generate multiple different release binaries (e.g., a 'lite' version vs. a 'full' version) from the same source code without modifying the main configuration file.
  9. Use advanced `:defines` per-test matchers

    master

    In the :test and :preprocess contexts, you can define C symbols that apply only to specific test executables based on their filenames. This allows you to test the same source file under different conditional compilation configurations (e.g., enabling different features) by using different test files.

    Key behaviors:

    • Scope: Matchers apply to the test filename. When a match occurs, the specified symbols are added to the build step for all C files that are components of that matched test executable.
    • Cumulative Symbols: Symbols from multiple matchers are cumulative. If a test filename matches multiple matchers, all symbols from those matchers are applied.
    • Contexts: This advanced matching is only available in :test and :preprocess contexts. In other contexts like :release, :defines applies to all builds.
    # Example: Testing Comms.c with different feature sets
    :defines:
      :test:
        :CommsFeatureX:
          - FEATURE_X=ON
          - FEATURE_Z=OFF
        :CommsFeatureZ:
          - FEATURE_X=OFF
          - FEATURE_Z=ON
  10. Specify generation paths and directory hints

    master

    The Module Generator uses the :paths: defined in your project.yml. You can influence where files are placed using two methods:

    1. Directory Hints (Colon Syntax)

    Use a colon (:) to provide a hint. The generator will attempt to match this hint against your existing :paths: configuration.

    • ceedling module:create[lab:SecretLair] will attempt to place files in the lab/ subdirectory of your source/include/test paths.
    • Multiple hints can be used for nested structures: lab:secret:lair.

    2. Explicit Subdirectories (Slash Syntax)

    Use a slash (/) to force a specific subdirectory. If the subdirectory does not exist, the generator will create it.

    • ceedling module:create[newlab/SecretLair] will create src/newlab/SecretLair.c, inc/newlab/SecretLair.h, and test/newlab/TestSecretLair.c.

    3. Default Configuration

    You can override the default generation paths in project.yml using the :module_generator: key.

    :module_generator:
      :path_src: src/
      :path_inc: src/
      :path_tst: test/
  11. Understand Ceedling's core tool dependencies

    master

    Ceedling relies on several core technologies to manage builds and configuration:

    • Ruby: The scripting language used for Ceedling's automation and code generation tasks.
    • Rake: A Ruby utility used for dependency tracking and task automation (similar to Make). Note that Ceedling is gradually reducing its dependency on Rake.
    • YAML: A human-friendly data serialization standard used by Ceedling for project configuration. Ceedling supports advanced YAML features like anchors and aliases, and proactively flattens YAML lists to handle nesting caused by aliasing.
  12. How Partials are used in the `wondrous_forest` project

    master

    The wondrous_forest project is designed to demonstrate Ceedling's Partials feature. Partials allow you to test static functions, inline functions, static inline functions, and static variables that are normally inaccessible due to C linkage rules.

    This project acts as a reference implementation for various Partials patterns, ranging from simple public module testing to complex scenarios involving local variable access and mocking private functions.