ceedling 1.2.0 → 1.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (157) hide show
  1. checksums.yaml +4 -4
  2. data/GIT_COMMIT_SHA +1 -1
  3. data/README.md +47 -50
  4. data/Rakefile +3 -2
  5. data/bin/app_cfg.rb +21 -0
  6. data/bin/cli_handler.rb +7 -1
  7. data/bin/cli_helper.rb +5 -0
  8. data/docs/Changelog.md +10 -0
  9. data/docs/overrides/main.html +11 -8
  10. data/lib/ceedling/config/configurator.rb +5 -2
  11. data/lib/ceedling/config/configurator_setup.rb +26 -15
  12. data/lib/ceedling/file_wrapper.rb +56 -26
  13. data/lib/ceedling/rake_app/test_task_name.rb +29 -0
  14. data/lib/ceedling/rakefile.rb +1 -0
  15. data/lib/ceedling/rakefiles/tests/rules_tests.rake +3 -20
  16. data/lib/ceedling/rakefiles/tests/rules_tests_generate.rake +4 -30
  17. data/lib/ceedling/setupinator.rb +4 -0
  18. data/lib/ceedling/test_invoker/test_build_executor.rb +18 -1
  19. data/lib/version.rb +1 -1
  20. data/plugins/bullseye/bullseye.rake +6 -9
  21. data/plugins/gcov/gcov.rake +6 -9
  22. data/plugins/sanitize/sanitize.rake +6 -6
  23. data/plugins/valgrind/valgrind.rake +6 -6
  24. data/site-local/404.html +6 -20
  25. data/site-local/assets/javascripts/{bundle.d7400e89.min.js → bundle.c21346df.min.js} +3 -3
  26. data/site-local/assets/javascripts/{bundle.d7400e89.min.js.map → bundle.c21346df.min.js.map} +2 -2
  27. data/site-local/assets/javascripts/workers/{search.2c215733.min.js → search.a7633da7.min.js} +2 -2
  28. data/site-local/assets/javascripts/workers/{search.2c215733.min.js.map → search.a7633da7.min.js.map} +1 -1
  29. data/site-local/assets/stylesheets/main.57a0d79d.min.css +6 -0
  30. data/site-local/assets/stylesheets/main.57a0d79d.min.css.map +1 -0
  31. data/site-local/assets/stylesheets/palette.fb2fffe2.min.css +4 -0
  32. data/site-local/assets/stylesheets/palette.fb2fffe2.min.css.map +1 -0
  33. data/site-local/configuration/environment-vars.html +6 -20
  34. data/site-local/configuration/global-collections.html +6 -20
  35. data/site-local/configuration/index.html +6 -20
  36. data/site-local/configuration/loading.html +6 -20
  37. data/site-local/configuration/mixins.html +10 -24
  38. data/site-local/configuration/parallel-builds.html +6 -20
  39. data/site-local/configuration/project-file.html +8 -22
  40. data/site-local/configuration/reference/cexception.html +6 -20
  41. data/site-local/configuration/reference/cmock.html +6 -20
  42. data/site-local/configuration/reference/defines.html +16 -30
  43. data/site-local/configuration/reference/environment.html +10 -24
  44. data/site-local/configuration/reference/extension.html +6 -20
  45. data/site-local/configuration/reference/files.html +13 -27
  46. data/site-local/configuration/reference/flags.html +13 -27
  47. data/site-local/configuration/reference/index.html +6 -20
  48. data/site-local/configuration/reference/libraries.html +6 -20
  49. data/site-local/configuration/reference/mixins.html +6 -20
  50. data/site-local/configuration/reference/partials.html +6 -20
  51. data/site-local/configuration/reference/paths.html +11 -25
  52. data/site-local/configuration/reference/plugins.html +6 -20
  53. data/site-local/configuration/reference/project.html +16 -30
  54. data/site-local/configuration/reference/release-build.html +6 -20
  55. data/site-local/configuration/reference/test-build.html +6 -20
  56. data/site-local/configuration/reference/test-runner.html +6 -20
  57. data/site-local/configuration/reference/tools.html +18 -32
  58. data/site-local/configuration/reference/unity.html +6 -20
  59. data/site-local/configuration/which-ceedling.html +6 -20
  60. data/site-local/development/index.html +6 -20
  61. data/site-local/development/plugins/configuration.html +6 -20
  62. data/site-local/development/plugins/index.html +6 -20
  63. data/site-local/development/plugins/plugin-subclass.html +54 -68
  64. data/site-local/development/plugins/rake-tasks.html +8 -22
  65. data/site-local/development/releases.html +79 -28
  66. data/site-local/development/workflow.html +14 -28
  67. data/site-local/getting-started/builds.html +6 -20
  68. data/site-local/getting-started/command-line.html +6 -20
  69. data/site-local/getting-started/example-projects/cipher-quest.html +6 -20
  70. data/site-local/getting-started/example-projects/index.html +6 -20
  71. data/site-local/getting-started/example-projects/temp-sensor.html +6 -20
  72. data/site-local/getting-started/example-projects/wondrous-forest.html +6 -20
  73. data/site-local/getting-started/index.html +6 -20
  74. data/site-local/getting-started/installation.html +6 -20
  75. data/site-local/getting-started/quick-start.html +6 -20
  76. data/site-local/help.html +6 -20
  77. data/site-local/index.html +11 -24
  78. data/site-local/overview/build-system.html +6 -20
  79. data/site-local/overview/index.html +6 -20
  80. data/site-local/overview/test-environments.html +6 -20
  81. data/site-local/overview/tools-and-frameworks.html +6 -20
  82. data/site-local/plugins/beep.html +6 -20
  83. data/site-local/plugins/bullseye/index.html +13 -24
  84. data/site-local/plugins/bullseye/licensing.html +14 -28
  85. data/site-local/plugins/command-hooks.html +8 -22
  86. data/site-local/plugins/compile-commands-json-db.html +6 -20
  87. data/site-local/plugins/cppcheck.html +8 -22
  88. data/site-local/plugins/dependencies.html +10 -24
  89. data/site-local/plugins/fff.html +7 -21
  90. data/site-local/plugins/gcov/examples.html +7 -21
  91. data/site-local/plugins/gcov/gcovr.html +7 -21
  92. data/site-local/plugins/gcov/index.html +6 -20
  93. data/site-local/plugins/gcov/overview.html +9 -20
  94. data/site-local/plugins/gcov/reportgenerator.html +9 -23
  95. data/site-local/plugins/gcov/reporting.html +6 -20
  96. data/site-local/plugins/gcov/setup.html +6 -20
  97. data/site-local/plugins/gcov/tool-versions.html +6 -20
  98. data/site-local/plugins/gcov/troubleshooting.html +10 -24
  99. data/site-local/plugins/index.html +6 -20
  100. data/site-local/plugins/module-generator.html +21 -35
  101. data/site-local/plugins/report-build-warnings-log.html +53 -67
  102. data/site-local/plugins/report-tests-gtestlike-stdout.html +6 -20
  103. data/site-local/plugins/report-tests-ide-stdout.html +43 -57
  104. data/site-local/plugins/report-tests-log-factory.html +50 -64
  105. data/site-local/plugins/report-tests-pretty-stdout.html +7 -21
  106. data/site-local/plugins/report-tests-raw-output-log.html +6 -20
  107. data/site-local/plugins/report-tests-teamcity-stdout.html +16 -30
  108. data/site-local/plugins/sanitize.html +54 -64
  109. data/site-local/plugins/valgrind.html +46 -56
  110. data/site-local/project/index.html +6 -20
  111. data/site-local/project/release-history.html +6 -20
  112. data/site-local/project/sbom.html +6 -20
  113. data/site-local/project/upgrade.html +6 -20
  114. data/site-local/reference/build-directives.html +6 -20
  115. data/site-local/reference/command-line.html +6 -20
  116. data/site-local/reference/environment-vars.html +6 -20
  117. data/site-local/reference/gcov-plugin.html +6 -20
  118. data/site-local/reference/global-collections.html +6 -20
  119. data/site-local/reference/index.html +6 -20
  120. data/site-local/reference/partials-macros.html +6 -20
  121. data/site-local/reference/project-configuration.html +6 -20
  122. data/site-local/sitemap.xml.gz +0 -0
  123. data/site-local/snapshot/examples/cipher_quest/index.html +16 -30
  124. data/site-local/snapshot/examples/temp_sensor/index.html +8 -22
  125. data/site-local/snapshot/examples/wondrous_forest/index.html +6 -20
  126. data/site-local/testing-guide/build-directives.html +14 -28
  127. data/site-local/testing-guide/conventions.html +13 -27
  128. data/site-local/testing-guide/frameworks.html +11 -25
  129. data/site-local/testing-guide/index.html +6 -20
  130. data/site-local/testing-guide/partials/configuration.html +8 -22
  131. data/site-local/testing-guide/partials/conventions.html +8 -22
  132. data/site-local/testing-guide/partials/directives.html +16 -30
  133. data/site-local/testing-guide/partials/example.html +14 -28
  134. data/site-local/testing-guide/partials/index.html +6 -20
  135. data/site-local/testing-guide/partials/overview.html +6 -20
  136. data/site-local/testing-guide/partials/variables.html +11 -25
  137. data/site-local/testing-guide/test-cases.html +13 -27
  138. data/site-local/testing-guide/test-sample.html +12 -26
  139. data/site-local/testing-guide/test-suite-anatomy.html +6 -20
  140. data/spec/integration/configurator_pipeline_spec.rb +10 -0
  141. data/spec/integration/dependencies/dependency_tracker_core_spec.rb +40 -0
  142. data/spec/integration/rake_task_registry_plugins_spec.rb +95 -0
  143. data/spec/integration/vendor_copy_transient_io_retry_spec.rb +122 -74
  144. data/spec/support/integration/configurator_integration_helper.rb +4 -1
  145. data/spec/units/bin/app_cfg_spec.rb +10 -0
  146. data/spec/units/bin/cli_handler_spec.rb +2 -1
  147. data/spec/units/bin/cli_helper_spec.rb +10 -0
  148. data/spec/units/config/configurator_setup_spec.rb +61 -43
  149. data/spec/units/config/configurator_spec.rb +10 -1
  150. data/spec/units/file_wrapper_spec.rb +66 -27
  151. data/spec/units/rake_app/test_task_name_spec.rb +47 -0
  152. data/spec/units/test_build_executor_spec.rb +42 -2
  153. metadata +16 -11
  154. data/site-local/assets/stylesheets/main.ec1eaa64.min.css +0 -1
  155. data/site-local/assets/stylesheets/main.ec1eaa64.min.css.map +0 -1
  156. data/site-local/assets/stylesheets/palette.ab4e12ef.min.css +0 -1
  157. data/site-local/assets/stylesheets/palette.ab4e12ef.min.css.map +0 -1
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0610e698b34fe7dc61a65a1c455e28438cbe132bea10d85634b19fc791f5a293
4
- data.tar.gz: 4f9b3d43150358c366de44a33697aa58460601fe372311524a303351b43eaba4
3
+ metadata.gz: 1eb94c2d7bae641fd66962f23ab8ee145a73c635f0fd7a5ae5fb2d9602f2713a
4
+ data.tar.gz: 2a20e6e6da82880a3ba78464a872c92ccb1be79174385a806477133e116d2682
5
5
  SHA512:
6
- metadata.gz: acac7be5ef1b0b19eac71e189d178a39834405372ca4349cb529720bb3bc4a3fadfdbecf5e5fc462f5c72617052b3eddd0f334bf99a23a71fb576e7f247175fb
7
- data.tar.gz: 9da4d2e23f1a6c45392177449d633332389093ca75804e22af4bb29d5feed971c5783296513cc4e6bf49492f337f45a154efa991829b3753aecb448959886084
6
+ metadata.gz: 0a5e8b807216ea64535a94e5b7b1a4b005f84ece39c5c4dad3bebf5cb0febe7236a8c8db30716baa2ffc3db7b48df8dfb2b3e7e3cced0bd851c88528f5b6773b
7
+ data.tar.gz: 1e46b99eba0c0fa4a8e365719688d0d643a8338ce7d01e30c5a77c918e5f0ca151c37da0959006ff13d2b8ae904da95f9be19ffb9d1ebb17c6ccbafe55760e11
data/GIT_COMMIT_SHA CHANGED
@@ -1 +1 @@
1
- 13a540f
1
+ 47d2c5e
data/README.md CHANGED
@@ -1,25 +1,58 @@
1
- Ceedling [![OpenSSF Best Practices](https://www.bestpractices.dev/projects/15117/badge)](https://www.bestpractices.dev/projects/15117) [![Docs](https://img.shields.io/badge/Docs-white?logo=materialformkdocs&link=https%3A%2F%2Fdocs.throwtheswitch.org%2FCeedling%2F)](https://docs.throwtheswitch.org/Ceedling/) [![Discourse](https://img.shields.io/badge/Discourse-purple?logo=discourse&link=https%3A%2F%2Fthrowtheswitch.discourse.group)](https://throwtheswitch.discourse.group) ![CI](https://github.com/ThrowTheSwitch/Ceedling/workflows/CI/badge.svg)
1
+ [![OpenSSF Best Practices](https://www.bestpractices.dev/projects/15117/badge)](https://www.bestpractices.dev/projects/15117) [![Docs](https://img.shields.io/badge/Docs-white?logo=materialformkdocs&link=https%3A%2F%2Fdocs.throwtheswitch.org%2FCeedling%2F)](https://docs.throwtheswitch.org/Ceedling/) [![Discourse](https://img.shields.io/badge/Discourse-purple?logo=discourse&link=https%3A%2F%2Fthrowtheswitch.discourse.group)](https://throwtheswitch.discourse.group) ![CI](https://github.com/ThrowTheSwitch/Ceedling/workflows/CI/badge.svg)
2
2
  ========
3
3
 
4
- **Ceedling 1.2.0** is the latest and greatest.
4
+ # 🌱 Ceedling is a handy-dandy build system for C projects
5
+
6
+ ## Developer-friendly release _and_ test builds
5
7
 
6
- See [_Changelog_](docs/Changelog.md). [_Release Notes_][release-notes],
7
- [_Breaking Changes_][breaking-changes], and [_Known Issues_][known-issues] are
8
- not yet updated.
8
+ Ceedling can build your release artifact but is especially adept at building
9
+ unit test suites for your C projects — even in tricky embedded systems.
9
10
 
10
- See [🚀 Getting Started](#-getting-started) for installation and new
11
- project set up.
11
+ ⭐️ **Eager to just get going? Jump to
12
+ [📚 Documentation & Learning](#-documentation--learning) and
13
+ [🚀 Getting Started](#-getting-started).**
14
+
15
+ For a test suite project using the default toolchain `gcc`, Ceedling’s
16
+ configuration file could be as simple as this:
17
+
18
+ ```yaml
19
+ :project:
20
+ :build_root: project/build/
21
+
22
+ :paths:
23
+ :test:
24
+ - tests/**
25
+ :source:
26
+ - source/**
27
+ :include:
28
+ - inc/**
29
+ ```
30
+
31
+ To execute all your unit tests, you would run `ceedling test:all`. That‘s it!
32
+
33
+ Ceedling works the way developers want to work. It is flexible and entirely
34
+ command-line driven. It drives code generation and command line tools for you.
35
+ All generated and framework code is easy to see and understand.
36
+
37
+ Ceedling’s features support all types of C development from low-level embedded
38
+ to enterprise systems. No tool is perfect, but Ceedling can do a whole lot to
39
+ help you and your team produce quality software.
40
+
41
+ ## Ceedling 1.2.1 is the latest and greatest
42
+
43
+ See [_Changelog_](docs/Changelog.md), [_Release Notes_][release-notes], [_Breaking Changes_][breaking-changes], and [_Known Issues_][known-issues].
12
44
 
13
45
  **New goodies in 1.2.0:**
14
46
  * **[Delta builds][delta-builds]** have been restored after a temporary hiatus following a major refactoring for 1.0.0. A [delta build][delta-build-overview] is simply a build run that only performs regeneration, compilation, or linking as needed because of changed files. [Delta builds][delta-builds] are automatic with no configuration and complement [parallel builds][parallel-builds] introduced in 1.0.0 for build time speedups.
15
47
  * **`#include` relative paths & duplicate filename disambiguation**. Ceedling now fully supports [relative paths in `#include` directives][same-named-files] and [`TEST_SOURCE_FILE()` build directive macros][test-source-file]. Ceedling is now also able to distinguish files of the same name using paths in the preceding and [at the command line][test-path-task] to distinguish test files of the same name (e.g. `ceedling test:foo/file` vs. `ceedling test:bar/file`).
16
48
  * **Multiple file extensions per file type.** You may now provide a list of file types via [`:extensions`][extension-config] to gather files into your project’s build. For instance, the extensions `.c` and `.cc` can now both be used together to collect all source file in your project.
17
49
  * **Shuffled test order.** Ceedling now supports [Unity’s][unity-framework] randomized test case ordering (via a [`:unity` configuration setting][shuffle-tests]). [Delta builds][delta-builds] automatically adjust to always rerun test executables so test case ordering is shuffled.
18
- * The [`TEST_SOURCE_FILE()` build directive macro][test-source-file-subtractive] can now be used to remove source files from a test executable build. This can be handy in overriding [Ceedling’s conventions][header-source-convention] for associating source files with a test executable if your project structure does not match up with [Ceedling’s conventions][header-source-convention].
19
- * The [build warnings], [JUnit report], [IDE integration], [GoogleTest report], [module generator], and [dependencies] plugins all received numerous bug fixes and feature expansions.
20
- * [Bullseye code coverage plugin][bullseye-plugin] re-enabled and modernized (disabled since 1.0.0).
50
+ * The **[`TEST_SOURCE_FILE()` build directive macro][test-source-file-subtractive]** can now be used to remove source files from a test executable build. This can be handy in overriding [Ceedling’s conventions][header-source-convention] for associating source files with a test executable if your project structure does not match up with Ceedling’s conventions.
51
+ * The **new [Sanitize plugin][sanitize-plugin]** builds and runs tests with ASan, UBSan, and LeakSanitizer, naming each finding where a test fails and writing text, JSON, and SARIF reports.
52
+ * The **[build warnings]**, **[JUnit report]**, **[IDE integration]**, **[GoogleTest report]**, **[module generator]**, and **[dependencies]** plugins all received numerous bug fixes and feature expansions.
53
+ * **[Bullseye code coverage plugin][bullseye-plugin]** re-enabled and modernized (disabled since 1.0.0).
21
54
  * **Dedicated mocks and test runner generation build tasks.** It is now possible to run the test build pipeline only up through generating mocks or test runners without running the rest of a build using `ceedling gen:mocks:<test>` and `ceedling gen:test_runner:<test>` mirroring the convention of `test:` tasks.
22
- * Ceedling prerelease and release builds now automatically [generate Software Bills of Material][sbom-docs] (SBOMs) and attach them to GitHub pre/releases along with the final Ruby gem.
55
+ * Ceedling prerelease and release builds now automatically **[generate Software Bills of Material][sbom-docs]** (SBOMs) and attach them to GitHub pre/releases along with the final Ruby gem.
23
56
 
24
57
  **Goodness introduced in 1.1.0:**
25
58
  * A [Partial][partials-docs] allows a test to mix mocked and real functions
@@ -48,47 +81,11 @@ from the same source module in a single test file and enables testing of
48
81
  [GoogleTest report]: https://docs.throwtheswitch.org/Ceedling/1.2.0/plugins/report-tests-gtestlike-stdout/
49
82
  [module generator]: https://docs.throwtheswitch.org/Ceedling/1.2.0/plugins/module-generator/
50
83
  [dependencies]: https://docs.throwtheswitch.org/Ceedling/1.2.0/plugins/dependencies/
84
+ [sanitize-plugin]: https://docs.throwtheswitch.org/Ceedling/1.2.0/plugins/sanitize/
51
85
  [bullseye-plugin]: https://docs.throwtheswitch.org/Ceedling/1.2.0/plugins/bullseye/
52
86
  [sbom-docs]: https://docs.throwtheswitch.org/Ceedling/latest/project/sbom/
53
- [partials-docs]: https://throwtheswitch.github.io/Ceedling/1.1.0/testing-guide/partials/
54
- [ceedling-docs-site]: https://throwtheswitch.github.io/Ceedling/
55
-
56
- # 🌱 Ceedling is a handy-dandy build system for C projects
57
-
58
- ## Developer-friendly release _and_ test builds
59
-
60
- Ceedling can build your release artifact but is especially adept at building
61
- unit test suites for your C projects — even in tricky embedded systems.
62
-
63
- ⭐️ **Eager to just get going? Jump to
64
- [📚 Documentation & Learning](#-documentation--learning) and
65
- [🚀 Getting Started](#-getting-started).**
66
-
67
- For a test suite project using the default toolchain `gcc`, Ceedling’s
68
- configuration file could be as simple as this:
69
-
70
- ```yaml
71
- :project:
72
- :build_root: project/build/
73
-
74
- :paths:
75
- :test:
76
- - tests/**
77
- :source:
78
- - source/**
79
- :include:
80
- - inc/**
81
- ```
82
-
83
- To execute all your unit tests, you would run `ceedling test:all`. That‘s it!
84
-
85
- Ceedling works the way developers want to work. It is flexible and entirely
86
- command-line driven. It drives code generation and command line tools for you.
87
- All generated and framework code is easy to see and understand.
88
-
89
- Ceedling’s features support all types of C development from low-level embedded
90
- to enterprise systems. No tool is perfect, but Ceedling can do a whole lot to
91
- help you and your team produce quality software.
87
+ [partials-docs]: https://docs.throwtheswitch.org/Ceedling/1.1.0/testing-guide/partials/
88
+ [ceedling-docs-site]: https://docs.throwtheswitch.org/Ceedling/
92
89
 
93
90
  ## Supporting this work
94
91
 
data/Rakefile CHANGED
@@ -948,10 +948,11 @@ namespace :docs do
948
948
  end
949
949
 
950
950
  namespace :release do
951
- desc "Deploy release docs to Github Pages without and set it as 'latest'"
951
+ desc "Deploy release docs to Github Pages and set it as 'latest'"
952
952
  task :latest, [:version] => [:snapshot] do |t, args|
953
953
  version = args[:version] || raise("Version required: rake docs:deploy:release:latest[#.#.#]")
954
- venv_sh "mike deploy --push #{version} latest"
954
+ # --update-aliases moves 'latest' off whichever version currently holds it
955
+ venv_sh "mike deploy --push --update-aliases #{version} latest"
955
956
  end
956
957
  end
957
958
  end
data/bin/app_cfg.rb CHANGED
@@ -61,6 +61,11 @@ class CeedlingAppConfig
61
61
  # Default to task categry other than build/plugin tasks
62
62
  :build_tasks? => false,
63
63
 
64
+ # Whether the tasks build tests (test:, gcov:, ...) or a release, which decides what
65
+ # build/vendor needs
66
+ :test_build_tasks? => false,
67
+ :release_build_tasks? => false,
68
+
64
69
  # Default to `exit(1)` upon failing test cases
65
70
  :tests_graceful_fail? => false,
66
71
 
@@ -106,6 +111,14 @@ class CeedlingAppConfig
106
111
  @app_cfg[:build_tasks?] = enable
107
112
  end
108
113
 
114
+ def set_test_build_tasks(enable)
115
+ @app_cfg[:test_build_tasks?] = enable
116
+ end
117
+
118
+ def set_release_build_tasks(enable)
119
+ @app_cfg[:release_build_tasks?] = enable
120
+ end
121
+
109
122
  def set_tests_graceful_fail(enable)
110
123
  @app_cfg[:tests_graceful_fail?] = enable
111
124
  end
@@ -129,6 +142,14 @@ class CeedlingAppConfig
129
142
  return @app_cfg[:build_tasks?]
130
143
  end
131
144
 
145
+ def test_build_tasks?()
146
+ return @app_cfg[:test_build_tasks?]
147
+ end
148
+
149
+ def release_build_tasks?()
150
+ return @app_cfg[:release_build_tasks?]
151
+ end
152
+
132
153
  def tests_graceful_fail?()
133
154
  return @app_cfg[:tests_graceful_fail?]
134
155
  end
data/bin/cli_handler.rb CHANGED
@@ -234,11 +234,17 @@ class CliHandler
234
234
  )
235
235
 
236
236
  # Look up if any tasks we will execute are build tasks
237
- build_tasks = @helper.build_task?( tasks: (tasks.empty? ? default_tasks : tasks ) )
237
+ requested = (tasks.empty? ? default_tasks : tasks)
238
+ build_tasks = @helper.build_task?( tasks: requested )
238
239
 
239
240
  # Enable setup / operations duration logging in Rake context if build tasks are being invoked
240
241
  app_cfg.set_build_tasks( build_tasks )
241
242
 
243
+ # Only a build populates build/vendor, so a command that only reads the project leaves a
244
+ # concurrent build's vendored files alone
245
+ app_cfg.set_test_build_tasks( @helper.test_task?( tasks: requested ) )
246
+ app_cfg.set_release_build_tasks( @helper.release_task?( tasks: requested ) )
247
+
242
248
  _, path = @helper.which_ceedling?( env:env, config:config, app_cfg:app_cfg )
243
249
 
244
250
  # Log Ceedling Application version information
data/bin/cli_helper.rb CHANGED
@@ -329,6 +329,11 @@ class CliHelper
329
329
  end
330
330
 
331
331
 
332
+ def release_task?(tasks:)
333
+ return tasks.any? { |task| @registry.task_is?( task, RakeTaskRegistry::TAG_RELEASE ) }
334
+ end
335
+
336
+
332
337
  def print_rake_tasks()
333
338
  # This all required digging into Rake internals a bit.
334
339
 
data/docs/Changelog.md CHANGED
@@ -10,6 +10,16 @@ This changelog is complemented by three other documents:
10
10
 
11
11
  ---
12
12
 
13
+ # [1.2.1] — 2026-10-24
14
+
15
+ ## 💪 Fixed
16
+
17
+ - [#1360](https://github.com/ThrowTheSwitch/Ceedling/issues/1360) Fixed a delta build reporting another run’s cached test results when the [`--test-case` or `--exclude_test_case`](https://docs.throwtheswitch.org/Ceedling/1.2.0/getting-started/command-line/#ceedling-test-test-casetest_case_name) filter changed between runs. It affected every project whose [`:use_backtrace`](https://docs.throwtheswitch.org/Ceedling/1.2.0/configuration/reference/project/#use_backtrace) is not `:none`, including the `:simple` default. A changed filter now reruns the test executable without recompiling or relinking it. An unchanged filter still reuses the cached results.
18
+ - [#1361](https://github.com/ThrowTheSwitch/Ceedling/issues/1361) Fixed every command that loads a project, `files:test` and `dumpconfig` included, rewriting the vendored Unity, CMock, and CException sources in `build/vendor/` in place. A second command run while a build compiled could leave the compiler reading a half-written header. Only a test build or release build now brings `build/vendor/` up to date. A vendored file that already matches its source is no longer written, and one that differs (e.g. after an accidental edit) is replaced whole.
19
+ - [#1362](https://github.com/ThrowTheSwitch/Ceedling/issues/1362) Fixed [`gcov:`](https://docs.throwtheswitch.org/Ceedling/1.2.0/plugins/gcov/), [`valgrind:`](https://docs.throwtheswitch.org/Ceedling/1.2.0/plugins/valgrind/), [`sanitize:`](https://docs.throwtheswitch.org/Ceedling/1.2.0/plugins/sanitize/), and [`bullseye:`](https://docs.throwtheswitch.org/Ceedling/1.2.0/plugins/bullseye/) single-file tasks rejecting a project-relative path, such as `gcov:test/test_calculator.c`. They now accept a path to tell same-named test files apart, as [`test:` tasks](https://docs.throwtheswitch.org/Ceedling/1.2.0/getting-started/command-line/#ceedling-test) do.
20
+
21
+ ---
22
+
13
23
  # [1.2.0] — 2026-10-21
14
24
 
15
25
  ## 🌟 Added
@@ -4,11 +4,14 @@
4
4
  Material's own `outdated`/`announce` blocks (base.html) ship empty by
5
5
  default -- both are opt-in via a project template override like this one.
6
6
 
7
+ Material only renders a block's wrapping banner markup when the block
8
+ produces non-empty output, and whitespace alone counts as output. The
9
+ `{%- -%}` whitespace control below is load-bearing: without it the
10
+ indentation around each `if` leaks out, rendering an empty banner (a blank
11
+ dark bar for `announce`) even when the condition is false.
12
+
7
13
  `outdated`: the standard "you're not viewing the latest version" warning
8
- banner. Material only renders its wrapping markup when this block actually
9
- produces non-empty output, so suppressing it here for prerelease pages
10
- (rather than just leaving the block's *content* blank) is what keeps the
11
- banner from appearing at all on those pages.
14
+ banner, suppressed entirely on prerelease pages.
12
15
 
13
16
  `announce`: a separate announcement bar, used here to carry the prerelease
14
17
  notice instead. `extra.prerelease` is set to `true` only in
@@ -17,16 +20,16 @@
17
20
  #}
18
21
 
19
22
  {% block outdated %}
20
- {% if not config.extra.prerelease %}
23
+ {%- if not config.extra.prerelease -%}
21
24
  You are not viewing the latest version.
22
25
  <a href="{{ '../' ~ base_url }}">
23
26
  <strong>Click here to go to latest.</strong>
24
27
  </a>
25
- {% endif %}
28
+ {%- endif -%}
26
29
  {% endblock %}
27
30
 
28
31
  {% block announce %}
29
- {% if config.extra.prerelease %}
32
+ {%- if config.extra.prerelease -%}
30
33
  This is prerelease documentation for an upcoming Ceedling release.
31
- {% endif %}
34
+ {%- endif -%}
32
35
  {% endblock %}
@@ -16,7 +16,8 @@ require 'deep_merge'
16
16
  class Configurator
17
17
 
18
18
  attr_reader :project_config_hash, :programmatic_plugins, :rake_plugins
19
- attr_accessor :project_logging, :sanity_checks, :include_test_case, :exclude_test_case, :force_test_rerun
19
+ attr_accessor :project_logging, :sanity_checks, :include_test_case, :exclude_test_case, :force_test_rerun,
20
+ :test_build_tasks, :release_build_tasks
20
21
 
21
22
  constructor :configurator_setup, :configurator_builder, :configurator_plugins, :config_walkinator, :yaml_wrapper, :system_wrapper, :loginator, :reportinator, :ruby_expandinator
22
23
 
@@ -431,7 +432,9 @@ class Configurator
431
432
  @configurator_setup.build_directory_structure( flattened_config )
432
433
 
433
434
  # Copy Unity, CMock, CException into vendor directory within build directory
434
- @configurator_setup.vendor_frameworks_and_support_files( ceedling_lib_path, flattened_config )
435
+ @configurator_setup.vendor_frameworks_and_support_files(
436
+ ceedling_lib_path, flattened_config, test_build: @test_build_tasks == true, release_build: @release_build_tasks == true
437
+ )
435
438
  @configurator_setup.build_project_collections( flattened_config )
436
439
 
437
440
  @project_config_hash = flattened_config.clone
@@ -83,23 +83,19 @@ class ConfiguratorSetup
83
83
  @file_wrapper.rm_rf( path )
84
84
  end
85
85
 
86
- # Copies the frameworks a build uses into build/vendor, and the support files its
87
- # features need. Copies always, every run. An errant edit beneath build/vendor/, by hand,
88
- # an IDE, or an automated agent, is overwritten from the canonical source by the next build.
89
- def vendor_frameworks_and_support_files(ceedling_lib_path, flattened_config)
90
- vendored_frameworks( flattened_config ).each do |source, destination, marker_file|
86
+ # Brings build/vendor up to date with the frameworks and support files a build needs. Only
87
+ # a build does this, so a command that only reads the project leaves a concurrent build's
88
+ # files alone. A file that already matches its source is not written, and one that differs,
89
+ # such as an errant edit by hand, an IDE, or an automated agent, is replaced whole.
90
+ #
91
+ # A release build needs only CException, and that only when exceptions are enabled.
92
+ def vendor_frameworks_and_support_files(ceedling_lib_path, flattened_config, test_build:, release_build:)
93
+ frameworks_for_build( flattened_config, test_build: test_build, release_build: release_build ).each do |source, destination, marker_file|
91
94
  heal_vendor_path( destination, marker_file )
92
- # '/.' to cause cp_r to copy directory contents
93
- @file_wrapper.cp_r_with_retry( File.join( source, '/.' ), destination )
95
+ @file_wrapper.sync_tree( source, destination )
94
96
  end
95
97
 
96
- copy_backtrace_script( ceedling_lib_path, flattened_config ) if flattened_config[:project_use_backtrace] == :gdb
97
-
98
- # Copy supporting partials code into build/vendor directory structure
99
- @file_wrapper.cp_r(
100
- File.join( ceedling_lib_path, CEEDLING_HEADER_FILEPATH ),
101
- flattened_config[:project_build_vendor_ceedling_path]
102
- ) if flattened_config[:project_use_partials]
98
+ vendor_test_support_files( ceedling_lib_path, flattened_config ) if test_build
103
99
  end
104
100
 
105
101
  # Tests are collected after path collections, both to merge and to filter out of sources
@@ -334,11 +330,26 @@ class ConfiguratorSetup
334
330
  return frameworks
335
331
  end
336
332
 
333
+ def frameworks_for_build(config, test_build:, release_build:)
334
+ return vendored_frameworks( config ) if test_build
335
+ return vendored_frameworks( config ).select { |_, _, marker_file| marker_file == CEXCEPTION_C_FILE } if release_build
336
+
337
+ return []
338
+ end
339
+
340
+ def vendor_test_support_files(ceedling_lib_path, config)
341
+ copy_backtrace_script( ceedling_lib_path, config ) if config[:project_use_backtrace] == :gdb
342
+
343
+ return unless config[:project_use_partials]
344
+
345
+ @file_wrapper.sync_file( File.join( ceedling_lib_path, CEEDLING_HEADER_FILEPATH ), config[:project_build_vendor_ceedling_path] )
346
+ end
347
+
337
348
  # The destination may not exist yet on a fresh build, since Rake creates directories
338
349
  # after configuration
339
350
  def copy_backtrace_script(ceedling_lib_path, flattened_config)
340
351
  @file_wrapper.mkdir( flattened_config[:project_build_tests_root] )
341
- @file_wrapper.cp_r( File.join( ceedling_lib_path, BACKTRACE_GDB_SCRIPT_FILE ), flattened_config[:project_build_tests_root] )
352
+ @file_wrapper.sync_file( File.join( ceedling_lib_path, BACKTRACE_GDB_SCRIPT_FILE ), flattened_config[:project_build_tests_root] )
342
353
  end
343
354
 
344
355
  def validate_simple_paths(paths, *keys)
@@ -238,36 +238,39 @@ class FileWrapper
238
238
  false
239
239
  end
240
240
 
241
- # As #cp_r, but retries the whole copy on a transient OS-level error instead of
242
- # surfacing it on the first attempt -- the same transient-visibility race
243
- # #open_with_retry guards against, here hitting FileUtils.cp_r's own internal
244
- # stat-then-open sequence on either the source or destination tree. A source/dest
245
- # entry briefly reporting the wrong type (a directory where a file was just stat'd,
246
- # or vice versa) mid-copy raises Errno::ENOTDIR/EISDIR from deep inside cp_r; a
247
- # retry a moment later re-walks the tree fresh rather than trusting stale type info
248
- # from the failed attempt. A failure that never clears still surfaces as a
249
- # CeedlingException naming the destination and how many attempts were made, not a
250
- # bare, unhelpful Errno.
251
- def cp_r_with_retry(source, destination, options={})
252
- attempts_remaining = TRANSIENT_IO_RETRY_DELAYS.dup
253
- begin
254
- cp_r(source, destination, options)
255
- rescue SystemCallError => e
256
- if attempts_remaining.empty?
257
- msg = "Failed to copy into '#{destination}' after #{TRANSIENT_IO_RETRY_DELAYS.size} retries ⏩️ #{e.message}\n" \
258
- "This path may be corrupted (a file exists where Ceedling expects a directory, or vice versa). " \
259
- "Try deleting this project's build/ directory and rebuilding -- or, if the error names a path " \
260
- "under your Ruby gem install, reinstall the ceedling gem."
261
- @loginator.log(msg, Verbosity::ERRORS)
262
- raise CeedlingException, msg
241
+ # Brings every file beneath source_dir up to date beneath destination_dir. A file that
242
+ # already matches its source is not written, so a reader elsewhere never sees it change. One
243
+ # that differs or is missing is replaced whole (see #replace_file). Files the destination
244
+ # has beyond the source are left alone.
245
+ #
246
+ # A transient OS-level error retries the whole pass: a path briefly reporting the wrong type
247
+ # mid-copy, or on Windows a file another process holds open. A failure that never clears
248
+ # surfaces as a CeedlingException naming the destination, not a bare Errno.
249
+ def sync_tree(source_dir, destination_dir)
250
+ with_copy_retry( destination_dir ) do
251
+ Dir.glob( '**/*', File::FNM_DOTMATCH, base: source_dir ).each do |relative|
252
+ source = File.join( source_dir, relative )
253
+ sync_one( source, File.join( destination_dir, relative ) ) if File.file?( source )
263
254
  end
264
- delay = attempts_remaining.shift
265
- @loginator.log("Retrying copy into '#{destination}' after a transient error: #{e.message}", Verbosity::DEBUG)
266
- sleep(delay)
267
- retry
268
255
  end
269
256
  end
270
257
 
258
+ # As #sync_tree, for a single file copied into destination_dir
259
+ def sync_file(source, destination_dir)
260
+ with_copy_retry( destination_dir ) { sync_one( source, File.join( destination_dir, File.basename( source ) ) ) }
261
+ end
262
+
263
+ # Copies source to a temporary name beside destination, then renames it over destination.
264
+ # A concurrent reader sees the old file or the new one, never a partial one.
265
+ def replace_file(source, destination)
266
+ temp = File.join( File.dirname( destination ), ".#{File.basename( destination )}.#{Process.pid}.#{Thread.current.object_id}.tmp" )
267
+ check_path_length( temp, origin: 'FileWrapper#replace_file' )
268
+ FileUtils.cp( source, temp )
269
+ File.rename( temp, destination )
270
+ ensure
271
+ FileUtils.rm_f( temp ) if temp
272
+ end
273
+
271
274
  def read(filepath, length=nil)
272
275
  return File.read(filepath, length)
273
276
  end
@@ -371,6 +374,33 @@ class FileWrapper
371
374
 
372
375
  private
373
376
 
377
+ def sync_one(source, destination)
378
+ return if File.file?( destination ) && File.size( source ) == File.size( destination ) && FileUtils.compare_file( source, destination )
379
+
380
+ FileUtils.mkdir_p( File.dirname( destination ) )
381
+ replace_file( source, destination )
382
+ end
383
+
384
+ def with_copy_retry(destination)
385
+ attempts_remaining = TRANSIENT_IO_RETRY_DELAYS.dup
386
+ begin
387
+ yield
388
+ rescue SystemCallError => e
389
+ if attempts_remaining.empty?
390
+ msg = "Failed to copy into '#{destination}' after #{TRANSIENT_IO_RETRY_DELAYS.size} retries ⏩️ #{e.message}\n" \
391
+ "This path may be corrupted (a file exists where Ceedling expects a directory, or vice versa). " \
392
+ "Try deleting this project's build/ directory and rebuilding -- or, if the error names a path " \
393
+ "under your Ruby gem install, reinstall the ceedling gem."
394
+ @loginator.log(msg, Verbosity::ERRORS)
395
+ raise CeedlingException, msg
396
+ end
397
+ delay = attempts_remaining.shift
398
+ @loginator.log("Retrying copy into '#{destination}' after a transient error: #{e.message}", Verbosity::DEBUG)
399
+ sleep(delay)
400
+ retry
401
+ end
402
+ end
403
+
374
404
  def path_length_limit
375
405
  return PATH_LENGTH_LIMITS[:windows] if SystemWrapper.windows?
376
406
  return PATH_LENGTH_LIMITS[:macos] if SystemWrapper.macos?
@@ -0,0 +1,29 @@
1
+ # =========================================================================
2
+ # Ceedling - Test-Centered Build System for C
3
+ # ThrowTheSwitch.org
4
+ # Copyright (c) 2010-26 Mike Karlesky, Mark VanderVoord, & Greg Williams
5
+ # SPDX-License-Identifier: MIT
6
+ # =========================================================================
7
+
8
+ # Turns a per-file test task's name (test:, gen:mocks:, gcov:, valgrind:, and the rest) into
9
+ # the test name file lookup needs. A directory typed ahead of the name tells same-named tests
10
+ # apart, so it is kept, and only the file name gets the test file prefix.
11
+ module TestTaskName
12
+
13
+ def self.test_name(task_name, root:, extensions: EXTENSION_SOURCE, prefix: PROJECT_TEST_FILE_PREFIX)
14
+ test = task_name.strip.delete_prefix( root )
15
+
16
+ # At most one configured extension ends the name, so trying each in turn is safe
17
+ extensions.each { |ext| test = test.chomp( ext ) }
18
+
19
+ # A Windows-style name under a POSIX Ruby (WSL, Cygwin) has backslashes File won't split on
20
+ test = test.tr( '\\', '/' )
21
+
22
+ dir = File.dirname( test )
23
+ base = File.basename( test )
24
+ base = prefix + base unless base.start_with?( prefix )
25
+
26
+ return (dir == '.') ? base : File.join( dir, base )
27
+ end
28
+
29
+ end
@@ -23,6 +23,7 @@ Rake::TaskManager.record_task_metadata = true
23
23
 
24
24
  require 'ceedling/system_wrapper'
25
25
  require 'ceedling/reportinator'
26
+ require 'ceedling/rake_app/test_task_name'
26
27
 
27
28
  # Operation duration logging
28
29
  def log_runtime(run, start_time_s, end_time_s, enabled)
@@ -9,26 +9,9 @@ namespace TEST_SYM do
9
9
  # Use rules to increase efficiency for large projects (instead of iterating through all sources and creating defined tasks)
10
10
  rule(/^#{TEST_TASK_ROOT}\S+$/ => [ # Test task names by regex
11
11
  proc do |task_name|
12
- # Yield clean test name => Strip the task string, remove Rake test task prefix, and remove any code file extension.
13
- # Only one configured source extension can actually be present at the end of a given
14
- # task name, so trying each in turn is safe -- chomp is a no-op for the ones that don't match.
15
- # Whatever directory the invoker typed ahead of the name (e.g. `test:unit/test_foo.c`)
16
- # is left exactly as given -- it's not decoration, it's what disambiguates one test
17
- # from another same-named test elsewhere in the project.
18
- test = task_name.strip().sub(/^#{TEST_TASK_ROOT}/, '')
19
- EXTENSION_SOURCE.each { |ext| test = test.chomp( ext ) }
20
-
21
- # Normalized to forward slashes so a directory the invoker typed with backslashes
22
- # (a Windows-style task name run under a POSIX Ruby, e.g. WSL or Cygwin, where
23
- # File.dirname/basename below don't treat '\' as a separator) still splits correctly.
24
- test = test.tr( '\\', '/' )
25
-
26
- # Ensure the test name's own basename begins with the test file prefix, without
27
- # disturbing any directory the invoker supplied ahead of it.
28
- dir = File.dirname( test )
29
- base = File.basename( test )
30
- base = PROJECT_TEST_FILE_PREFIX + base if not (base.start_with?( PROJECT_TEST_FILE_PREFIX ))
31
- test = (dir == '.') ? base : File.join( dir, base )
12
+ # Any directory typed ahead of the name (e.g. `test:unit/test_foo.c`) is kept, since it
13
+ # tells one test from a same-named test elsewhere. See TestTaskName.
14
+ test = TestTaskName.test_name( task_name, root: TEST_TASK_ROOT )
32
15
 
33
16
  # Provide the filepath for the target test task back to the Rake task
34
17
  @ceedling[:file_finder].find_test_file_from_name( test )
@@ -21,26 +21,9 @@ namespace GEN_SYM do
21
21
  # Use a rule to increase efficiency for large projects (instead of iterating through all sources and creating defined tasks)
22
22
  rule(/^#{GENERATE_MOCKS_TASK_ROOT}\S+$/ => [ # Task names by regex
23
23
  proc do |task_name|
24
- # Yield clean test name => Strip the task string, remove Rake task prefix, and remove any code file extension.
25
- # Only one configured source extension can actually be present at the end of a given
26
- # task name, so trying each in turn is safe -- chomp is a no-op for the ones that don't match.
27
- # Whatever directory the invoker typed ahead of the name (e.g. `gen:mocks:unit/foo.c`)
28
- # is left exactly as given -- it's not decoration, it's what disambiguates one test
29
- # from another same-named test elsewhere in the project.
30
- test = task_name.strip().sub(/^#{GENERATE_MOCKS_TASK_ROOT}/, '')
31
- EXTENSION_SOURCE.each { |ext| test = test.chomp( ext ) }
32
-
33
- # Normalized to forward slashes so a directory the invoker typed with backslashes
34
- # (a Windows-style task name run under a POSIX Ruby, e.g. WSL or Cygwin, where
35
- # File.dirname/basename below don't treat '\' as a separator) still splits correctly.
36
- test = test.tr( '\\', '/' )
37
-
38
- # Ensure the test name's own basename begins with the test file prefix, without
39
- # disturbing any directory the invoker supplied ahead of it.
40
- dir = File.dirname( test )
41
- base = File.basename( test )
42
- base = PROJECT_TEST_FILE_PREFIX + base if not (base.start_with?( PROJECT_TEST_FILE_PREFIX ))
43
- test = (dir == '.') ? base : File.join( dir, base )
24
+ # Any directory typed ahead of the name (e.g. `gen:mocks:unit/foo.c`) is kept, since it
25
+ # tells one test from a same-named test elsewhere. See TestTaskName.
26
+ test = TestTaskName.test_name( task_name, root: GENERATE_MOCKS_TASK_ROOT )
44
27
 
45
28
  # Provide the filepath for the target test task back to the Rake task
46
29
  @ceedling[:file_finder].find_test_file_from_name( test )
@@ -56,16 +39,7 @@ namespace GEN_SYM do
56
39
  # Use a rule to increase efficiency for large projects (instead of iterating through all sources and creating defined tasks)
57
40
  rule(/^#{GENERATE_TEST_RUNNER_TASK_ROOT}\S+$/ => [ # Task names by regex
58
41
  proc do |task_name|
59
- # See gen:mocks's identical rule above for a full explanation of this resolution.
60
- test = task_name.strip().sub(/^#{GENERATE_TEST_RUNNER_TASK_ROOT}/, '')
61
- EXTENSION_SOURCE.each { |ext| test = test.chomp( ext ) }
62
-
63
- test = test.tr( '\\', '/' )
64
-
65
- dir = File.dirname( test )
66
- base = File.basename( test )
67
- base = PROJECT_TEST_FILE_PREFIX + base if not (base.start_with?( PROJECT_TEST_FILE_PREFIX ))
68
- test = (dir == '.') ? base : File.join( dir, base )
42
+ test = TestTaskName.test_name( task_name, root: GENERATE_TEST_RUNNER_TASK_ROOT )
69
43
 
70
44
  @ceedling[:file_finder].find_test_file_from_name( test )
71
45
  end
@@ -50,6 +50,10 @@ class Setupinator
50
50
  @configurator.include_test_case = app_cfg[:include_test_case]
51
51
  @configurator.exclude_test_case = app_cfg[:exclude_test_case]
52
52
 
53
+ # Whether the requested tasks build tests or a release, which decides what build/vendor needs
54
+ @configurator.test_build_tasks = app_cfg[:test_build_tasks?]
55
+ @configurator.release_build_tasks = app_cfg[:release_build_tasks?]
56
+
53
57
  # Set special purpose forced test re-execution (from command line)
54
58
  @configurator.force_test_rerun = app_cfg[:force_test_rerun]
55
59