Summary
Running ctest in a pFUnit build directory on Windows fails immediately with a CMake parse error, before any tests run, because the generated CTestCustom.cmake embeds a native Windows path (with backslashes) inside a double-quoted CMake string without escaping the backslashes themselves.
Reproduction
- Windows 11, gfortran (conda-forge), CMake 4.4.2, Ninja
- Standard standalone build:
cmake -S . -B build -G Ninja
cmake --build build
cd build
ctest
Fails with:
CMake Error at C:/.../pFUnit/build/CTestCustom.cmake:1 (set):
Syntax error in cmake code at
C:/.../pFUnit/build/CTestCustom.cmake:1
when parsing string
C:\Users\<user>\...\cmake.exe --build . --config \"Release\" --target \"build-tests\"
Invalid character escape '\U'.
Problem reading custom configuration: C:/.../pFUnit/build/CTestCustom.cmake
Root cause
Top-level CMakeLists.txt (around line 172-177) generates CTestCustom.cmake like this:
build_command(CTEST_CUSTOM_PRE_TEST TARGET build-tests)
string(CONFIGURE \"@CTEST_CUSTOM_PRE_TEST@\" CTEST_CUSTOM_PRE_TEST_QUOTED ESCAPE_QUOTES)
file(WRITE "${CMAKE_BINARY_DIR}/CTestCustom.cmake" "set(CTEST_CUSTOM_PRE_TEST ${CTEST_CUSTOM_PRE_TEST_QUOTED})" "\n")
build_command() returns the path to the CMake executable using native (backslash) path separators on Windows. string(CONFIGURE ... ESCAPE_QUOTES) only escapes embedded double quotes (" -> \"); it does not escape the backslashes in the path itself. The resulting CTestCustom.cmake therefore contains a raw Windows path with literal backslashes inside a double-quoted string.
When CTest later parses that file as CMake script, backslashes inside a quoted string are interpreted as escape sequences per CMake's own string-escaping rules. \U (from ...\Users\...) is treated as the start of a Unicode escape, which is invalid without following hex digits, so parsing fails and ctest aborts before running any tests - a full functional regression on Windows, not just a cosmetic warning.
Suggested fix
Escape backslashes (in addition to quotes) when embedding the native CTEST_CUSTOM_PRE_TEST command path into the generated CMake string, e.g. by replacing \ with \ before/via string(CONFIGURE ...), or by writing the path with forward slashes instead of relying on build_command()'s native-separator output.
Workaround
Skip CTestCustom.cmake and run the built test executables directly instead of via ctest, e.g. tests/funit-core/funit_tests.x.exe, new_tests.x.exe, filter_cmdline_tests.x.exe, and tests/fhamcrest/fhamcrest_tests.x.exe. All pass cleanly once the build itself succeeds.
Related
Found while verifying the fix in #566 / the accompanying PR.
Drafted with Claude's assistance.
- Root cause traced by reading the generated
build/CTestCustom.cmake output and the file(WRITE ...) call in the top-level CMakeLists.txt that produces it.
- Reproduced consistently on a clean build directory; confirmed the workaround (running the test executables directly) succeeds with all tests passing.
🤖 Generated with Claude Code
Summary
Running
ctestin a pFUnit build directory on Windows fails immediately with a CMake parse error, before any tests run, because the generatedCTestCustom.cmakeembeds a native Windows path (with backslashes) inside a double-quoted CMake string without escaping the backslashes themselves.Reproduction
Fails with:
Root cause
Top-level
CMakeLists.txt(around line 172-177) generatesCTestCustom.cmakelike this:build_command()returns the path to the CMake executable using native (backslash) path separators on Windows.string(CONFIGURE ... ESCAPE_QUOTES)only escapes embedded double quotes ("->\"); it does not escape the backslashes in the path itself. The resultingCTestCustom.cmaketherefore contains a raw Windows path with literal backslashes inside a double-quoted string.When CTest later parses that file as CMake script, backslashes inside a quoted string are interpreted as escape sequences per CMake's own string-escaping rules.
\U(from...\Users\...) is treated as the start of a Unicode escape, which is invalid without following hex digits, so parsing fails andctestaborts before running any tests - a full functional regression on Windows, not just a cosmetic warning.Suggested fix
Escape backslashes (in addition to quotes) when embedding the native
CTEST_CUSTOM_PRE_TESTcommand path into the generated CMake string, e.g. by replacing\with\before/viastring(CONFIGURE ...), or by writing the path with forward slashes instead of relying onbuild_command()'s native-separator output.Workaround
Skip
CTestCustom.cmakeand run the built test executables directly instead of viactest, e.g.tests/funit-core/funit_tests.x.exe,new_tests.x.exe,filter_cmdline_tests.x.exe, andtests/fhamcrest/fhamcrest_tests.x.exe. All pass cleanly once the build itself succeeds.Related
Found while verifying the fix in #566 / the accompanying PR.
Drafted with Claude's assistance.
build/CTestCustom.cmakeoutput and thefile(WRITE ...)call in the top-levelCMakeLists.txtthat produces it.🤖 Generated with Claude Code