From 980f331bc6cbea0ff3befd3401b08fddf9dd5ff5 Mon Sep 17 00:00:00 2001 From: Matt Wilson Date: Mon, 3 Aug 2026 11:21:34 +1000 Subject: [PATCH 01/21] .gitattributes --- .gitattributes | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/.gitattributes b/.gitattributes index e69de29..a9c5470 100644 --- a/.gitattributes +++ b/.gitattributes @@ -0,0 +1,17 @@ +*.c linguist-language=C +*.cmake linguist-vendored +*.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-vendored +makefile linguist-detectable=false From 27058364112a07109ab3ff389e3d84542b8ff410 Mon Sep 17 00:00:00 2001 From: Matt Wilson Date: Mon, 3 Aug 2026 11:21:46 +1000 Subject: [PATCH 02/21] .gitignore --- .gitignore | 144 ++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 142 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index bc5e712..191488c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,12 +1,152 @@ +# directories (by name) + +/.svn/ +/.vs/ + +/_build/ +/_internal/ + +/bin/ +/doc/ +/include/ +/lib/ +/node_modules/ + +/include/b64/ +/include/shwild/ +/include/xcontract/ +/include/xcover/ +/include/xtests/ + +/src/b64/ +/src/shwild/ +/src/xcontract/ +/src/xcover/ +/src/xtests/ + +Debug Multithreaded DLL/ +Debug Multithreaded Dll/ +Debug Multithreaded pseudoUNIX/ +Debug Multithreaded pseudoUnix/ +Debug Multithreaded/ +Debug/ +DebugDLLUNIX/ +DebugDll/ +DebugMTDLL/ +DebugMt/ +DebugNox/ +DebugUNIX/ +DebugUnix/ +Release Multithreaded DLL/ +Release Multithreaded Dll/ +Release Multithreaded pseudoUNIX/ +Release Multithreaded pseudoUnix/ +Release Multithreaded/ +Release/ +ReleaseDLLUNIX/ +ReleaseDll/ +ReleaseMTDLL/ +ReleaseMt/ +ReleaseNox/ +ReleaseUnix/ +UDebug/ +UDebugMt/ +URelease/ +UReleaseMt/ +Unicode Debug Multithreaded DLL/ +Unicode Debug Multithreaded Dll/ +Unicode Debug Multithreaded/ +Unicode Debug/ +Unicode Release Multithreaded DLL/ +Unicode Release Multithreaded Dll/ +Unicode Release Multithreaded/ +Unicode Release/ + +Win32/ +ipch/ +x64/ + + +# directories (by pattern) + + +# files (by name) + +.DS_Store +.ruby-version +.svnignore +.svnignore-at-root +.update_deps + +list_changes.cmd +logging-bailout.txt +prepare.cmd +sh.exe.stackdump +update_deps.cmd + +build/makefile.tmpl +build/makefile.tools.xml + +WriteDebugString +WriteDebugString_test + + +# files (by pattern) + +RCa0* +RCb0* + *~ -*.*~ +*.???_obj +*.a +*.app +*.aps +*.b64 +*.bak +*.chm +*.class +*.csproj*user +*.d +*.dll +*.dylib *.exe +*.gch +*.gem +*.idb *.ilk +*.iobj +*.ipch +*.ipdb +*.la +*.lai +*.lib +*.lo +*.log +*.ncb +*.o *.obj -*.map +*.opensdf +*.opt +*.org +*.out +*.pch *.pdb +*.pyc +*.rar +*.res +*.sbr +*.scc +*.sdf +*.slo +*.so +*.suo *.swp +*.tlog *.tmp +*.unsuccessfulbuild +*.vcproj*user +*.vcxproj*user +*.xcuserstate *.zip From 9016d5f7fce49ff9477a584b471137c6a42a4211 Mon Sep 17 00:00:00 2001 From: Matt Wilson Date: Mon, 3 Aug 2026 11:22:03 +1000 Subject: [PATCH 03/21] .vimrc --- .vimrc | 70 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 .vimrc diff --git a/.vimrc b/.vimrc new file mode 100644 index 0000000..1bf33a0 --- /dev/null +++ b/.vimrc @@ -0,0 +1,70 @@ +" Synesis C/C++ project .vimrc — aligned with .sis/.vscode/c_cxx/settings.json + +set nocompatible +filetype indent plugin on +syntax enable +set autoindent +set backspace=indent,eol,start +set hlsearch +set incsearch +set number + +" files.insertFinalNewline +set eol +set fixeol + +" editor.renderWhitespace: all +set list +set listchars=tab:->,trail:-,extends:>,precedes:<,nbsp:+ + +" editor.detectIndentation: false — global defaults (editor.tabSize: 4, insertSpaces: true) +set colorcolumn=76 +set expandtab +set shiftwidth=4 +set softtabstop=4 +set tabstop=4 + +" colorcolumn draws a full-column tint in Vim (not a VS Code-style 1px line). +" Keep it subtle via the ColorColumn highlight group; reapply after colorscheme changes. +if has('termguicolors') + " set termguicolors +endif + +function! s:ConfigureColorColumn() abort + highlight ColorColumn ctermbg=236 guibg=#2a2a2a cterm=NONE gui=NONE +endfunction + +call s:ConfigureColorColumn() +autocmd ColorScheme * call s:ConfigureColorColumn() + +" files.trimTrailingWhitespace +autocmd BufWritePre * %s/\s\+$//e + +augroup sis_c_cxx + autocmd! + + " [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 + + " [python] + autocmd FileType python setlocal expandtab tabstop=4 shiftwidth=4 softtabstop=4 colorcolumn=60,76 + + " [toml] + autocmd FileType toml setlocal noexpandtab tabstop=2 shiftwidth=2 softtabstop=2 +augroup END + From 5678dcd3de53132350bd4908efaaa12a4649912b Mon Sep 17 00:00:00 2001 From: Matt Wilson Date: Mon, 3 Aug 2026 11:22:14 +1000 Subject: [PATCH 04/21] settings --- .vscode/settings.json | 197 ++++++++++++++++++++++++++++++++++++++---- 1 file changed, 181 insertions(+), 16 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 2c808f7..4044afc 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,18 +1,183 @@ { - "editor.detectIndentation": false, - "editor.insertSpaces": true, - "editor.tabSize": 4, - "files.associations": { - "format": "cpp", - "istream": "cpp", - "memory": "cpp", - "tuple": "cpp", - "type_traits": "cpp", - "utility": "cpp", - "xlocmes": "cpp", - "xlocmon": "cpp", - "xlocnum": "cpp", - "xloctime": "cpp", - "xutility": "cpp", - }, + "[bat]": { + "editor.insertSpaces": true, + "editor.rulers": [ 60, 76 ], + "editor.tabSize": 4, + }, + "[c]": { + "editor.insertSpaces": true, + "editor.rulers": [ 60, 64, 68, 72, 76 ], + "editor.tabSize": 4, + }, + "[cmake]": { + "editor.insertSpaces": false, + "editor.tabSize": 4, + }, + "[cpp]": { + "editor.insertSpaces": true, + "editor.rulers": [ 60, 64, 68, 72, 76 ], + "editor.tabSize": 4, + }, + "[json]": { + "editor.insertSpaces": true, + "editor.tabSize": 2, + }, + "[markdown]": { + "editor.insertSpaces": true, + "editor.tabSize": 2, + }, + "[python]": { + "diffEditor.ignoreTrimWhitespace": false, + "editor.insertSpaces": true, + "editor.rulers": [ 51, 60, 61, 76 ], + "editor.tabSize": 4, + }, + "[ruby]": { + "editor.insertSpaces": true, + "editor.tabSize": 2, + }, + "[shellscript]": { + "editor.insertSpaces": true, + "editor.rulers": [ 60, 76 ], + "editor.tabSize": 2, + }, + "[toml]": { + "editor.insertSpaces": false, + "editor.tabSize": 2, + }, + "[yaml]": { + "editor.insertSpaces": true, + "editor.tabSize": 2, + }, + "cmake.configureOnOpen": false, + "editor.detectIndentation": false, + "editor.insertSpaces": false, + "editor.renderWhitespace": "all", + "editor.rulers": [ 76 ], + "editor.tabSize": 2, + "files.associations": { + "__bit_reference": "cpp", + "__bits": "cpp", + "__config": "cpp", + "__debug": "cpp", + "__errc": "cpp", + "__functional_03": "cpp", + "__functional_base": "cpp", + "__hash_table": "cpp", + "__locale": "cpp", + "__memory": "cpp", + "__mutex_base": "cpp", + "__node_handle": "cpp", + "__nullptr": "cpp", + "__split_buffer": "cpp", + "__string": "cpp", + "__threading_support": "cpp", + "__tree": "cpp", + "__tuple": "cpp", + "__verbose_abort": "cpp", + "algorithm": "cpp", + "array": "cpp", + "atomic": "cpp", + "bit": "cpp", + "bitset": "cpp", + "cctype": "cpp", + "charconv": "cpp", + "chrono": "cpp", + "clocale": "cpp", + "cmath": "cpp", + "compare": "cpp", + "complex": "cpp", + "concepts": "cpp", + "console_functions.h": "c", + "corecrt.h": "c", + "crtdefs.h": "c", + "cstdarg": "cpp", + "cstddef": "cpp", + "cstdint": "cpp", + "cstdio": "cpp", + "cstdlib": "cpp", + "cstring": "cpp", + "ctime": "cpp", + "cwchar": "cpp", + "cwctype": "cpp", + "deque": "cpp", + "exception": "cpp", + "execution": "cpp", + "fcntl.h": "c", + "format": "cpp", + "forward_list": "cpp", + "functional": "cpp", + "implicit_link.h": "c", + "initializer_list": "cpp", + "io.h": "c", + "iomanip": "cpp", + "ios": "cpp", + "iosfwd": "cpp", + "iostream": "cpp", + "istream": "cpp", + "iterator": "cpp", + "limits": "cpp", + "list": "cpp", + "locale": "cpp", + "map": "cpp", + "memory": "cpp", + "memory_resource": "cpp", + "mutex": "cpp", + "new": "cpp", + "numbers": "cpp", + "numeric": "cpp", + "optional": "cpp", + "ostream": "cpp", + "queue": "cpp", + "random": "cpp", + "ranges": "cpp", + "ratio": "cpp", + "semaphore": "cpp", + "set": "cpp", + "setenv.h": "c", + "shwild.h": "c", + "span": "cpp", + "sstream": "cpp", + "stack": "cpp", + "stdexcept": "cpp", + "stdio.h": "c", + "stop_token": "cpp", + "streambuf": "cpp", + "string": "cpp", + "string_view": "cpp", + "system_error": "cpp", + "terse-api.h": "c", + "text_encoding": "cpp", + "thread": "cpp", + "tuple": "cpp", + "type_traits": "cpp", + "typeinfo": "cpp", + "uio.h": "c", + "unixem.h": "c", + "unordered_map": "cpp", + "util.h": "c", + "utility": "cpp", + "variant": "cpp", + "vector": "cpp", + "xfacet": "cpp", + "xhash": "cpp", + "xiosbase": "cpp", + "xlocale": "cpp", + "xlocbuf": "cpp", + "xlocinfo": "cpp", + "xlocmes": "cpp", + "xlocmon": "cpp", + "xlocnum": "cpp", + "xloctime": "cpp", + "xmemory": "cpp", + "xstring": "cpp", + "xtests.internal.string.c": "cpp", + "xtr1common": "cpp", + "xtree": "cpp", + "xutility": "cpp", + }, + "files.insertFinalNewline": true, + "files.trimTrailingWhitespace": true, + "git.mergeEditor": false, } + From 910f5c5d47c0d40516d6ba1ff94ff495b39277a9 Mon Sep 17 00:00:00 2001 From: Matt Wilson Date: Mon, 3 Aug 2026 11:22:49 +1000 Subject: [PATCH 05/21] chore: project helper scripts --- .sis/project_name.txt | 1 + .sis/script_info_lines.txt | 2 + build_cmake.sh | 130 ++++++++++++++++++++++++++ clean_cmake.sh | 92 ++++++++++++++++++ prepare_cmake.sh | 186 +++++++++++++++++++++++++++++++++++++ remove_cmake_artefacts.sh | 151 ++++++++++++++++++++++++++++++ run_all_unit_tests.cmd | 141 ++++++++++++++++++++++++++++ 7 files changed, 703 insertions(+) create mode 100644 .sis/project_name.txt create mode 100644 .sis/script_info_lines.txt create mode 100755 build_cmake.sh create mode 100755 clean_cmake.sh create mode 100755 prepare_cmake.sh create mode 100755 remove_cmake_artefacts.sh create mode 100644 run_all_unit_tests.cmd diff --git a/.sis/project_name.txt b/.sis/project_name.txt new file mode 100644 index 0000000..917da25 --- /dev/null +++ b/.sis/project_name.txt @@ -0,0 +1 @@ +WriteDebugString diff --git a/.sis/script_info_lines.txt b/.sis/script_info_lines.txt new file mode 100644 index 0000000..a387ee3 --- /dev/null +++ b/.sis/script_info_lines.txt @@ -0,0 +1,2 @@ +WriteDebugString is a Windows CLI that writes messages to the debugger via OutputDebugString +Copyright (c) 2025-2026, Matthew Wilson and Synesis Information Systems diff --git a/build_cmake.sh b/build_cmake.sh new file mode 100755 index 0000000..cca1448 --- /dev/null +++ b/build_cmake.sh @@ -0,0 +1,130 @@ +#! /bin/bash + +ScriptPath=$0 +Dir=$(cd $(dirname "$ScriptPath"); pwd) +Basename=$(basename "$ScriptPath") +CMakeDir=${SIS_CMAKE_BUILD_DIR:-$Dir/_build} +if [[ -n "$MSYSTEM" ]]; then + + DefaultMakeCmd=mingw32-make.exe + MinGW=1 +else + + DefaultMakeCmd=make +fi +MakeCmd=${SIS_CMAKE_MAKE_COMMAND:-${SIS_CMAKE_COMMAND:-$DefaultMakeCmd}} + +IgnoreRemainingFlagsAndOptions=0 +Targets=() + + +# ########################################################## +# functions + +function join_by { local IFS="$1"; shift; echo "$*"; } + + +# ########################################################## +# command-line handling + +while [[ $# -gt 0 ]]; do + + if [ $IgnoreRemainingFlagsAndOptions -ne 0 ]; then + + Targets+=($1) + + shift + + continue + else + + if [ ! ${1:0:1} = '-' ]; then + + Targets+=($1) + + shift + + continue + fi + fi + + case $1 in + --) + + IgnoreRemainingFlagsAndOptions=1 + ;; + --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 ... ] + +Flags/options: + + behaviour: + + + standard flags: + + --help + displays this help and terminates + +EOF + + exit 0 + ;; + *) + + >&2 echo "$ScriptPath: unrecognised argument '$1'; use --help for usage" + + exit 1 + ;; + esac + + shift +done + + +# ########################################################## +# main() + +if [ ! -d "$CMakeDir" ]; 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" + + 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 + + $MakeCmd ${Targets[*]} + status=$? + + cd ->/dev/null + + exit $status + fi +fi + + +# ############################## end of file ############################# # + diff --git a/clean_cmake.sh b/clean_cmake.sh new file mode 100755 index 0000000..886a201 --- /dev/null +++ b/clean_cmake.sh @@ -0,0 +1,92 @@ +#! /bin/bash + +ScriptPath=$0 +Dir=$(cd $(dirname "$ScriptPath"); pwd) +Basename=$(basename "$ScriptPath") +CMakeDir=${SIS_CMAKE_BUILD_DIR:-$Dir/_build} +if [[ -n "$MSYSTEM" ]]; then + + DefaultMakeCmd=mingw32-make.exe + MinGW=1 +else + + DefaultMakeCmd=make +fi +MakeCmd=${SIS_CMAKE_MAKE_COMMAND:-${SIS_CMAKE_COMMAND:-$DefaultMakeCmd}} + + +# ########################################################## +# command-line handling + +while [[ $# -gt 0 ]]; do + + case $1 in + --help) + + [ -f "$Dir/.sis/script_info_lines.txt" ] && cat "$Dir/.sis/script_info_lines.txt" + cat << EOF +Executes CMake-generated artefacts to clean project + +$ScriptPath [ ... flags/options ... ] + +Flags/options: + + behaviour: + + + standard flags: + + --help + displays this help and terminates + +EOF + + exit 0 + ;; + *) + + >&2 echo "$ScriptPath: unrecognised argument '$1'; use --help for usage" + + exit 1 + ;; + esac + + shift +done + + +# ########################################################## +# main() + +if [ ! -d "$CMakeDir" ]; 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" + + 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 + + +# ############################## end of file ############################# # + diff --git a/prepare_cmake.sh b/prepare_cmake.sh new file mode 100755 index 0000000..d837045 --- /dev/null +++ b/prepare_cmake.sh @@ -0,0 +1,186 @@ +#! /bin/bash + +ScriptPath=$0 +Dir=$(cd $(dirname "$ScriptPath"); pwd) +Basename=$(basename "$ScriptPath") +CMakeDir=${SIS_CMAKE_BUILD_DIR:-$Dir/_build} +if [[ -n "$MSYSTEM" ]]; then + + DefaultMakeCmd=mingw32-make.exe + MinGW=1 +else + + DefaultMakeCmd=make +fi +MakeCmd=${SIS_CMAKE_MAKE_COMMAND:-${SIS_CMAKE_COMMAND:-$DefaultMakeCmd}} + +Configuration=Release +MSVC_MT=0 +MinGW="${MinGW:=0}" +RunMake=0 +STLSoftDirGiven= +TestingDisabled=0 +VerboseMakefile=0 + + +# ########################################################## +# command-line handling + +while [[ $# -gt 0 ]]; do + + case $1 in + --cmake-verbose-makefile|-v) + + VerboseMakefile=1 + ;; + --debug-configuration|-d) + + Configuration=Debug + ;; + --disable-testing|-T) + + TestingDisabled=1 + ;; + --mingw) + + MinGW=1 + ;; + --msvc-mt) + + MSVC_MT=1 + ;; + --run-make|-m) + + RunMake=1 + ;; + --stlsoft-root-dir|-s) + + shift + STLSoftDirGiven=$1 + ;; + --help) + + [ -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 ... ] + +Flags/options: + + behaviour: + + -v + --cmake-verbose-makefile + configures CMake to run verbosely (by setting CMAKE_VERBOSE_MAKEFILE + to be ON) + + -d + --debug-configuration + use Debug configuration (by setting CMAKE_BUILD_TYPE=Debug). Default + is to use Release + + -T + --disable-testing + disables building of tests (by setting BUILD_TESTING=OFF) + + --mingw + uses explicitly the "MinGW Makefiles" generator, and defaults the + make-command to "mingw32-make.exe" + + --msvc-mt + when using Visual C++ (MSVC), the static runtime library will be + selected; the default is the dynamic runtime library + + -m + --run-make + executes make after a successful running of CMake + + -s + --stlsoft-root-dir + specifies the STLSoft root-directory, which will be passed to CMake + as the variable STLSOFT, and which will override the environment + variable STLSOFT (if present) + + + standard flags: + + --help + displays this help and terminates + +EOF + + exit 0 + ;; + *) + + >&2 echo "$ScriptPath: unrecognised argument '$1'; use --help for usage" + + exit 1 + ;; + esac + + shift +done + + +# ########################################################## +# main() + +mkdir -p $CMakeDir || exit 1 + +cd $CMakeDir + +echo "Executing CMake (in ${CMakeDir})" + +if [ $MSVC_MT -eq 0 ]; then CMakeMsvcMtFlag="OFF" ; else CMakeMsvcMtFlag="ON" ; 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 + +if [ $MinGW -ne 0 ]; then + + cmake \ + $CMakeSTLSoftVariable \ + -DBUILD_TESTING:BOOL=$CMakeBuildTestingFlag \ + -DCMAKE_BUILD_TYPE=$Configuration \ + -G "MinGW Makefiles" \ + -S $Dir \ + -B $CMakeDir \ + || (cd ->/dev/null ; exit 1) +else + + cmake \ + $CMakeSTLSoftVariable \ + -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) +fi + +status=0 + +if [ $RunMake -ne 0 ]; then + + echo "Executing build (via command \`$MakeCmd\`)" + + $MakeCmd + status=$? +fi + +cd ->/dev/null + +if [ $VerboseMakefile -ne 0 ]; then + + echo -e "contents of $CMakeDir:" + ls -al $CMakeDir +fi + +exit $status + + +# ############################## end of file ############################# # + diff --git a/remove_cmake_artefacts.sh b/remove_cmake_artefacts.sh new file mode 100755 index 0000000..7416db9 --- /dev/null +++ b/remove_cmake_artefacts.sh @@ -0,0 +1,151 @@ +#! /bin/bash + +ScriptPath=$0 +Dir=$(cd $(dirname "$ScriptPath"); pwd) +Basename=$(basename "$ScriptPath") +CMakeDir=${SIS_CMAKE_BUILD_DIR:-$Dir/_build} + +Directories=( + CMakeFiles + Testing + cmake + examples + projects + src + test +) +Files=( + CMakeCache.txt + CTestTestfile.cmake + DartConfiguration.tcl + Makefile + cmake_install.cmake + install_manifest.txt +) + + +# ########################################################## +# operating environment detection + +OsName="$(uname -s)" +case "${OsName}" in + CYGWIN*|MINGW*|MSYS_NT*) + + Directories+=( + ARM64 + Win32 + x64 + ) + Files+=( + "*.filters" + "*.sln" + "*.vcxproj" + ) + ;; + *) + + ;; +esac + + +# ########################################################## +# command-line handling + +while [[ $# -gt 0 ]]; do + + case $1 in + --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 ... ] + +Flags/options: + + behaviour: + + + standard flags: + + --help + displays this help and terminates + +EOF + + exit 0 + ;; + *) + + >&2 echo "$ScriptPath: unrecognised argument '$1'; use --help for usage" + + exit 1 + ;; + esac + + shift +done + + +# ########################################################## +# main() + +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" + + exit 0 +else + + echo "Removing all cmake artefacts in '$CMakeDir'" + + num_dirs_removed=0 + num_files_removed=0 + + for d in ${Directories[@]} + do + + fq_dir_path="$CMakeDir/$d" + + [ -d "$fq_dir_path" ] || continue + + echo "removing directory '$d'" + + rm -dfr "$fq_dir_path" + + num_dirs_removed=$((num_dirs_removed+1)) + done + + cd "$CMakeDir" + + for f in ${Files[@]} + do + + for fq_file_path in $f + do + + [ -f "$fq_file_path" ] || continue + + echo "removing file '$fq_file_path'" + + rm -f "$fq_file_path" + + num_files_removed=$((num_files_removed+1)) + done + done + + cd ->/dev/null + + if [ 0 -eq $num_dirs_removed ] && [ 0 -eq $num_files_removed ]; then + + echo "nothing to do" + else + + echo "removed $num_dirs_removed directories and $num_files_removed files" + fi +fi + + +# ############################## end of file ############################# # + diff --git a/run_all_unit_tests.cmd b/run_all_unit_tests.cmd new file mode 100644 index 0000000..8c88eae --- /dev/null +++ b/run_all_unit_tests.cmd @@ -0,0 +1,141 @@ +@echo off + +SETLOCAL ENABLEEXTENSIONS ENABLEDELAYEDEXPANSION + +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" +) + +SET ListOnly=0 +SET Verbose=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" + ) + ECHO ^ + +Runs all ^(matching^) component and unit test programs ^ + +^ + +%SCRIPT_PATH_DOC% [ ... flags/options ... ] ^ + +^ + +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^) ^ + +^ + + -v ^ + + --verbose ^ + + lists each test program before executing it ^ + +^ + + standard flags: ^ + +^ + + --help ^ + + displays this help and terminates ^ + + + 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 {-v}=={%%a} ( + SET Verbose=1 + ) ELSE IF /I {--verbose}=={%%a} ( + SET Verbose=1 + ) ELSE ( + ECHO %SCRIPT_PATH_DOC%: unrecognised argument '%%a'; use --help for usage 1>&2 + + EXIT /B 1 + ) +) + +IF NOT EXIST "%CMAKE_DIR%" ( + + ECHO %SCRIPT_PATH_DOC%: CMake build directory '%CMAKE_DIR%' does not exist 1>&2 + + 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 +) + +IF !ListOnly! EQU 1 ( + + ECHO Listing all component and unit test programs +) ELSE ( + + ECHO Running all component and unit test programs +) + +FOR /F "usebackq delims=" %%f IN (`DIR /A:-D /B /S "%CMAKE_DIR%\*.exe" 2^>NUL ^| FINDSTR /I /R "!ProjectName!.*test.*\.exe$"`) 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 + ) + ) +) + +:done +EXIT /B !status! From f2e4ebf4acdba2c89dce9d501876f31461809453 Mon Sep 17 00:00:00 2001 From: Matt Wilson Date: Mon, 3 Aug 2026 11:23:14 +1000 Subject: [PATCH 06/21] chore: added project markdown files --- AUTHORS.md | 17 +++++++++++ CHANGES.md | 16 ++++++++++ INSTALL.md | 84 +++++++++++++++++++++++++++++++++++++++++++++++++++ NEWS.md | 9 ++++++ README.md | 80 ++++++++++++++++++++++++++++++++++++++++++++++-- REQUISITES.md | 45 +++++++++++++++++++++++++++ TODO.md | 10 ++++++ 7 files changed, 258 insertions(+), 3 deletions(-) create mode 100644 AUTHORS.md create mode 100644 CHANGES.md create mode 100644 INSTALL.md create mode 100644 NEWS.md create mode 100644 REQUISITES.md create mode 100644 TODO.md diff --git a/AUTHORS.md b/AUTHORS.md new file mode 100644 index 0000000..d9b948a --- /dev/null +++ b/AUTHORS.md @@ -0,0 +1,17 @@ +# WriteDebugString - Authors + + +## Major Contributors: + +* Matt Wilson ([mwsis](https://github.com/mwsis)) + + +## Defect reports, fixes and suggestions (for which we are very grateful): + +* \ (yet) + + +Contributions are welcomed. + + + diff --git a/CHANGES.md b/CHANGES.md new file mode 100644 index 0000000..866de6d --- /dev/null +++ b/CHANGES.md @@ -0,0 +1,16 @@ +# **WriteDebugString** Changes + + +## 0.0.1 - 3rd August 2026 + +* Initial CMake-based release (**CMakeLists.txt**, helper scripts, and project documentation); +* Added modular GitHub Actions CI (**ci.yml** / **ci-cell.yml**) for Windows (Windows-only tool); +* Added **cmake/BuildType.cmake**; +* Added CMake helper scripts (**prepare_cmake.sh**, **build_cmake.sh**, **clean_cmake.sh**, **remove_cmake_artefacts.sh**) and **run_all_unit_tests.cmd**; +* Added **.sis/script_info_lines.txt** and **.sis/project_name.txt**; +* Project boilerplate bootstrap (**.gitattributes**, **.gitignore**, **.vimrc**, **.vscode/settings.json**, **AUTHORS.md**, **LICENSE**, **README.md**, **INSTALL.md**, **REQUISITES.md**, **TODO.md**, **NEWS.md**); +* Renamed **main.c** to **WriteDebugString.c**; added version macros, **--version**, and explicit **windows.h** include; +* Retired the broken nmake **Makefile**; + + + diff --git a/INSTALL.md b/INSTALL.md new file mode 100644 index 0000000..31c4993 --- /dev/null +++ b/INSTALL.md @@ -0,0 +1,84 @@ +# WriteDebugString - Installation and Use + + +- [Requisites](#requisites) +- [Building](#building) + - [via CMake](#via-cmake) + + +## Requisites + +The **WriteDebugString** program (implemented in [**WriteDebugString.c**](./WriteDebugString.c)) is implemented in terms of: + +* [**STLSoft**](https://github.com/synesissoftware/STLSoft) - for WinSTL diagnostics helpers and platform utilities; + +Detailed instructions are provided in the [**REQUISITES.md**](./REQUISITES.md) document for how to obtain and install **STLSoft**. + +> **NOTE**: **WriteDebugString** targets Windows only. + + +## Building + + +### via CMake + +The primary choice for installation is by use of **CMake**. + +1. Obtain the latest distribution of **WriteDebugString**, from + https://github.com/sistools/WriteDebugString/, e.g. + + ```bash + $ mkdir -p ~/open-source + $ cd ~/open-source + $ git clone https://github.com/sistools/WriteDebugString/ + ``` + +2. Prepare the CMake configuration, via the **prepare_cmake.sh** script, as + in: + + ```bash + $ cd ~/open-source/WriteDebugString + $ ./prepare_cmake.sh + ``` + + **NOTE**: if you do not have **STLSoft** installed via **CMake** package + config, point at a local tree with `-s` / `--stlsoft-root-dir`, or set the + **STLSOFT** environment variable. + + Tests are currently a no-op for this project; you may disable the testing + option with `-T` if desired: + + ```bash + $ cd ~/open-source/WriteDebugString + $ ./prepare_cmake.sh -T + ``` + +3. Run a build of the generated **CMake**-derived build files via the + **build_cmake.sh** script, as in: + + ```bash + $ cd ~/open-source/WriteDebugString + $ ./build_cmake.sh + ``` + + (**NOTE**: if you provide the flag `--run-make` (=== `-m`) in step 2 then you do + not need this step.) + +4. As a check, execute the built program, as in: + + ```bash + $ cd ~/open-source/WriteDebugString + $ ./_build/WriteDebugString.exe --help + ``` + + You should see usage output naming **WriteDebugString**. + +5. Install (optional), as in: + + ```bash + $ cd ~/open-source/WriteDebugString + $ cmake --install ./_build --config Release + ``` + + + diff --git a/NEWS.md b/NEWS.md new file mode 100644 index 0000000..db8f646 --- /dev/null +++ b/NEWS.md @@ -0,0 +1,9 @@ +# WriteDebugString - News + + +| Date | News Item | +| -------------------- | -------------------------------------------------- | +| 3rd August 2026 | 0.0.1 released | + + + diff --git a/README.md b/README.md index 43ae8ed..ef5ffb6 100644 --- a/README.md +++ b/README.md @@ -1,15 +1,89 @@ # WriteDebugString -[![License](https://img.shields.io/badge/License-BSD_3--Clause-blue.svg)](https://img.shields.io/badge/License-BSD_3--Clause-blue.svg) +Windows CLI that writes messages to the debugger via **OutputDebugString** -Simple Windows CLI program that permits writing to the Windows debugger + +![C](https://img.shields.io/badge/C-00599C?style=flat&logo=c&logoColor=white) +[![License](https://img.shields.io/badge/License-BSD_3--Clause-blue.svg)](https://opensource.org/licenses/BSD-3-Clause) +[![GitHub release](https://img.shields.io/github/v/release/sistools/WriteDebugString.svg)](https://github.com/sistools/WriteDebugString/releases/latest) +[![Last Commit](https://img.shields.io/github/last-commit/sistools/WriteDebugString)](https://github.com/sistools/WriteDebugString/commits/master) +[![CI](https://github.com/sistools/WriteDebugString/actions/workflows/ci.yml/badge.svg)](https://github.com/sistools/WriteDebugString/actions/workflows/ci.yml) ## Table of Contents +- [Introduction](#introduction) +- [Installation](#installation) +- [Components](#components) +- [Examples](#examples) +- [Project Information](#project-information) + - [Where to get help](#where-to-get-help) + - [Contribution guidelines](#contribution-guidelines) + - [Dependencies](#dependencies) + - [Related projects](#related-projects) + - [License](#license) + ## Introduction +**WriteDebugString** is a small Windows-only utility that writes one or more +messages to the Windows debug output stream (as consumed by debuggers and +tools such as DebugView), using **STLSoft**/**WinSTL** helpers. - +## Installation + +Detailed instructions - via **CMake** - are provided in the accompanying +[INSTALL.md](./INSTALL.md) file. + + +## Components + +The project creates a single executable program, **WriteDebugString**. + + +## Examples + +```plaintext +> WriteDebugString.exe hello world +wrote 2 message(s) to debug stream + +> WriteDebugString.exe --sleep-after-writes "hold for listener" +wrote 1 message(s) to debug stream +``` + + +## Project Information + + +### Where to get help + +[GitHub Page](https://github.com/sistools/WriteDebugString "GitHub Page") + + +### Contribution guidelines + +Defect reports, feature requests, and pull requests are welcome on [the **WriteDebugString** GitHub page](https://github.com/sistools/WriteDebugString). + + +### Dependencies + +**WriteDebugString** depends on: + +* [**STLSoft**](https://github.com/synesissoftware/STLSoft); + + +### Related projects + +Other (similar) projects include: + +* [**ReadDebugString**](https://github.com/sistools/ReadDebugString) +* [**realpath**](https://github.com/sistools/realpath) + + +### License + +**WriteDebugString** is released under the 3-clause BSD license. See [LICENSE](./LICENSE) for details. + + + diff --git a/REQUISITES.md b/REQUISITES.md new file mode 100644 index 0000000..f0a1317 --- /dev/null +++ b/REQUISITES.md @@ -0,0 +1,45 @@ +# WriteDebugString - Requisites + + +- [Introduction](#introduction) +- [Installation by CMake](#installation-by-cmake) + - [STLSoft](#stlsoft) +- [Installation by other means](#installation-by-other-means) + + +## Introduction + +The **WriteDebugString** program (implemented in [**WriteDebugString.c**](./WriteDebugString.c)) is implemented in terms of: + +* [**STLSoft**](https://github.com/synesissoftware/STLSoft) - for WinSTL diagnostics helpers and platform utilities; + +> **NOTE**: **WriteDebugString** is a Windows-only tool. + + +## Installation by CMake + + +### STLSoft + +The **STLSoft** libraries provide a wide range of compiler/library discrimination and compatibility facilities, operating system API façades, and a number of extended components over and above what is provided in the standard library. + +**STLSoft** is obtained from **https://github.com/synesissoftware/STLSoft**, and it provides the means to install via **CMake**, as in the following: + +```bash +$ mkdir -p ~/open-source +$ cd ~/open-source +$ git clone https://github.com/synesissoftware/STLSoft +$ cd ~/open-source/STLSoft +$ ./prepare_cmake.sh -m +$ cmake --install ./_build --config Release +``` + +Alternatively, set the **STLSOFT** environment variable (or pass `-DSTLSOFT=...` / `./prepare_cmake.sh -s ...`) to a local checkout that contains an `include/` directory. + + +## Installation by other means + +If you do not use **CMake** to install **STLSoft**, ensure the headers are available via the **STLSOFT** environment variable (pointing at the library root) before configuring this project. + + + diff --git a/TODO.md b/TODO.md new file mode 100644 index 0000000..db2ba1d --- /dev/null +++ b/TODO.md @@ -0,0 +1,10 @@ +# WriteDebugString - TODO list + + +## WriteDebugString 0.0.x TODOs: + +* Consider promoting from ad-hoc argv parsing toward **CLASP** later (optional; **realpath** stays manual); +* Set GitHub repository topics: `c`, `cli`, `command-line`, `cmake`, `stlsoft`, `windows`, `win32`, `debugging`, `debugger`, `outputdebugstring`, `bsd-3-clause`, `sistools`; + + + From c98ab29a50510baa239275f70f64aa873328368a Mon Sep 17 00:00:00 2001 From: Matt Wilson Date: Mon, 3 Aug 2026 11:24:13 +1000 Subject: [PATCH 07/21] LICENSE --- LICENSE | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/LICENSE b/LICENSE index a753d5b..e9f5dfb 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ WriteDebugString - BSD 3-Clause License -Copyright (c) 2025, sistools +Copyright (c) 2025-2026, Synesis Information Systems All rights reserved. Redistribution and use in source and binary forms, with or without @@ -28,4 +28,3 @@ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - From c283e8cd03e61800da5f3fb101a8719f835b2a6a Mon Sep 17 00:00:00 2001 From: Matt Wilson Date: Mon, 3 Aug 2026 11:27:12 +1000 Subject: [PATCH 08/21] chore: CMake updates --- CHANGES.md | 2 +- CMakeLists.txt | 233 ++++++++++++++++++++++++++++++++++++++++++ INSTALL.md | 2 +- REQUISITES.md | 2 +- cmake/BuildType.cmake | 59 +++++++++++ main.c | 35 ++++++- 6 files changed, 326 insertions(+), 7 deletions(-) create mode 100644 CMakeLists.txt create mode 100644 cmake/BuildType.cmake diff --git a/CHANGES.md b/CHANGES.md index 866de6d..eb8efd3 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -9,7 +9,7 @@ * Added CMake helper scripts (**prepare_cmake.sh**, **build_cmake.sh**, **clean_cmake.sh**, **remove_cmake_artefacts.sh**) and **run_all_unit_tests.cmd**; * Added **.sis/script_info_lines.txt** and **.sis/project_name.txt**; * Project boilerplate bootstrap (**.gitattributes**, **.gitignore**, **.vimrc**, **.vscode/settings.json**, **AUTHORS.md**, **LICENSE**, **README.md**, **INSTALL.md**, **REQUISITES.md**, **TODO.md**, **NEWS.md**); -* Renamed **main.c** to **WriteDebugString.c**; added version macros, **--version**, and explicit **windows.h** include; +* Added version macros, **--version**, and explicit **windows.h** include; * Retired the broken nmake **Makefile**; diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..f05142a --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,233 @@ +# ######################################################################## # +# File: /CMakeLists.txt +# +# Purpose: Top-level CMake lists file for WriteDebugString +# +# Created: 3rd August 2026 +# Updated: 3rd August 2026 +# +# ######################################################################## # + + +# ########################################################## +# CMake + +cmake_minimum_required(VERSION 3.20 FATAL_ERROR) + +# require out-of-source builds +file(TO_CMAKE_PATH "${CMAKE_CURRENT_BINARY_DIR}/CMakeLists.txt" LOC_PATH) +if(EXISTS "${LOC_PATH}") + + message(FATAL_ERROR "You cannot build in a source directory (or any directory with a CMakeLists.txt file). Please make a build subdirectory. Feel free to remove CMakeCache.txt and CMakeFiles.") +endif() + +# directory for CMake specific extensions and source files. +set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake" ${CMAKE_MODULE_PATH}) + + +# ########################################################## +# project + +project(WriteDebugString + DESCRIPTION "WriteDebugString is a Windows CLI that writes messages to the debugger via OutputDebugString." + HOMEPAGE_URL "https://github.com/sistools/WriteDebugString" + LANGUAGES C CXX +) + +string(TOLOWER ${PROJECT_NAME} PROJECT_NAME_LOWER) +string(TOUPPER ${PROJECT_NAME} PROJECT_NAME_UPPER) + +# handle version number +set(RX_PROJ_TAG "${PROJECT_NAME_UPPER}") +set(RX_WS "[ \t]") +file(READ "${CMAKE_SOURCE_DIR}/main.c" _impl_file) +string(REGEX MATCH "#${RX_WS}*define${RX_WS}+_?${RX_PROJ_TAG}_VER_MAJOR${RX_WS}+([0-9]+)" MAJOR_DUMMY ${_impl_file}) +set(_VERSION_MAJOR ${CMAKE_MATCH_1}) +string(REGEX MATCH "#${RX_WS}*define${RX_WS}+_?${RX_PROJ_TAG}_VER_MINOR${RX_WS}+([0-9]+)" MINOR_DUMMY ${_impl_file}) +set(_VERSION_MINOR ${CMAKE_MATCH_1}) +string(REGEX MATCH "#${RX_WS}*define${RX_WS}+_?${RX_PROJ_TAG}_VER_PATCH${RX_WS}+([0-9]+)" PATCH_DUMMY ${_impl_file}) +set(_VERSION_PATCH ${CMAKE_MATCH_1}) + +# set project version number here +set(PROJECT_VERSION_MAJOR ${_VERSION_MAJOR}) +set(PROJECT_VERSION_MINOR ${_VERSION_MINOR}) +set(PROJECT_VERSION_PATCH ${_VERSION_PATCH}) +set(PROJECT_VERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}") + +# adhere strictly to C and C++ standards plus extensions. These are actually +# useless since we do not compile anything; they merely state our intention. +set(CMAKE_C_STANDARD 17) +set(CMAKE_C_STANDARD_REQUIRED ON) +set(CMAKE_C_EXTENSIONS ON) # GNU extensions and POSIX standard +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_CXX_EXTENSIONS ON) + +if(MSVC) + + if(MSVC_VERSION GREATER_EQUAL 1914) + + add_compile_options("/Zc:__cplusplus") + + add_definitions(-D_SILENCE_CXX17_ITERATOR_BASE_CLASS_DEPRECATION_WARNING) + endif() + + if(MSVC_VERSION LESS 1930) + + set(CMAKE_C_STANDARD 90) + set(CMAKE_CXX_STANDARD 98) + endif() + + if(MSVC_USE_MT) + + set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>") + endif(MSVC_USE_MT) +else(MSVC) + + if(MSVC_USE_MT) + + # this here just to absorb warning about not using `MSVC_USE_MT` (to + # enable **prepare_cmake.sh** to be simple) + endif(MSVC_USE_MT) +endif(MSVC) + + +# ########################################################## +# dependencies, includes, options + +# ################################################ +# includes - 1 + +include(BuildType) +#[====[ +include(LanguageFullVersion) +include(TargetMacros) +#]====] + + +# ################################################ +# dependencies, features, and options + + +# ###################################### +# options + +option(BUILD_EXAMPLES "Build examples" ON) + +option(BUILD_TESTING "Build tests" ON) + + +# ###################################### +# features + +# This tool targets Windows only (WinSTL). +if(NOT WIN32) + + message(FATAL_ERROR "${PROJECT_NAME} targets Windows only") +endif() + + +# ###################################### +# dependencies +# +# required: +# - STLSoft; +# +# required if testing enabled: +# - (none); +# +# optional: + + +# ############################ +# STLSoft + +if(DEFINED STLSOFT) + + message("-- STLSOFT provided as CMake variable with value '${STLSOFT}'") + + set(STLSOFT_INCLUDE_DIR ${STLSOFT}/include) +elseif(DEFINED ENV{STLSOFT}) + + message("-- STLSOFT provided as environment variable with value '$ENV{STLSOFT}'") + + set(STLSOFT_INCLUDE_DIR $ENV{STLSOFT}/include) +else() + + set(STLSoft_REQUIRED_VERSION_ 1.11.1) + + find_package(STLSoft ${STLSoft_REQUIRED_VERSION_} REQUIRED) + + message("-- CMake package STLSoft found (version ${STLSoft_VERSION}; ${STLSoft_REQUIRED_VERSION_} requested)") +endif() + +if(DEFINED STLSOFT_INCLUDE_DIR) + + include_directories(${STLSOFT_INCLUDE_DIR}) +endif() + + +# ################################################ +# includes - 2 + +include(CMakePackageConfigHelpers) +if(BUILD_TESTING) + + include(CTest) +endif(BUILD_TESTING) +include(GNUInstallDirs) + + +# ########################################################## +# tool + +add_executable(${PROJECT_NAME} + main.c +) + +target_compile_options(${PROJECT_NAME} + PRIVATE + $<$,$,$>: + -Werror -Wall -Wextra -pedantic + + -Wno-ignored-qualifiers + -Wno-incompatible-pointer-types-discards-qualifiers + -Wno-unused-parameter + > + $<$: + /WX /W4 + > +) + +target_link_libraries(${PROJECT_NAME} + $<$:STLSoft::STLSoft> +) + +install(TARGETS ${PROJECT_NAME} + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} +) + + +# ################################################ +# examples + + +# ################################################ +# tests + +if(BUILD_TESTING) + + message("-- enabled building of tests ...") +else(BUILD_TESTING) + + message("-- disabled building of tests - define BUILD_TESTING to enable") +endif(BUILD_TESTING) + + +# ########################################################## +# completion + +message(NOTICE "Generating CMake build scripts for ${PROJECT_NAME} ${PROJECT_VERSION}, for C${CMAKE_C_STANDARD} C++${CMAKE_CXX_STANDARD}") + + +# ############################## end of file ############################# # diff --git a/INSTALL.md b/INSTALL.md index 31c4993..b40e426 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -8,7 +8,7 @@ ## Requisites -The **WriteDebugString** program (implemented in [**WriteDebugString.c**](./WriteDebugString.c)) is implemented in terms of: +The **WriteDebugString** program (implemented in [**main.c**](./main.c)) is implemented in terms of: * [**STLSoft**](https://github.com/synesissoftware/STLSoft) - for WinSTL diagnostics helpers and platform utilities; diff --git a/REQUISITES.md b/REQUISITES.md index f0a1317..8dd9a95 100644 --- a/REQUISITES.md +++ b/REQUISITES.md @@ -9,7 +9,7 @@ ## Introduction -The **WriteDebugString** program (implemented in [**WriteDebugString.c**](./WriteDebugString.c)) is implemented in terms of: +The **WriteDebugString** program (implemented in [**main.c**](./main.c)) is implemented in terms of: * [**STLSoft**](https://github.com/synesissoftware/STLSoft) - for WinSTL diagnostics helpers and platform utilities; diff --git a/cmake/BuildType.cmake b/cmake/BuildType.cmake new file mode 100644 index 0000000..a315b8d --- /dev/null +++ b/cmake/BuildType.cmake @@ -0,0 +1,59 @@ + +# ######################################################################## # +# File: /cmake/BuildType.cmake +# +# Purpose: CMake module file (for BuildType) +# +# Created: 16th October 2019 +# Updated: 25th October 2024 +# +# ######################################################################## # + + +# Including this module sets the `CMAKE_BUILD_TYPE` value as follows: +# +# 1. If user specifies on the command line, then `CMAKE_BUILD_TYPE` already +# has a valid, so this is accepted; +# 2. If the top-level .git directory is specified, then "Debug" is used; +# otherwise +# 3. "Release" is used. +# +# Note: +# - `CMAKE_BUILD_TYPE` is the build (configuration) type; +# - `CMAKE_CONFIGURATION_TYPES` is, if specified, a list of valid +# configurations (see +# https://cmake.org/cmake/help/latest/variable/CMAKE_CONFIGURATION_TYPES.html); +# +# Example usage: +# +#[========[ + +# CMakeLists.txt + +include(BuildType) + +]========] + + +if(EXISTS "${CMAKE_SOURCE_DIR}/.git") + set(DEFAULT_BUILD_TYPE "Debug") +else() + set(DEFAULT_BUILD_TYPE "Release") +endif() + +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}" + STRING "Choose the type of build." FORCE + ) + + # Set the possible values of build type for cmake-gui + set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS + "Debug" "Release" "MinSizeRel" "RelWithDebInfo" + ) +endif() + +# ############################## end of file ############################# # + diff --git a/main.c b/main.c index e1e8c0d..352921c 100644 --- a/main.c +++ b/main.c @@ -1,11 +1,25 @@ -#include +#include + +#if _STLSOFT_VER < 0x010b0184 +# error requires STLSoft v1.11.1-b4 or later +#endif + #include +#include + +#include #include #include #include + +#define WRITEDEBUGSTRING_VER_MAJOR 0 +#define WRITEDEBUGSTRING_VER_MINOR 0 +#define WRITEDEBUGSTRING_VER_PATCH 1 + + int main(int argc, char* argv[]) { stlsoft_C_string_slice_m_t const program_name = platformstl_C_get_executable_name_from_path(argv[0]); @@ -27,8 +41,22 @@ int main(int argc, char* argv[]) { fprintf( stdout - , "USAGE: %.*s { --help | [ --sleep-after-writes ] [ ... ] }\n" + , "USAGE: %.*s { --help | --version | [ --sleep-after-writes ] [ ... ] }\n" + , (int)program_name.len, program_name.ptr + ); + + return EXIT_SUCCESS; + } + else + if (0 == strcmp("--version", argv[1])) + { + fprintf( + stdout + , "%.*s %d.%d.%d\n" , (int)program_name.len, program_name.ptr + , WRITEDEBUGSTRING_VER_MAJOR + , WRITEDEBUGSTRING_VER_MINOR + , WRITEDEBUGSTRING_VER_PATCH ); return EXIT_SUCCESS; @@ -42,7 +70,7 @@ int main(int argc, char* argv[]) { char const* const arg = argv[i]; - if (0 == strcmp("--sleep-after-writes", argv[i])) + if (0 == strcmp("--sleep-after-writes", arg)) { do_sleep = 1; } @@ -69,4 +97,3 @@ int main(int argc, char* argv[]) return EXIT_SUCCESS; } } - From 063fe07b3993c1eca4142444d8cbb9bd67055a5c Mon Sep 17 00:00:00 2001 From: Matt Wilson Date: Mon, 3 Aug 2026 11:27:19 +1000 Subject: [PATCH 09/21] CI --- .github/workflows/ci-cell.yml | 268 ++++++++++++++++++++++++++++++++++ .github/workflows/ci.yml | 39 +++++ 2 files changed, 307 insertions(+) create mode 100644 .github/workflows/ci-cell.yml create mode 100644 .github/workflows/ci.yml diff --git a/.github/workflows/ci-cell.yml b/.github/workflows/ci-cell.yml new file mode 100644 index 0000000..c17166d --- /dev/null +++ b/.github/workflows/ci-cell.yml @@ -0,0 +1,268 @@ +name: CI cell + +on: + workflow_call: + inputs: + cell-id: + required: true + type: string + os: + required: true + type: string + c-compiler: + required: true + type: string + cpp-compiler: + required: true + type: string + build-type: + required: false + type: string + default: Release + with-clasp: + required: false + type: boolean + default: true + with-cstring: + required: false + type: boolean + default: false + with-test-deps: + required: false + type: boolean + default: true + run-tests: + required: false + type: boolean + default: true + +jobs: + cell: + name: ${{ inputs.cell-id }} + runs-on: ${{ inputs.os }} + + steps: + - uses: actions/checkout@v4 + + - name: Install Clang (Ubuntu) + if: runner.os == 'Linux' && inputs.c-compiler == 'clang' + run: sudo apt-get update && sudo apt-get install -y clang + + - name: Setup MSYS2 MinGW + if: runner.os == 'Windows' && inputs.c-compiler == 'mingw' + uses: msys2/setup-msys2@v2 + with: + msystem: MINGW64 + update: true + install: >- + mingw-w64-x86_64-toolchain + mingw-w64-x86_64-cmake + mingw-w64-x86_64-make + + - name: Install dependencies + shell: bash + run: | + set -euxo pipefail + + DEPS="${RUNNER_TEMP}/sis-deps" + mkdir -p "$DEPS" + echo "SIS_DEPS=$DEPS" >> "$GITHUB_ENV" + + if [ "${{ inputs.c-compiler }}" = "mingw" ]; then + export PATH="/mingw64/bin:$PATH" + fi + + cmake_configure() { + local src="$1" bld="$2" + shift 2 + if [ "${{ inputs.c-compiler }}" = "cl" ]; then + cmake -S "$src" -B "$bld" \ + -DCMAKE_DISABLE_FIND_PACKAGE_MFC=TRUE \ + -DCMAKE_INSTALL_PREFIX="$DEPS" \ + -DCMAKE_PREFIX_PATH="$DEPS" \ + -DBUILD_EXAMPLES=OFF \ + -DBUILD_TESTING=OFF \ + "$@" + elif [ "${{ inputs.c-compiler }}" = "mingw" ]; then + cmake -S "$src" -B "$bld" -G "MinGW Makefiles" \ + -DCMAKE_BUILD_TYPE="${{ inputs.build-type }}" \ + -DCMAKE_INSTALL_PREFIX="$DEPS" \ + -DCMAKE_PREFIX_PATH="$DEPS" \ + -DBUILD_EXAMPLES=OFF \ + -DBUILD_TESTING=OFF \ + "$@" + else + cmake -S "$src" -B "$bld" \ + -DCMAKE_BUILD_TYPE="${{ inputs.build-type }}" \ + -DCMAKE_C_COMPILER="${{ inputs.c-compiler }}" \ + -DCMAKE_CXX_COMPILER="${{ inputs.cpp-compiler }}" \ + -DCMAKE_INSTALL_PREFIX="$DEPS" \ + -DCMAKE_PREFIX_PATH="$DEPS" \ + -DBUILD_EXAMPLES=OFF \ + -DBUILD_TESTING=OFF \ + "$@" + fi + } + + cmake_build_install() { + local bld="$1" + if [ "${{ inputs.c-compiler }}" = "cl" ]; then + cmake --build "$bld" --config "${{ inputs.build-type }}" --parallel + cmake --install "$bld" --config "${{ inputs.build-type }}" + elif [ "${{ inputs.c-compiler }}" = "mingw" ]; then + cmake --build "$bld" --parallel 2 + cmake --install "$bld" + else + cmake --build "$bld" --parallel + cmake --install "$bld" + fi + } + + # STLSoft (required) + STLSRC="${RUNNER_TEMP}/stlsoft-src" + STLBUILD="${RUNNER_TEMP}/stlsoft-build" + git clone --depth 1 https://github.com/synesissoftware/STLSoft "$STLSRC" + cmake_configure "$STLSRC" "$STLBUILD" + cmake_build_install "$STLBUILD" + + # Catch2 v2 + xTests (test-only) + if [ "${{ inputs.with-test-deps }}" = "true" ]; then + CATCHSRC="${RUNNER_TEMP}/catch2-src" + CATCHBUILD="${RUNNER_TEMP}/catch2-build" + git clone --depth 1 --branch v2.x https://github.com/catchorg/Catch2 "$CATCHSRC" + cmake_configure "$CATCHSRC" "$CATCHBUILD" \ + -DCATCH_BUILD_TESTING=OFF \ + -DCATCH_ENABLE_WERROR=OFF \ + -DCATCH_INSTALL_DOCS=OFF + cmake_build_install "$CATCHBUILD" + + XTSRC="${RUNNER_TEMP}/xtests-src" + XTBUILD="${RUNNER_TEMP}/xtests-build" + git clone --depth 1 https://github.com/synesissoftware/xTests "$XTSRC" + cmake_configure "$XTSRC" "$XTBUILD" -DNO_SHWILD=TRUE + cmake_build_install "$XTBUILD" + fi + + # CLASP + if [ "${{ inputs.with-clasp }}" = "true" ]; then + CLASPSRC="${RUNNER_TEMP}/clasp-src" + CLASPBUILD="${RUNNER_TEMP}/clasp-build" + git clone --depth 1 https://github.com/synesissoftware/CLASP "$CLASPSRC" + cmake_configure "$CLASPSRC" "$CLASPBUILD" + cmake_build_install "$CLASPBUILD" + fi + + # cstring + if [ "${{ inputs.with-cstring }}" = "true" ]; then + CSTRSRC="${RUNNER_TEMP}/cstring-src" + CSTRBUILD="${RUNNER_TEMP}/cstring-build" + git clone --depth 1 https://github.com/synesissoftware/cstring "$CSTRSRC" + cmake_configure "$CSTRSRC" "$CSTRBUILD" + cmake_build_install "$CSTRBUILD" + fi + + - name: Configure + shell: bash + run: | + set -euo pipefail + DEPS="${{ env.SIS_DEPS }}" + + if [ "${{ inputs.c-compiler }}" = "mingw" ]; then + export PATH="/mingw64/bin:$PATH" + fi + + # Bare `cstring` link (rstrip) needs include/lib search paths beyond + # find_package(CLASP)-style imported targets. + if [ "${{ inputs.with-cstring }}" = "true" ]; then + if [ "${{ inputs.c-compiler }}" = "cl" ]; then + export INCLUDE="$(cygpath -w "$DEPS/include");${INCLUDE:-}" + export LIB="$(cygpath -w "$DEPS/lib");${LIB:-}" + else + export CPATH="$DEPS/include${CPATH:+:$CPATH}" + export LIBRARY_PATH="$DEPS/lib${LIBRARY_PATH:+:$LIBRARY_PATH}" + fi + fi + + if [ "${{ inputs.c-compiler }}" = "cl" ]; then + cmake -B build -S . \ + -DCMAKE_DISABLE_FIND_PACKAGE_MFC=TRUE \ + -DCMAKE_PREFIX_PATH="$DEPS" \ + -DBUILD_EXAMPLES=OFF \ + -DBUILD_TESTING=ON + elif [ "${{ inputs.c-compiler }}" = "mingw" ]; then + cmake -B build -G "MinGW Makefiles" \ + -DCMAKE_BUILD_TYPE="${{ inputs.build-type }}" \ + -DCMAKE_C_COMPILER=gcc \ + -DCMAKE_CXX_COMPILER=g++ \ + -DCMAKE_PREFIX_PATH="$DEPS" \ + -DBUILD_EXAMPLES=OFF \ + -DBUILD_TESTING=ON + else + cmake -B build -S . \ + -DCMAKE_BUILD_TYPE="${{ inputs.build-type }}" \ + -DCMAKE_C_COMPILER="${{ inputs.c-compiler }}" \ + -DCMAKE_CXX_COMPILER="${{ inputs.cpp-compiler }}" \ + -DCMAKE_PREFIX_PATH="$DEPS" \ + -DBUILD_EXAMPLES=OFF \ + -DBUILD_TESTING=ON + fi + + - name: Build + shell: bash + run: | + set -euo pipefail + if [ "${{ inputs.c-compiler }}" = "mingw" ]; then + export PATH="/mingw64/bin:$PATH" + fi + if [ "${{ inputs.with-cstring }}" = "true" ]; then + DEPS="${{ env.SIS_DEPS }}" + if [ "${{ inputs.c-compiler }}" = "cl" ]; then + export INCLUDE="$(cygpath -w "$DEPS/include");${INCLUDE:-}" + export LIB="$(cygpath -w "$DEPS/lib");${LIB:-}" + else + export CPATH="$DEPS/include${CPATH:+:$CPATH}" + export LIBRARY_PATH="$DEPS/lib${LIBRARY_PATH:+:$LIBRARY_PATH}" + fi + fi + if [ "${{ inputs.c-compiler }}" = "cl" ]; then + cmake --build build --config "${{ inputs.build-type }}" --parallel + elif [ "${{ inputs.c-compiler }}" = "mingw" ]; then + cmake --build build --parallel 2 + else + cmake --build build --parallel + fi + + - name: Run tests + if: inputs.run-tests + shell: bash + run: | + set -euo pipefail + if [ "${{ inputs.c-compiler }}" = "mingw" ]; then + export PATH="/mingw64/bin:$PATH" + fi + export SIS_CMAKE_BUILD_DIR="${{ github.workspace }}/build" + if [ "${{ runner.os }}" = "Windows" ]; then + cmd.exe //c "run_all_unit_tests.cmd -M -v" + else + ./run_all_unit_tests.sh -M -v + fi + + - name: Install and verify + shell: bash + run: | + set -euo pipefail + PREFIX="${RUNNER_TEMP}/install-prefix" + PROJECT="$(tr -d '[:space:]' < .sis/project_name.txt)" + if [ "${{ inputs.c-compiler }}" = "mingw" ]; then + export PATH="/mingw64/bin:$PATH" + fi + if [ "${{ inputs.c-compiler }}" = "cl" ]; then + cmake --install build --config "${{ inputs.build-type }}" --prefix "$PREFIX" + else + cmake --install build --prefix "$PREFIX" + fi + if [ "${{ inputs.c-compiler }}" = "cl" ] || [ "${{ inputs.c-compiler }}" = "mingw" ]; then + test -f "$PREFIX/bin/${PROJECT}.exe" + else + test -x "$PREFIX/bin/${PROJECT}" + fi diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..05d1e48 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,39 @@ +name: CI + +on: + push: + branches: + - master + - boilerplate + pull_request: + +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + +jobs: + cell: + name: CI (${{ matrix.id }}) + strategy: + fail-fast: false + matrix: + include: + - id: windows-cl + os: windows-latest + c_compiler: cl + cpp_compiler: cl + - id: windows-mingw + os: windows-latest + c_compiler: mingw + cpp_compiler: g++ + uses: ./.github/workflows/ci-cell.yml + with: + cell-id: ${{ matrix.id }} + os: ${{ matrix.os }} + c-compiler: ${{ matrix.c_compiler }} + cpp-compiler: ${{ matrix.cpp_compiler }} + build-type: Release + with-clasp: false + with-cstring: false + with-test-deps: false + run-tests: true From 262b1cfb758c862af6dbb15bb12b51b4e7d6f8ad Mon Sep 17 00:00:00 2001 From: Matt Wilson Date: Sun, 16 Aug 2026 21:05:08 +1000 Subject: [PATCH 10/21] .vscode/settings.json --- .vscode/settings.json | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 4044afc..a20fc3c 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -5,6 +5,8 @@ "editor.tabSize": 4, }, "[c]": { + "editor.defaultFormatter": "ms-vscode.cpptools", + "editor.formatOnSave": true, "editor.insertSpaces": true, "editor.rulers": [ 60, 64, 68, 72, 76 ], "editor.tabSize": 4, @@ -14,6 +16,8 @@ "editor.tabSize": 4, }, "[cpp]": { + "editor.defaultFormatter": "ms-vscode.cpptools", + "editor.formatOnSave": true, "editor.insertSpaces": true, "editor.rulers": [ 60, 64, 68, 72, 76 ], "editor.tabSize": 4, @@ -49,7 +53,17 @@ "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", @@ -128,6 +142,7 @@ "numeric": "cpp", "optional": "cpp", "ostream": "cpp", + "print": "cpp", "queue": "cpp", "random": "cpp", "ranges": "cpp", @@ -180,4 +195,3 @@ "files.trimTrailingWhitespace": true, "git.mergeEditor": false, } - From 5980e85fa6bd7ac879a2ff4a91e5b80b81a4a690 Mon Sep 17 00:00:00 2001 From: Matt Wilson Date: Mon, 17 Aug 2026 14:26:59 +1000 Subject: [PATCH 11/21] .gitattributes --- .gitattributes | 102 ++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 85 insertions(+), 17 deletions(-) diff --git a/.gitattributes b/.gitattributes index a9c5470..d58dcc9 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,17 +1,85 @@ -*.c linguist-language=C -*.cmake linguist-vendored -*.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-vendored -makefile linguist-detectable=false +# .gitattributes — C (GitHub-hosted) +# +# Sources: GitHub Docs (line endings), git-scm gitattributes (diff=cpp), +# gitattributes/gitattributes C++.gitattributes + Common.gitattributes, +# github-linguist overrides. + +# Default: detect text, normalize to LF in the repository +* text=auto + +# --- Source --- +*.c text diff=cpp +*.h text diff=cpp +*.inc text +*.inl 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 +*.lib binary +*.o binary +*.obj binary +*.out binary +*.pch binary +*.so binary + +# --- Archives / images (common) --- +*.gif binary +*.gz binary +*.ico binary +*.jpeg binary +*.jpg binary +*.png binary +*.tar binary +*.zip binary + +# --- GitHub Linguist --- +# Object / build trees if committed (prefer .gitignore; mark if present) +**/build/** linguist-generated +**/cmake-build-*/** linguist-generated From ecf6e5a5b7b4faef110520494d881d3fe96904db Mon Sep 17 00:00:00 2001 From: Matt Wilson Date: Mon, 17 Aug 2026 15:20:00 +1000 Subject: [PATCH 12/21] ci --- .github/workflows/ci.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 05d1e48..fe85f6f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -4,7 +4,12 @@ on: push: branches: - master + - dev - boilerplate + - idiomatic + - rc1 + - rc2 + - rc3 pull_request: concurrency: From 7a1aa7afbc56d117b41b551a798165c75d07e34c Mon Sep 17 00:00:00 2001 From: Matt Wilson Date: Mon, 17 Aug 2026 16:03:35 +1000 Subject: [PATCH 13/21] README.md "related projects" --- README.md | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index ef5ffb6..acabe2d 100644 --- a/README.md +++ b/README.md @@ -77,8 +77,15 @@ Defect reports, feature requests, and pull requests are welcome on [the **WriteD Other (similar) projects include: -* [**ReadDebugString**](https://github.com/sistools/ReadDebugString) -* [**realpath**](https://github.com/sistools/realpath) +* [**chomp**](https://github.com/sistools/chomp); +* [**errni**](https://github.com/sistools/errni) (errno on all platforms, and also GetLastError codes on Windows); +* [**lnunique**](https://github.com/sistools/lnunique); +* [**lslocales**](https://github.com/sistools/lslocales); +* [**lstrip**](https://github.com/sistools/lstrip); +* [**mksock**](https://github.com/sistools/mksock) (Unix-only); +* [**ReadDebugString**](https://github.com/sistools/ReadDebugString) (Windows-only); +* [**realpath**](https://github.com/sistools/realpath) (Windows-only); +* [**rstrip**](https://github.com/sistools/rstrip); ### License From 0f7c1890872733b4c076c4907b5e6f9a2a7cf97d Mon Sep 17 00:00:00 2001 From: Matt Wilson Date: Mon, 17 Aug 2026 16:08:16 +1000 Subject: [PATCH 14/21] README.md operating-system badge --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index acabe2d..5f90958 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,7 @@ Windows CLI that writes messages to the debugger via **OutputDebugString** ![C](https://img.shields.io/badge/C-00599C?style=flat&logo=c&logoColor=white) +![Windows](https://img.shields.io/badge/OS-Windows-0078D6?style=flat&logo=windows&logoColor=white) [![License](https://img.shields.io/badge/License-BSD_3--Clause-blue.svg)](https://opensource.org/licenses/BSD-3-Clause) [![GitHub release](https://img.shields.io/github/v/release/sistools/WriteDebugString.svg)](https://github.com/sistools/WriteDebugString/releases/latest) [![Last Commit](https://img.shields.io/github/last-commit/sistools/WriteDebugString)](https://github.com/sistools/WriteDebugString/commits/master) From e70a0c904a6eefd4bf06f747cefaf72849fb1a87 Mon Sep 17 00:00:00 2001 From: Matt Wilson Date: Mon, 17 Aug 2026 16:16:40 +1000 Subject: [PATCH 15/21] README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 5f90958..99aace2 100644 --- a/README.md +++ b/README.md @@ -76,7 +76,7 @@ Defect reports, feature requests, and pull requests are welcome on [the **WriteD ### Related projects -Other (similar) projects include: +Other **sistools** projects include: * [**chomp**](https://github.com/sistools/chomp); * [**errni**](https://github.com/sistools/errni) (errno on all platforms, and also GetLastError codes on Windows); From cdd7c0781894166c2af3cef3584825edd0d24518 Mon Sep 17 00:00:00 2001 From: Matt Wilson Date: Mon, 17 Aug 2026 16:29:25 +1000 Subject: [PATCH 16/21] chore: harmonize CMake standards and install targets --- CMakeLists.txt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index f05142a..7163d53 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -181,11 +181,11 @@ include(GNUInstallDirs) # ########################################################## # tool -add_executable(${PROJECT_NAME} +add_executable(${PROJECT_NAME_LOWER} main.c ) -target_compile_options(${PROJECT_NAME} +target_compile_options(${PROJECT_NAME_LOWER} PRIVATE $<$,$,$>: -Werror -Wall -Wextra -pedantic @@ -199,11 +199,11 @@ target_compile_options(${PROJECT_NAME} > ) -target_link_libraries(${PROJECT_NAME} +target_link_libraries(${PROJECT_NAME_LOWER} $<$:STLSoft::STLSoft> ) -install(TARGETS ${PROJECT_NAME} +install(TARGETS ${PROJECT_NAME_LOWER} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} ) From 84b5ca35231490f3e82c195fce4a7e882328b11d Mon Sep 17 00:00:00 2001 From: Matt Wilson Date: Mon, 17 Aug 2026 16:39:33 +1000 Subject: [PATCH 17/21] chore: standardise helper project identity handling --- build_cmake.sh | 2 ++ clean_cmake.sh | 2 ++ prepare_cmake.sh | 4 +++- remove_cmake_artefacts.sh | 2 ++ 4 files changed, 9 insertions(+), 1 deletion(-) diff --git a/build_cmake.sh b/build_cmake.sh index cca1448..65bee2b 100755 --- a/build_cmake.sh +++ b/build_cmake.sh @@ -4,6 +4,8 @@ ScriptPath=$0 Dir=$(cd $(dirname "$ScriptPath"); pwd) Basename=$(basename "$ScriptPath") CMakeDir=${SIS_CMAKE_BUILD_DIR:-$Dir/_build} +ProjectNameFile="$Dir/.sis/project_name.txt" +ProjectName=$(tr -d '[:space:]' < "$ProjectNameFile") if [[ -n "$MSYSTEM" ]]; then DefaultMakeCmd=mingw32-make.exe diff --git a/clean_cmake.sh b/clean_cmake.sh index 886a201..cef4212 100755 --- a/clean_cmake.sh +++ b/clean_cmake.sh @@ -4,6 +4,8 @@ ScriptPath=$0 Dir=$(cd $(dirname "$ScriptPath"); pwd) Basename=$(basename "$ScriptPath") CMakeDir=${SIS_CMAKE_BUILD_DIR:-$Dir/_build} +ProjectNameFile="$Dir/.sis/project_name.txt" +ProjectName=$(tr -d '[:space:]' < "$ProjectNameFile") if [[ -n "$MSYSTEM" ]]; then DefaultMakeCmd=mingw32-make.exe diff --git a/prepare_cmake.sh b/prepare_cmake.sh index d837045..6adeb66 100755 --- a/prepare_cmake.sh +++ b/prepare_cmake.sh @@ -4,6 +4,8 @@ ScriptPath=$0 Dir=$(cd $(dirname "$ScriptPath"); pwd) Basename=$(basename "$ScriptPath") CMakeDir=${SIS_CMAKE_BUILD_DIR:-$Dir/_build} +ProjectNameFile="$Dir/.sis/project_name.txt" +ProjectName=$(tr -d '[:space:]' < "$ProjectNameFile") if [[ -n "$MSYSTEM" ]]; then DefaultMakeCmd=mingw32-make.exe @@ -131,7 +133,7 @@ mkdir -p $CMakeDir || exit 1 cd $CMakeDir -echo "Executing CMake (in ${CMakeDir})" +echo "Executing CMake for ${ProjectName} (in ${CMakeDir})" if [ $MSVC_MT -eq 0 ]; then CMakeMsvcMtFlag="OFF" ; else CMakeMsvcMtFlag="ON" ; fi if [ -z $STLSoftDirGiven ]; then CMakeSTLSoftVariable="" ; else CMakeSTLSoftVariable="-DSTLSOFT=$STLSoftDirGiven/" ; fi diff --git a/remove_cmake_artefacts.sh b/remove_cmake_artefacts.sh index 7416db9..0e5a7b3 100755 --- a/remove_cmake_artefacts.sh +++ b/remove_cmake_artefacts.sh @@ -4,6 +4,8 @@ ScriptPath=$0 Dir=$(cd $(dirname "$ScriptPath"); pwd) Basename=$(basename "$ScriptPath") CMakeDir=${SIS_CMAKE_BUILD_DIR:-$Dir/_build} +ProjectNameFile="$Dir/.sis/project_name.txt" +ProjectName=$(tr -d '[:space:]' < "$ProjectNameFile") Directories=( CMakeFiles From f4919a5d3561a1e1320a47bd3b95b17f4f6767d7 Mon Sep 17 00:00:00 2001 From: Matt Wilson Date: Mon, 17 Aug 2026 16:46:24 +1000 Subject: [PATCH 18/21] chore: standardize shell-script color output --- build_cmake.sh | 28 +++++++++++++++++++++++----- clean_cmake.sh | 24 +++++++++++++++++++++--- prepare_cmake.sh | 24 +++++++++++++++++++++--- remove_cmake_artefacts.sh | 22 ++++++++++++++++++++-- 4 files changed, 85 insertions(+), 13 deletions(-) diff --git a/build_cmake.sh b/build_cmake.sh index 65bee2b..3f455e2 100755 --- a/build_cmake.sh +++ b/build_cmake.sh @@ -6,6 +6,24 @@ Basename=$(basename "$ScriptPath") CMakeDir=${SIS_CMAKE_BUILD_DIR:-$Dir/_build} ProjectNameFile="$Dir/.sis/project_name.txt" ProjectName=$(tr -d '[:space:]' < "$ProjectNameFile") + +# ########################################################## +# colours + +if command -v tput > /dev/null; then + + SisClr_Blue=${FG_BLUE:-$(tput setaf 4)} + SisClr_Red=${FG_RED:-$(tput setaf 1)} + SisClr_Bold=${FD_BOLD:-$(tput bold)} + SisClr_None=${FD_NONE:-$(tput sgr0)} +else + + SisClr_Blue= + SisClr_Red= + SisClr_Bold= + SisClr_None= +fi + if [[ -n "$MSYSTEM" ]]; then DefaultMakeCmd=mingw32-make.exe @@ -79,7 +97,7 @@ EOF ;; *) - >&2 echo "$ScriptPath: unrecognised argument '$1'; use --help for usage" + >&2 echo "$ScriptPath: ${SisClr_Red}${SisClr_Bold}unrecognised argument '$1'${SisClr_None}; use --help for usage" exit 1 ;; @@ -94,7 +112,7 @@ done if [ ! -d "$CMakeDir" ]; 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 "$ScriptPath: CMake build directory '$CMakeDir' ${SisClr_Red}${SisClr_Bold}not found${SisClr_None} so nothing to do; use script 'prepare_cmake.sh' if you wish to prepare CMake artefacts" exit 1 else @@ -103,7 +121,7 @@ else 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'" + >&2 echo "$ScriptPath: ${SisClr_Red}${SisClr_Bold}CMake build directory '$CMakeDir' does not contain${SisClr_None} 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 @@ -112,10 +130,10 @@ else if [ -z "$Targets" ]; then - echo "Executing build (via command \`$MakeCmd\`)" + echo "Executing build (via command \`${SisClr_Blue}${SisClr_Bold}$MakeCmd${SisClr_None}\`)" else - echo "Executing build (via command \`$MakeCmd\`) with specific target(s) $(join_by , "${Targets[@]}")" + echo "Executing build (via command \`${SisClr_Blue}${SisClr_Bold}$MakeCmd${SisClr_None}\`) with specific target(s) $(join_by , "${Targets[@]}")" fi $MakeCmd ${Targets[*]} diff --git a/clean_cmake.sh b/clean_cmake.sh index cef4212..3bcdb95 100755 --- a/clean_cmake.sh +++ b/clean_cmake.sh @@ -6,6 +6,24 @@ Basename=$(basename "$ScriptPath") CMakeDir=${SIS_CMAKE_BUILD_DIR:-$Dir/_build} ProjectNameFile="$Dir/.sis/project_name.txt" ProjectName=$(tr -d '[:space:]' < "$ProjectNameFile") + +# ########################################################## +# colours + +if command -v tput > /dev/null; then + + SisClr_Blue=${FG_BLUE:-$(tput setaf 4)} + SisClr_Red=${FG_RED:-$(tput setaf 1)} + SisClr_Bold=${FD_BOLD:-$(tput bold)} + SisClr_None=${FD_NONE:-$(tput sgr0)} +else + + SisClr_Blue= + SisClr_Red= + SisClr_Bold= + SisClr_None= +fi + if [[ -n "$MSYSTEM" ]]; then DefaultMakeCmd=mingw32-make.exe @@ -47,7 +65,7 @@ EOF ;; *) - >&2 echo "$ScriptPath: unrecognised argument '$1'; use --help for usage" + >&2 echo "$ScriptPath: ${SisClr_Red}${SisClr_Bold}unrecognised argument '$1'${SisClr_None}; use --help for usage" exit 1 ;; @@ -62,7 +80,7 @@ done if [ ! -d "$CMakeDir" ]; 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 "$ScriptPath: CMake build directory '$CMakeDir' ${SisClr_Red}${SisClr_Bold}not found${SisClr_None} so nothing to do; use script 'prepare_cmake.sh' if you wish to prepare CMake artefacts" exit 1 else @@ -71,7 +89,7 @@ else 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'" + >&2 echo "$ScriptPath: ${SisClr_Red}${SisClr_Bold}CMake build directory '$CMakeDir' does not contain${SisClr_None} 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 diff --git a/prepare_cmake.sh b/prepare_cmake.sh index 6adeb66..5c1bdae 100755 --- a/prepare_cmake.sh +++ b/prepare_cmake.sh @@ -6,6 +6,24 @@ Basename=$(basename "$ScriptPath") CMakeDir=${SIS_CMAKE_BUILD_DIR:-$Dir/_build} ProjectNameFile="$Dir/.sis/project_name.txt" ProjectName=$(tr -d '[:space:]' < "$ProjectNameFile") + +# ########################################################## +# colours + +if command -v tput > /dev/null; then + + SisClr_Blue=${FG_BLUE:-$(tput setaf 4)} + SisClr_Red=${FG_RED:-$(tput setaf 1)} + SisClr_Bold=${FD_BOLD:-$(tput bold)} + SisClr_None=${FD_NONE:-$(tput sgr0)} +else + + SisClr_Blue= + SisClr_Red= + SisClr_Bold= + SisClr_None= +fi + if [[ -n "$MSYSTEM" ]]; then DefaultMakeCmd=mingw32-make.exe @@ -116,7 +134,7 @@ EOF ;; *) - >&2 echo "$ScriptPath: unrecognised argument '$1'; use --help for usage" + >&2 echo "$ScriptPath: ${SisClr_Red}${SisClr_Bold}unrecognised argument '$1'${SisClr_None}; use --help for usage" exit 1 ;; @@ -133,7 +151,7 @@ mkdir -p $CMakeDir || exit 1 cd $CMakeDir -echo "Executing CMake for ${ProjectName} (in ${CMakeDir})" +echo "Executing CMake for ${SisClr_Blue}${SisClr_Bold}${ProjectName}${SisClr_None} (in ${SisClr_Blue}${SisClr_Bold}${CMakeDir}${SisClr_None})" if [ $MSVC_MT -eq 0 ]; then CMakeMsvcMtFlag="OFF" ; else CMakeMsvcMtFlag="ON" ; fi if [ -z $STLSoftDirGiven ]; then CMakeSTLSoftVariable="" ; else CMakeSTLSoftVariable="-DSTLSOFT=$STLSoftDirGiven/" ; fi @@ -167,7 +185,7 @@ status=0 if [ $RunMake -ne 0 ]; then - echo "Executing build (via command \`$MakeCmd\`)" + echo "Executing build (via command \`${SisClr_Blue}${SisClr_Bold}$MakeCmd${SisClr_None}\`)" $MakeCmd status=$? diff --git a/remove_cmake_artefacts.sh b/remove_cmake_artefacts.sh index 0e5a7b3..aa41a0a 100755 --- a/remove_cmake_artefacts.sh +++ b/remove_cmake_artefacts.sh @@ -7,6 +7,24 @@ CMakeDir=${SIS_CMAKE_BUILD_DIR:-$Dir/_build} ProjectNameFile="$Dir/.sis/project_name.txt" ProjectName=$(tr -d '[:space:]' < "$ProjectNameFile") +# ########################################################## +# colours + +if command -v tput > /dev/null; then + + SisClr_Blue=${FG_BLUE:-$(tput setaf 4)} + SisClr_Red=${FG_RED:-$(tput setaf 1)} + SisClr_Bold=${FD_BOLD:-$(tput bold)} + SisClr_None=${FD_NONE:-$(tput sgr0)} +else + + SisClr_Blue= + SisClr_Red= + SisClr_Bold= + SisClr_None= +fi + + Directories=( CMakeFiles Testing @@ -80,7 +98,7 @@ EOF ;; *) - >&2 echo "$ScriptPath: unrecognised argument '$1'; use --help for usage" + >&2 echo "$ScriptPath: ${SisClr_Red}${SisClr_Bold}unrecognised argument '$1'${SisClr_None}; use --help for usage" exit 1 ;; @@ -95,7 +113,7 @@ 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 "$ScriptPath: CMake build directory '$CMakeDir' ${SisClr_Red}${SisClr_Bold}not found${SisClr_None} so nothing to do; use script 'prepare_cmake.sh' if you wish to prepare CMake artefacts" exit 0 else From 56fb0cb114629bae280ccf5a84f2801f323b15af Mon Sep 17 00:00:00 2001 From: Matt Wilson Date: Mon, 17 Aug 2026 20:51:39 +1000 Subject: [PATCH 19/21] chore: canonicalised helper scripts --- build_cmake.sh | 38 ++++++++--------- clean_cmake.sh | 30 +++++++------- prepare_cmake.sh | 64 +++++++++++++++++++---------- remove_cmake_artefacts.sh | 42 +++++++++---------- run_all_unit_tests.cmd | 86 +++++++++++++++++++-------------------- 5 files changed, 141 insertions(+), 119 deletions(-) diff --git a/build_cmake.sh b/build_cmake.sh index 3f455e2..3f261e7 100755 --- a/build_cmake.sh +++ b/build_cmake.sh @@ -1,12 +1,26 @@ #! /bin/bash ScriptPath=$0 -Dir=$(cd $(dirname "$ScriptPath"); pwd) +Dir=$(cd "$(dirname "$ScriptPath")" && pwd) Basename=$(basename "$ScriptPath") + CMakeDir=${SIS_CMAKE_BUILD_DIR:-$Dir/_build} +if [[ -n "$MSYSTEM" ]]; then + + DefaultMakeCmd=mingw32-make.exe + MinGW=1 +else + + DefaultMakeCmd=make +fi +MakeCmd=${SIS_CMAKE_MAKE_COMMAND:-${SIS_CMAKE_COMMAND:-$DefaultMakeCmd}} ProjectNameFile="$Dir/.sis/project_name.txt" ProjectName=$(tr -d '[:space:]' < "$ProjectNameFile") +IgnoreRemainingFlagsAndOptions=0 +Targets=() + + # ########################################################## # colours @@ -24,19 +38,6 @@ else SisClr_None= fi -if [[ -n "$MSYSTEM" ]]; then - - DefaultMakeCmd=mingw32-make.exe - MinGW=1 -else - - DefaultMakeCmd=make -fi -MakeCmd=${SIS_CMAKE_MAKE_COMMAND:-${SIS_CMAKE_COMMAND:-$DefaultMakeCmd}} - -IgnoreRemainingFlagsAndOptions=0 -Targets=() - # ########################################################## # functions @@ -112,7 +113,7 @@ done if [ ! -d "$CMakeDir" ]; then - >&2 echo "$ScriptPath: CMake build directory '$CMakeDir' ${SisClr_Red}${SisClr_Bold}not found${SisClr_None} so nothing to do; use script 'prepare_cmake.sh' if you wish to prepare CMake artefacts" + >&2 echo "$ScriptPath: ${SisClr_Red}${SisClr_Bold}CMake build directory '$CMakeDir' not found${SisClr_None} so nothing to do; use script 'prepare_cmake.sh' if you wish to prepare CMake artefacts" exit 1 else @@ -121,7 +122,7 @@ else if [ ! -f "$CMakeDir/Makefile" ]; then - >&2 echo "$ScriptPath: ${SisClr_Red}${SisClr_Bold}CMake build directory '$CMakeDir' does not contain${SisClr_None} 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'" + >&2 echo "$ScriptPath: ${SisClr_Red}${SisClr_Bold}CMake build directory '$CMakeDir' does not contain expected file 'Makefile'${SisClr_None}, 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 @@ -130,10 +131,10 @@ else if [ -z "$Targets" ]; then - echo "Executing build (via command \`${SisClr_Blue}${SisClr_Bold}$MakeCmd${SisClr_None}\`)" + echo "Executing build of ${SisClr_Blue}${SisClr_Bold}${ProjectName}${SisClr_None} (via command \`${SisClr_Blue}${SisClr_Bold}$MakeCmd${SisClr_None}\`)" else - echo "Executing build (via command \`${SisClr_Blue}${SisClr_Bold}$MakeCmd${SisClr_None}\`) with specific target(s) $(join_by , "${Targets[@]}")" + echo "Executing build of ${SisClr_Blue}${SisClr_Bold}${ProjectName}${SisClr_None} (via command \`${SisClr_Blue}${SisClr_Bold}$MakeCmd${SisClr_None}\`) with specific target(s) $(join_by , "${Targets[@]}")" fi $MakeCmd ${Targets[*]} @@ -147,4 +148,3 @@ fi # ############################## end of file ############################# # - diff --git a/clean_cmake.sh b/clean_cmake.sh index 3bcdb95..96b6c07 100755 --- a/clean_cmake.sh +++ b/clean_cmake.sh @@ -1,12 +1,23 @@ #! /bin/bash ScriptPath=$0 -Dir=$(cd $(dirname "$ScriptPath"); pwd) +Dir=$(cd "$(dirname "$ScriptPath")" && pwd) Basename=$(basename "$ScriptPath") + CMakeDir=${SIS_CMAKE_BUILD_DIR:-$Dir/_build} +if [[ -n "$MSYSTEM" ]]; then + + DefaultMakeCmd=mingw32-make.exe + MinGW=1 +else + + DefaultMakeCmd=make +fi +MakeCmd=${SIS_CMAKE_MAKE_COMMAND:-${SIS_CMAKE_COMMAND:-$DefaultMakeCmd}} ProjectNameFile="$Dir/.sis/project_name.txt" ProjectName=$(tr -d '[:space:]' < "$ProjectNameFile") + # ########################################################## # colours @@ -24,16 +35,6 @@ else SisClr_None= fi -if [[ -n "$MSYSTEM" ]]; then - - DefaultMakeCmd=mingw32-make.exe - MinGW=1 -else - - DefaultMakeCmd=make -fi -MakeCmd=${SIS_CMAKE_MAKE_COMMAND:-${SIS_CMAKE_COMMAND:-$DefaultMakeCmd}} - # ########################################################## # command-line handling @@ -80,7 +81,7 @@ done if [ ! -d "$CMakeDir" ]; then - >&2 echo "$ScriptPath: CMake build directory '$CMakeDir' ${SisClr_Red}${SisClr_Bold}not found${SisClr_None} so nothing to do; use script 'prepare_cmake.sh' if you wish to prepare CMake artefacts" + >&2 echo "$ScriptPath: ${SisClr_Red}${SisClr_Bold}CMake build directory '$CMakeDir' not found${SisClr_None} so nothing to do; use script 'prepare_cmake.sh' if you wish to prepare CMake artefacts" exit 1 else @@ -89,14 +90,14 @@ else if [ ! -f "$CMakeDir/Makefile" ]; then - >&2 echo "$ScriptPath: ${SisClr_Red}${SisClr_Bold}CMake build directory '$CMakeDir' does not contain${SisClr_None} 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'" + >&2 echo "$ScriptPath: ${SisClr_Red}${SisClr_Bold}CMake build directory '$CMakeDir' does not contain expected file 'Makefile'${SisClr_None}, 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\`)" + echo "Cleaning ${SisClr_Blue}${SisClr_Bold}${ProjectName}${SisClr_None} (via command \`${SisClr_Blue}${SisClr_Bold}$MakeCmd clean${SisClr_None}\`)" $MakeCmd clean status=$? @@ -109,4 +110,3 @@ fi # ############################## end of file ############################# # - diff --git a/prepare_cmake.sh b/prepare_cmake.sh index 5c1bdae..417cb1b 100755 --- a/prepare_cmake.sh +++ b/prepare_cmake.sh @@ -1,12 +1,32 @@ #! /bin/bash ScriptPath=$0 -Dir=$(cd $(dirname "$ScriptPath"); pwd) +Dir=$(cd "$(dirname "$ScriptPath")" && pwd) Basename=$(basename "$ScriptPath") + CMakeDir=${SIS_CMAKE_BUILD_DIR:-$Dir/_build} +if [[ -n "$MSYSTEM" ]]; then + + DefaultMakeCmd=mingw32-make.exe + MinGW=1 +else + + DefaultMakeCmd=make +fi +MakeCmd=${SIS_CMAKE_MAKE_COMMAND:-${SIS_CMAKE_COMMAND:-$DefaultMakeCmd}} ProjectNameFile="$Dir/.sis/project_name.txt" ProjectName=$(tr -d '[:space:]' < "$ProjectNameFile") +Configuration=Release +CStandard= +MSVC_MT=0 +MinGW="${MinGW:=0}" +RunMake=0 +STLSoftDirGiven= +TestingDisabled=0 +VerboseMakefile=0 + + # ########################################################## # colours @@ -24,24 +44,6 @@ else SisClr_None= fi -if [[ -n "$MSYSTEM" ]]; then - - DefaultMakeCmd=mingw32-make.exe - MinGW=1 -else - - DefaultMakeCmd=make -fi -MakeCmd=${SIS_CMAKE_MAKE_COMMAND:-${SIS_CMAKE_COMMAND:-$DefaultMakeCmd}} - -Configuration=Release -MSVC_MT=0 -MinGW="${MinGW:=0}" -RunMake=0 -STLSoftDirGiven= -TestingDisabled=0 -VerboseMakefile=0 - # ########################################################## # command-line handling @@ -49,6 +51,21 @@ VerboseMakefile=0 while [[ $# -gt 0 ]]; do case $1 in + --c-standard) + + shift + CStandard=$1 + case $CStandard in + 99|11|17|23) + ;; + *) + + >&2 echo "$ScriptPath: ${SisClr_Red}${SisClr_Bold}invalid C standard '$CStandard'${SisClr_None}; expected 99, 11, 17, or 23" + + exit 1 + ;; + esac + ;; --cmake-verbose-makefile|-v) VerboseMakefile=1 @@ -90,6 +107,9 @@ Flags/options: behaviour: + --c-standard {99|11|17|23} + sets CMAKE_C_STANDARD (default is 11) + -v --cmake-verbose-makefile configures CMake to run verbosely (by setting CMAKE_VERBOSE_MAKEFILE @@ -153,14 +173,16 @@ cd $CMakeDir echo "Executing CMake for ${SisClr_Blue}${SisClr_Bold}${ProjectName}${SisClr_None} (in ${SisClr_Blue}${SisClr_Bold}${CMakeDir}${SisClr_None})" +if [ -z "$CStandard" ]; then CMakeCStandardVariable="" ; else CMakeCStandardVariable="-DCMAKE_C_STANDARD=$CStandard" ; 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 if [ $MinGW -ne 0 ]; then cmake \ + $CMakeCStandardVariable \ $CMakeSTLSoftVariable \ -DBUILD_TESTING:BOOL=$CMakeBuildTestingFlag \ -DCMAKE_BUILD_TYPE=$Configuration \ @@ -171,6 +193,7 @@ if [ $MinGW -ne 0 ]; then else cmake \ + $CMakeCStandardVariable \ $CMakeSTLSoftVariable \ -DBUILD_TESTING:BOOL=$CMakeBuildTestingFlag \ -DCMAKE_BUILD_TYPE=$Configuration \ @@ -203,4 +226,3 @@ exit $status # ############################## end of file ############################# # - diff --git a/remove_cmake_artefacts.sh b/remove_cmake_artefacts.sh index aa41a0a..992153f 100755 --- a/remove_cmake_artefacts.sh +++ b/remove_cmake_artefacts.sh @@ -1,30 +1,13 @@ #! /bin/bash ScriptPath=$0 -Dir=$(cd $(dirname "$ScriptPath"); pwd) +Dir=$(cd "$(dirname "$ScriptPath")" && pwd) Basename=$(basename "$ScriptPath") + CMakeDir=${SIS_CMAKE_BUILD_DIR:-$Dir/_build} ProjectNameFile="$Dir/.sis/project_name.txt" ProjectName=$(tr -d '[:space:]' < "$ProjectNameFile") -# ########################################################## -# colours - -if command -v tput > /dev/null; then - - SisClr_Blue=${FG_BLUE:-$(tput setaf 4)} - SisClr_Red=${FG_RED:-$(tput setaf 1)} - SisClr_Bold=${FD_BOLD:-$(tput bold)} - SisClr_None=${FD_NONE:-$(tput sgr0)} -else - - SisClr_Blue= - SisClr_Red= - SisClr_Bold= - SisClr_None= -fi - - Directories=( CMakeFiles Testing @@ -44,6 +27,24 @@ Files=( ) +# ########################################################## +# colours + +if command -v tput > /dev/null; then + + SisClr_Blue=${FG_BLUE:-$(tput setaf 4)} + SisClr_Red=${FG_RED:-$(tput setaf 1)} + SisClr_Bold=${FD_BOLD:-$(tput bold)} + SisClr_None=${FD_NONE:-$(tput sgr0)} +else + + SisClr_Blue= + SisClr_Red= + SisClr_Bold= + SisClr_None= +fi + + # ########################################################## # operating environment detection @@ -118,7 +119,7 @@ if [ ! -d "$CMakeDir" ]; then exit 0 else - echo "Removing all cmake artefacts in '$CMakeDir'" + echo "Removing all ${SisClr_Blue}${SisClr_Bold}${ProjectName}${SisClr_None} cmake artefacts in '${SisClr_Blue}${SisClr_Bold}$CMakeDir${SisClr_None}'" num_dirs_removed=0 num_files_removed=0 @@ -168,4 +169,3 @@ fi # ############################## end of file ############################# # - diff --git a/run_all_unit_tests.cmd b/run_all_unit_tests.cmd index 8c88eae..8c11cf4 100644 --- a/run_all_unit_tests.cmd +++ b/run_all_unit_tests.cmd @@ -6,10 +6,10 @@ 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 @@ -17,12 +17,12 @@ SET Verbose=0 SET status=0 FOR %%a IN (%*) DO ( - IF /I {--help}=={%%a} ( - IF EXIST "%SCRIPT_DIRECTORY%.sis\script_info_lines.txt" ( + IF /I {--help}=={%%a} ( + IF EXIST "%SCRIPT_DIRECTORY%.sis\script_info_lines.txt" ( - type "%SCRIPT_DIRECTORY%.sis\script_info_lines.txt" - ) - ECHO ^ + type "%SCRIPT_DIRECTORY%.sis\script_info_lines.txt" + ) + ECHO ^ Runs all ^(matching^) component and unit test programs ^ @@ -71,31 +71,31 @@ Flags/options: ^ displays this help and terminates ^ - 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 {-v}=={%%a} ( - SET Verbose=1 - ) ELSE IF /I {--verbose}=={%%a} ( - SET Verbose=1 - ) ELSE ( - ECHO %SCRIPT_PATH_DOC%: unrecognised argument '%%a'; use --help for usage 1>&2 - - EXIT /B 1 - ) + 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 {-v}=={%%a} ( + SET Verbose=1 + ) ELSE IF /I {--verbose}=={%%a} ( + SET Verbose=1 + ) ELSE ( + ECHO %SCRIPT_PATH_DOC%: unrecognised argument '%%a'; use --help for usage 1>&2 + + EXIT /B 1 + ) ) IF NOT EXIST "%CMAKE_DIR%" ( - ECHO %SCRIPT_PATH_DOC%: CMake build directory '%CMAKE_DIR%' does not exist 1>&2 + ECHO %SCRIPT_PATH_DOC%: CMake build directory '%CMAKE_DIR%' does not exist 1>&2 - EXIT /B 1 + EXIT /B 1 ) SET "ProjectName=" @@ -103,38 +103,38 @@ 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 + ECHO %SCRIPT_PATH_DOC%: could not read project name from .sis\project_name.txt 1>&2 - EXIT /B 1 + EXIT /B 1 ) IF !ListOnly! EQU 1 ( - ECHO Listing all component and unit test programs + ECHO Listing all component and unit test programs ) ELSE ( - ECHO Running all component and unit test programs + ECHO Running all component and unit test programs ) FOR /F "usebackq delims=" %%f IN (`DIR /A:-D /B /S "%CMAKE_DIR%\*.exe" 2^>NUL ^| FINDSTR /I /R "!ProjectName!.*test.*\.exe$"`) DO ( - IF !ListOnly! EQU 1 ( + IF !ListOnly! EQU 1 ( - ECHO would execute %%f: - ) ELSE ( + ECHO would execute %%f: + ) ELSE ( - IF !Verbose! EQU 1 ( + IF !Verbose! EQU 1 ( - ECHO executing %%f: - ) + ECHO executing %%f: + ) - "%%f" - IF ERRORLEVEL 1 ( + "%%f" + IF ERRORLEVEL 1 ( - SET status=1 + SET status=1 - GOTO :done - ) - ) + GOTO :done + ) + ) ) :done From 1c5351ff957c7160e1bdf932fa369b4b4ec0b8fd Mon Sep 17 00:00:00 2001 From: Matt Wilson Date: Mon, 17 Aug 2026 21:05:40 +1000 Subject: [PATCH 20/21] CMake --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7163d53..90a6861 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -227,7 +227,7 @@ endif(BUILD_TESTING) # ########################################################## # completion -message(NOTICE "Generating CMake build scripts for ${PROJECT_NAME} ${PROJECT_VERSION}, for C${CMAKE_C_STANDARD} C++${CMAKE_CXX_STANDARD}") +message(NOTICE "Generating CMake build scripts for ${PROJECT_NAME} ${PROJECT_VERSION}, for C${CMAKE_C_STANDARD} C++${CMAKE_CXX_STANDARD}, with build type ${CMAKE_BUILD_TYPE}") # ############################## end of file ############################# # From ec9f0a374ed1b32d4679700fa41f7277ef9b7e30 Mon Sep 17 00:00:00 2001 From: Matt Wilson Date: Mon, 17 Aug 2026 21:13:57 +1000 Subject: [PATCH 21/21] CMake --- CMakeLists.txt | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 90a6861..5aa9d14 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -56,10 +56,16 @@ set(PROJECT_VERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT # adhere strictly to C and C++ standards plus extensions. These are actually # useless since we do not compile anything; they merely state our intention. -set(CMAKE_C_STANDARD 17) +if(NOT CMAKE_C_STANDARD) + + set(CMAKE_C_STANDARD 17) +endif() set(CMAKE_C_STANDARD_REQUIRED ON) set(CMAKE_C_EXTENSIONS ON) # GNU extensions and POSIX standard -set(CMAKE_CXX_STANDARD 17) +if(NOT CMAKE_CXX_STANDARD) + + set(CMAKE_CXX_STANDARD 17) +endif() set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_EXTENSIONS ON)