diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..47f1966 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,55 @@ +root = true + +# Language indent/EOL/charset overlap with .vscode/settings.json. +# Rulers, renderWhitespace, detectIndentation, mergeEditor, and +# language-server settings cannot be expressed here — they stay in +# settings.json. + +[*] +charset = utf-8 +end_of_line = lf +indent_size = 2 +indent_style = tab +insert_final_newline = true +trim_trailing_whitespace = true + +# [bat] +[*.{bat,cmd}] +end_of_line = crlf +indent_size = 4 +indent_style = space + +# [c] +[*.{c,h}] +indent_size = 4 +indent_style = space + +# [cmake] +[{CMakeLists.txt,*.cmake}] +indent_size = 4 +indent_style = tab + +# [cpp] +[*.{cpp,cxx,hpp,hxx}] +indent_size = 4 +indent_style = space + +# [json] +[*.json] +indent_size = 2 +indent_style = space + +# [markdown] +[*.md] +indent_size = 2 +indent_style = space + +# [shellscript] +[*.{bash,sh,zsh}] +indent_size = 2 +indent_style = space + +# [yaml] +[*.{yaml,yml}] +indent_size = 2 +indent_style = space diff --git a/.gitattributes b/.gitattributes index e6605d1..1ad0590 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,17 +1,126 @@ +# .gitattributes — C / C++ (GitHub-hosted) +# +# Sources: GitHub Docs (line endings), git-scm gitattributes (diff=cpp), +# gitattributes/gitattributes C++.gitattributes + Common.gitattributes, +# github-linguist overrides. +# +# Linguist language-bar policy (Synesis): classify public C API headers as C +# and *.cmake as CMake scripts; keep helper scripts, IDE project files, and +# CMakeLists.txt config out of the advertised language mix. Prefer +# -linguist-detectable over linguist-detectable=false. + +# Default: detect text, normalize to LF in the repository +* text=auto + +# --- Source --- +*.c text diff=cpp +*.c++ text diff=cpp +*.cc text diff=cpp +*.cpp text diff=cpp +*.cxx text diff=cpp +*.h text diff=cpp +*.h++ text diff=cpp +*.hh text diff=cpp +*.hpp text diff=cpp +*.hxx text diff=cpp +*.inc text +*.inl text +*.ipp text +*.tcc text +*.tpp text + +# --- Build / config --- +*.am text +*.cmake text +*.m4 text +*.mak text +*.mk text +*akefile text +CMakeLists.txt text +configure text eol=lf +configure.ac text + +# --- Scripts --- +*.bash text eol=lf +*.bat text eol=crlf +*.cmd text eol=crlf +*.ps1 text eol=crlf +*.sh text eol=lf +*.zsh text eol=lf + +# --- Docs / meta --- +*.adoc text +*.markdown text diff=markdown +*.md text diff=markdown +*.txt text +AUTHORS text +CHANGELOG text +CHANGES text +CONTRIBUTING text +COPYING text +LICENSE text +NEWS text +README text +TODO text +.gitattributes text +.gitignore text + +# --- Serialisation --- +*.json text +*.toml text +*.xml text +*.yaml text +*.yml text + +# --- Compiled / binary artefacts --- +*.a binary +*.dll binary +*.dylib binary +*.exe binary +*.gch binary +*.la binary +*.lai binary +*.lib binary +*.lo binary +*.o binary +*.obj binary +*.out binary +*.pch binary +*.slo binary +*.so binary + +# --- Archives / images (common) --- +*.gif binary +*.gz binary +*.ico binary +*.jpeg binary +*.jpg binary +*.png binary +*.tar binary +*.zip binary + +# --- GitHub Linguist --- +**/build/** linguist-generated +**/cmake-build-*/** linguist-generated + +# Classification (C-primary / C API with C++ tests; *.cmake as CMake scripts) *.c linguist-language=C *.cmake linguist-language=CMake -*.cmd linguist-detectable=false *.cpp linguist-language=C++ *.cxx linguist-language=C++ -*.dsp linguist-detectable=false -*.dsw linguist-detectable=false *.h linguist-language=C *.hpp linguist-language=C++ -*.html linguist-detectable=false *.hxx linguist-language=C++ -*.sh linguist-detectable=false -*.sln linguist-detectable=false -*.vcxproj linguist-detectable=false -*.vimrc linguist-detectable=false -CMakeLists.txt linguist-language=CMake -makefile linguist-detectable=false + +# Keep the bar on library languages (helpers / legacy IDE / docs / +# CMakeLists.txt config; leave *.cmake detectable as CMake) +*.cmd -linguist-detectable +*.dsp -linguist-detectable +*.dsw -linguist-detectable +*.html -linguist-detectable +*.sh -linguist-detectable +*.sln -linguist-detectable +*.vcxproj -linguist-detectable +*.vimrc -linguist-detectable +CMakeLists.txt -linguist-detectable +makefile -linguist-detectable diff --git a/.github/workflows/ci-cell.yml b/.github/workflows/ci-cell.yml index dc1f587..cd836e4 100644 --- a/.github/workflows/ci-cell.yml +++ b/.github/workflows/ci-cell.yml @@ -297,7 +297,7 @@ jobs: if [ "${{ inputs.c-compiler }}" = "mingw" ]; then export PATH="/mingw64/bin:$PATH" fi - SIS_CMAKE_BUILD_DIR="${{ github.workspace }}/build" ./run_all_unit_tests.sh -M --component-only + SIS_CMAKE_BUILD_DIR="${{ github.workspace }}/build" ./run_all_component_tests.sh -M test-scratch: name: Scratch tests (${{ inputs.cell-id }}) diff --git a/.gitignore b/.gitignore index 68e4424..226c160 100644 --- a/.gitignore +++ b/.gitignore @@ -1,164 +1,127 @@ -# Synesis Information Systems .gitignore for C/C++ libraries +# Synesis Information Systems .gitignore for C / C++ libraries # directories (by name) -/.git-old/ -/.vs/ +bin/ +ideas/ +ipch/ +lib/ +scripts/internal/ +Win32/ +x64/ +.idea/ .svn/ +.vs/ -.classpath -/.idea/ -/__pycache__ -/node_modules +__pycache__/ -/_build/ +/_analyses/ /_build-ci/ +/_build/ /_internal/ -/_analyses/ - -/bin/ -/ipch/ -/lib/ -bin/ -ipch/ -lib/ -/doc/ /docs/ /dox/ -/dox /ideas/ -ideas/ +/include/xcontract/ +/include/xcover/ /included/ +/node_modules/ /releases/ /scratch/ -/temp/ - -/--include -/--src -/-include -/-src - -/examples/bin -/examples/c/bin -/examples/cpp/bin - -/examples/lib -/examples/c/lib -/examples/cpp/lib - -projects/util/vc10-generated/ - -perf_test/ - -scripts/internal/ - -/include/shwild/ -/include/xcontract/ -/include/xcover/ -/include/xtests/ -/src/shwild/ /src/xcontract/ /src/xcover/ -/src/xtests/ +/target/ +/temp/ + +/examples/bin/ +/examples/c/bin/ +/examples/c/lib/ +/examples/cpp/bin/ +/examples/cpp/lib/ +/examples/lib/ -Debug Multithreaded DLL/ Debug Multithreaded Dll/ -Debug Multithreaded pseudoUNIX/ +Debug Multithreaded DLL/ Debug Multithreaded pseudoUnix/ +Debug Multithreaded pseudoUNIX/ Debug Multithreaded/ Debug/ +DebugDll/ DebugDLL/ DebugDLLUNIX/ -DebugDll/ -DebugMTDLL/ +DebugMt/ DebugMTDll/ +DebugMTDLL/ DebugMTUnix/ -DebugMt/ DebugNox/ -DebugUNIX/ DebugUnix/ -Release Multithreaded DLL/ +DebugUNIX/ Release Multithreaded Dll/ -Release Multithreaded pseudoUNIX/ +Release Multithreaded DLL/ Release Multithreaded pseudoUnix/ +Release Multithreaded pseudoUNIX/ Release Multithreaded/ Release/ +ReleaseDll/ ReleaseDLL/ ReleaseDLLUNIX/ -ReleaseDll/ -ReleaseMTDLL/ +ReleaseMt/ ReleaseMTDll/ +ReleaseMTDLL/ ReleaseMTUnix/ -ReleaseMt/ ReleaseNox/ ReleaseUnix/ UDebug/ UDebugMt/ -URelease/ -UReleaseMt/ -Unicode Debug Multithreaded DLL/ Unicode Debug Multithreaded Dll/ +Unicode Debug Multithreaded DLL/ Unicode Debug Multithreaded/ Unicode Debug/ -Unicode Release Multithreaded DLL/ Unicode Release Multithreaded Dll/ +Unicode Release Multithreaded DLL/ Unicode Release Multithreaded/ Unicode Release/ - -Win32/ -x64/ +URelease/ +UReleaseMt/ # directories (by pattern) -/build/ar* -/build/bc5* -/build/como* -/build/cw* -/build/gcc3* -/build/gcc4* -/build/icl* -/build/vc5* -/build/*.zip - /include-*/ # files (by name) .DS_Store + +.classpath +.env.development.local +.env.local +.env.production.local +.env.test.local .ruby-version -.ruby-version-exclusions .svnignore .svnignore-at-root .update_deps -.env.local -.env.development.local -.env.test.local -.env.production.local - -list_changes.cmd -logging-bailout.txt -prepare.cmd -sh.exe.stackdump -tidydir.cmd -update_deps.cmd +build/CMakeCache.txt build/makefile.tmpl build/makefile.tools.xml build/shwild.tmplgen -build/CMakeCache.txt - -include/fastformat/internal/dos2unix.has.been.performed include/pantheios/internal/dos2unix.has.been.performed include/stlsoft/dos2unix.has.been.performed include/stlsoft/internal/dos2unix.has.been.performed - +list_changes.cmd +logging-bailout.txt +prepare.cmd +sh.exe.stackdump test/testpatterns.orj test/tests-plan.txt +tidydir.cmd +update_deps.cmd # files (by pattern) @@ -166,8 +129,6 @@ test/tests-plan.txt *~ *.*~ *.???_obj -*.VC.db -*.VC.opendb *.a *.app *.aps @@ -175,6 +136,7 @@ test/tests-plan.txt *.bak *.chm *.class +*.csproj*user *.d *.diff *.dll @@ -211,32 +173,42 @@ test/tests-plan.txt *.slo *.so *.suo -*.swp *.sw[ponm] +*.swp *.test *.tlog *.tmp *.unsuccessfulbuild -*.vcproj*.user -*.vcxproj*.user -*.csproj*user -*.vcproj*user -*.vcxproj*user +*.VC.db +*.VC.opendb *.xcuserstate *.zip -*.vc71.sln -*.vc8.sln -*.vc9.sln +/build/*.tmpl +/build/*.tmplgen +/build/*.tools.xml +/build/*.zip +/build/ar* +/build/bc5* +/build/como* +/build/cw* +/build/gcc3* +/build/gcc4* +/build/icl* +/build/vc5* RCa0* RCb0* -build/*.tmplgen -build/*.tmpl -build/*.tools.xml - npm-debug.log* yarn-debug.log* yarn-error.log* +*.vc71.sln +*.vc8.sln +*.vc9.sln +*.vcproj*.user +*.vcproj*user +*.vcxproj*.user +*.vcxproj*user + diff --git a/.vimrc b/.vimrc index 1bf33a0..cebe6af 100644 --- a/.vimrc +++ b/.vimrc @@ -42,29 +42,29 @@ autocmd BufWritePre * %s/\s\+$//e augroup sis_c_cxx autocmd! + " [bat] + autocmd FileType bat,dosbatch setlocal expandtab tabstop=4 shiftwidth=4 softtabstop=4 colorcolumn=60,76 " [c] / [cpp] autocmd FileType c,cpp setlocal expandtab tabstop=4 shiftwidth=4 softtabstop=4 colorcolumn=60,64,68,72,76 - " [rust] - autocmd FileType rs setlocal expandtab tabstop=4 shiftwidth=4 softtabstop=4 colorcolumn=76 - " [cmake] autocmd FileType cmake setlocal noexpandtab tabstop=4 shiftwidth=4 softtabstop=4 - " [shellscript] - autocmd FileType sh,bash,zsh setlocal expandtab tabstop=2 shiftwidth=2 softtabstop=2 colorcolumn=60,76 - - " [bat] - autocmd FileType bat,dosbatch setlocal expandtab tabstop=4 shiftwidth=4 softtabstop=4 colorcolumn=60,76 - - " [json] / [markdown] / [yaml] / [ruby] - autocmd FileType json,markdown,yaml,ruby setlocal expandtab tabstop=2 shiftwidth=2 softtabstop=2 + " [json] / [markdown] / [ruby] / [yaml] + autocmd FileType json,markdown,ruby,yaml setlocal expandtab tabstop=2 shiftwidth=2 softtabstop=2 " [python] autocmd FileType python setlocal expandtab tabstop=4 shiftwidth=4 softtabstop=4 colorcolumn=60,76 + " [rust] + autocmd FileType rs setlocal expandtab tabstop=4 shiftwidth=4 softtabstop=4 colorcolumn=76 + + " [shellscript] + autocmd FileType bash,sh,zsh setlocal expandtab tabstop=2 shiftwidth=2 softtabstop=2 colorcolumn=60,76 + " [toml] autocmd FileType toml setlocal noexpandtab tabstop=2 shiftwidth=2 softtabstop=2 + augroup END diff --git a/.vscode/settings.json b/.vscode/settings.json index 3fe51d2..6aa78f6 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -5,8 +5,10 @@ "editor.tabSize": 4, }, "[c]": { + "editor.defaultFormatter": "ms-vscode.cpptools", + "editor.formatOnSave": true, "editor.insertSpaces": true, - "editor.rulers": [ 60, 64, 68, 72, 76 ], + "editor.rulers": [ 60, 64, 68, 72, 76, 120 ], "editor.tabSize": 4, }, "[cmake]": { @@ -14,8 +16,10 @@ "editor.tabSize": 4, }, "[cpp]": { + "editor.defaultFormatter": "ms-vscode.cpptools", + "editor.formatOnSave": true, "editor.insertSpaces": true, - "editor.rulers": [ 60, 64, 68, 72, 76 ], + "editor.rulers": [ 60, 64, 68, 72, 76, 120 ], "editor.tabSize": 4, }, "[json]": { @@ -34,6 +38,7 @@ }, "[ruby]": { "editor.insertSpaces": true, + "editor.rulers": [ 60, 76 ], "editor.tabSize": 2, }, "[shellscript]": { @@ -49,13 +54,28 @@ "editor.insertSpaces": true, "editor.tabSize": 2, }, + "C_Cpp.autocompleteAddParentheses": true, + "C_Cpp.clang_format_fallbackStyle": "none", + "C_Cpp.clang_format_style": "file", + "C_Cpp.default.cStandard": "c17", + "C_Cpp.default.cppStandard": "c++17", + "C_Cpp.enhancedColorization": "enabled", + "C_Cpp.errorSquiggles": "enabled", + "C_Cpp.formatting": "clangFormat", + "C_Cpp.intelliSenseEngine": "default", "cmake.configureOnOpen": false, + "debug.allowBreakpointsEverywhere": true, "editor.detectIndentation": false, "editor.insertSpaces": false, "editor.renderWhitespace": "all", "editor.rulers": [ 76 ], "editor.tabSize": 2, "files.associations": { + "*.gemspec": "ruby", + "*.mdoc": "troff", + "*.roff": "troff", + "Gemfile": "ruby", + "Rakefile": "ruby", "__bit_reference": "cpp", "__bits": "cpp", "__config": "cpp", @@ -76,13 +96,17 @@ "__tuple": "cpp", "__verbose_abort": "cpp", "algorithm": "cpp", + "api.h": "c", "array": "cpp", "atomic": "cpp", + "auto_buffer.h": "c", "bit": "cpp", "bitset": "cpp", "cctype": "cpp", "charconv": "cpp", "chrono": "cpp", + "clasp.h": "c", + "cli_helpers.h": "c", "clocale": "cpp", "cmath": "cpp", "compare": "cpp", @@ -109,6 +133,7 @@ "functional": "cpp", "implicit_link.h": "c", "initializer_list": "cpp", + "invoke.h": "c", "io.h": "c", "iomanip": "cpp", "ios": "cpp", @@ -119,28 +144,39 @@ "limits": "cpp", "list": "cpp", "locale": "cpp", + "main.h": "c", "map": "cpp", "memory": "cpp", "memory_resource": "cpp", "mutex": "cpp", + "net_helpers.h": "c", "new": "cpp", "numbers": "cpp", "numeric": "cpp", "optional": "cpp", "ostream": "cpp", + "path_functions.h": "c", + "print": "cpp", "queue": "cpp", "random": "cpp", "ranges": "cpp", "ratio": "cpp", + "rc.h": "c", + "recls.h": "c", + "result_codes_.h": "c", "semaphore": "cpp", "set": "cpp", "setenv.h": "c", "shwild.h": "c", + "sleep_functions.h": "c", "span": "cpp", "sstream": "cpp", "stack": "cpp", + "stdatomic.h": "c", + "stdbool.h": "c", "stdexcept": "cpp", "stdio.h": "c", + "stock.h": "c", "stop_token": "cpp", "streambuf": "cpp", "string": "cpp", @@ -149,6 +185,7 @@ "terse-api.h": "c", "text_encoding": "cpp", "thread": "cpp", + "trace.h": "c", "tuple": "cpp", "type_traits": "cpp", "typeinfo": "cpp", @@ -159,6 +196,7 @@ "utility": "cpp", "variant": "cpp", "vector": "cpp", + "williamscrc.h": "c", "xfacet": "cpp", "xhash": "cpp", "xiosbase": "cpp", diff --git a/CHANGES.md b/CHANGES.md index f967f0b..b374b70 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,6 +1,17 @@ # Pantheios.Extras.AtExit - Changes +## 0.1.4-beta1 - 9th October 2026 + +* Applied **misc-dev-scripts** **0.6.0** editor/Git/`.sis` drop-in templates on **boilerplate**; +* Restored historical **.gitignore** patterns as a sorted union with **misc-dev-scripts** gold section layout; +* Modernised CMake helpers to the Phase 4b dialect (`SisClr_*` / `-A`, `sis_cmake_build`, no MinGW-from-`MSYSTEM`), retaining **`--stlsoft-root-dir`** as a project-specific **prepare_cmake.sh** flag; +* Native Windows **`run_all_*.cmd`** runners (no Bash wrap); aggregate **`run_all_automated_tests.*`**, with **`run_all_unit_tests.*`** now unit-only; +* Renamed the scratch version-reporter target to **`test.scratch.versions`**; +* Updated the **ci-cell.yml** component-test job to call **run_all_component_tests.sh**, since **run_all_unit_tests.sh** is now unit-only; +* Added `PANTHEIOS_EXTRAS_ATEXIT_VER_0_1_4_BETA_1` and updated unit test **test.unit.version** accordingly; + + ## 0.1.3 - 31st August 2026 * Retargeted the current line from **0.1.2-alpha1** to **0.1.3**; diff --git a/LICENSE b/LICENSE index fce9e29..00114e8 100644 --- a/LICENSE +++ b/LICENSE @@ -2,12 +2,10 @@ Pantheios.Extras.AtExit - BSD 3-Clause License Copyright (c) 2019-2026, Matthew Wilson and Synesis Information Systems Copyright (c) 2011-2019, Matthew Wilson and Synesis Software - All rights reserved. Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: +modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. diff --git a/NEWS.md b/NEWS.md index 1311512..8921bb2 100644 --- a/NEWS.md +++ b/NEWS.md @@ -8,11 +8,12 @@ ## News -| Date | News Item | -| ---------------- | -------------------------------------------------------------------------------- | -| 31st August 2026 | Pantheios.Extras.AtExit 0.1.3 | -| 21st August 2026 | Pantheios.Extras.AtExit 0.1.2-alpha1 | -| 16th August 2026 | Pantheios.Extras.AtExit 0.1.1 recovered and released | +| Date | News Item | Details | +| ------------------- | ---------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------ | +| 9th October 2026 | [Pantheios.Extras.AtExit 0.1.4-beta1](https://github.com/synesissoftware/Pantheios.Extras.AtExit/releases/tag/0.1.4-beta1) | Phase 4b helpers; `test.scratch.versions` | +| 31st August 2026 | [Pantheios.Extras.AtExit 0.1.3](https://github.com/synesissoftware/Pantheios.Extras.AtExit/releases/tag/0.1.3) | `add` / `init` / `uninit` hardening; **README.md** rationale | +| 21st August 2026 | [Pantheios.Extras.AtExit 0.1.2-alpha1](https://github.com/synesissoftware/Pantheios.Extras.AtExit/releases/tag/0.1.2-alpha1) | computed `PANTHEIOS_EXTRAS_ATEXIT_VER`; **ctest_cmake.sh** | +| 16th August 2026 | [Pantheios.Extras.AtExit 0.1.1](https://github.com/synesissoftware/Pantheios.Extras.AtExit/releases/tag/0.1.1) | recovered from Hautacam; CMake packaging, CI | diff --git a/build_cmake.sh b/build_cmake.sh index 1f6b55d..a675a9d 100755 --- a/build_cmake.sh +++ b/build_cmake.sh @@ -1,22 +1,119 @@ #! /bin/bash -ScriptPath=$0 -Dir=$(cd $(dirname "$ScriptPath"); pwd) +# ########################################################## +# functions - 1 + +sis_cmake_is_truey() { + case "$(printf '%s' "${1:-}" | tr '[:upper:]' '[:lower:]')" in + + 1|ok|on|true|yes|y) + + return 0 + ;; + *) + + return 1 + ;; + esac +} + + +# ########################################################## +# constants and variables + +Basename=$(basename "$0") +Dir=$(cd "$(dirname "$0")" && pwd) +CMakeDir=${SIS_CMAKE_BUILD_DIR:-$Dir/_build} ProjectNameFile="$Dir/.sis/project_name.txt" ProjectName=$(tr -d '[:space:]' < "$ProjectNameFile") -Basename=$(basename "$ScriptPath") -CMakeDir=${SIS_CMAKE_BUILD_DIR:-$Dir/_build} -[[ -n "$MSYSTEM" ]] && DefaultMakeCmd=mingw32-make.exe || DefaultMakeCmd=make -MakeCmd=${SIS_CMAKE_MAKE_COMMAND:-${SIS_CMAKE_COMMAND:-$DefaultMakeCmd}} +ScriptPath=$0 +AlwaysUseColours=${SIS_CMAKE_ALWAYS_USE_COLOURS:-${SIS_ALWAYS_USE_COLOURS:-0}} IgnoreRemainingFlagsAndOptions=0 +SisUseColours=0 Targets=() # ########################################################## -# functions +# colours +# +# Enable when tput is available and either: +# - AlwaysUseColours is set (overrides NO_COLOR; may set TERM if +# empty/dumb), or +# - NO_COLOR is unset, stdout is a TTY, and TERM is not dumb (union of +# collect-c's "TERM set + TTY" and cstring's "TTY" — empty TERM on a +# TTY is OK). + +SisClr_Blue= +SisClr_Bold= +SisClr_Green= +SisClr_None= +SisClr_Red= +SisClr_Yellow= + +for arg in "$@"; do + + case $arg in + --always-use-colors|--always-use-colours|-A) + + AlwaysUseColours=1 + ;; + esac +done + +if command -v tput >/dev/null 2>&1; then + + if [ $AlwaysUseColours -ne 0 ]; then + + if [ -z "${TERM:-}" ] || [ "$TERM" = "dumb" ]; then + + TERM=xterm-256color + fi + + SisUseColours=1 + elif [ -z "${NO_COLOR:-}" ] && [ -t 1 ] && [ "${TERM:-}" != "dumb" ]; then + + SisUseColours=1 + fi +fi + +if [ $SisUseColours -ne 0 ]; then + + SisClr_Blue=${FG_BLUE:-$(tput setaf 4)} + SisClr_Bold=${FD_BOLD:-$(tput bold)} + SisClr_Green=${FG_GREEN:-$(tput setaf 2)} + SisClr_None=${FD_NONE:-$(tput sgr0)} + SisClr_Red=${FG_RED:-$(tput setaf 1)} + SisClr_Yellow=${FG_YELLOW:-$(tput setaf 3)} +fi + +CMakeDirClr="${SisClr_Blue}${SisClr_Bold}${CMakeDir}${SisClr_None}" +ProjectNameClr="${SisClr_Blue}${SisClr_Bold}${ProjectName}${SisClr_None}" +ScriptPathClr="${SisClr_Blue}${SisClr_Bold}${ScriptPath}${SisClr_None}" + + +# ########################################################## +# functions - 2 -function join_by { local IFS="$1"; shift; echo "$*"; } +sis_cmake_build() { + + local config="${SIS_CMAKE_CONFIG:-Release}" + local args=(--build "$CMakeDir") + if [ -f "$CMakeDir/CMakeCache.txt" ] && grep -q '^CMAKE_CONFIGURATION_TYPES:' "$CMakeDir/CMakeCache.txt" 2>/dev/null; then + + args+=(--config "$config") + fi + if [ "$#" -gt 0 ]; then + + local t + for t in "$@"; do + + args+=(--target "$t") + done + fi + + cmake "${args[@]}" +} # ########################################################## @@ -26,21 +123,16 @@ while [[ $# -gt 0 ]]; do if [ $IgnoreRemainingFlagsAndOptions -ne 0 ]; then - Targets+=($1) - + Targets+=("$1") shift - continue - else - - if [ ! ${1:0:1} = '-' ]; then - - Targets+=($1) + fi - shift + if [ "${1:0:1}" != '-' ]; then - continue - fi + Targets+=("$1") + shift + continue fi case $1 in @@ -48,18 +140,33 @@ while [[ $# -gt 0 ]]; do IgnoreRemainingFlagsAndOptions=1 ;; + --always-use-colors|--always-use-colours|-A) + + # AlwaysUseColours=1 - this is handled by the for loop above + ;; --help) [ -f "$Dir/.sis/script_info_lines.txt" ] && cat "$Dir/.sis/script_info_lines.txt" cat << EOF Executes CMake-generated artefacts to (re)build project -$ScriptPath [ ... flags/options ... ] +${ScriptPath} [ ... flags/options ... ] Flags/options: behaviour: + (no arguments) + builds all default targets + + ... + builds one or more specific targets + + -A + --always-use-colors + --always-use-colours + forces use of colours even when stdout is not a TTY + standard flags: @@ -72,7 +179,7 @@ EOF ;; *) - >&2 echo "$ScriptPath: unrecognised argument '$1'; use --help for usage" + >&2 echo "${ScriptPathClr}: unrecognised argument '${SisClr_Red}${SisClr_Bold}$1${SisClr_None}'; use --help for usage" exit 1 ;; @@ -85,41 +192,26 @@ done # ########################################################## # main() -if [ ! -d "$CMakeDir" ]; then +if [ ! -d "$CMakeDir" ] || [ ! -f "$CMakeDir/CMakeCache.txt" ]; then - >&2 echo "$ScriptPath: CMake build directory '$CMakeDir' not found so nothing to do; use script 'prepare_cmake.sh' if you wish to prepare CMake artefacts" + >&2 echo "${ScriptPathClr}: CMake build directory '${CMakeDirClr}' not found or not configured; use script 'prepare_cmake.sh' first" exit 1 -else - - cd $CMakeDir - - if [ ! -f "$CMakeDir/Makefile" ]; then - - >&2 echo "$ScriptPath: CMake build directory '$CMakeDir' does not contain expected file 'Makefile', so a clean cannot be performed. It is recommended that you remove all CMake artefacts using script 'remove_cmake_artefacts.sh' followed by regeneration via 'prepare_cmake.sh'" - - cd ->/dev/null - - exit 1 - else - - if [ -z "$Targets" ]; then - - echo "Executing build (via command \`$MakeCmd\`)" - else - - echo "Executing build (via command \`$MakeCmd\`) with specific target(s) $(join_by , "${Targets[@]}")" - fi +fi - $MakeCmd ${Targets[*]} - status=$? +if [ ${#Targets[@]} -eq 0 ]; then - cd ->/dev/null + echo "Executing build of ${ProjectNameClr} (via cmake --build)" + sis_cmake_build + status=$? +else - exit $status - fi + echo "Executing build of ${ProjectNameClr} (via cmake --build) with specific target(s): ${Targets[*]}" + sis_cmake_build "${Targets[@]}" + status=$? fi +exit $status -# ############################## end of file ############################# # +# ############################## end of file ############################# # diff --git a/clean_cmake.sh b/clean_cmake.sh index 87b42eb..733afbd 100755 --- a/clean_cmake.sh +++ b/clean_cmake.sh @@ -1,13 +1,117 @@ #! /bin/bash -ScriptPath=$0 -Dir=$(cd $(dirname "$ScriptPath"); pwd) +# ########################################################## +# functions - 1 + +sis_cmake_is_truey() { + case "$(printf '%s' "${1:-}" | tr '[:upper:]' '[:lower:]')" in + + 1|ok|on|true|yes|y) + + return 0 + ;; + *) + + return 1 + ;; + esac +} + + +# ########################################################## +# constants and variables + +Basename=$(basename "$0") +Dir=$(cd "$(dirname "$0")" && pwd) +CMakeDir=${SIS_CMAKE_BUILD_DIR:-$Dir/_build} ProjectNameFile="$Dir/.sis/project_name.txt" ProjectName=$(tr -d '[:space:]' < "$ProjectNameFile") -Basename=$(basename "$ScriptPath") -CMakeDir=${SIS_CMAKE_BUILD_DIR:-$Dir/_build} -[[ -n "$MSYSTEM" ]] && DefaultMakeCmd=mingw32-make.exe || DefaultMakeCmd=make -MakeCmd=${SIS_CMAKE_MAKE_COMMAND:-${SIS_CMAKE_COMMAND:-$DefaultMakeCmd}} +ScriptPath=$0 + +AlwaysUseColours=${SIS_CMAKE_ALWAYS_USE_COLOURS:-${SIS_ALWAYS_USE_COLOURS:-0}} +SisUseColours=0 + + +# ########################################################## +# colours +# +# Enable when tput is available and either: +# - AlwaysUseColours is set (overrides NO_COLOR; may set TERM if +# empty/dumb), or +# - NO_COLOR is unset, stdout is a TTY, and TERM is not dumb (union of +# collect-c's "TERM set + TTY" and cstring's "TTY" — empty TERM on a +# TTY is OK). + +SisClr_Blue= +SisClr_Bold= +SisClr_Green= +SisClr_None= +SisClr_Red= +SisClr_Yellow= + +for arg in "$@"; do + + case $arg in + --always-use-colors|--always-use-colours|-A) + + AlwaysUseColours=1 + ;; + esac +done + +if command -v tput >/dev/null 2>&1; then + + if [ $AlwaysUseColours -ne 0 ]; then + + if [ -z "${TERM:-}" ] || [ "$TERM" = "dumb" ]; then + + TERM=xterm-256color + fi + + SisUseColours=1 + elif [ -z "${NO_COLOR:-}" ] && [ -t 1 ] && [ "${TERM:-}" != "dumb" ]; then + + SisUseColours=1 + fi +fi + +if [ $SisUseColours -ne 0 ]; then + + SisClr_Blue=${FG_BLUE:-$(tput setaf 4)} + SisClr_Bold=${FD_BOLD:-$(tput bold)} + SisClr_Green=${FG_GREEN:-$(tput setaf 2)} + SisClr_None=${FD_NONE:-$(tput sgr0)} + SisClr_Red=${FG_RED:-$(tput setaf 1)} + SisClr_Yellow=${FG_YELLOW:-$(tput setaf 3)} +fi + +CMakeDirClr="${SisClr_Blue}${SisClr_Bold}${CMakeDir}${SisClr_None}" +ProjectNameClr="${SisClr_Blue}${SisClr_Bold}${ProjectName}${SisClr_None}" +ScriptPathClr="${SisClr_Blue}${SisClr_Bold}${ScriptPath}${SisClr_None}" + + +# ########################################################## +# functions - 2 + +sis_cmake_build() { + + local config="${SIS_CMAKE_CONFIG:-Release}" + local args=(--build "$CMakeDir") + if [ -f "$CMakeDir/CMakeCache.txt" ] && grep -q '^CMAKE_CONFIGURATION_TYPES:' "$CMakeDir/CMakeCache.txt" 2>/dev/null; then + + args+=(--config "$config") + fi + if [ "$#" -gt 0 ]; then + + local t + for t in "$@"; do + + args+=(--target "$t") + done + fi + + cmake "${args[@]}" +} # ########################################################## @@ -16,18 +120,27 @@ MakeCmd=${SIS_CMAKE_MAKE_COMMAND:-${SIS_CMAKE_COMMAND:-$DefaultMakeCmd}} while [[ $# -gt 0 ]]; do case $1 in + --always-use-colors|--always-use-colours|-A) + + # AlwaysUseColours=1 - this is handled by the for loop above + ;; --help) [ -f "$Dir/.sis/script_info_lines.txt" ] && cat "$Dir/.sis/script_info_lines.txt" cat << EOF -Executes CMake-generated artefacts to clean project +Cleans CMake-generated build artefacts via cmake --build --target clean -$ScriptPath [ ... flags/options ... ] +${ScriptPath} [ ... flags/options ... ] Flags/options: behaviour: + -A + --always-use-colors + --always-use-colours + forces use of colours even when stdout is not a TTY + standard flags: @@ -40,7 +153,7 @@ EOF ;; *) - >&2 echo "$ScriptPath: unrecognised argument '$1'; use --help for usage" + >&2 echo "${ScriptPathClr}: unrecognised argument '${SisClr_Red}${SisClr_Bold}$1${SisClr_None}'; use --help for usage" exit 1 ;; @@ -53,35 +166,16 @@ done # ########################################################## # main() -if [ ! -d "$CMakeDir" ]; then +if [ ! -d "$CMakeDir" ] || [ ! -f "$CMakeDir/CMakeCache.txt" ]; then - >&2 echo "$ScriptPath: CMake build directory '$CMakeDir' not found so nothing to do; use script 'prepare_cmake.sh' if you wish to prepare CMake artefacts" + >&2 echo "${ScriptPathClr}: CMake build directory '${CMakeDirClr}' not found or not configured; nothing to clean" exit 1 -else - - cd $CMakeDir - - if [ ! -f "$CMakeDir/Makefile" ]; then - - >&2 echo "$ScriptPath: CMake build directory '$CMakeDir' does not contain expected file 'Makefile', so a clean cannot be performed. It is recommended that you remove all CMake artefacts using script 'remove_cmake_artefacts.sh' followed by regeneration via 'prepare_cmake.sh'" - - cd ->/dev/null - - exit 1 - else - - echo "Cleaning build (via command \`$MakeCmd clean\`)" - - $MakeCmd clean - status=$? - - cd ->/dev/null - - exit $status - fi fi +echo "Executing clean of ${ProjectNameClr} (via cmake --build --target clean)" +sis_cmake_build clean +exit $? -# ############################## end of file ############################# # +# ############################## end of file ############################# # diff --git a/cmake/BuildType.cmake b/cmake/BuildType.cmake index e83cfbb..bb9c386 100644 --- a/cmake/BuildType.cmake +++ b/cmake/BuildType.cmake @@ -5,7 +5,7 @@ # Purpose: CMake module file (for BuildType) # # Created: 16th October 2019 -# Updated: 12th January 2024 +# Updated: 2nd September 2026 # # ######################################################################## # @@ -47,7 +47,7 @@ if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) message(STATUS "Setting build type to '${default_build_type}' as none was specified.") - set(CACHE CMAKE_BUILD_TYPE "${default_build_type}" + set(CMAKE_BUILD_TYPE "${default_build_type}" CACHE STRING "Choose the type of build." FORCE ) diff --git a/ctest_cmake.sh b/ctest_cmake.sh index 24c2172..4e09ee2 100755 --- a/ctest_cmake.sh +++ b/ctest_cmake.sh @@ -1,16 +1,119 @@ #! /bin/bash -ScriptPath=$0 -Dir=$(cd $(dirname "$ScriptPath"); pwd) -Basename=$(basename "$ScriptPath") +# ########################################################## +# functions - 1 + +sis_cmake_is_truey() { + case "$(printf '%s' "${1:-}" | tr '[:upper:]' '[:lower:]')" in + + 1|ok|on|true|yes|y) + + return 0 + ;; + *) + + return 1 + ;; + esac +} + + +# ########################################################## +# constants and variables + +Basename=$(basename "$0") +Dir=$(cd "$(dirname "$0")" && pwd) CMakeDir=${SIS_CMAKE_BUILD_DIR:-$Dir/_build} -[[ -n "$MSYSTEM" ]] && DefaultMakeCmd=mingw32-make.exe || DefaultMakeCmd=make -MakeCmd=${SIS_CMAKE_MAKE_COMMAND:-${SIS_CMAKE_COMMAND:-$DefaultMakeCmd}} ProjectNameFile="$Dir/.sis/project_name.txt" ProjectName=$(tr -d '[:space:]' < "$ProjectNameFile") +ScriptPath=$0 -CMakeVerbose= +AlwaysUseColours=${SIS_CMAKE_ALWAYS_USE_COLOURS:-${SIS_ALWAYS_USE_COLOURS:-0}} +CTestVerbose= RunMake=1 +SisUseColours=0 + + +# ########################################################## +# colours +# +# Enable when tput is available and either: +# - AlwaysUseColours is set (overrides NO_COLOR; may set TERM if +# empty/dumb), or +# - NO_COLOR is unset, stdout is a TTY, and TERM is not dumb (union of +# collect-c's "TERM set + TTY" and cstring's "TTY" — empty TERM on a +# TTY is OK). + +SisClr_Blue= +SisClr_Bold= +SisClr_Green= +SisClr_None= +SisClr_Red= +SisClr_Yellow= + +for arg in "$@"; do + + case $arg in + --always-use-colors|--always-use-colours|-A) + + AlwaysUseColours=1 + ;; + esac +done + +if command -v tput >/dev/null 2>&1; then + + if [ $AlwaysUseColours -ne 0 ]; then + + if [ -z "${TERM:-}" ] || [ "$TERM" = "dumb" ]; then + + TERM=xterm-256color + fi + + SisUseColours=1 + elif [ -z "${NO_COLOR:-}" ] && [ -t 1 ] && [ "${TERM:-}" != "dumb" ]; then + + SisUseColours=1 + fi +fi + +if [ $SisUseColours -ne 0 ]; then + + SisClr_Blue=${FG_BLUE:-$(tput setaf 4)} + SisClr_Bold=${FD_BOLD:-$(tput bold)} + SisClr_Green=${FG_GREEN:-$(tput setaf 2)} + SisClr_None=${FD_NONE:-$(tput sgr0)} + SisClr_Red=${FG_RED:-$(tput setaf 1)} + SisClr_Yellow=${FG_YELLOW:-$(tput setaf 3)} +fi + +CMakeDirClr="${SisClr_Blue}${SisClr_Bold}${CMakeDir}${SisClr_None}" +ProjectNameClr="${SisClr_Blue}${SisClr_Bold}${ProjectName}${SisClr_None}" +ScriptPathClr="${SisClr_Blue}${SisClr_Bold}${ScriptPath}${SisClr_None}" + + +# ########################################################## +# functions - 2 + +sis_cmake_build() { + + local config="${SIS_CMAKE_CONFIG:-Release}" + local args=(--build "$CMakeDir") + if [ -f "$CMakeDir/CMakeCache.txt" ] && grep -q '^CMAKE_CONFIGURATION_TYPES:' "$CMakeDir/CMakeCache.txt" 2>/dev/null; then + + args+=(--config "$config") + fi + if [ "$#" -gt 0 ]; then + + local t + for t in "$@"; do + + args+=(--target "$t") + done + fi + + cmake "${args[@]}" +} # ########################################################## @@ -19,13 +122,17 @@ RunMake=1 while [[ $# -gt 0 ]]; do case $1 in + --always-use-colors|--always-use-colours|-A) + + # AlwaysUseColours=1 - this is handled by the for loop above + ;; --no-make|-M) RunMake=0 ;; --verbose|-V) - CMakeVerbose=--verbose + CTestVerbose=--verbose ;; --help) @@ -33,15 +140,20 @@ while [[ $# -gt 0 ]]; do cat << EOF Runs CMake's CTest test program(s) -$ScriptPath [ ... flags/options ... ] +${ScriptPath} [ ... flags/options ... ] Flags/options: behaviour: + -A + --always-use-colors + --always-use-colours + forces use of colours even when stdout is not a TTY + -M --no-make - does not execute CMake and make before running tests + does not execute a build before running tests -V --verbose @@ -59,7 +171,7 @@ EOF ;; *) - >&2 echo "$ScriptPath: unrecognised argument '$1'; use --help for usage" + >&2 echo "${ScriptPathClr}: unrecognised argument '${SisClr_Red}${SisClr_Bold}$1${SisClr_None}'; use --help for usage" exit 1 ;; @@ -76,29 +188,48 @@ status=0 if [ $RunMake -ne 0 ]; then - echo "Executing build for ${ProjectName} (via command \`$MakeCmd\`) and then running all component and unit test programs" + echo + echo "Executing build of ${ProjectNameClr} (via cmake --build) and then running CTest" - mkdir -p $CMakeDir || exit 1 + mkdir -p "$CMakeDir" || exit 1 - cd $CMakeDir + if [ ! -f "$CMakeDir/CMakeCache.txt" ]; then - $MakeCmd - status=$? + >&2 echo "${ScriptPathClr}: '${CMakeDirClr}' is not configured; use prepare_cmake.sh first" + + exit 1 + fi - cd ->/dev/null + sis_cmake_build + status=$? else - if [ ! -d "$CMakeDir" ] || [ ! -f "$CMakeDir/CMakeCache.txt" ] || [ ! -d "$CMakeDir/CMakeFiles" ]; then + if [ ! -d "$CMakeDir" ] || [ ! -f "$CMakeDir/CMakeCache.txt" ]; then + + >&2 echo "${ScriptPathClr}: cannot run in '--no-make' mode without a previous successful configure/build" - >&2 echo "$ScriptPath: cannot run in '--no-make' mode without a previous successful build step" + exit 1 fi fi if [ $status -eq 0 ]; then - echo "Running CMake tests" + echo + echo "Running ${ProjectNameClr} CMake tests" + + # Multi-config generators (e.g. Visual Studio) need -C ; + # mirror sis_cmake_build's CMAKE_CONFIGURATION_TYPES detection. + ctest_args=(--test-dir "$CMakeDir" --output-on-failure) + if [ -n "$CTestVerbose" ]; then + + ctest_args+=("$CTestVerbose") + fi + if [ -f "$CMakeDir/CMakeCache.txt" ] && grep -q '^CMAKE_CONFIGURATION_TYPES:' "$CMakeDir/CMakeCache.txt" 2>/dev/null; then + + ctest_args+=(-C "${SIS_CMAKE_CONFIG:-Release}") + fi - ctest --test-dir $CMakeDir $CMakeVerbose + ctest "${ctest_args[@]}" status=$? fi diff --git a/include/pantheios/extras/atexit/atexit.h b/include/pantheios/extras/atexit/atexit.h index ce115ce..aa3e65c 100644 --- a/include/pantheios/extras/atexit/atexit.h +++ b/include/pantheios/extras/atexit/atexit.h @@ -4,7 +4,7 @@ * Purpose: Header file for Pantheios.Extras.AtExit. * * Created: 30th December 2011 - * Updated: 31st August 2026 + * Updated: 9th October 2026 * * Home: http://www.pantheios.org/ * @@ -80,21 +80,17 @@ * The current composite version number of Pantheios.Extras.AtExit */ -/** \def PANTHEIOS_EXTRAS_ATEXIT_VER_REVISION - * Alias of PANTHEIOS_EXTRAS_ATEXIT_VER_PATCH (for CMake scrapers / older - * consumers) - */ - #ifndef PANTHEIOS_DOCUMENTATION_SKIP_SECTION # define PANTHEIOS_EXTRAS_ATEXIT_VER_0_1_1 0x000101ff # define PANTHEIOS_EXTRAS_ATEXIT_VER_0_1_2_ALPHA_1 0x00010241 # define PANTHEIOS_EXTRAS_ATEXIT_VER_0_1_3 0x000103ff +# define PANTHEIOS_EXTRAS_ATEXIT_VER_0_1_4_BETA_1 0x00010481 #endif /* !PANTHEIOS_DOCUMENTATION_SKIP_SECTION */ #define PANTHEIOS_EXTRAS_ATEXIT_VER_MAJOR 0 #define PANTHEIOS_EXTRAS_ATEXIT_VER_MINOR 1 -#define PANTHEIOS_EXTRAS_ATEXIT_VER_PATCH 3 -#define PANTHEIOS_EXTRAS_ATEXIT_VER_ALPHABETA 0xFF +#define PANTHEIOS_EXTRAS_ATEXIT_VER_PATCH 4 +#define PANTHEIOS_EXTRAS_ATEXIT_VER_ALPHABETA 0x81 #define PANTHEIOS_EXTRAS_ATEXIT_VER \ (0\ @@ -104,7 +100,9 @@ | ( PANTHEIOS_EXTRAS_ATEXIT_VER_ALPHABETA << 0 ) \ ) -#define PANTHEIOS_EXTRAS_ATEXIT_VER_REVISION PANTHEIOS_EXTRAS_ATEXIT_VER_PATCH +#ifndef PANTHEIOS_DOCUMENTATION_SKIP_SECTION +# define PANTHEIOS_EXTRAS_ATEXIT_VER_REVISION PANTHEIOS_EXTRAS_ATEXIT_VER_PATCH +#endif /* !PANTHEIOS_DOCUMENTATION_SKIP_SECTION */ #ifdef __cplusplus extern "C" { diff --git a/prepare_cmake.sh b/prepare_cmake.sh index cd236f2..40fccd9 100755 --- a/prepare_cmake.sh +++ b/prepare_cmake.sh @@ -1,23 +1,135 @@ #! /bin/bash -ScriptPath=$0 -Dir=$(cd $(dirname "$ScriptPath"); pwd) +# ########################################################## +# functions - 1 + +sis_cmake_is_truey() { + case "$(printf '%s' "${1:-}" | tr '[:upper:]' '[:lower:]')" in + + 1|ok|on|true|yes|y) + + return 0 + ;; + *) + + return 1 + ;; + esac +} + + +# ########################################################## +# constants and variables + +Basename=$(basename "$0") +Dir=$(cd "$(dirname "$0")" && pwd) +CMakeDir=${SIS_CMAKE_BUILD_DIR:-$Dir/_build} ProjectNameFile="$Dir/.sis/project_name.txt" ProjectName=$(tr -d '[:space:]' < "$ProjectNameFile") -Basename=$(basename "$ScriptPath") -CMakeDir=${SIS_CMAKE_BUILD_DIR:-$Dir/_build} -[[ -n "$MSYSTEM" ]] && DefaultMakeCmd=mingw32-make.exe || DefaultMakeCmd=make -MakeCmd=${SIS_CMAKE_MAKE_COMMAND:-${SIS_CMAKE_COMMAND:-$DefaultMakeCmd}} +ScriptPath=$0 +AlwaysUseColours=${SIS_CMAKE_ALWAYS_USE_COLOURS:-${SIS_ALWAYS_USE_COLOURS:-0}} +BuildSharedLibs=0 Configuration=Release ExamplesDisabled=0 +MinGW=$(sis_cmake_is_truey "${SIS_CMAKE_MINGW:-}" && echo 1 || echo 0) MSVC_MT=0 -MinGW=0 RunMake=0 -STLSoftDirGiven= +SisUseColours=0 TestingDisabled=0 VerboseMakefile=0 +# ########################################################## +# PROJECT-SPECIFIC FLAGS (customise per library; keep marker) +# +# Add project-only options here (e.g. --no-cpp, --stlsoft-root-dir, +# --no-shwild). The common body below must stay aligned with +# misc-dev-scripts/shell-scripts/cmake-helpers/prepare_cmake.sh. + + +STLSoftDirGiven= + +# ########################################################## +# colours +# +# Enable when tput is available and either: +# - AlwaysUseColours is set (overrides NO_COLOR; may set TERM if +# empty/dumb), or +# - NO_COLOR is unset, stdout is a TTY, and TERM is not dumb (union of +# collect-c's "TERM set + TTY" and cstring's "TTY" — empty TERM on a +# TTY is OK). + +SisClr_Blue= +SisClr_Bold= +SisClr_Green= +SisClr_None= +SisClr_Red= +SisClr_Yellow= + +for arg in "$@"; do + + case $arg in + --always-use-colors|--always-use-colours|-A) + + AlwaysUseColours=1 + ;; + esac +done + +if command -v tput >/dev/null 2>&1; then + + if [ $AlwaysUseColours -ne 0 ]; then + + if [ -z "${TERM:-}" ] || [ "$TERM" = "dumb" ]; then + + TERM=xterm-256color + fi + + SisUseColours=1 + elif [ -z "${NO_COLOR:-}" ] && [ -t 1 ] && [ "${TERM:-}" != "dumb" ]; then + + SisUseColours=1 + fi +fi + +if [ $SisUseColours -ne 0 ]; then + + SisClr_Blue=${FG_BLUE:-$(tput setaf 4)} + SisClr_Bold=${FD_BOLD:-$(tput bold)} + SisClr_Green=${FG_GREEN:-$(tput setaf 2)} + SisClr_None=${FD_NONE:-$(tput sgr0)} + SisClr_Red=${FG_RED:-$(tput setaf 1)} + SisClr_Yellow=${FG_YELLOW:-$(tput setaf 3)} +fi + +CMakeDirClr="${SisClr_Blue}${SisClr_Bold}${CMakeDir}${SisClr_None}" +ProjectNameClr="${SisClr_Blue}${SisClr_Bold}${ProjectName}${SisClr_None}" +ScriptPathClr="${SisClr_Blue}${SisClr_Bold}${ScriptPath}${SisClr_None}" + + +# ########################################################## +# functions - 2 + +sis_cmake_build() { + + local config="${SIS_CMAKE_CONFIG:-Release}" + local args=(--build "$CMakeDir") + if [ -f "$CMakeDir/CMakeCache.txt" ] && grep -q '^CMAKE_CONFIGURATION_TYPES:' "$CMakeDir/CMakeCache.txt" 2>/dev/null; then + + args+=(--config "$config") + fi + if [ "$#" -gt 0 ]; then + + local t + for t in "$@"; do + + args+=(--target "$t") + done + fi + + cmake "${args[@]}" +} + # ########################################################## # command-line handling @@ -25,6 +137,14 @@ VerboseMakefile=0 while [[ $# -gt 0 ]]; do case $1 in + --always-use-colors|--always-use-colours|-A) + + # AlwaysUseColours=1 - this is handled by the for loop above + ;; + --build-shared-libs) + + BuildSharedLibs=1 + ;; --cmake-verbose-makefile|-v) VerboseMakefile=1 @@ -60,46 +180,50 @@ while [[ $# -gt 0 ]]; do ;; --help) - [ -f "$Dir/.sis/script_info_lines.txt" ] && cat "$Dir/.sis/script_info_lines.txt" - cat << EOF -Creates/reinitialises the CMake build script(s) for ${ProjectName} + [ -f "$Dir/.sis/script_info_lines.txt" ] && cat "$Dir/.sis/script_info_lines.txt" + cat << EOF +Creates/reinitialises the CMake build script(s) -$ScriptPath [ ... flags/options ... ] +${ScriptPath} [ ... flags/options ... ] Flags/options: behaviour: + -A + --always-use-colors + --always-use-colours + forces use of colours even when stdout is not a TTY + + --build-shared-libs + builds ${ProjectName} as a shared library (BUILD_SHARED_LIBS=ON) + -v --cmake-verbose-makefile - configures CMake to run verbosely (by setting CMAKE_VERBOSE_MAKEFILE - to be ON) + configures CMake to run verbosely (CMAKE_VERBOSE_MAKEFILE=ON) -d --debug-configuration - use Debug configuration (by setting CMAKE_BUILD_TYPE=Debug). Default - is to use Release + use Debug configuration (CMAKE_BUILD_TYPE=Debug). Default is Release -E --disable-examples - disables building of examples (by setting BUILD_EXAMPLES=OFF) + disables building of examples (BUILD_EXAMPLES=OFF) -T --disable-testing - disables building of tests (by setting BUILD_TESTING=OFF). Unless - testing is disabled the STLSoft and xTests libraries will be - required to be available to CMake + disables building of tests (BUILD_TESTING=OFF) --mingw uses explicitly the "MinGW Makefiles" generator --msvc-mt - when using Visual C++ (MSVC), the static runtime library will be - selected; the default is the dynamic runtime library + when using Visual C++ (MSVC), select the static runtime library -m --run-make - executes make after a successful running of CMake + executes a build via cmake --build after a successful configure + -s --stlsoft-root-dir @@ -107,7 +231,6 @@ Flags/options: as the variable STLSOFT, and which will override the environment variable STLSOFT (if present) - standard flags: --help @@ -119,7 +242,7 @@ EOF ;; *) - >&2 echo "$ScriptPath: unrecognised argument '$1'; use --help for usage" + >&2 echo "${ScriptPathClr}: unrecognised argument '${SisClr_Red}${SisClr_Bold}$1${SisClr_None}'; use --help for usage" exit 1 ;; @@ -132,59 +255,63 @@ done # ########################################################## # main() -mkdir -p $CMakeDir || exit 1 - -cd $CMakeDir +mkdir -p "$CMakeDir" || exit 1 -echo "Executing CMake (in ${CMakeDir})" +echo +echo "Executing CMake for ${ProjectNameClr} (in ${CMakeDirClr})" +if [ $BuildSharedLibs -eq 0 ]; then CMakeBuildSharedLibsFlag="OFF" ; else CMakeBuildSharedLibsFlag="ON" ; fi if [ $ExamplesDisabled -eq 0 ]; then CMakeBuildExamplesFlag="ON" ; else CMakeBuildExamplesFlag="OFF" ; fi if [ $MSVC_MT -eq 0 ]; then CMakeMsvcMtFlag="OFF" ; else CMakeMsvcMtFlag="ON" ; fi -if [ -z $STLSoftDirGiven ]; then CMakeSTLSoftVariable="" ; else CMakeSTLSoftVariable="-DSTLSOFT=$STLSoftDirGiven/" ; fi +if [ -z "$STLSoftDirGiven" ]; then CMakeSTLSoftVariable="" ; else CMakeSTLSoftVariable="-DSTLSOFT=$STLSoftDirGiven/" ; fi if [ $TestingDisabled -eq 0 ]; then CMakeBuildTestingFlag="ON" ; else CMakeBuildTestingFlag="OFF" ; fi if [ $VerboseMakefile -eq 0 ]; then CMakeVerboseMakefileFlag="OFF" ; else CMakeVerboseMakefileFlag="ON" ; fi +# NOTE: the generator is the *only* thing that may differ between the MinGW +# and the default paths; every -D option is passed in both cases, so that no +# flag can be silently ignored according to the generator selected. + +CMakeGeneratorArgs=() + +if [ -n "${SIS_CMAKE_GENERATOR:-}" ] && [ $MinGW -eq 0 ]; then + + CMakeGeneratorArgs=(-G "$SIS_CMAKE_GENERATOR") +fi + if [ $MinGW -ne 0 ]; then - cmake \ - $CMakeSTLSoftVariable \ - -DBUILD_EXAMPLES:BOOL=$CMakeBuildExamplesFlag \ - -DBUILD_TESTING:BOOL=$CMakeBuildTestingFlag \ - -DCMAKE_BUILD_TYPE=$Configuration \ - -G "MinGW Makefiles" \ - -S $Dir \ - -B $CMakeDir \ - || (cd ->/dev/null ; exit 1) -else - - cmake \ - $CMakeSTLSoftVariable \ - -DBUILD_EXAMPLES:BOOL=$CMakeBuildExamplesFlag \ - -DBUILD_TESTING:BOOL=$CMakeBuildTestingFlag \ - -DCMAKE_BUILD_TYPE=$Configuration \ - -DCMAKE_VERBOSE_MAKEFILE:BOOL=$CMakeVerboseMakefileFlag \ - -DMSVC_USE_MT:BOOL=$CMakeMsvcMtFlag \ - -S $Dir \ - -B $CMakeDir \ - || (cd ->/dev/null ; exit 1) + CMakeGeneratorArgs=(-G "MinGW Makefiles") fi +cmake \ + -DBUILD_EXAMPLES:BOOL=$CMakeBuildExamplesFlag \ + -DBUILD_SHARED_LIBS:BOOL=$CMakeBuildSharedLibsFlag \ + -DBUILD_TESTING:BOOL=$CMakeBuildTestingFlag \ + -DCMAKE_BUILD_TYPE=$Configuration \ + -DCMAKE_VERBOSE_MAKEFILE:BOOL=$CMakeVerboseMakefileFlag \ + -DMSVC_USE_MT:BOOL=$CMakeMsvcMtFlag \ + $CMakeSTLSoftVariable \ + "${CMakeGeneratorArgs[@]}" \ + -B "$CMakeDir" \ + -S "$Dir" \ + || exit 1 + status=0 if [ $RunMake -ne 0 ]; then - echo "Executing build (via command \`$MakeCmd\`)" + echo + echo "Executing build of ${ProjectNameClr} (via cmake --build)" - $MakeCmd + sis_cmake_build status=$? fi -cd ->/dev/null - if [ $VerboseMakefile -ne 0 ]; then - echo -e "contents of $CMakeDir:" - ls -al $CMakeDir + echo + echo -e "contents of ${CMakeDirClr}:" + ls -al "$CMakeDir" fi exit $status diff --git a/remove_cmake_artefacts.sh b/remove_cmake_artefacts.sh index 076a84a..377d3ab 100755 --- a/remove_cmake_artefacts.sh +++ b/remove_cmake_artefacts.sh @@ -1,12 +1,16 @@ #! /bin/bash -ScriptPath=$0 -Dir=$(cd $(dirname "$ScriptPath"); pwd) +# ########################################################## +# constants and variables + +Basename=$(basename "$0") +Dir=$(cd "$(dirname "$0")" && pwd) +CMakeDir=${SIS_CMAKE_BUILD_DIR:-$Dir/_build} ProjectNameFile="$Dir/.sis/project_name.txt" ProjectName=$(tr -d '[:space:]' < "$ProjectNameFile") -Basename=$(basename "$ScriptPath") -CMakeDir=${SIS_CMAKE_BUILD_DIR:-$Dir/_build} +ScriptPath=$0 +AlwaysUseColours=${SIS_CMAKE_ALWAYS_USE_COLOURS:-${SIS_ALWAYS_USE_COLOURS:-0}} Directories=( CMakeFiles Testing @@ -24,14 +28,73 @@ Files=( cmake_install.cmake install_manifest.txt ) +SisUseColours=0 + + +# ########################################################## +# colours +# +# Enable when tput is available and either: +# - AlwaysUseColours is set (overrides NO_COLOR; may set TERM if +# empty/dumb), or +# - NO_COLOR is unset, stdout is a TTY, and TERM is not dumb (union of +# collect-c's "TERM set + TTY" and cstring's "TTY" — empty TERM on a +# TTY is OK). + +SisClr_Blue= +SisClr_Bold= +SisClr_Green= +SisClr_None= +SisClr_Red= +SisClr_Yellow= + +for arg in "$@"; do + + case $arg in + --always-use-colors|--always-use-colours|-A) + + AlwaysUseColours=1 + ;; + esac +done + +if command -v tput >/dev/null 2>&1; then + + if [ $AlwaysUseColours -ne 0 ]; then + + if [ -z "${TERM:-}" ] || [ "$TERM" = "dumb" ]; then + + TERM=xterm-256color + fi + + SisUseColours=1 + elif [ -z "${NO_COLOR:-}" ] && [ -t 1 ] && [ "${TERM:-}" != "dumb" ]; then + + SisUseColours=1 + fi +fi + +if [ $SisUseColours -ne 0 ]; then + + SisClr_Blue=${FG_BLUE:-$(tput setaf 4)} + SisClr_Bold=${FD_BOLD:-$(tput bold)} + SisClr_Green=${FG_GREEN:-$(tput setaf 2)} + SisClr_None=${FD_NONE:-$(tput sgr0)} + SisClr_Red=${FG_RED:-$(tput setaf 1)} + SisClr_Yellow=${FG_YELLOW:-$(tput setaf 3)} +fi + +CMakeDirClr="${SisClr_Blue}${SisClr_Bold}${CMakeDir}${SisClr_None}" +ProjectNameClr="${SisClr_Blue}${SisClr_Bold}${ProjectName}${SisClr_None}" +ScriptPathClr="${SisClr_Blue}${SisClr_Bold}${ScriptPath}${SisClr_None}" # ########################################################## # operating environment detection -OsName="$(uname -s)" +OsName="$(uname -s 2>/dev/null || echo Unknown)" case "${OsName}" in - CYGWIN*|MINGW*|MSYS_NT*) + CYGWIN*|MINGW*|MSYS_NT*|Windows_NT) Directories+=( ARM64 @@ -43,9 +106,6 @@ case "${OsName}" in "*.sln" "*.vcxproj" ) - ;; - *) - ;; esac @@ -56,18 +116,27 @@ esac while [[ $# -gt 0 ]]; do case $1 in + --always-use-colors|--always-use-colours|-A) + + # AlwaysUseColours=1 - this is handled by the for loop above + ;; --help) [ -f "$Dir/.sis/script_info_lines.txt" ] && cat "$Dir/.sis/script_info_lines.txt" cat << EOF Removes all known CMake artefacts -$ScriptPath [ ... flags/options ... ] +${ScriptPath} [ ... flags/options ... ] Flags/options: behaviour: + -A + --always-use-colors + --always-use-colours + forces use of colours even when stdout is not a TTY + standard flags: @@ -80,7 +149,7 @@ EOF ;; *) - >&2 echo "$ScriptPath: unrecognised argument '$1'; use --help for usage" + >&2 echo "${ScriptPathClr}: unrecognised argument '${SisClr_Red}${SisClr_Bold}$1${SisClr_None}'; use --help for usage" exit 1 ;; @@ -95,59 +164,50 @@ done if [ ! -d "$CMakeDir" ]; then - echo "$ScriptPath: CMake build directory '$CMakeDir' not found so nothing to do; use script 'prepare_cmake.sh' if you wish to prepare CMake artefacts" + echo "${ScriptPathClr}: CMake build directory '${CMakeDirClr}' not found so nothing to do; use script 'prepare_cmake.sh' if you wish to prepare CMake artefacts" exit 0 -else - - echo "Removing all cmake artefacts in '$CMakeDir'" +fi - num_dirs_removed=0 - num_files_removed=0 +echo "Removing all ${ProjectNameClr} cmake artefacts in '${CMakeDirClr}'" - for d in ${Directories[@]} - do +num_dirs_removed=0 +num_files_removed=0 - fq_dir_path="$CMakeDir/$d" +for d in "${Directories[@]}"; do - [ -d "$fq_dir_path" ] || continue + fq_dir_path="$CMakeDir/$d" - echo "removing directory '$d'" + [ -d "$fq_dir_path" ] || continue - rm -dfr "$fq_dir_path" + echo "removing directory '$d'" - num_dirs_removed=$((num_dirs_removed+1)) - done + rm -dfr "$fq_dir_path" - cd "$CMakeDir" + num_dirs_removed=$((num_dirs_removed+1)) +done - for f in ${Files[@]} - do +for f in "${Files[@]}"; do - for fq_file_path in $f - do + for fq_file_path in "$CMakeDir"/$f; do - [ -f "$fq_file_path" ] || continue + [ -f "$fq_file_path" ] || continue - echo "removing file '$fq_file_path'" + echo "removing file '$fq_file_path'" - rm -f "$fq_file_path" + rm -f "$fq_file_path" - num_files_removed=$((num_files_removed+1)) - done + num_files_removed=$((num_files_removed+1)) done +done - cd ->/dev/null - - if [ 0 -eq $num_dirs_removed ] && [ 0 -eq $num_files_removed ]; then +if [ 0 -eq $num_dirs_removed ] && [ 0 -eq $num_files_removed ]; then - echo "nothing to do" - else + echo "nothing to do" +else - echo "removed $num_dirs_removed directories and $num_files_removed files" - fi + echo "removed $num_dirs_removed directories and $num_files_removed files" fi # ############################## end of file ############################# # - diff --git a/run_all_automated_tests.cmd b/run_all_automated_tests.cmd new file mode 100644 index 0000000..b6dd937 --- /dev/null +++ b/run_all_automated_tests.cmd @@ -0,0 +1,106 @@ +@echo off + +SETLOCAL + +SET SCRIPT_DIRECTORY=%~dp0 +SET SCRIPT_PATH_DOC=%~n0[%~x0] + +SET UnitOnly=0 +SET ComponentOnly=0 + +FOR %%a IN (%*) DO ( + + IF /I {--help}=={%%a} ( + + IF EXIST "%SCRIPT_DIRECTORY%.sis\script_info_lines.txt" ( + + type "%SCRIPT_DIRECTORY%.sis\script_info_lines.txt" + ) + ECHO ^ + +Runs all ^(matching^) automated test programs ^(unit and component^) ^ + +^ + +%SCRIPT_PATH_DOC% [ ... flags/options ... ] ^ + +^ + +Flags/options: ^ + + behaviour: ^ + +^ + + --unit-only ^ + + runs only unit-test programs ^ + +^ + + --component-only ^ + + runs only component-test programs ^ + +^ + + standard flags: ^ + +^ + + --help ^ + + displays this help and terminates ^ + + + EXIT /B 0 + ) ELSE IF /I {--unit-only}=={%%a} ( + + SET UnitOnly=1 + ) ELSE IF /I {--component-only}=={%%a} ( + + SET ComponentOnly=1 + ) ELSE ( + + ECHO "%SCRIPT_DIRECTORY%: unrecognised argument '%%a'; use --help for usage" 1>&2 + + EXIT /B 1 + ) +) + +IF %UnitOnly% NEQ 0 IF %ComponentOnly% NEQ 0 ( + + ECHO %SCRIPT_PATH_DOC%: --unit-only and --component-only are mutually exclusive 1>&2 + + EXIT /B 1 +) + +IF %UnitOnly% NEQ 0 ( + CALL "%SCRIPT_DIRECTORY%run_all_unit_tests.cmd" + EXIT /B %ERRORLEVEL% +) + +IF %ComponentOnly% NEQ 0 ( + CALL "%SCRIPT_DIRECTORY%run_all_component_tests.cmd" + EXIT /B %ERRORLEVEL% +) + +SET "ProjectName=" +FOR /F "usebackq delims=" %%p IN ("%SCRIPT_DIRECTORY%.sis\project_name.txt") DO SET "ProjectName=%%p" + +IF NOT DEFINED ProjectName ( + + ECHO %SCRIPT_PATH_DOC%: could not read project name from .sis\project_name.txt 1>&2 + + EXIT /B 1 +) + +ECHO Running all %ProjectName% automated test programs ^(unit and component^) + +CALL "%SCRIPT_DIRECTORY%run_all_unit_tests.cmd" +IF ERRORLEVEL 1 EXIT /B %ERRORLEVEL% + +CALL "%SCRIPT_DIRECTORY%run_all_component_tests.cmd" +EXIT /B %ERRORLEVEL% + +ENDLOCAL diff --git a/run_all_automated_tests.sh b/run_all_automated_tests.sh new file mode 100755 index 0000000..2c13b16 --- /dev/null +++ b/run_all_automated_tests.sh @@ -0,0 +1,180 @@ +#! /bin/bash + +# ########################################################## +# constants and variables + +Basename=$(basename "$0") +Dir=$(cd "$(dirname "$0")" && pwd) +CMakeDir=${SIS_CMAKE_BUILD_DIR:-$Dir/_build} +ProjectNameFile="$Dir/.sis/project_name.txt" +ProjectName=$(tr -d '[:space:]' < "$ProjectNameFile") +ScriptPath=$0 + +AlwaysUseColours=${SIS_CMAKE_ALWAYS_USE_COLOURS:-${SIS_ALWAYS_USE_COLOURS:-0}} +ComponentOnly=0 +ForwardedArgs=() +SisUseColours=0 +UnitOnly=0 + + +# ########################################################## +# colours +# +# Enable when tput is available and either: +# - AlwaysUseColours is set (overrides NO_COLOR; may set TERM if +# empty/dumb), or +# - NO_COLOR is unset, stdout is a TTY, and TERM is not dumb (union of +# collect-c's "TERM set + TTY" and cstring's "TTY" — empty TERM on a +# TTY is OK). + +SisClr_Blue= +SisClr_Bold= +SisClr_Green= +SisClr_None= +SisClr_Red= +SisClr_Yellow= + +for arg in "$@"; do + + case $arg in + --always-use-colors|--always-use-colours|-A) + + AlwaysUseColours=1 + ;; + esac +done + +if command -v tput >/dev/null 2>&1; then + + if [ $AlwaysUseColours -ne 0 ]; then + + if [ -z "${TERM:-}" ] || [ "$TERM" = "dumb" ]; then + + TERM=xterm-256color + fi + + SisUseColours=1 + elif [ -z "${NO_COLOR:-}" ] && [ -t 1 ] && [ "${TERM:-}" != "dumb" ]; then + + SisUseColours=1 + fi +fi + +if [ $SisUseColours -ne 0 ]; then + + SisClr_Blue=${FG_BLUE:-$(tput setaf 4)} + SisClr_Bold=${FD_BOLD:-$(tput bold)} + SisClr_Green=${FG_GREEN:-$(tput setaf 2)} + SisClr_None=${FD_NONE:-$(tput sgr0)} + SisClr_Red=${FG_RED:-$(tput setaf 1)} + SisClr_Yellow=${FG_YELLOW:-$(tput setaf 3)} +fi + +ProjectNameClr="${SisClr_Blue}${SisClr_Bold}${ProjectName}${SisClr_None}" +ScriptPathClr="${SisClr_Blue}${SisClr_Bold}${ScriptPath}${SisClr_None}" + + +# ########################################################## +# command-line handling + +while [[ $# -gt 0 ]]; do + + case $1 in + --always-use-colors|--always-use-colours|-A) + + # AlwaysUseColours=1 - handled above; forward so category runners see it + ForwardedArgs+=("$1") + ;; + --unit-only) + + UnitOnly=1 + ;; + --component-only) + + ComponentOnly=1 + ;; + --help) + + [ -f "$Dir/.sis/script_info_lines.txt" ] && cat "$Dir/.sis/script_info_lines.txt" + cat << EOF +Runs all (matching) automated test programs (unit and component) + +${ScriptPath} [ ... flags/options ... ] + +Flags/options: + + behaviour: + + -A + --always-use-colors + --always-use-colours + forces use of colours even when stdout is not a TTY + + --component-only + runs only component-test programs + + --unit-only + runs only unit-test programs + + (all other flags are forwarded to the category runner script) + + + standard flags: + + --help + displays this help and terminates + +EOF + + exit 0 + ;; + *) + + ForwardedArgs+=("$1") + ;; + esac + + shift +done + +if [ $UnitOnly -ne 0 ] && [ $ComponentOnly -ne 0 ]; then + + >&2 echo "${ScriptPathClr}: ${SisClr_Red}${SisClr_Bold}--unit-only${SisClr_None} and ${SisClr_Red}${SisClr_Bold}--component-only${SisClr_None} are mutually exclusive" + + exit 1 +fi + + +# ########################################################## +# main() + +status=0 + +if [ $UnitOnly -ne 0 ]; then + + "$Dir/run_all_unit_tests.sh" "${ForwardedArgs[@]}" + exit $? +fi + +if [ $ComponentOnly -ne 0 ]; then + + "$Dir/run_all_component_tests.sh" "${ForwardedArgs[@]}" + exit $? +fi + +echo +echo "Running all ${ProjectNameClr} automated test programs (unit and component)" + +"$Dir/run_all_unit_tests.sh" "${ForwardedArgs[@]}" +status=$? + +if [ $status -eq 0 ]; then + + "$Dir/run_all_component_tests.sh" "${ForwardedArgs[@]}" + status=$? +fi + +exit $status + + +# ############################## end of file ############################# # diff --git a/run_all_component_tests.cmd b/run_all_component_tests.cmd new file mode 100644 index 0000000..970c9ba --- /dev/null +++ b/run_all_component_tests.cmd @@ -0,0 +1,94 @@ +@echo off + +SETLOCAL + +SET SCRIPT_DIRECTORY=%~dp0 +SET SCRIPT_PATH_DOC=%~n0[%~x0] + +IF DEFINED SIS_CMAKE_BUILD_DIR ( + + SET CMAKE_DIR=%SIS_CMAKE_BUILD_DIR% +) ELSE ( + + SET CMAKE_DIR=%SCRIPT_DIRECTORY%_build +) + +FOR %%a IN (%*) DO ( + + IF /I {--help}=={%%a} ( + + IF EXIST "%SCRIPT_DIRECTORY%.sis\script_info_lines.txt" ( + + type "%SCRIPT_DIRECTORY%.sis\script_info_lines.txt" + ) + ECHO ^ + +Runs all ^(matching^) component-test programs ^ + +^ + +%SCRIPT_PATH_DOC% [ ... flags/options ... ] ^ + +^ + +Flags/options: ^ + + behaviour: ^ + +^ + + --component-only ^ + + accepted for compatibility; this script always runs component tests only ^ + +^ + + standard flags: ^ + +^ + + --help ^ + + displays this help and terminates ^ + + + EXIT /B 0 + ) ELSE IF /I {--component-only}=={%%a} ( + + REM Benign: this script is already component-only + ) ELSE ( + + ECHO "%SCRIPT_DIRECTORY%: unrecognised argument '%%a'; use --help for usage" 1>&2 + + EXIT /B 1 + ) +) + +if NOT EXIST "%CMAKE_DIR%" ( + + ECHO "CMake build directory '%CMAKE_DIR%' does not exist" + + EXIT /B 1 +) + +SET "ProjectName=" +FOR /F "usebackq delims=" %%p IN ("%SCRIPT_DIRECTORY%.sis\project_name.txt") DO SET "ProjectName=%%p" + +IF NOT DEFINED ProjectName ( + + ECHO %SCRIPT_PATH_DOC%: could not read project name from .sis\project_name.txt 1>&2 + + EXIT /B 1 +) + +ECHO Running all %ProjectName% component-test programs + +FOR /F "usebackq" %%f IN (`DIR /A:-D /B /S "%CMAKE_DIR%" ^| FINDSTR /I test.*component.*\.exe$`) DO ( + + ECHO . + ECHO executing %%f + %%f + IF ERRORLEVEL 1 EXIT /B %ERRORLEVEL% +) + +ENDLOCAL diff --git a/run_all_component_tests.sh b/run_all_component_tests.sh new file mode 100755 index 0000000..c0bd27e --- /dev/null +++ b/run_all_component_tests.sh @@ -0,0 +1,300 @@ +#! /bin/bash + +# ########################################################## +# functions - 1 + +sis_cmake_is_truey() { + case "$(printf '%s' "${1:-}" | tr '[:upper:]' '[:lower:]')" in + + 1|ok|on|true|yes|y) + + return 0 + ;; + *) + + return 1 + ;; + esac +} + + +# ########################################################## +# constants and variables + +Basename=$(basename "$0") +Dir=$(cd "$(dirname "$0")" && pwd) +CMakeDir=${SIS_CMAKE_BUILD_DIR:-$Dir/_build} +ProjectNameFile="$Dir/.sis/project_name.txt" +ProjectName=$(tr -d '[:space:]' < "$ProjectNameFile") +ScriptPath=$0 + +AlwaysUseColours=${SIS_CMAKE_ALWAYS_USE_COLOURS:-${SIS_ALWAYS_USE_COLOURS:-0}} +ListOnly=0 +RunMake=1 +SisUseColours=0 +Verbosity=${XTESTS_VERBOSITY:-${TEST_VERBOSITY:-3}} + + +# ########################################################## +# colours +# +# Enable when tput is available and either: +# - AlwaysUseColours is set (overrides NO_COLOR; may set TERM if +# empty/dumb), or +# - NO_COLOR is unset, stdout is a TTY, and TERM is not dumb (union of +# collect-c's "TERM set + TTY" and cstring's "TTY" — empty TERM on a +# TTY is OK). + +SisClr_Blue= +SisClr_Bold= +SisClr_Green= +SisClr_None= +SisClr_Red= +SisClr_Yellow= + +for arg in "$@"; do + + case $arg in + --always-use-colors|--always-use-colours|-A) + + AlwaysUseColours=1 + ;; + esac +done + +if command -v tput >/dev/null 2>&1; then + + if [ $AlwaysUseColours -ne 0 ]; then + + if [ -z "${TERM:-}" ] || [ "$TERM" = "dumb" ]; then + + TERM=xterm-256color + fi + + SisUseColours=1 + elif [ -z "${NO_COLOR:-}" ] && [ -t 1 ] && [ "${TERM:-}" != "dumb" ]; then + + SisUseColours=1 + fi +fi + +if [ $SisUseColours -ne 0 ]; then + + SisClr_Blue=${FG_BLUE:-$(tput setaf 4)} + SisClr_Bold=${FD_BOLD:-$(tput bold)} + SisClr_Green=${FG_GREEN:-$(tput setaf 2)} + SisClr_None=${FD_NONE:-$(tput sgr0)} + SisClr_Red=${FG_RED:-$(tput setaf 1)} + SisClr_Yellow=${FG_YELLOW:-$(tput setaf 3)} +fi + +CMakeDirClr="${SisClr_Blue}${SisClr_Bold}${CMakeDir}${SisClr_None}" +ProjectNameClr="${SisClr_Blue}${SisClr_Bold}${ProjectName}${SisClr_None}" +ScriptPathClr="${SisClr_Blue}${SisClr_Bold}${ScriptPath}${SisClr_None}" + + +# ########################################################## +# functions - 2 + +sis_cmake_build() { + + local config="${SIS_CMAKE_CONFIG:-Release}" + local args=(--build "$CMakeDir") + if [ -f "$CMakeDir/CMakeCache.txt" ] && grep -q '^CMAKE_CONFIGURATION_TYPES:' "$CMakeDir/CMakeCache.txt" 2>/dev/null; then + + args+=(--config "$config") + fi + if [ "$#" -gt 0 ]; then + + local t + for t in "$@"; do + + args+=(--target "$t") + done + fi + + cmake "${args[@]}" +} + + +# ########################################################## +# command-line handling + +while [[ $# -gt 0 ]]; do + + case $1 in + --always-use-colors|--always-use-colours|-A) + + # AlwaysUseColours=1 - this is handled by the for loop above + ;; + --component-only) + + # Benign: this script is already component-only (aggregate / CI may + # pass it) + ;; + --list-only|-l) + + ListOnly=1 + ;; + --no-make|-M) + + RunMake=0 + ;; + --verbosity) + + shift + Verbosity=$1 + ;; + --help) + + [ -f "$Dir/.sis/script_info_lines.txt" ] && cat "$Dir/.sis/script_info_lines.txt" + cat << EOF +Runs all (matching) component-test programs + +${ScriptPath} [ ... flags/options ... ] + +Flags/options: + + behaviour: + + -A + --always-use-colors + --always-use-colours + forces use of colours even when stdout is not a TTY + + --component-only + accepted for compatibility; this script always runs component tests + only + + -l + --list-only + lists the target programs but does not execute them + + -M + --no-make + does not execute a build before running programs + + --verbosity + specifies an explicit verbosity, forwarded to each program + + + standard flags: + + --help + displays this help and terminates + +EOF + + exit 0 + ;; + *) + + >&2 echo "${ScriptPathClr}: unrecognised argument '${SisClr_Red}${SisClr_Bold}$1${SisClr_None}'; use --help for usage" + + exit 1 + ;; + esac + + shift +done + + +# ########################################################## +# main() + +status=0 + +if [ $RunMake -ne 0 ]; then + + if [ $ListOnly -eq 0 ]; then + + echo + echo "Executing build of ${ProjectNameClr} (via cmake --build) and then running all component-test programs" + + mkdir -p "$CMakeDir" || exit 1 + + if [ ! -f "$CMakeDir/CMakeCache.txt" ]; then + + >&2 echo "${ScriptPathClr}: '${CMakeDirClr}' is not configured; use prepare_cmake.sh first" + + exit 1 + fi + + sis_cmake_build + status=$? + fi +else + + if [ ! -d "$CMakeDir" ] || [ ! -f "$CMakeDir/CMakeCache.txt" ]; then + + >&2 echo "${ScriptPathClr}: cannot run in '--no-make' mode without a previous successful configure/build" + + exit 1 + fi +fi + +if [ $status -eq 0 ]; then + + if [ $ListOnly -ne 0 ]; then + + echo + echo "Listing all ${ProjectNameClr} component-test programs" + else + + echo + echo "Running all ${ProjectNameClr} component-test programs" + fi + + NumPrograms=0 + + while IFS= read -r -d '' f; do + + case "$f" in + *.pdb|*.ilk|*.log|*.obj|*.o) + continue + ;; + esac + + NumPrograms=$((NumPrograms + 1)) + + fClr="${SisClr_Blue}${SisClr_Bold}${f}${SisClr_None}" + + if [ $ListOnly -ne 0 ]; then + + echo "would execute ${fClr}:" + + continue + fi + + if [ $Verbosity -ge 3 ]; then + + echo + fi + if [ $Verbosity -ge 2 ]; then + + echo "executing ${fClr}:" + fi + + if "$f" --verbosity="$Verbosity"; then + + : + else + + status=$? + + break 1 + fi + done < <(find "$CMakeDir" -type f \( -name 'test_component*' -o -name 'test.component.*' \) \( -perm -100 -o -name '*.exe' \) -print0 2>/dev/null | sort -z) + + if [ $NumPrograms -eq 0 ]; then + + echo "${ScriptPathClr}: found no component-test programs under '${CMakeDirClr}' (none found)" + + exit 0 + fi +fi + +exit $status + + +# ############################## end of file ############################# # diff --git a/run_all_examples.cmd b/run_all_examples.cmd new file mode 100644 index 0000000..11273cb --- /dev/null +++ b/run_all_examples.cmd @@ -0,0 +1,89 @@ +@echo off + +SETLOCAL + +SET SCRIPT_DIRECTORY=%~dp0 +SET SCRIPT_PATH_DOC=%~n0[%~x0] + +IF DEFINED SIS_CMAKE_BUILD_DIR ( + + SET CMAKE_DIR=%SIS_CMAKE_BUILD_DIR% +) ELSE ( + + SET CMAKE_DIR=%SCRIPT_DIRECTORY%_build +) + +FOR %%a IN (%*) DO ( + + IF /I {--help}=={%%a} ( + + IF EXIST "%SCRIPT_DIRECTORY%.sis\script_info_lines.txt" ( + + type "%SCRIPT_DIRECTORY%.sis\script_info_lines.txt" + ) + ECHO ^ + +Runs all ^(matching^) example programs ^ + +^ + +%SCRIPT_PATH_DOC% [ ... flags/options ... ] ^ + +^ + +Flags/options: ^ + + behaviour: ^ + +^ + + standard flags: ^ + +^ + + --help ^ + + displays this help and terminates ^ + + + EXIT /B 0 + ) ELSE ( + + ECHO "%SCRIPT_DIRECTORY%: unrecognised argument '%%a'; use --help for usage" 1>&2 + + EXIT /B 1 + ) +) + +if NOT EXIST "%CMAKE_DIR%" ( + + ECHO "CMake build directory '%CMAKE_DIR%' does not exist" + + EXIT /B 1 +) + +SET "ProjectName=" +FOR /F "usebackq delims=" %%p IN ("%SCRIPT_DIRECTORY%.sis\project_name.txt") DO SET "ProjectName=%%p" + +IF NOT DEFINED ProjectName ( + + ECHO %SCRIPT_PATH_DOC%: could not read project name from .sis\project_name.txt 1>&2 + + EXIT /B 1 +) + +REM Examples that require human input may honour SIS_EXAMPLE_SMOKE for a +REM no-arg built-in tmpfile demo (see example.c.cstring_vector). +SET SIS_EXAMPLE_SMOKE=1 + +ECHO Running all %ProjectName% example programs + +FOR /F "usebackq" %%f IN (`DIR /A:-D /B /S "%CMAKE_DIR%" ^| FINDSTR /I example.*\.exe$`) DO ( + + ECHO . + ECHO executing %%f + %%f + IF ERRORLEVEL 1 EXIT /B %ERRORLEVEL% +) + +ENDLOCAL diff --git a/run_all_examples.sh b/run_all_examples.sh index bb7ef70..967f82c 100755 --- a/run_all_examples.sh +++ b/run_all_examples.sh @@ -1,16 +1,119 @@ #! /bin/bash -ScriptPath=$0 -Dir=$(cd $(dirname "$ScriptPath"); pwd) +# ########################################################## +# functions - 1 + +sis_cmake_is_truey() { + case "$(printf '%s' "${1:-}" | tr '[:upper:]' '[:lower:]')" in + + 1|ok|on|true|yes|y) + + return 0 + ;; + *) + + return 1 + ;; + esac +} + + +# ########################################################## +# constants and variables + +Basename=$(basename "$0") +Dir=$(cd "$(dirname "$0")" && pwd) +CMakeDir=${SIS_CMAKE_BUILD_DIR:-$Dir/_build} ProjectNameFile="$Dir/.sis/project_name.txt" ProjectName=$(tr -d '[:space:]' < "$ProjectNameFile") -Basename=$(basename "$ScriptPath") -CMakeDir=${SIS_CMAKE_BUILD_DIR:-$Dir/_build} -[[ -n "$MSYSTEM" ]] && DefaultMakeCmd=mingw32-make.exe || DefaultMakeCmd=make -MakeCmd=${SIS_CMAKE_MAKE_COMMAND:-${SIS_CMAKE_COMMAND:-$DefaultMakeCmd}} +ScriptPath=$0 +AlwaysUseColours=${SIS_CMAKE_ALWAYS_USE_COLOURS:-${SIS_ALWAYS_USE_COLOURS:-0}} ListOnly=0 RunMake=1 +SisUseColours=0 + + +# ########################################################## +# colours +# +# Enable when tput is available and either: +# - AlwaysUseColours is set (overrides NO_COLOR; may set TERM if +# empty/dumb), or +# - NO_COLOR is unset, stdout is a TTY, and TERM is not dumb (union of +# collect-c's "TERM set + TTY" and cstring's "TTY" — empty TERM on a +# TTY is OK). + +SisClr_Blue= +SisClr_Bold= +SisClr_Green= +SisClr_None= +SisClr_Red= +SisClr_Yellow= + +for arg in "$@"; do + + case $arg in + --always-use-colors|--always-use-colours|-A) + + AlwaysUseColours=1 + ;; + esac +done + +if command -v tput >/dev/null 2>&1; then + + if [ $AlwaysUseColours -ne 0 ]; then + + if [ -z "${TERM:-}" ] || [ "$TERM" = "dumb" ]; then + + TERM=xterm-256color + fi + + SisUseColours=1 + elif [ -z "${NO_COLOR:-}" ] && [ -t 1 ] && [ "${TERM:-}" != "dumb" ]; then + + SisUseColours=1 + fi +fi + +if [ $SisUseColours -ne 0 ]; then + + SisClr_Blue=${FG_BLUE:-$(tput setaf 4)} + SisClr_Bold=${FD_BOLD:-$(tput bold)} + SisClr_Green=${FG_GREEN:-$(tput setaf 2)} + SisClr_None=${FD_NONE:-$(tput sgr0)} + SisClr_Red=${FG_RED:-$(tput setaf 1)} + SisClr_Yellow=${FG_YELLOW:-$(tput setaf 3)} +fi + +CMakeDirClr="${SisClr_Blue}${SisClr_Bold}${CMakeDir}${SisClr_None}" +ProjectNameClr="${SisClr_Blue}${SisClr_Bold}${ProjectName}${SisClr_None}" +ScriptPathClr="${SisClr_Blue}${SisClr_Bold}${ScriptPath}${SisClr_None}" + + +# ########################################################## +# functions - 2 + +sis_cmake_build() { + + local config="${SIS_CMAKE_CONFIG:-Release}" + local args=(--build "$CMakeDir") + if [ -f "$CMakeDir/CMakeCache.txt" ] && grep -q '^CMAKE_CONFIGURATION_TYPES:' "$CMakeDir/CMakeCache.txt" 2>/dev/null; then + + args+=(--config "$config") + fi + if [ "$#" -gt 0 ]; then + + local t + for t in "$@"; do + + args+=(--target "$t") + done + fi + + cmake "${args[@]}" +} # ########################################################## @@ -19,6 +122,10 @@ RunMake=1 while [[ $# -gt 0 ]]; do case $1 in + --always-use-colors|--always-use-colours|-A) + + # AlwaysUseColours=1 - this is handled by the for loop above + ;; --list-only|-l) ListOnly=1 @@ -31,21 +138,26 @@ while [[ $# -gt 0 ]]; do [ -f "$Dir/.sis/script_info_lines.txt" ] && cat "$Dir/.sis/script_info_lines.txt" cat << EOF -Runs all example programs +Runs all (matching) example programs -$ScriptPath [ ... flags/options ... ] +${ScriptPath} [ ... flags/options ... ] Flags/options: behaviour: + -A + --always-use-colors + --always-use-colours + forces use of colours even when stdout is not a TTY + -l --list-only lists the target programs but does not execute them -M --no-make - does not execute CMake and make before running tests + does not execute a build before running programs standard flags: @@ -59,7 +171,7 @@ EOF ;; *) - >&2 echo "$ScriptPath: unrecognised argument '$1'; use --help for usage" + >&2 echo "${ScriptPathClr}: unrecognised argument '${SisClr_Red}${SisClr_Bold}$1${SisClr_None}'; use --help for usage" exit 1 ;; @@ -78,22 +190,28 @@ if [ $RunMake -ne 0 ]; then if [ $ListOnly -eq 0 ]; then - echo "Executing build (via command \`$MakeCmd\`) and then running all example programs" + echo + echo "Executing build of ${ProjectNameClr} (via cmake --build) and then running all example programs" - mkdir -p $CMakeDir || exit 1 + mkdir -p "$CMakeDir" || exit 1 - cd $CMakeDir + if [ ! -f "$CMakeDir/CMakeCache.txt" ]; then - $MakeCmd - status=$? + >&2 echo "${ScriptPathClr}: '${CMakeDirClr}' is not configured; use prepare_cmake.sh first" + + exit 1 + fi - cd ->/dev/null + sis_cmake_build + status=$? fi else - if [ ! -d "$CMakeDir" ] || [ ! -f "$CMakeDir/CMakeCache.txt" ] || [ ! -d "$CMakeDir/CMakeFiles" ]; then + if [ ! -d "$CMakeDir" ] || [ ! -f "$CMakeDir/CMakeCache.txt" ]; then + + >&2 echo "${ScriptPathClr}: cannot run in '--no-make' mode without a previous successful configure/build" - >&2 echo "$ScriptPath: cannot run in '--no-make' mode without a previous successful build step" + exit 1 fi fi @@ -101,32 +219,62 @@ if [ $status -eq 0 ]; then if [ $ListOnly -ne 0 ]; then - echo "Listing all example programs" + echo + echo "Listing all ${ProjectNameClr} example programs" else - echo "Running all example programs" + echo + echo "Running all ${ProjectNameClr} example programs" fi - for f in $(find $CMakeDir -type f '(' -name 'example.c.*' -o -name 'example.cpp.*' ')' -exec test -x {} \; -print) - do + # Examples that require human input may honour SIS_EXAMPLE_SMOKE for a + # no-arg built-in tmpfile demo (see example.c.cstring_vector). + export SIS_EXAMPLE_SMOKE=1 + + NumPrograms=0 + + while IFS= read -r -d '' f; do + + case "$f" in + *.pdb|*.ilk|*.log|*.obj|*.o) + continue + ;; + esac + + NumPrograms=$((NumPrograms + 1)) + + fClr="${SisClr_Blue}${SisClr_Bold}${f}${SisClr_None}" if [ $ListOnly -ne 0 ]; then - echo "would execute $f:" + echo "would execute ${fClr}:" continue fi echo - echo "executing $f:" + echo "executing ${fClr}:" - # NOTE: we do not break on fail, because, this being a unit-testing library, the scratch-tests actually fail - $f - done + if "$f"; then + + : + else + + status=$? + + break 1 + fi + done < <(find "$CMakeDir" -type f \( -name 'example*' ! -name '*.md' \) \( -perm -100 -o -name '*.exe' \) -print0 2>/dev/null | sort -z) + + if [ $NumPrograms -eq 0 ]; then + + echo "${ScriptPathClr}: found no example programs under '${CMakeDirClr}' (none found)" + + exit 0 + fi fi exit $status # ############################## end of file ############################# # - diff --git a/run_all_performance_tests.cmd b/run_all_performance_tests.cmd new file mode 100644 index 0000000..ae97766 --- /dev/null +++ b/run_all_performance_tests.cmd @@ -0,0 +1,85 @@ +@echo off + +SETLOCAL + +SET SCRIPT_DIRECTORY=%~dp0 +SET SCRIPT_PATH_DOC=%~n0[%~x0] + +IF DEFINED SIS_CMAKE_BUILD_DIR ( + + SET CMAKE_DIR=%SIS_CMAKE_BUILD_DIR% +) ELSE ( + + SET CMAKE_DIR=%SCRIPT_DIRECTORY%_build +) + +FOR %%a IN (%*) DO ( + + IF /I {--help}=={%%a} ( + + IF EXIST "%SCRIPT_DIRECTORY%.sis\script_info_lines.txt" ( + + type "%SCRIPT_DIRECTORY%.sis\script_info_lines.txt" + ) + ECHO ^ + +Runs all ^(matching^) performance-test programs ^ + +^ + +%SCRIPT_PATH_DOC% [ ... flags/options ... ] ^ + +^ + +Flags/options: ^ + + behaviour: ^ + +^ + + standard flags: ^ + +^ + + --help ^ + + displays this help and terminates ^ + + + EXIT /B 0 + ) ELSE ( + + ECHO "%SCRIPT_DIRECTORY%: unrecognised argument '%%a'; use --help for usage" 1>&2 + + EXIT /B 1 + ) +) + +if NOT EXIST "%CMAKE_DIR%" ( + + ECHO "CMake build directory '%CMAKE_DIR%' does not exist" + + EXIT /B 1 +) + +SET "ProjectName=" +FOR /F "usebackq delims=" %%p IN ("%SCRIPT_DIRECTORY%.sis\project_name.txt") DO SET "ProjectName=%%p" + +IF NOT DEFINED ProjectName ( + + ECHO %SCRIPT_PATH_DOC%: could not read project name from .sis\project_name.txt 1>&2 + + EXIT /B 1 +) + +ECHO Running all %ProjectName% performance-test programs + +FOR /F "usebackq" %%f IN (`DIR /A:-D /B /S "%CMAKE_DIR%" ^| FINDSTR /I test.*performance.*\.exe$`) DO ( + + ECHO . + ECHO executing %%f + %%f + IF ERRORLEVEL 1 EXIT /B %ERRORLEVEL% +) + +ENDLOCAL diff --git a/run_all_performance_tests.sh b/run_all_performance_tests.sh new file mode 100755 index 0000000..3feaaff --- /dev/null +++ b/run_all_performance_tests.sh @@ -0,0 +1,276 @@ +#! /bin/bash + +# ########################################################## +# functions - 1 + +sis_cmake_is_truey() { + case "$(printf '%s' "${1:-}" | tr '[:upper:]' '[:lower:]')" in + + 1|ok|on|true|yes|y) + + return 0 + ;; + *) + + return 1 + ;; + esac +} + + +# ########################################################## +# constants and variables + +Basename=$(basename "$0") +Dir=$(cd "$(dirname "$0")" && pwd) +CMakeDir=${SIS_CMAKE_BUILD_DIR:-$Dir/_build} +ProjectNameFile="$Dir/.sis/project_name.txt" +ProjectName=$(tr -d '[:space:]' < "$ProjectNameFile") +ScriptPath=$0 + +AlwaysUseColours=${SIS_CMAKE_ALWAYS_USE_COLOURS:-${SIS_ALWAYS_USE_COLOURS:-0}} +ListOnly=0 +RunMake=1 +SisUseColours=0 + + +# ########################################################## +# colours +# +# Enable when tput is available and either: +# - AlwaysUseColours is set (overrides NO_COLOR; may set TERM if +# empty/dumb), or +# - NO_COLOR is unset, stdout is a TTY, and TERM is not dumb (union of +# collect-c's "TERM set + TTY" and cstring's "TTY" — empty TERM on a +# TTY is OK). + +SisClr_Blue= +SisClr_Bold= +SisClr_Green= +SisClr_None= +SisClr_Red= +SisClr_Yellow= + +for arg in "$@"; do + + case $arg in + --always-use-colors|--always-use-colours|-A) + + AlwaysUseColours=1 + ;; + esac +done + +if command -v tput >/dev/null 2>&1; then + + if [ $AlwaysUseColours -ne 0 ]; then + + if [ -z "${TERM:-}" ] || [ "$TERM" = "dumb" ]; then + + TERM=xterm-256color + fi + + SisUseColours=1 + elif [ -z "${NO_COLOR:-}" ] && [ -t 1 ] && [ "${TERM:-}" != "dumb" ]; then + + SisUseColours=1 + fi +fi + +if [ $SisUseColours -ne 0 ]; then + + SisClr_Blue=${FG_BLUE:-$(tput setaf 4)} + SisClr_Bold=${FD_BOLD:-$(tput bold)} + SisClr_Green=${FG_GREEN:-$(tput setaf 2)} + SisClr_None=${FD_NONE:-$(tput sgr0)} + SisClr_Red=${FG_RED:-$(tput setaf 1)} + SisClr_Yellow=${FG_YELLOW:-$(tput setaf 3)} +fi + +CMakeDirClr="${SisClr_Blue}${SisClr_Bold}${CMakeDir}${SisClr_None}" +ProjectNameClr="${SisClr_Blue}${SisClr_Bold}${ProjectName}${SisClr_None}" +ScriptPathClr="${SisClr_Blue}${SisClr_Bold}${ScriptPath}${SisClr_None}" + + +# ########################################################## +# functions - 2 + +sis_cmake_build() { + + local config="${SIS_CMAKE_CONFIG:-Release}" + local args=(--build "$CMakeDir") + if [ -f "$CMakeDir/CMakeCache.txt" ] && grep -q '^CMAKE_CONFIGURATION_TYPES:' "$CMakeDir/CMakeCache.txt" 2>/dev/null; then + + args+=(--config "$config") + fi + if [ "$#" -gt 0 ]; then + + local t + for t in "$@"; do + + args+=(--target "$t") + done + fi + + cmake "${args[@]}" +} + + +# ########################################################## +# command-line handling + +while [[ $# -gt 0 ]]; do + + case $1 in + --always-use-colors|--always-use-colours|-A) + + # AlwaysUseColours=1 - this is handled by the for loop above + ;; + --list-only|-l) + + ListOnly=1 + ;; + --no-make|-M) + + RunMake=0 + ;; + --help) + + [ -f "$Dir/.sis/script_info_lines.txt" ] && cat "$Dir/.sis/script_info_lines.txt" + cat << EOF +Runs all (matching) performance-test programs + +${ScriptPath} [ ... flags/options ... ] + +Flags/options: + + behaviour: + + -A + --always-use-colors + --always-use-colours + forces use of colours even when stdout is not a TTY + + -l + --list-only + lists the target programs but does not execute them + + -M + --no-make + does not execute a build before running programs + + + standard flags: + + --help + displays this help and terminates + +EOF + + exit 0 + ;; + *) + + >&2 echo "${ScriptPathClr}: unrecognised argument '${SisClr_Red}${SisClr_Bold}$1${SisClr_None}'; use --help for usage" + + exit 1 + ;; + esac + + shift +done + + +# ########################################################## +# main() + +status=0 + +if [ $RunMake -ne 0 ]; then + + if [ $ListOnly -eq 0 ]; then + + echo + echo "Executing build of ${ProjectNameClr} (via cmake --build) and then running all performance-test programs" + + mkdir -p "$CMakeDir" || exit 1 + + if [ ! -f "$CMakeDir/CMakeCache.txt" ]; then + + >&2 echo "${ScriptPathClr}: '${CMakeDirClr}' is not configured; use prepare_cmake.sh first" + + exit 1 + fi + + sis_cmake_build + status=$? + fi +else + + if [ ! -d "$CMakeDir" ] || [ ! -f "$CMakeDir/CMakeCache.txt" ]; then + + >&2 echo "${ScriptPathClr}: cannot run in '--no-make' mode without a previous successful configure/build" + + exit 1 + fi +fi + +if [ $status -eq 0 ]; then + + if [ $ListOnly -ne 0 ]; then + + echo + echo "Listing all ${ProjectNameClr} performance-test programs" + else + + echo + echo "Running all ${ProjectNameClr} performance-test programs" + fi + + NumPrograms=0 + + while IFS= read -r -d '' f; do + + case "$f" in + *.pdb|*.ilk|*.log|*.obj|*.o) + continue + ;; + esac + + NumPrograms=$((NumPrograms + 1)) + + fClr="${SisClr_Blue}${SisClr_Bold}${f}${SisClr_None}" + + if [ $ListOnly -ne 0 ]; then + + echo "would execute ${fClr}:" + + continue + fi + + echo + echo "executing ${fClr}:" + + if "$f"; then + + : + else + + status=$? + + break 1 + fi + done < <(find "$CMakeDir" -type f \( -name 'test_performance*' -o -name 'test.performance.*' \) \( -perm -100 -o -name '*.exe' \) -print0 2>/dev/null | sort -z) + + if [ $NumPrograms -eq 0 ]; then + + echo "${ScriptPathClr}: found no performance-test programs under '${CMakeDirClr}' (none found)" + + exit 0 + fi +fi + +exit $status + + +# ############################## end of file ############################# # diff --git a/run_all_scratch_tests.cmd b/run_all_scratch_tests.cmd new file mode 100644 index 0000000..9b05623 --- /dev/null +++ b/run_all_scratch_tests.cmd @@ -0,0 +1,85 @@ +@echo off + +SETLOCAL + +SET SCRIPT_DIRECTORY=%~dp0 +SET SCRIPT_PATH_DOC=%~n0[%~x0] + +IF DEFINED SIS_CMAKE_BUILD_DIR ( + + SET CMAKE_DIR=%SIS_CMAKE_BUILD_DIR% +) ELSE ( + + SET CMAKE_DIR=%SCRIPT_DIRECTORY%_build +) + +FOR %%a IN (%*) DO ( + + IF /I {--help}=={%%a} ( + + IF EXIST "%SCRIPT_DIRECTORY%.sis\script_info_lines.txt" ( + + type "%SCRIPT_DIRECTORY%.sis\script_info_lines.txt" + ) + ECHO ^ + +Runs all ^(matching^) scratch-test programs ^ + +^ + +%SCRIPT_PATH_DOC% [ ... flags/options ... ] ^ + +^ + +Flags/options: ^ + + behaviour: ^ + +^ + + standard flags: ^ + +^ + + --help ^ + + displays this help and terminates ^ + + + EXIT /B 0 + ) ELSE ( + + ECHO "%SCRIPT_DIRECTORY%: unrecognised argument '%%a'; use --help for usage" 1>&2 + + EXIT /B 1 + ) +) + +if NOT EXIST "%CMAKE_DIR%" ( + + ECHO "CMake build directory '%CMAKE_DIR%' does not exist" + + EXIT /B 1 +) + +SET "ProjectName=" +FOR /F "usebackq delims=" %%p IN ("%SCRIPT_DIRECTORY%.sis\project_name.txt") DO SET "ProjectName=%%p" + +IF NOT DEFINED ProjectName ( + + ECHO %SCRIPT_PATH_DOC%: could not read project name from .sis\project_name.txt 1>&2 + + EXIT /B 1 +) + +ECHO Running all %ProjectName% scratch-test programs + +FOR /F "usebackq" %%f IN (`DIR /A:-D /B /S "%CMAKE_DIR%" ^| FINDSTR /I test.*scratch.*\.exe$`) DO ( + + ECHO . + ECHO executing %%f + %%f + IF ERRORLEVEL 1 EXIT /B %ERRORLEVEL% +) + +ENDLOCAL diff --git a/run_all_scratch_tests.sh b/run_all_scratch_tests.sh index 25aa4c1..5e6659a 100755 --- a/run_all_scratch_tests.sh +++ b/run_all_scratch_tests.sh @@ -1,16 +1,119 @@ #! /bin/bash -ScriptPath=$0 -Dir=$(cd $(dirname "$ScriptPath"); pwd) +# ########################################################## +# functions - 1 + +sis_cmake_is_truey() { + case "$(printf '%s' "${1:-}" | tr '[:upper:]' '[:lower:]')" in + + 1|ok|on|true|yes|y) + + return 0 + ;; + *) + + return 1 + ;; + esac +} + + +# ########################################################## +# constants and variables + +Basename=$(basename "$0") +Dir=$(cd "$(dirname "$0")" && pwd) +CMakeDir=${SIS_CMAKE_BUILD_DIR:-$Dir/_build} ProjectNameFile="$Dir/.sis/project_name.txt" ProjectName=$(tr -d '[:space:]' < "$ProjectNameFile") -Basename=$(basename "$ScriptPath") -CMakeDir=${SIS_CMAKE_BUILD_DIR:-$Dir/_build} -[[ -n "$MSYSTEM" ]] && DefaultMakeCmd=mingw32-make.exe || DefaultMakeCmd=make -MakeCmd=${SIS_CMAKE_MAKE_COMMAND:-${SIS_CMAKE_COMMAND:-$DefaultMakeCmd}} +ScriptPath=$0 +AlwaysUseColours=${SIS_CMAKE_ALWAYS_USE_COLOURS:-${SIS_ALWAYS_USE_COLOURS:-0}} ListOnly=0 RunMake=1 +SisUseColours=0 + + +# ########################################################## +# colours +# +# Enable when tput is available and either: +# - AlwaysUseColours is set (overrides NO_COLOR; may set TERM if +# empty/dumb), or +# - NO_COLOR is unset, stdout is a TTY, and TERM is not dumb (union of +# collect-c's "TERM set + TTY" and cstring's "TTY" — empty TERM on a +# TTY is OK). + +SisClr_Blue= +SisClr_Bold= +SisClr_Green= +SisClr_None= +SisClr_Red= +SisClr_Yellow= + +for arg in "$@"; do + + case $arg in + --always-use-colors|--always-use-colours|-A) + + AlwaysUseColours=1 + ;; + esac +done + +if command -v tput >/dev/null 2>&1; then + + if [ $AlwaysUseColours -ne 0 ]; then + + if [ -z "${TERM:-}" ] || [ "$TERM" = "dumb" ]; then + + TERM=xterm-256color + fi + + SisUseColours=1 + elif [ -z "${NO_COLOR:-}" ] && [ -t 1 ] && [ "${TERM:-}" != "dumb" ]; then + + SisUseColours=1 + fi +fi + +if [ $SisUseColours -ne 0 ]; then + + SisClr_Blue=${FG_BLUE:-$(tput setaf 4)} + SisClr_Bold=${FD_BOLD:-$(tput bold)} + SisClr_Green=${FG_GREEN:-$(tput setaf 2)} + SisClr_None=${FD_NONE:-$(tput sgr0)} + SisClr_Red=${FG_RED:-$(tput setaf 1)} + SisClr_Yellow=${FG_YELLOW:-$(tput setaf 3)} +fi + +CMakeDirClr="${SisClr_Blue}${SisClr_Bold}${CMakeDir}${SisClr_None}" +ProjectNameClr="${SisClr_Blue}${SisClr_Bold}${ProjectName}${SisClr_None}" +ScriptPathClr="${SisClr_Blue}${SisClr_Bold}${ScriptPath}${SisClr_None}" + + +# ########################################################## +# functions - 2 + +sis_cmake_build() { + + local config="${SIS_CMAKE_CONFIG:-Release}" + local args=(--build "$CMakeDir") + if [ -f "$CMakeDir/CMakeCache.txt" ] && grep -q '^CMAKE_CONFIGURATION_TYPES:' "$CMakeDir/CMakeCache.txt" 2>/dev/null; then + + args+=(--config "$config") + fi + if [ "$#" -gt 0 ]; then + + local t + for t in "$@"; do + + args+=(--target "$t") + done + fi + + cmake "${args[@]}" +} # ########################################################## @@ -19,6 +122,10 @@ RunMake=1 while [[ $# -gt 0 ]]; do case $1 in + --always-use-colors|--always-use-colours|-A) + + # AlwaysUseColours=1 - this is handled by the for loop above + ;; --list-only|-l) ListOnly=1 @@ -33,19 +140,24 @@ while [[ $# -gt 0 ]]; do cat << EOF Runs all (matching) scratch-test programs -$ScriptPath [ ... flags/options ... ] +${ScriptPath} [ ... flags/options ... ] Flags/options: behaviour: + -A + --always-use-colors + --always-use-colours + forces use of colours even when stdout is not a TTY + -l --list-only lists the target programs but does not execute them -M --no-make - does not execute CMake and make before running tests + does not execute a build before running programs standard flags: @@ -59,7 +171,7 @@ EOF ;; *) - >&2 echo "$ScriptPath: unrecognised argument '$1'; use --help for usage" + >&2 echo "${ScriptPathClr}: unrecognised argument '${SisClr_Red}${SisClr_Bold}$1${SisClr_None}'; use --help for usage" exit 1 ;; @@ -78,22 +190,28 @@ if [ $RunMake -ne 0 ]; then if [ $ListOnly -eq 0 ]; then - echo "Executing build (via command \`$MakeCmd\`) and then running all scratch test programs" + echo + echo "Executing build of ${ProjectNameClr} (via cmake --build) and then running all scratch-test programs" - mkdir -p $CMakeDir || exit 1 + mkdir -p "$CMakeDir" || exit 1 - cd $CMakeDir + if [ ! -f "$CMakeDir/CMakeCache.txt" ]; then - $MakeCmd - status=$? + >&2 echo "${ScriptPathClr}: '${CMakeDirClr}' is not configured; use prepare_cmake.sh first" - cd ->/dev/null + exit 1 + fi + + sis_cmake_build + status=$? fi else - if [ ! -d "$CMakeDir" ] || [ ! -f "$CMakeDir/CMakeCache.txt" ] || [ ! -d "$CMakeDir/CMakeFiles" ]; then + if [ ! -d "$CMakeDir" ] || [ ! -f "$CMakeDir/CMakeCache.txt" ]; then + + >&2 echo "${ScriptPathClr}: cannot run in '--no-make' mode without a previous successful configure/build" - >&2 echo "$ScriptPath: cannot run in '--no-make' mode without a previous successful build step" + exit 1 fi fi @@ -101,37 +219,58 @@ if [ $status -eq 0 ]; then if [ $ListOnly -ne 0 ]; then - echo "Listing all scratch (and performance) test programs" + echo + echo "Listing all ${ProjectNameClr} scratch-test programs" else - echo "Running all scratch (and performance) test programs" + echo + echo "Running all ${ProjectNameClr} scratch-test programs" fi - for f in $(find $CMakeDir -type f '(' -name 'test_scratch*' -o -name 'test.scratch.*' -o -name 'test_performance*' -o -name 'test.performance.*' ')' -exec test -x {} \; -print) - do + NumPrograms=0 + + while IFS= read -r -d '' f; do + + case "$f" in + *.pdb|*.ilk|*.log|*.obj|*.o) + continue + ;; + esac + + NumPrograms=$((NumPrograms + 1)) + + fClr="${SisClr_Blue}${SisClr_Bold}${f}${SisClr_None}" if [ $ListOnly -ne 0 ]; then - echo "would execute $f:" + echo "would execute ${fClr}:" continue fi echo - echo "executing $f:" + echo "executing ${fClr}:" - if $f; then + if "$f"; then : else status=$? + + break 1 fi - done + done < <(find "$CMakeDir" -type f \( -name 'test_scratch*' -o -name 'test.scratch.*' \) \( -perm -100 -o -name '*.exe' \) -print0 2>/dev/null | sort -z) + + if [ $NumPrograms -eq 0 ]; then + + echo "${ScriptPathClr}: found no scratch-test programs under '${CMakeDirClr}' (none found)" + + exit 0 + fi fi exit $status # ############################## end of file ############################# # - diff --git a/run_all_unit_tests.cmd b/run_all_unit_tests.cmd index b68c97e..18b040a 100644 --- a/run_all_unit_tests.cmd +++ b/run_all_unit_tests.cmd @@ -1,32 +1,29 @@ @echo off -SETLOCAL ENABLEEXTENSIONS ENABLEDELAYEDEXPANSION +SETLOCAL SET SCRIPT_DIRECTORY=%~dp0 SET SCRIPT_PATH_DOC=%~n0[%~x0] + IF DEFINED SIS_CMAKE_BUILD_DIR ( - SET "CMAKE_DIR=%SIS_CMAKE_BUILD_DIR%" + SET CMAKE_DIR=%SIS_CMAKE_BUILD_DIR% ) ELSE ( - SET "CMAKE_DIR=%SCRIPT_DIRECTORY%_build" + SET CMAKE_DIR=%SCRIPT_DIRECTORY%_build ) -SET ListOnly=0 -SET Verbose=0 -SET UnitOnly=0 -SET ComponentOnly=0 -SET status=0 - FOR %%a IN (%*) DO ( + IF /I {--help}=={%%a} ( + IF EXIST "%SCRIPT_DIRECTORY%.sis\script_info_lines.txt" ( - type "%SCRIPT_DIRECTORY%.sis\script_info_lines.txt" + type "%SCRIPT_DIRECTORY%.sis\script_info_lines.txt" ) ECHO ^ -Runs all ^(matching^) unit-test and/or component-test programs ^ +Runs all ^(matching^) unit-test programs ^ ^ @@ -38,41 +35,11 @@ Flags/options: ^ behaviour: ^ -^ - - -l ^ - - --list-only ^ - - lists the target programs but does not execute them ^ - -^ - - -M ^ - - --no-make ^ - - accepted for parity with the .sh script ^(build is not invoked^) ^ - ^ --unit-only ^ - runs only unit-test programs ^(test.unit.* / test_unit*^) ^ - -^ - - --component-only ^ - - runs only component-test programs ^(test.component.* / test_component*^) ^ - -^ - - -v ^ - - --verbose ^ - - lists each test program before executing it ^ + accepted for compatibility; this script always runs unit tests only ^ ^ @@ -86,41 +53,22 @@ Flags/options: ^ EXIT /B 0 - ) ELSE IF /I {-l}=={%%a} ( - SET ListOnly=1 - ) ELSE IF /I {--list-only}=={%%a} ( - SET ListOnly=1 - ) ELSE IF /I {-M}=={%%a} ( - REM no-op: this .cmd never invokes the build - ) ELSE IF /I {--no-make}=={%%a} ( - REM no-op: this .cmd never invokes the build ) ELSE IF /I {--unit-only}=={%%a} ( - SET UnitOnly=1 - ) ELSE IF /I {--component-only}=={%%a} ( - SET ComponentOnly=1 - ) ELSE IF /I {-v}=={%%a} ( - SET Verbose=1 - ) ELSE IF /I {--verbose}=={%%a} ( - SET Verbose=1 + + REM Benign: this script is already unit-only ) ELSE ( - ECHO %SCRIPT_PATH_DOC%: unrecognised argument '%%a'; use --help for usage 1>&2 + + ECHO "%SCRIPT_DIRECTORY%: unrecognised argument '%%a'; use --help for usage" 1>&2 EXIT /B 1 ) ) -IF !UnitOnly! EQU 1 IF !ComponentOnly! EQU 1 ( - - ECHO %SCRIPT_PATH_DOC%: --unit-only and --component-only are mutually exclusive 1>&2 - - EXIT /B 1 -) - -IF NOT EXIST "%CMAKE_DIR%" ( +if NOT EXIST "%CMAKE_DIR%" ( - ECHO %SCRIPT_PATH_DOC%: CMake build directory '%CMAKE_DIR%' does not exist 1>&2 + ECHO "CMake build directory '%CMAKE_DIR%' does not exist" - EXIT /B 1 + EXIT /B 1 ) SET "ProjectName=" @@ -128,61 +76,19 @@ FOR /F "usebackq delims=" %%p IN ("%SCRIPT_DIRECTORY%.sis\project_name.txt") DO IF NOT DEFINED ProjectName ( - ECHO %SCRIPT_PATH_DOC%: could not read project name from .sis\project_name.txt 1>&2 - - EXIT /B 1 -) - -IF !UnitOnly! EQU 1 ( - - SET "TestKindDescription=unit test" -) ELSE IF !ComponentOnly! EQU 1 ( - - SET "TestKindDescription=component test" -) ELSE ( + ECHO %SCRIPT_PATH_DOC%: could not read project name from .sis\project_name.txt 1>&2 - SET "TestKindDescription=component and unit test" + EXIT /B 1 ) -IF !ListOnly! EQU 1 ( - - ECHO Listing all !ProjectName! !TestKindDescription! programs -) ELSE ( +ECHO Running all %ProjectName% unit-test programs - ECHO Running all !ProjectName! !TestKindDescription! programs -) +FOR /F "usebackq" %%f IN (`DIR /A:-D /B /S "%CMAKE_DIR%" ^| FINDSTR /I test.*unit.*\.exe$`) DO ( -IF !UnitOnly! EQU 1 ( - - SET "FindPattern=test\.unit\..*\.exe$" -) ELSE IF !ComponentOnly! EQU 1 ( - - SET "FindPattern=test\.component\..*\.exe$" -) ELSE ( - - SET "FindPattern=test\.unit\..*\.exe$ test\.component\..*\.exe$" -) - -FOR /F "usebackq delims=" %%f IN (`DIR /A:-D /B /S "%CMAKE_DIR%\*.exe" 2^>NUL ^| FINDSTR /I /R "!FindPattern!"`) DO ( - IF !ListOnly! EQU 1 ( - - ECHO would execute %%f: - ) ELSE ( - - IF !Verbose! EQU 1 ( - - ECHO executing %%f: - ) - - "%%f" - IF ERRORLEVEL 1 ( - - SET status=1 - - GOTO :done - ) - ) + ECHO . + ECHO executing %%f + %%f + IF ERRORLEVEL 1 EXIT /B %ERRORLEVEL% ) -:done -EXIT /B !status! +ENDLOCAL diff --git a/run_all_unit_tests.sh b/run_all_unit_tests.sh index 22efd84..301ccae 100755 --- a/run_all_unit_tests.sh +++ b/run_all_unit_tests.sh @@ -1,27 +1,132 @@ #! /bin/bash -ScriptPath=$0 -Dir=$(cd $(dirname "$ScriptPath"); pwd) +# ########################################################## +# functions - 1 + +sis_cmake_is_truey() { + case "$(printf '%s' "${1:-}" | tr '[:upper:]' '[:lower:]')" in + + 1|ok|on|true|yes|y) + + return 0 + ;; + *) + + return 1 + ;; + esac +} + + +# ########################################################## +# constants and variables + +Basename=$(basename "$0") +Dir=$(cd "$(dirname "$0")" && pwd) +CMakeDir=${SIS_CMAKE_BUILD_DIR:-$Dir/_build} ProjectNameFile="$Dir/.sis/project_name.txt" ProjectName=$(tr -d '[:space:]' < "$ProjectNameFile") -Basename=$(basename "$ScriptPath") -CMakeDir=${SIS_CMAKE_BUILD_DIR:-$Dir/_build} -[[ -n "$MSYSTEM" ]] && DefaultMakeCmd=mingw32-make.exe || DefaultMakeCmd=make -MakeCmd=${SIS_CMAKE_MAKE_COMMAND:-${SIS_CMAKE_COMMAND:-$DefaultMakeCmd}} +ScriptPath=$0 +AlwaysUseColours=${SIS_CMAKE_ALWAYS_USE_COLOURS:-${SIS_ALWAYS_USE_COLOURS:-0}} ListOnly=0 RunMake=1 -UnitOnly=0 -ComponentOnly=0 +SisUseColours=0 Verbosity=${XTESTS_VERBOSITY:-${TEST_VERBOSITY:-3}} +# ########################################################## +# colours +# +# Enable when tput is available and either: +# - AlwaysUseColours is set (overrides NO_COLOR; may set TERM if +# empty/dumb), or +# - NO_COLOR is unset, stdout is a TTY, and TERM is not dumb (union of +# collect-c's "TERM set + TTY" and cstring's "TTY" — empty TERM on a +# TTY is OK). + +SisClr_Blue= +SisClr_Bold= +SisClr_Green= +SisClr_None= +SisClr_Red= +SisClr_Yellow= + +for arg in "$@"; do + + case $arg in + --always-use-colors|--always-use-colours|-A) + + AlwaysUseColours=1 + ;; + esac +done + +if command -v tput >/dev/null 2>&1; then + + if [ $AlwaysUseColours -ne 0 ]; then + + if [ -z "${TERM:-}" ] || [ "$TERM" = "dumb" ]; then + + TERM=xterm-256color + fi + + SisUseColours=1 + elif [ -z "${NO_COLOR:-}" ] && [ -t 1 ] && [ "${TERM:-}" != "dumb" ]; then + + SisUseColours=1 + fi +fi + +if [ $SisUseColours -ne 0 ]; then + + SisClr_Blue=${FG_BLUE:-$(tput setaf 4)} + SisClr_Bold=${FD_BOLD:-$(tput bold)} + SisClr_Green=${FG_GREEN:-$(tput setaf 2)} + SisClr_None=${FD_NONE:-$(tput sgr0)} + SisClr_Red=${FG_RED:-$(tput setaf 1)} + SisClr_Yellow=${FG_YELLOW:-$(tput setaf 3)} +fi + +CMakeDirClr="${SisClr_Blue}${SisClr_Bold}${CMakeDir}${SisClr_None}" +ProjectNameClr="${SisClr_Blue}${SisClr_Bold}${ProjectName}${SisClr_None}" +ScriptPathClr="${SisClr_Blue}${SisClr_Bold}${ScriptPath}${SisClr_None}" + + +# ########################################################## +# functions - 2 + +sis_cmake_build() { + + local config="${SIS_CMAKE_CONFIG:-Release}" + local args=(--build "$CMakeDir") + if [ -f "$CMakeDir/CMakeCache.txt" ] && grep -q '^CMAKE_CONFIGURATION_TYPES:' "$CMakeDir/CMakeCache.txt" 2>/dev/null; then + + args+=(--config "$config") + fi + if [ "$#" -gt 0 ]; then + + local t + for t in "$@"; do + + args+=(--target "$t") + done + fi + + cmake "${args[@]}" +} + + # ########################################################## # command-line handling while [[ $# -gt 0 ]]; do case $1 in + --always-use-colors|--always-use-colours|-A) + + # AlwaysUseColours=1 - this is handled by the for loop above + ;; --list-only|-l) ListOnly=1 @@ -32,11 +137,7 @@ while [[ $# -gt 0 ]]; do ;; --unit-only) - UnitOnly=1 - ;; - --component-only) - - ComponentOnly=1 + # Benign: this script is already unit-only (aggregate / CI may pass it) ;; --verbosity) @@ -47,30 +148,32 @@ while [[ $# -gt 0 ]]; do [ -f "$Dir/.sis/script_info_lines.txt" ] && cat "$Dir/.sis/script_info_lines.txt" cat << EOF -Runs all (matching) unit-test and/or component-test programs +Runs all (matching) unit-test programs -$ScriptPath [ ... flags/options ... ] +${ScriptPath} [ ... flags/options ... ] Flags/options: behaviour: + -A + --always-use-colors + --always-use-colours + forces use of colours even when stdout is not a TTY + -l --list-only lists the target programs but does not execute them -M --no-make - does not execute CMake and make before running tests + does not execute a build before running programs --unit-only - runs only unit-test programs (test.unit.* / test_unit*) - - --component-only - runs only component-test programs (test.component.* / test_component*) + accepted for compatibility; this script always runs unit tests only --verbosity - specifies an explicit verbosity for the unit-test(s) + specifies an explicit verbosity, forwarded to each program standard flags: @@ -84,7 +187,7 @@ EOF ;; *) - >&2 echo "$ScriptPath: unrecognised argument '$1'; use --help for usage" + >&2 echo "${ScriptPathClr}: unrecognised argument '${SisClr_Red}${SisClr_Bold}$1${SisClr_None}'; use --help for usage" exit 1 ;; @@ -93,50 +196,36 @@ EOF shift done -if [ $UnitOnly -ne 0 ] && [ $ComponentOnly -ne 0 ]; then - - >&2 echo "$ScriptPath: --unit-only and --component-only are mutually exclusive" - - exit 1 -fi - # ########################################################## # main() status=0 -if [ $UnitOnly -ne 0 ]; then - - TestKindDescription='unit test' -elif [ $ComponentOnly -ne 0 ]; then - - TestKindDescription='component test' -else - - TestKindDescription='component and unit test' -fi - if [ $RunMake -ne 0 ]; then if [ $ListOnly -eq 0 ]; then - echo "Executing build (via command \`$MakeCmd\`) and then running all ${TestKindDescription} programs" + echo + echo "Executing build of ${ProjectNameClr} (via cmake --build) and then running all unit-test programs" - mkdir -p $CMakeDir || exit 1 + mkdir -p "$CMakeDir" || exit 1 - cd $CMakeDir + if [ ! -f "$CMakeDir/CMakeCache.txt" ]; then - $MakeCmd - status=$? + >&2 echo "${ScriptPathClr}: '${CMakeDirClr}' is not configured; use prepare_cmake.sh first" + + exit 1 + fi - cd ->/dev/null + sis_cmake_build + status=$? fi else - if [ ! -d "$CMakeDir" ] || [ ! -f "$CMakeDir/CMakeCache.txt" ] || [ ! -d "$CMakeDir/CMakeFiles" ]; then + if [ ! -d "$CMakeDir" ] || [ ! -f "$CMakeDir/CMakeCache.txt" ]; then - >&2 echo "$ScriptPath: cannot run in '--no-make' mode without a previous successful build step" + >&2 echo "${ScriptPathClr}: cannot run in '--no-make' mode without a previous successful configure/build" exit 1 fi @@ -146,29 +235,31 @@ if [ $status -eq 0 ]; then if [ $ListOnly -ne 0 ]; then - echo "Listing all ${TestKindDescription} programs" + echo + echo "Listing all ${ProjectNameClr} unit-test programs" else - echo "Running all ${TestKindDescription} programs" + echo + echo "Running all ${ProjectNameClr} unit-test programs" fi - if [ $UnitOnly -ne 0 ]; then + NumPrograms=0 - find_name_expr=( \( -name 'test_unit*' -o -name 'test.unit.*' \) ) - elif [ $ComponentOnly -ne 0 ]; then + while IFS= read -r -d '' f; do - find_name_expr=( \( -name 'test_component*' -o -name 'test.component.*' \) ) - else + case "$f" in + *.pdb|*.ilk|*.log|*.obj|*.o) + continue + ;; + esac - find_name_expr=( \( -name 'test_unit*' -o -name 'test.unit.*' -o -name 'test_component*' -o -name 'test.component.*' \) ) - fi + NumPrograms=$((NumPrograms + 1)) - for f in $(find "$CMakeDir" -type f "${find_name_expr[@]}" -exec test -x {} \; -print | sort) - do + fClr="${SisClr_Blue}${SisClr_Bold}${f}${SisClr_None}" if [ $ListOnly -ne 0 ]; then - echo "would execute $f:" + echo "would execute ${fClr}:" continue fi @@ -179,10 +270,10 @@ if [ $status -eq 0 ]; then fi if [ $Verbosity -ge 2 ]; then - echo "executing $f:" + echo "executing ${fClr}:" fi - if $f --verbosity=$Verbosity; then + if "$f" --verbosity="$Verbosity"; then : else @@ -191,7 +282,14 @@ if [ $status -eq 0 ]; then break 1 fi - done + done < <(find "$CMakeDir" -type f \( -name 'test_unit*' -o -name 'test.unit.*' \) \( -perm -100 -o -name '*.exe' \) -print0 2>/dev/null | sort -z) + + if [ $NumPrograms -eq 0 ]; then + + echo "${ScriptPathClr}: found no unit-test programs under '${CMakeDirClr}' (none found)" + + exit 0 + fi fi exit $status diff --git a/test/scratch/CMakeLists.txt b/test/scratch/CMakeLists.txt index c0cad39..084a242 100644 --- a/test/scratch/CMakeLists.txt +++ b/test/scratch/CMakeLists.txt @@ -1,4 +1,5 @@ add_subdirectory(test.scratch.atexit) +add_subdirectory(versions) # ############################## end of file ############################# # diff --git a/test/scratch/versions/CMakeLists.txt b/test/scratch/versions/CMakeLists.txt new file mode 100644 index 0000000..87318b1 --- /dev/null +++ b/test/scratch/versions/CMakeLists.txt @@ -0,0 +1 @@ +define_example_program(test.scratch.versions main.cpp) diff --git a/test/scratch/versions/main.cpp b/test/scratch/versions/main.cpp new file mode 100644 index 0000000..a1907e1 --- /dev/null +++ b/test/scratch/versions/main.cpp @@ -0,0 +1,58 @@ + +#include + +#include +#include + +#include + + +#define PROGRAM_NAME "versions" + + +template< + typename T_stream +, typename T_integer +> +void +version( + T_stream& stm +, char const* prefix +, char const* libname +, char const* macroname +, T_integer libver +) +{ + stm + << prefix + << libname + << ": v" + << ((libver >> 24) & 0xff) + << '.' + << ((libver >> 16) & 0xff) + << '.' + << ((libver >> 8) & 0xff) + << '.' + << ((libver >> 0) & 0xff) + << " (" + << macroname + << " = 0x" + << std::hex << std::setfill('0') << std::setw(8) + << static_cast(libver) + << std::dec + << ")" + << std::endl + ; +} + + +int main(int /* argc */, char* /* argv */[]) +{ + { + unsigned const libver = PANTHEIOS_EXTRAS_ATEXIT_VER; + + version(std::cout, "", "Pantheios.Extras.AtExit", "PANTHEIOS_EXTRAS_ATEXIT_VER", libver); + } + + return EXIT_SUCCESS; +} diff --git a/test/unit/test.unit.version/test.unit.version.c b/test/unit/test.unit.version/test.unit.version.c index 10ea1a4..e7221dd 100644 --- a/test/unit/test.unit.version/test.unit.version.c +++ b/test/unit/test.unit.version/test.unit.version.c @@ -4,7 +4,7 @@ * Purpose: Unit tests for Pantheios.Extras.AtExit version macros. * * Created: 21st August 2026 - * Updated: 21st August 2026 + * Updated: 9th October 2026 * * ////////////////////////////////////////////////////////////////////// */ @@ -21,8 +21,8 @@ test_version_components(void) { XTESTS_TEST_INTEGER_EQUAL(0, PANTHEIOS_EXTRAS_ATEXIT_VER_MAJOR); XTESTS_TEST_INTEGER_EQUAL(1, PANTHEIOS_EXTRAS_ATEXIT_VER_MINOR); - XTESTS_TEST_INTEGER_EQUAL(3, PANTHEIOS_EXTRAS_ATEXIT_VER_PATCH); - XTESTS_TEST_INTEGER_EQUAL(0xFF, PANTHEIOS_EXTRAS_ATEXIT_VER_ALPHABETA); + XTESTS_TEST_INTEGER_EQUAL(4, PANTHEIOS_EXTRAS_ATEXIT_VER_PATCH); + XTESTS_TEST_INTEGER_EQUAL(0x81, PANTHEIOS_EXTRAS_ATEXIT_VER_ALPHABETA); XTESTS_TEST_INTEGER_EQUAL(PANTHEIOS_EXTRAS_ATEXIT_VER_PATCH, PANTHEIOS_EXTRAS_ATEXIT_VER_REVISION); } @@ -38,8 +38,8 @@ test_version_composite(void) ); XTESTS_TEST_INTEGER_EQUAL(computed, PANTHEIOS_EXTRAS_ATEXIT_VER); - XTESTS_TEST_INTEGER_EQUAL(PANTHEIOS_EXTRAS_ATEXIT_VER_0_1_3, PANTHEIOS_EXTRAS_ATEXIT_VER); - XTESTS_TEST_INTEGER_EQUAL(0x000103ff, PANTHEIOS_EXTRAS_ATEXIT_VER); + XTESTS_TEST_INTEGER_EQUAL(PANTHEIOS_EXTRAS_ATEXIT_VER_0_1_4_BETA_1, PANTHEIOS_EXTRAS_ATEXIT_VER); + XTESTS_TEST_INTEGER_EQUAL(0x00010481, PANTHEIOS_EXTRAS_ATEXIT_VER); }