Skip to content

v1.2.0

Choose a tag to compare

@github-actions github-actions released this 21 Oct 22:07
· 72 commits to master since this release
v1.2.0
13a540f

🌟 Added

Delta builds

Delta builds have been restored after a temporary hiatus following a major refactoring for 1.0.0 (Restore delta test builds to Ceedling 1.0.0+).

A delta build is simply a build run that only performs regeneration, compilation, linking, or execution as needed because of changed files or configuration. Ceedling 1.0.0 introduced threaded parallel build steps but had to remove delta builds in the process. As of 1.2.0, both build speedups are now available. Delta builds are automatic with no configuration needed.

If a build requests a test to be built/run but no changes for it exist, its cached test results will be reported. The --force-test-rerun flag is available at the command line for any test-related tasks to force the delta build mechanism to rerun test executables and produce new test results.

Delta builds are fully integrated with test build plugins (e.g. GCov, Valgrind). Each runs its own build through the same test pipeline as an ordinary test build, under its own build context, so it benefits from the same staleness tracking within its own isolated dependency cache

#include relative paths & duplicate filename disambiguation

Added support for properly distinguishing all C files by filepath (addressing #1167 specifically but also the fundamental problem generally).

In Ceedling’s early history simplicity won out with the assumption that every C file would be uniquely named. But, for example, this meant dir1/foo.h and dir2/foo.h were indistiguishable and Ceedling “guessed” to disambiguate using the ordering of filepath collections. This worked, but there was no ability to use partial paths to explicitly select a specific file. Now Ceedling fully utilizes filepaths to distinguish all elements of a test build. Relative paths are supported in #include directives. test: build tasks at the command line can optionally include a filepath to distinguish test files of the same name. The previous convention still works where the ordering of paths is identical among compiler search paths and those used to find files for test builds, but now additional path information can be provided to target specific files in your source collection.

Partials filepaths & duplicate module name disambiguation

#1311 Added directory-qualified Partial directive macros so Partials share the filepath handling the rest of a test build gained in this release (see previous section).

Previously, Partial directive macros took only a bare module name with no means to provide path information to distinguish modules of the same name. Every Partials _MODULE and _CONFIG macro now has an _AT variant taking that module’s directory as a separate first argument (e.g. TEST_PARTIAL_PRIVATE_MODULE_AT(sensors/soil, Calibration)). As with #include directives elsewhere, the directory is matched against the trailing end of a real file’s path. Supply only as much of it as it takes to name the module you mean. A bare module name in the original macros continues to work unchanged.

A test file can now test two same-named modules together, and it can mock both of them too (see the next section).

Mocking same-named headers by directory

A test file can now mock two headers that share a filename, such as drivers/uart/config.h and drivers/spi/config.h, by including each mock through its folder (#include "drivers/uart/mock_config.h"). This works for traditional mocks, MOCK_PARTIAL_*_MODULE_AT() Partials, and the FFF plugin’s fakes. The new :cmock ↳ :mock_name_include_folder setting, enabled by default, names each mock’s internals by that folder so the two mocks no longer collide. It relies on matching features in CMock and Unity, which Ceedling’s vendored copies include.

Multiple file extensions per file type

Added support for multiple file extensions per type (e.g. :extension ↳ :source ⇒ ['.c', '.C']) such as requested in #947.

Dedicated mocks and test runner generation build tasks

Some users have asked for the ability to run the test build pipeline only up through generating mocks or test runners without running the rest of a build. This is now possible.

Tasks mirroring command line test: task invocation but with an early termination like test:build_only now exist:

Like with command line test: tasks, <test> can be all, a test file name, or a source file name that has a corresponding test file.

Test build fallback preprocessing improvements

If your toolchain’s preprocessor lacks certain features, Ceedling still attempts to extract information and code from C files through fallback text processing. In 1.1.0 this was exposed as a project configuration option mostly for Ceedling’s self-tests and also noted as a possible option should Ceedling’s probe for toolchain preprocessor features ever provide a false positive.

In 1.2.0, fallback preprocessing can now sometimes be used in projects with simple conditional compilation (e.g. #ifdef) as a faster alternative to full toolchain preprocessing. A test file’s #includes are now checked against a plain run of your toolchain’s preprocessor. A mock in an #if branch that is off no longer stops a build or replaces the real module it guards. Fallback preprocessing remains a best effort with no guarantees. Error messages will indicate if fallback preprocessing is insufficient for your project’s preprocessing needs.

Force fallback preprocessing with :test_build ↳ :preprocess_force_fallback but be sure to understand Ceedling’s test preprocessing before doing so.

Test case shuffling at runtime

Ceedling now integrates Unity’s features for randomizing test case execution within a test executable (PR #1041 via :unity ↳ :shuffle_tests ⇒ TRUE. If enabled, the behavior of delta builds automatically adjusts to always execute test executables even if no code changes have occurred. This ensures the randomization occurs when test executables would otherwise fail to run for lack of any code or configuration changes up the dependency tree.

Subtractive paths in TEST_SOURCE_FILE()

The TEST_SOURCE_FILE() build directive macro can now be used to remove source files from a test executable build using the same -: filepath decorator as available in :paths project configuration (ex. TEST_SOURCE_FILE("-:foo/bar/file.c")). This can be handy in overriding Ceedling’s conventions for associating source files with a test executable if your project structure does not match up with Ceedling’s conventions.

ceedling.yml as an alternate default project file

#1250 ceedling.yml is now recognized as an alternate default project filename alongside project.yml. Either name is loaded the same way; neither is preferred over the other. If both exist in the same directory, Ceedling raises an error. ceedling new continues to generate project.yml by default; pass --ceedling-yml to generate ceedling.yml instead. See Loading a Project Configuration.

ceedling dumpconfig gains a --stdout option

Running the dumpconfig application command to produce a fully resolved project configuration now supports an option to send the resulting YAML directly to $stdout instead of a filepath. This is one small step towards Ceedling support for working with other tooling (e.g. agentic coding tools) in future releases.

Gcov plugin

Gcovr raw custom arguments

#1159 Added :gcov ↳ :gcovr ↳ :custom_args:, a list of raw command line arguments passed straight through to gcovr. This is an escape hatch for any gcovr flag Ceedling has no named option for (e.g. limiting gcovr’s search root), mirroring the :report_generator ↳ :custom_args: option that already existed for the ReportGenerator side of the Gcov plugin. Unlike every other GCovr option, :custom_args: still applies even when :config_file is set.

Gcovr JaCoCo and LCOV reports

#963 Added JaCoCo to the Gcov plugin’s :reports, a JaCoCo XML coverage report generated by gcovr and importable by IDEs such as CLion. The existing lcov report, previously generated only by ReportGenerator, is now also generated by gcovr. Both require gcovr 7.0 or higher and come with options for pretty-printing, LCOV comments and test names, and artifact filenames.

ReportGenerator coverage-threshold parity

Added :gcov ↳ :report_generator ↳ :fail_under_line/:fail_under_branch/:fail_under_method/:fail_under_full_method, ReportGenerator’s own coverage-threshold options mirroring the Gcovr side’s existing :fail_under_* family. A configured threshold breaks the build in the same way as these options do with Gcovr.

Bullseye plugin

The Bullseye code coverage plugin using the commercial Bullseye tool is enabled again (disabled since 1.0.0). The makers of Bullseye generously provided a license in order to modernize the plugin.

The refreshed Bullseye plugin offers additional features over the original version including support for branch coverage detail, machine-readable coverage reports (XML flavors), and an optional coverage threshold that will break a test build.

Sanitize plugin

The new Sanitize plugin builds and runs tests with the compiler’s sanitizers. sanitize:all and its sibling tasks run AddressSanitizer, UndefinedBehaviorSanitizer, and LeakSanitizer in a build of their own, and :sanitize ↳ :test_builds instruments ordinary test: builds as well. The plugin’s flags never reach another plugin’s build, such as Gcov or Valgrind. A test a sanitizer stops fails with its finding named, such as AddressSanitizer heap-buffer-overflow at test/test_buffer.c:21, while a leak is reported as a finding without disturbing test results. Each test’s sanitizer reports are kept in a log of its own, :reports writes text, JSON, and SARIF reports, and :fail_build fails the build on any finding. The plugin runs on Linux and macOS; leak detection is Linux only.

Valgrind plugin

Cppcheck plugin

  • Added :cppcheck ↳ :fail_build: and :fail_build_severities: to break a build on findings. Cppcheck exits successfully even when it finds defects, so cppcheck:all previously could not fail a build at all. Only error severity fails by default, since whole project analysis always enables every check.
  • cppcheck:all now prints a per-severity tally of findings. Results previously landed only in report files, with nothing shown at the console.

Module Generator plugin

Dependencies plugin executables

#1110 A dependency can now list the programs it builds under :artifacts ↳ :executables for tools rather than libraries. A release build or dependencies:make builds them when missing, test builds do not wait on them, and they are never linked. dependencies:deploy copies them, along with dynamic libraries, to a new optional :paths ↳ :deploy folder, by default beside the release executable.

Build warnings plugin context, deduplication, and filtering

The Build Warnings Log plugin now logs each GCC or Clang warning with the lines that explain it — the function or include context before it along with the source line, caret, and any note after it. Each distinct warning is logged once per build context, so a header's warning appears once rather than once per file including it, and compiler summary lines are left out. New :patterns and :excludes settings optionally take regular expressions that replace the default match of any line mentioning “warning” and optionally drop warnings you have already accepted or prevent false positives.

Build warnings plugin SARIF and JSON reports

The Build Warnings Log plugin can now write its warnings as SARIF and JSON reports alongside, or instead of, its plain text log. SARIF, the standard format for static analysis results, lets GitHub code scanning, Azure DevOps, SonarQube, Jenkins, and IDE viewers show each warning on the line it concerns. The JSON report lists each warning’s file, line, column, severity, flag, message, and context for scripts. The new :reports setting selects any of :text, :sarif, and :json, and defaults to :text. The structured reports are written for every build context that ran a build step, even without warnings, so a CI step always finds its file.

JUnit report plugin test locations

#583 The Test Suite Report Log Factory plugin’s JUnit report now says where each test case lives. Each <testcase> carries classname, file, and line attributes, and a failure’s message starts with its file and line (e.g. test/TestUsartModel.c:44: ...). CI tools such as GitLab can then link a result to its code. classname keeps the test file’s path so same-named test files in different folders stay distinct. The new :junit ↳ :file_line_anchor option writes file as path#line for tools that follow that form.

GTest-like report plugin skipped tests

The GTest-like console report (report_tests_gtestlike_stdout) now reports a Unity test ignored with TEST_IGNORE() or TEST_IGNORE_MESSAGE() as a GoogleTest skipped test. A skipped test is listed with its location and message, counted in the run, and summarized between passed and failed tests, the way GoogleTest 1.10.0 and later reports GTEST_SKIP(). A test file whose every test is ignored now gets its own section. The new :report_tests_gtestlike_stdout ↳ :ignored_as_skipped: setting defaults to TRUE. Set it to FALSE to leave ignored tests out of the report for tools that do not understand skipped tests (see the related Changed entry below).

IDE report plugin formats

#633 The IDE console report (report_tests_ide_stdout) now lists failed and ignored tests in the shape of GCC diagnostics (e.g. test/TestModel.c:21:1: error: testInit: Expected 5 Was 4). Eclipse CDT, VS Code, CLion, and other tools that read GCC output show each failure as an error and each ignored test as a warning, linked to the test. The new :report_tests_ide_stdout ↳ :format setting defaults to :gcc. :legacy restores the earlier, simpler lines. :vscode, :eclipse, and :clion name the settings each IDE needs. The plugin documentation now covers set up for each of these IDEs (see the related Changed entry below).

Filepath limit checks

Platform filepath limits (especially on Windows) can lead to mysterious build failures, especially in CI where deep project subdirectories can occur. To help track down funny business, filepaths are intercepted and their lengths logged if they are nearing or exceed the platform limit.

Retry handling for child process generated file dependencies

In certain intervening circumstances, particularly on Windows, a child process may successfully generate a file that Ceedling expects to be present but OS-related issues (e.g. virus software, security checks, cloud storage syncing) delay from actually appearing in the file system. A new application-wide retry mechanism deals with the situations and fails properly if the delay exceeds the retry limit.

Windows test executable manifests

#146 #116 On Windows, Ceedling now writes a manifest beside each test executable to help ensure that any test filename can be run. The Installer Detection feature of User Account Control (UAC) otherwise demands administrator privileges for an executable whose name contains install, setup, update, or patch. A test filename containing one of these words is noted with a warning. Note that modern Windows compiler toolchains tend to
embed a manifest that prevents the privilege limitation; Ceedling’s external manifest is further insurance.

💪 Fixed

Note: 1.2.0 includes all bug fixes for 1.1.x.

  • A CLI parameter string mutation issue that could corrupt certain build or plugin task invocations.
  • Fixed a Unity TEST_IGNORE_MESSAGE() test case being misreported as crash evidence during crash-diagnosis retries when it shares a test file with a genuine crash.
  • #104 Fixed a literal [ or ] in a path being silently misread as a glob or regular expression syntax. This could drop files from a build with no error, cause issues with a :build_root entry, or cause a passing test run to be reported as "no tests executed."
  • #1083 Fixed a test file’s #include of a mock being dropped with :use_test_preprocessor set to :tests or :all when an #ifdef or #if around it depended on a macro defined in a header. The mock was never generated, and the build stopped on a missing mock header. The macro now decides the #include as it will at compile time, whether it reaches the test file through a header the test includes directly or through one it mocks.
  • #1267 Fixed a conditional #include whose target is a macro invocation (e.g. #include DEVICE_HEADER(x)) being silently dropped from includes extraction whenever its own guard condition depended on a symbol defined in another header.
  • #1292 Fixed an intermittent Errno::ENOTDIR/EISDIR crash when automatically vendoring Unity, CMock, and CException into a project’s build directory, caused by a transient file-system race (e.g. an antivirus/EDR lock, a cloud-sync filter driver, or a second concurrent Ceedling invocation). The copy step now retries transient races and self-heals a stale, wrong-typed leftover from a previous failed copy.
  • Fixed a rare, Ruby-version- and platform-dependent misordering of include lists and mixin environment variable resolution caused by relying on sort/sort_by’s ordering among tied elements, which Ruby does not guarantee to be stable.
  • Fixed two source files of the same name in one test executable sharing a single preprocessed intermediate file, so whichever was preprocessed second overwrote the first. Preprocessed files now mirror their source’s own directory, matching the convention compiled objects already follow.
  • Fixed a generated header’s fallback #include guard being built from a filename alone, so two same-named headers in one test shared one guard and whichever the compiler read second was emptied of its declarations.
  • Fixed a local release gem build packaging leftover build output from the machine that built it, including compiled object files and executables. Fixed the same packaging omitting the configuration file that the test suites bundled with the gem need in order to run at all. Since the release gem is produced in a clean CI environment the underlying issue never affected gems published through GitHub and RubyGems.org.

Backtrace / gdb handling

  • Fixed :use_backtrace ⇒ :gdb remaining active on a machine where gdb cannot actually attach to a process (e.g. lost macOS codesigning trust after a system update or Homebrew upgrade). Previously, Ceedling validated that gdb was available but not its ability to probe a process. Ceedling now detects a degraded gdb at build startup and falls back to :simple automatically, with a prominent warning for the condition.
  • Fixed handling for a crashed test executable that gdb could not usefully explain looking identical to an ordinary crash report. Ceedling now better detects this and prominently warns when this happens.

Partials

  • Fixed a bare, top-level macro invocation that expands to a full function definition (a common x-macro boilerplate idiom) silently corrupting or losing whatever construct followed it during Partials extraction.
  • Fixed a Partial resolving its module’s header and its module’s source independently, which could pair one module’s header with a same-named other module’s source.
  • Fixed a Partialized module’s own real header being reachable by its bare filename from inside the generated Partial, so a Partial could be compiled against a same-named other module’s header.

Mixins

  • Fixed priority / precedence issues with command line mixin edge case (same mixin provided multiple times).
  • Fixed mixin environment variable name matching issues such as a leading zero for 01 numbering or improperly matching on an environment variable similar to the mixin convention.
  • Fixed an edge case for tools: argument special handling merging involving a single string argument instead of list of arguments.

Reporting plugins

  • Fixed a thread-safety issue in report_build_warnings_log that could crash a multi-threaded build or produce an incomplete warnings log.
  • Fixed the GTest-like console report (report_tests_gtestlike_stdout) mislabeling ignored tests as passing and silently dropping their ignore message; its header and footer test counts could also disagree whenever a build had ignored tests.
  • Fixed the TeamCity console report (report_tests_teamcity_stdout) not escaping a real line break in a failure message, corrupting the TeamCity service message it produced.

report_tests_log_factory

Module Generator plugin

  • Fixed a path hint carrying over from one module to the next when a call names several, such as module:create[lab:First,Second].
  • Fixed several ordered hints such as lab:secret:lair creating a file named secret:lair rather than matching nested folders. A Windows drive letter in a hint now stays part of its path.
  • Fixed a hint failing the whole command when it matched no path of one kind. Files of that kind now go to its first path, and only a hint matching nothing at all stops the command. Headers go with the source when no include paths are listed.
  • Fixed any name beginning with test being taken as a test file, turning testimony into imony. Only a name carrying the configured :test_file_prefix asks for a test file alone.
  • Fixed module:stub ignoring the project’s :cmock settings and a subdirectory named with a slash, printing its configuration, and triggering a CMock warning about :includes.
  • Fixed :boilerplate_files changing the configured :boilerplates. A boilerplate file that does not exist now stops the command rather than being ignored.

Command Hooks plugin

Dependencies plugin

  • Fixed enabling the plugin making its fetch tools (unzip, tar, git, svn) and its :build_lib compiler and archiver requirements of every Ceedling command, including plain test:all. Each is now checked just before a dependency fetches or builds with it.
  • #1076 Fixed a second dependencies:fetch, or a dependencies:make after a fetch, failing because git clone ran into the already-populated folder. A dependency whose fetch path holds files now counts as fetched, and dependencies:clean allows a fresh fetch. Working paths are no longer created ahead of fetching, which made a clone into a fetch path containing the build path fail.
  • #1110 Fixed dependencies:deploy trying to copy a file named for the dependency rather than its dynamic libraries. It now copies every dynamic library from the artifact path beside the release executable.
  • Fixed a :tar_gzip fetch from an absolute Windows path failing with "Cannot connect to D: resolve failed" where GNU tar, as Git for Windows provides, came first on the path. GNU tar reads a path beginning with a drive letter as a remote host, so tar now reads the archive on its standard input.
  • Fixed a dependency's :environment variables lasting for the rest of the run, reaching every later dependency and Ceedling itself. They now apply only while that dependency's commands run. An entry not of the form NAME=value, NAME+=value, or NAME-=value now stops the build rather than being ignored. Text after += and -= now keeps its leading space, so an appended flag can carry the delimiter it needs.
  • Fixed a dependency without :artifacts crashing the build. Configuration problems now stop the build with a message naming the dependency: a missing name, a name without letters or digits, two names sharing a task name, an unknown fetch method, or a fetch method missing its :source or :executable.
  • Fixed an :includes glob under :artifacts expanding against the working directory rather than the artifact path, and joining every directory it found into one path.
  • Fixed :build_lib depending on the process working directory, and miscomputing where to copy its library when the :artifact path was absolute or climbed with ... The :deps_compiler tool now receives its search paths and defines as ${5} and ${6}, like Ceedling's own compilers.

Valgrind & Cppcheck plugins

  • Fixed enabling either plugin making its analysis tool a hard dependency of every Ceedling command, including plain test:all. Each tool is now required only by its own plugin’s tasks. ceedling files:cppcheck no longer needs Cppcheck installed either.

Valgrind plugin

  • Fixed memory errors being undercounted for a test that forks. Valgrind reports a separate error summary for each process it traces, and only the first was counted.
  • Fixed a test whose Valgrind report could not be read being treated as a clean result. Ceedling now warns that the memory error status is unknown.
  • Fixed the "Wrote N Valgrind report(s)" notice repeating with a different partial count for each test that found errors. It is reported once and counts the reports actually written.
  • Fixed settings other than :arguments configured under :tools ↳ :valgrind being silently discarded.
  • Fixed a valgrind: build’s test results report coming up empty. The plugin looked for results where an ordinary test: build writes them, not where its own build does.
  • Fixed --test-case and --exclude_test_case filters in a valgrind: build being handed to Valgrind rather than to the test executable.
  • A valgrind: task on a platform without Valgrind now explains that Valgrind runs on Linux and other Unix-like systems rather than only reporting a missing executable.

Cppcheck plugin

  • Fixed :cppcheck ↳ :xml_report_version defaulting to a version older Cppcheck releases reject outright, breaking the XML report on common installations. The default is now the version every release accepts.
  • Fixed requesting an html report making cppcheck-htmlreport mandatory, contradicting that tool’s own optional status.
  • Fixed cppcheck:all analyzing nothing and saying nothing when no report is configured, which read like a successful run. The plugin now explains what to configure.
  • Fixed a configuration list containing a single non-string entry silently disabling #{...} expansion for every other entry in that same list.
  • Fixed a misspelled path under :paths ↳ :cppcheck silently collecting no suppression files, indistinguishable from a directory holding none.

⚠️ Changed

Build warnings plugin :filename is a base name

The Build Warnings Log plugin’s :filename now names the base of each report, and each report adds its own extension (.log, .sarif, .json). Its default is warnings, so the text log is still warnings.log. A project that sets :filename with any extension will have that extension overwritten by the default associated with each report type.

Module Generator :naming takes effect

#518 The Module Generator plugin’s :naming setting now applies. Previously it had no effect, and every name kept the case typed. :naming no longer defaults to :snake, so a project that does not set it still sees names kept as typed. :bumpy and :camel produce the case their documentation describes (BumpyFiles, camelFiles). A project that sets :naming will see generated file names change.

Performance improvements

Optimizations and fixes have yielded a 5–10% speed increase for most builds before the second-run speedup of the new delta build abilities.

#include relative paths & duplicate filename disambiguation in test builds

Because of the support added for handling paths and distinguishing duplicated filenames, the functional interface for testing has changed.

  1. The interface for test-build command line tasks has expanded. If you need to distinguish foo/test_thing.c from bar/test_thing.c, you must now add a trailing path to disambiguate the tests — ceedling test:foo/thing and ceedling test:bar/thing. The trailing path is optional and is only required to distinguish test files of the same name in different subdirectories. Of course, the test files must both be in the collection created by your :paths and :extension configurations.
  2. Paths in #include directives are optional but available to direct Ceedling to the proper header file for your test build needs. This is especially useful to distinguish header files of the same name in your project. Without a path in an #include directive, Ceedling works identically to a compiler, selecting the first file among ordered search paths.

Use TEST_SOURCE_FILE() to override Ceedling’s .c / .h correspondence convention in tests

Historically, Ceedling automatically compiles and links into a test executable any C source file whose name matches an #included header file. Sometimes this convention can select the wrong file among same-named files or compile and link an entirely unwanted source file whose name happens to match a header file. Subtractive entries now allow this to be overridden (see more above).

Partials no longer silence CMock’s :treat_inlines project-wide

#1247 Enabling :use_partials previously turned off CMock’s :treat_inlines ⇒ :include option for every mock in every test in your project. This prevented unnecessary overhead and generation of files never used. However, this affected tests that used no Partials at all. Each mock now gets exactly the inline handling it needs on its own terms. A test using Partials gets Partials’ own handling for that mock, while every other mock keeps using whatever :treat_inlines setting you’ve configured.

A mock or Partial silently bypassed by its own real header

#1240 Added handling for edge cases where a mock or Partial could be silently bypassed by the real header these are meant to replace. Idiosyncrasies of C compilation search paths together with combinations of #include guards and #include ordering can lead to false negative test failures or outright crashes. Ceedling now discovers these scenarios on the other side of test compilation, rewires the test build to isolate the problematic header, and rebuilds with the fix in place. This intervention is only employed for shallow #include scenarios where this action is safe. More complex scenarios are prominently and proactively logged to provide hints on diagnosing failures that require more complex solutions than Ceedling should ever attempt to implement.

Guidance for a Partial colliding with its own module’s real header

#1247 Ceedling now recognizes when test compilation fails because a Partial’s generated content and its source module’s own real, un-Partialized header somehow both reached the compilation of the test fixture translation unit. Logging explains the likely cause and suggested solutions directly alongside the raw compiler error instead of leaving a confusing, bare redeclaration/conflicting types error.

Partials generation dependending on fallback preprocessing inadequaices

Partials generation now stops with an error if text-only fallback preprocessing cannot resolve a code element — an #include naming a macro or a type behind a conditional expression. The message names the file and line instead of the test build failing later with a confusing compiler or linker error.

report_build_warnings_log plugin warning lines

report_build_warnings_log’s log files now contain only the actual warning line(s) from a build step’s output, not that step’s entire lengthy console output whenever it happened to contain the word "warning."

Internal verbosity level mapping for Ceedling to CMock

Ceedling and CMock are interdependent but distinct tools. They each perform their own logging and have different verbosity level conventions. The internal mapping has been adjusted to configure CMock for verbosity levels that match the spirit of the selected top-level Ceedling logging verbosity level.

Smarter :flags and :defines matching for preprocessing overrides

Preprocessing flags and defines matchers now pass through to test compilation flags and defines for any matchers that are not defined. Previously, any preprocessing flags and defines matchers entirely overrode the test compilation flags and defines matchers. Now, you can selectively override them. Note that preprocessing flags and defines matchers are fairly specialized features used in rare cases.

Options that suppress preprocessor line markers are rejected

With test preprocessing enabled, Ceedling now stops at startup if -P or --no-line-commands appears in flags that reach preprocessing or in a preprocessing tool’s arguments. Test preprocessing reads the line markers these options remove to find #includes, mockable functions, and test cases. A preprocessor given either option still succeeds, so builds failed later with confusing errors or ran no tests at all. The error names each offending entry. Remember that :compile flags also apply to preprocessing wherever :preprocess flags do not.

Inline Ruby string expansion evaluates only #{…}

#289 Inline Ruby string expansion evaluates only the Ruby inside each #{…} and keeps all other text as written. Backslashes in Windows paths and quote marks around an expansion survive intact. Ruby escape sequences written outside #{…} (e.g. \" or \n in a single-quoted YAML string) are no longer interpreted.

Gcov console coverage summary names a module by path when needed

The Gcov plugin’s console summary labeled every file by filename alone, so a test covering two same-named modules produced two sets of figures with nothing to say which module either belonged to. Each label now carries as much trailing path as it takes to tell it apart from the other files in that same test’s summary. A filename that is already unique is labeled exactly as before.

More strict regex matching to exclude test artifacts from Gcov plugin coverage reports

Gcovr and ReportGenerator support within the GCov plugin now make use of more sophisticated and explicit regular expressions to filter out test files and test-build-generated files from coverage reporting. This helps prevent mistaken exclusions of source filenames with substrings (e.g. "_runner") that might otherwise match test filenames or generated files.

Test results report template filenames

The templates behind the $stdout test results reporting plugins have been renamed for what they produce. report_tests_pretty_stdout and report_tests_gtestlike_stdout now use assets/test_results.template, and the Bullseye plugin uses assets/coverage.template. The former assets/template.erb name is still honored, so a user-created custom plugin shipping that filename continues to work without changes.

Status line coloring for ceedling new, ceedling example, and ceedling upgrade

The create, exist, identical, and force status lines these commands print are now colored according to Ceedling’s own decoration settings rather than a separate scheme. Coloring also requires a terminal, so redirecting output to a file produces plain text. Set CEEDLING_DECORATORS to 0 to disable the coloring entirely.

Generated #include guard format

Ceedling writes #include guards into the headers it generates for test builds (e.g. Partials and reconstructed headers resulting from preprocessing). These guards now take the form GEN<hash>_<NAME>_H_CEEDLING (e.g. GEN2B4E27AE_DRIVERS_UART_CONFIG_H_CEEDLING), where the hash is derived from the header’s path. This format ensures uniqueness while conforming to the C standard’s reserved identifier and significant length rules (C99 §7.1.3, §5.2.4.1), MISRA C:2012 Rules 5.4 and 21.1, and CERT DCL37-C. Nothing in your project configuration or source code needs to change unless you referenced a generated guard by name.

GTest-like report plugin output matches GoogleTest

The GTest-like console report’s output now better matches GoogleTest’s own console format. Counts read in the singular for one (1 test, 1 FAILED TEST), test files are named test suites, and the run’s total time appears on its closing line. The failure list and its trailer appear only when a test fails. By default, ignored tests now appear in the report and its counts as skipped tests (see the related Added entry above). A tool that checks this report’s totals will see ignored tests counted unless :report_tests_gtestlike_stdout ↳ :ignored_as_skipped: is set to FALSE.

Valgrind builds stop on sanitizer flags

A test executable built with sanitizers cannot run under Valgrind. A valgrind: build uses :flags ↳ :test for any operation it has no flags of its own for, so sanitizer flags meant for test builds reached it. It now stops with a message naming the -fsanitize flags and how to keep them out. The Sanitize plugin instruments only its own builds.

Test case filters follow a custom test fixture tool’s arguments

--test-case, --exclude_test_case, and :simple backtrace filters now come after a :test_fixture tool’s own arguments rather than right after its executable. A wrapper tool runs the test executable as one of its arguments, so the filters now reach the test executable. The default test fixture tool has no arguments, so its command line is unchanged. A custom fixture tool with arguments after ${1} sees the filters move to the end of its command line.

IDE report plugin lines default to the GCC output format

The IDE console report’s failed and ignored tests now print as GCC diagnostics by default (see the related Added entry above). A multi-line message keeps its first line with the test’s location and indents the rest. The Gcov, Bullseye, and Valgrind plugins’ test results change the same way when this plugin is enabled. A script or tool that reads the earlier format needs :report_tests_ide_stdout ↳ :format: :legacy (see Breaking Changes).

👋 Removed

  • The erb gem dependency has been removed. Ceedling renders some of its plugin reports with a small template compiler of its own in place of erb. This reduces Ceedling’s external dependencies, simplifies installations where more recent versions of erb pull in further dependencies, and resolves security scanning findings against erb (CVE-2026-41316). Ceedling never used the feature that security advisory concerns, but carrying the dependency at all was enough to be flagged. Custom plugin templates are unaffected unless they use ERB syntax Ceedling itself never used — see plugin development documentation for the supported template syntax.
  • The Module Generator plugin no longer adds and removes generated files in Subversion, and its :update_svn setting is ignored with a deprecation warning. Add new files to source control with your own tools.