Tests: RunCMake.FindPkgConfig fails on x86_64-windows-msvc142
I'm trying to get my baseline updated before I start submitting a few other MRs, but I'm finding that RunCMake.FindPkgConfig fails on an unmodified master branch (51f285b9), in the release tags for (at least) 3.17, 3.18, 3.19, and 3.20 (I didn't have anything older handy)
bin\ctest.exe -V -R FindPkgConfig
test 486
Start 486: RunCMake.FindPkgConfig
486: Test command: C:\projects\build\cmake\bin\cmake.exe "-DCMAKE_MODULE_PATH=C:/projects/cmake/Tests/RunCMake" "-DRunCMake_GENERATOR_IS_MULTI_CONFIG=0" "-DRunCMake_GENERATOR=Ninja" "-DRunCMake_GENERATOR_INSTANCE=" "-DRunCMake_GENERATOR_PLATFORM=" "-DRunCMake_GENERATOR_TOOLSET=" "-DRunCMake_MAKE_PROGRAM=C:/PROGRA~1/bin/ninja.exe" "-DRunCMake_SOURCE_DIR=C:/projects/cmake/Tests/RunCMake/FindPkgConfig" "-DRunCMake_BINARY_DIR=C:/projects/build/cmake/Tests/RunCMake/FindPkgConfig" "-P" "C:/projects/cmake/Tests/RunCMake/FindPkgConfig/RunCMakeTest.cmake"
486: Test timeout computed to be: 1500
486: -- PkgConfigDoesNotExist - PASSED
486: CMake Error at C:/projects/cmake/Tests/RunCMake/RunCMake.cmake:197 (message):
486: FindPkgConfig_NO_PKGCONFIG_PATH - FAILED:
486:
486: Result is [1], not [0].
486:
486: stderr does not match that expected.
486:
486: Command was:
486:
486: command> "C:/Users/re41236/scratch/build/cmake/bin/cmake.exe" "C:/projects/cmake/Tests/RunCMake/FindPkgConfig" "-G" "Ninja" "-DRunCMake_TEST=FindPkgConfig_NO_PKGCONFIG_PATH" "--no-warn-unused-cli" "-DCMAKE_MAKE_PROGRAM=C:/PROGRA~1/bin/ninja.exe"
486:
486: Actual stdout:
486:
486: actual-out> Not searching for unused variables given on the command line.
486: actual-out> -- Found PkgConfig: C:/projects/cmake/Tests/RunCMake/FindPkgConfig\dummy-pkg-config.bat (found version "0.0-cmake-dummy")
486: actual-out> -- Configuring incomplete, errors occurred!
486: actual-out> See also "C:/projects/build/cmake/Tests/RunCMake/FindPkgConfig/FindPkgConfig_NO_PKGCONFIG_PATH-build/CMakeFiles/CMakeOutput.log".
486:
486: Expected stderr to match:
486:
486: expect-err> ^$
486:
486: Actual stderr:
486:
486: actual-err> CMake Error at C:/projects/cmake/Modules/FindPkgConfig.cmake:773 (_pkgconfig_parse_options):
486: actual-err> Syntax error in cmake code at
486: actual-err>
486: actual-err> C:/projects/cmake/Modules/FindPkgConfig.cmake:773
486: actual-err>
486: actual-err> when parsing string
486: actual-err>
486: actual-err> C:\baz
486: actual-err>
486: actual-err> Invalid character escape '\b'.
486: actual-err> Call Stack (most recent call first):
486: actual-err> FindPkgConfig_NO_PKGCONFIG_PATH.cmake:24 (pkg_check_modules)
486: actual-err> CMakeLists.txt:3 (include)
486:
486: Call Stack (most recent call first):
486: C:/projects/cmake/Tests/RunCMake/FindPkgConfig/RunCMakeTest.cmake:10 (run_cmake)
Looking at https://gitlab.kitware.com/cmake/cmake/-/pipelines/222366, though, it doesn't look like the kitware robot even runs this test on windows. Presumably that's because find_package(PkgConfig QUIET
) didn't find a pkg-config.exe to use - I have one from graphviz package, and one from msys, but that's probably a little unusual on windows. So it's likely been broken for quite a while. I can easily enough just ignore the failure, but there is clearly an attempt in this test to cover windows, and it does seem to be a real bug.
The problem is that a windows-style path using \
(using backslashes) got passed to pkg_check_modules, and then somehow got "un-escaped" twice. One can isolate it to just:
cmake_minimum_required(VERSION 3.19)
function(frob_f str)
message(STATUS "frob_f(\"${str}\")")
endfunction()
macro(frob_m str)
message(STATUS "frob_m(\"${str}\")")
endmacro()
frob_f("C:\\tar")
frob_m("C:\\tar")
frob_f("C:\\bar")
frob_m("C:\\bar")
$ cmake -P test.cmake
-- frob_f("C:\tar")
-- frob_m("C: ar")
-- frob_f("C:\bar")
CMake Error at test.cmake:8 (message):
Syntax error in cmake code at
C:/projects/cmake-language-test/test.cmake:8
when parsing string
frob_m(\"C:\bar\")
Invalid character escape '\b'.
Call Stack (most recent call first):
test.cmake:14 (frob_m)
which shows function(frob_f)
works, but macro(frob_m)
has a parse error. I assume this is somehow a consequence of https://cmake.org/cmake/help/latest/command/macro.html#argument-caveats, though I don't quite see how. I thought macros pretty much just token-pasted in the caller's source argument, which is a quoted-argument string and should be fine. Apparently somehow it gets parsed from quoted argument to string twice...
It would presumably be possible to rework FindPkgConfig.cmake to use function() instead of macro(), but it looks like it would involve a lot of mess to promoting variables back to the parent scope (and it's not always obvious which all variables that would be in the case of things like _pkg_find_libs that produce a varying set of outputs and would propagate back through multiple macros).
So I figure first to ask whether this misbehavior when one passes a macro a quoted string containing escaped backslashes is a bug, or just how things work...