Skip to content

ctest fails on Windows: CTestCustom.cmake has unescaped backslashes in CTEST_CUSTOM_PRE_TEST path #567

Description

@djkees

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

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions