Copy runtime DLLs on Windows working on cli but not on add_custom_comand

I have a function to copy my targets runtime DLLs.

function(copy_runtime_dlls_at_build __targetName)
    if (WIN32)
        add_custom_command(
            TARGET ${__targetName} POST_BUILD
            COMMAND ${CMAKE_COMMAND} -E copy_if_different
                $<TARGET_RUNTIME_DLLS:${__targetName}>
                $<TARGET_FILE_DIR:${__targetName}>
            COMMAND_EXPAND_LISTS
        )
    endif ()
endfunction(copy_runtime_dlls_at_build)

It used to work fine, but after adding a library installed at "C:/Program Files/Optris GmbH & Co. KG/Thermal Camera SDK/bin", it no longer works. Here’s the output:

[proc] Executing command: "C:\Program Files\CMake\bin\cmake.EXE" --build D:/dev/gaintech/build/gt_iaq_otc_sdk --config Debug --target ExemploOTCSDK --
[build] [1/1] Linking CXX executable examples\Debug\ExemploOTCSDK.exe
[build] FAILED: [code=1] examples/Debug/ExemploOTCSDK.exe 
[build] C:\WINDOWS\system32\cmd.exe /C "cd . && "C:\Program Files\CMake\bin\cmake.exe" -E vs_link_exe --msvc-ver=1943 --intdir=examples\CMakeFiles\ExemploOTCSDK.dir\Debug --rc=C:\dev\llvm\bin\llvm-rc.exe --mt=C:\dev\llvm\bin\llvm-mt.exe --manifests  -- C:\dev\llvm\bin\lld-link.exe /nologo examples\CMakeFiles\ExemploOTCSDK.dir\Debug\test.cpp.obj  /out:examples\Debug\ExemploOTCSDK.exe /implib:examples\Debug\ExemploOTCSDK.lib /pdb:examples\Debug\ExemploOTCSDK.pdb /version:0.0 /machine:x64 /debug /INCREMENTAL /subsystem:console  Debug\gt_iaq_otc_sdkd.lib  C:\dev\vcpkg\installed\x64-windows\debug\lib\opencv_world4d.lib  C:\dev\vcpkg\installed\x64-windows\debug\lib\opencv_world4d.lib  C:\dev\vcpkg\installed\x64-windows\debug\lib\opencv_world4d.lib  C:\dev\vcpkg\installed\x64-windows\debug\lib\opencv_world4d.lib  C:\dev\vcpkg\installed\x64-windows\debug\lib\opencv_world4d.lib  C:\dev\vcpkg\installed\x64-windows\debug\lib\opencv_world4d.lib  C:\dev\vcpkg\installed\x64-windows\debug\lib\opencv_world4d.lib  C:\dev\vcpkg\installed\x64-windows\debug\lib\opencv_world4d.lib  C:\dev\vcpkg\installed\x64-windows\debug\lib\opencv_world4d.lib  C:\dev\vcpkg\installed\x64-windows\debug\lib\opencv_world4d.lib  C:\dev\vcpkg\installed\x64-windows\debug\lib\opencv_world4d.lib  C:\dev\vcpkg\installed\x64-windows\debug\lib\opencv_world4d.lib  C:\dev\vcpkg\installed\x64-windows\debug\lib\opencv_world4d.lib  C:\dev\vcpkg\installed\x64-windows\debug\lib\opencv_world4d.lib  C:\dev\vcpkg\installed\x64-windows\debug\lib\opencv_world4d.lib  C:\dev\vcpkg\installed\x64-windows\debug\lib\yaml-cppd.lib  D:\dev\gaintech\install\gt_timer\Debug\lib\gt_timerd.lib  "C:\Program Files\Optris GmbH & Co. KG\Thermal Camera SDK\lib\otcsdk.lib"  kernel32.lib user32.lib gdi32.lib winspool.lib shell32.lib ole32.lib oleaut32.lib uuid.lib comdlg32.lib advapi32.lib && C:\WINDOWS\system32\cmd.exe /C "cd /D D:\dev\gaintech\build\gt_iaq_otc_sdk\examples && C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -noprofile -executionpolicy Bypass -file C:/dev/vcpkg/scripts/buildsystems/msbuild/applocal.ps1 -targetBinary D:/dev/gaintech/build/gt_iaq_otc_sdk/examples/Debug/ExemploOTCSDK.exe -installedDir C:/dev/vcpkg/installed/x64-windows/debug/bin -OutVariable out && cd /D D:\dev\gaintech\build\gt_iaq_otc_sdk\examples && "C:\Program Files\CMake\bin\cmake.exe" -E copy_if_different C:/dev/vcpkg/installed/x64-windows/debug/bin/opencv_world4d.dll C:/dev/vcpkg/installed/x64-windows/debug/bin/opencv_world4d.dll C:/dev/vcpkg/installed/x64-windows/debug/bin/opencv_world4d.dll C:/dev/vcpkg/installed/x64-windows/debug/bin/opencv_world4d.dll C:/dev/vcpkg/installed/x64-windows/debug/bin/opencv_world4d.dll C:/dev/vcpkg/installed/x64-windows/debug/bin/opencv_world4d.dll C:/dev/vcpkg/installed/x64-windows/debug/bin/opencv_world4d.dll C:/dev/vcpkg/installed/x64-windows/debug/bin/opencv_world4d.dll C:/dev/vcpkg/installed/x64-windows/debug/bin/opencv_world4d.dll C:/dev/vcpkg/installed/x64-windows/debug/bin/opencv_world4d.dll C:/dev/vcpkg/installed/x64-windows/debug/bin/opencv_world4d.dll C:/dev/vcpkg/installed/x64-windows/debug/bin/opencv_world4d.dll C:/dev/vcpkg/installed/x64-windows/debug/bin/opencv_world4d.dll C:/dev/vcpkg/installed/x64-windows/debug/bin/opencv_world4d.dll C:/dev/vcpkg/installed/x64-windows/debug/bin/opencv_world4d.dll C:/dev/vcpkg/installed/x64-windows/debug/bin/libprotobufd.dll C:/dev/vcpkg/installed/x64-windows/debug/bin/abseil_dll.dll C:/dev/vcpkg/installed/x64-windows/debug/bin/yaml-cppd.dll "C:/Program Files/Optris GmbH & Co. KG/Thermal Camera SDK/bin/otcsdk.dll" D:/dev/gaintech/build/gt_iaq_otc_sdk/examples/Debug""
[build] Error: Target (for copy_if_different command) "GmbH" is not a directory.
[build] 'Co.' não é reconhecido como um comando interno
[build] ou externo, um programa operável ou um arquivo em lotes.
[build] ninja: build stopped: subcommand failed.

I suspected whitespace or special characters were the cause, but running the command directly in the terminal works:

PS D:\dev\gaintech\src\gt_iaq_otc_sdk> cmake -E copy_if_different C:/dev/vcpkg/installed/x64-windows/debug/bin/opencv_world4d.dll C:/dev/vcpkg/installed/x64-windows/debug/bin/libprotobufd.dll C:/dev/vcpkg/installed/x64-windows/debug/bin/abseil_dll.dll C:/dev/vcpkg/installed/x64-windows/debug/bin/yaml-cppd.dll "C:/Program Files/Optris GmbH & Co. KG/Thermal Camera SDK/bin/otcsdk.dll" D:/dev/gaintech/build/gt_iaq_otc_sdk/examples/Debug

Could you help me?

I’m using:

  • CMake 4.1.0
  • Ninja 1.13.1
  • clang-cl 19.1.5
  • Windows 11

Add the VERBATIM keyword to your add_custom_command() call. It looks like the & character isn’t being escaped correctly, and the VERBATIM keyword should take care of that.

Hello Craig,

I had tried to use the VERBATIM command, but I was unsuccessful, the exact same problem continued to occur.

function(_copy_runtime_dlls_at_build __targetName )
    if (WIN32)
        add_custom_command(
            TARGET ${__targetName} POST_BUILD
            COMMAND ${CMAKE_COMMAND} -E $<IF:$<BOOL:$<TARGET_RUNTIME_DLLS:${__targetName}>>,copy_if_different,true>
                $<TARGET_RUNTIME_DLLS:${__targetName}>
                $<TARGET_FILE_DIR:${__targetName}>
            COMMAND_EXPAND_LISTS
            VERBATIM
        )
    endif ()
endfunction(_copy_runtime_dlls_at_build)

Here is the output:

[build] FAILED: [code=1] examples/Debug/ExemploOTCSDK.exe 
[build] C:\WINDOWS\system32\cmd.exe /C "cd . && "C:\Program Files\CMake\bin\cmake.exe" -E vs_link_exe --msvc-ver=1943 --intdir=examples\CMakeFiles\ExemploOTCSDK.dir\Debug --rc=C:\dev\llvm\bin\llvm-rc.exe --mt=C:\dev\llvm\bin\llvm-mt.exe --manifests  -- C:\dev\llvm\bin\lld-link.exe /nologo examples\CMakeFiles\ExemploOTCSDK.dir\Debug\test.cpp.obj  /out:examples\Debug\ExemploOTCSDK.exe /implib:examples\Debug\ExemploOTCSDK.lib /pdb:examples\Debug\ExemploOTCSDK.pdb /version:0.0 /machine:x64 /debug /INCREMENTAL /subsystem:console  Debug\gt_iaq_otc_sdkd.lib  C:\dev\vcpkg\installed\x64-windows\debug\lib\opencv_world4d.lib  C:\dev\vcpkg\installed\x64-windows\debug\lib\opencv_world4d.lib  C:\dev\vcpkg\installed\x64-windows\debug\lib\opencv_world4d.lib  C:\dev\vcpkg\installed\x64-windows\debug\lib\opencv_world4d.lib  C:\dev\vcpkg\installed\x64-windows\debug\lib\opencv_world4d.lib  C:\dev\vcpkg\installed\x64-windows\debug\lib\opencv_world4d.lib  C:\dev\vcpkg\installed\x64-windows\debug\lib\opencv_world4d.lib  C:\dev\vcpkg\installed\x64-windows\debug\lib\opencv_world4d.lib  C:\dev\vcpkg\installed\x64-windows\debug\lib\opencv_world4d.lib  C:\dev\vcpkg\installed\x64-windows\debug\lib\opencv_world4d.lib  C:\dev\vcpkg\installed\x64-windows\debug\lib\opencv_world4d.lib  C:\dev\vcpkg\installed\x64-windows\debug\lib\opencv_world4d.lib  C:\dev\vcpkg\installed\x64-windows\debug\lib\opencv_world4d.lib  C:\dev\vcpkg\installed\x64-windows\debug\lib\opencv_world4d.lib  C:\dev\vcpkg\installed\x64-windows\debug\lib\opencv_world4d.lib  C:\dev\vcpkg\installed\x64-windows\debug\lib\yaml-cppd.lib  D:\dev\gaintech\install\gt_timer\Debug\lib\gt_timerd.lib  "C:\Program Files\Optris GmbH & Co. KG\Thermal Camera SDK\lib\otcsdk.lib"  kernel32.lib user32.lib gdi32.lib winspool.lib shell32.lib ole32.lib oleaut32.lib uuid.lib comdlg32.lib advapi32.lib && C:\WINDOWS\system32\cmd.exe /C "cd /D D:\dev\gaintech\build\gt_iaq_otc_sdk\examples && C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -noprofile -executionpolicy Bypass -file C:/dev/vcpkg/scripts/buildsystems/msbuild/applocal.ps1 -targetBinary D:/dev/gaintech/build/gt_iaq_otc_sdk/examples/Debug/ExemploOTCSDK.exe -installedDir C:/dev/vcpkg/installed/x64-windows/debug/bin -OutVariable out && cd /D D:\dev\gaintech\build\gt_iaq_otc_sdk\examples && "C:\Program Files\CMake\bin\cmake.exe" -E copy_if_different C:/dev/vcpkg/installed/x64-windows/debug/bin/opencv_world4d.dll C:/dev/vcpkg/installed/x64-windows/debug/bin/opencv_world4d.dll C:/dev/vcpkg/installed/x64-windows/debug/bin/opencv_world4d.dll C:/dev/vcpkg/installed/x64-windows/debug/bin/opencv_world4d.dll C:/dev/vcpkg/installed/x64-windows/debug/bin/opencv_world4d.dll C:/dev/vcpkg/installed/x64-windows/debug/bin/opencv_world4d.dll C:/dev/vcpkg/installed/x64-windows/debug/bin/opencv_world4d.dll C:/dev/vcpkg/installed/x64-windows/debug/bin/opencv_world4d.dll C:/dev/vcpkg/installed/x64-windows/debug/bin/opencv_world4d.dll C:/dev/vcpkg/installed/x64-windows/debug/bin/opencv_world4d.dll C:/dev/vcpkg/installed/x64-windows/debug/bin/opencv_world4d.dll C:/dev/vcpkg/installed/x64-windows/debug/bin/opencv_world4d.dll C:/dev/vcpkg/installed/x64-windows/debug/bin/opencv_world4d.dll C:/dev/vcpkg/installed/x64-windows/debug/bin/opencv_world4d.dll C:/dev/vcpkg/installed/x64-windows/debug/bin/opencv_world4d.dll C:/dev/vcpkg/installed/x64-windows/debug/bin/libprotobufd.dll C:/dev/vcpkg/installed/x64-windows/debug/bin/abseil_dll.dll C:/dev/vcpkg/installed/x64-windows/debug/bin/yaml-cppd.dll "C:/Program Files/Optris GmbH & Co. KG/Thermal Camera SDK/bin/otcsdk.dll" D:/dev/gaintech/build/gt_iaq_otc_sdk/examples/Debug""
[build] Error: Target (for copy_if_different command) "GmbH" is not a directory.
[build] 'Co.' não é reconhecido como um comando interno
[build] ou externo, um programa operável ou um arquivo em lotes.
[proc] The command: "C:\Program Files\CMake\bin\cmake.EXE" --build D:/dev/gaintech/build/gt_iaq_otc_sdk --config Debug --target ExemploOTCSDK -- exited with code: 1
[build] ninja: build stopped: subcommand failed.
[driver] Build completed: 00:00:12.347
[build] Build finished with exit code 1

It seems that the generated command has an error in the positioning of the quotation marks. The command I do is:

cmake --build D:/dev/gaintech/build/gt_iaq_otc_sdk --config Debug --target ExemploOTCSDK

and the generated command is:

C:\WINDOWS\system32\cmd.exe /C "cd . && "C:\Program Files\CMake\bin\cmake.exe" -E vs_link_exe --msvc-ver=1943 --intdir=examples\CMakeFiles\ExemploOTCSDK.dir\Debug --rc=C:\dev\llvm\bin\llvm-rc.exe --mt=C:\dev\llvm\bin\llvm-mt.exe --manifests  -- C:\dev\llvm\bin\lld-link.exe /nologo examples\CMakeFiles\ExemploOTCSDK.dir\Debug\test.cpp.obj  /out:examples\Debug\ExemploOTCSDK.exe /implib:examples\Debug\ExemploOTCSDK.lib /pdb:examples\Debug\ExemploOTCSDK.pdb /version:0.0 /machine:x64 /debug /INCREMENTAL /subsystem:console  Debug\gt_iaq_otc_sdkd.lib  C:\dev\vcpkg\installed\x64-windows\debug\lib\opencv_world4d.lib  C:\dev\vcpkg\installed\x64-windows\debug\lib\opencv_world4d.lib  C:\dev\vcpkg\installed\x64-windows\debug\lib\opencv_world4d.lib  C:\dev\vcpkg\installed\x64-windows\debug\lib\opencv_world4d.lib  C:\dev\vcpkg\installed\x64-windows\debug\lib\opencv_world4d.lib  C:\dev\vcpkg\installed\x64-windows\debug\lib\opencv_world4d.lib  C:\dev\vcpkg\installed\x64-windows\debug\lib\opencv_world4d.lib  C:\dev\vcpkg\installed\x64-windows\debug\lib\opencv_world4d.lib  C:\dev\vcpkg\installed\x64-windows\debug\lib\opencv_world4d.lib  C:\dev\vcpkg\installed\x64-windows\debug\lib\opencv_world4d.lib  C:\dev\vcpkg\installed\x64-windows\debug\lib\opencv_world4d.lib  C:\dev\vcpkg\installed\x64-windows\debug\lib\opencv_world4d.lib  C:\dev\vcpkg\installed\x64-windows\debug\lib\opencv_world4d.lib  C:\dev\vcpkg\installed\x64-windows\debug\lib\opencv_world4d.lib  C:\dev\vcpkg\installed\x64-windows\debug\lib\opencv_world4d.lib  C:\dev\vcpkg\installed\x64-windows\debug\lib\yaml-cppd.lib  D:\dev\gaintech\install\gt_timer\Debug\lib\gt_timerd.lib  "C:\Program Files\Optris GmbH & Co. KG\Thermal Camera SDK\lib\otcsdk.lib"  kernel32.lib user32.lib gdi32.lib winspool.lib shell32.lib ole32.lib oleaut32.lib uuid.lib comdlg32.lib advapi32.lib && C:\WINDOWS\system32\cmd.exe /C "cd /D D:\dev\gaintech\build\gt_iaq_otc_sdk\examples && C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -noprofile -executionpolicy Bypass -file C:/dev/vcpkg/scripts/buildsystems/msbuild/applocal.ps1 -targetBinary D:/dev/gaintech/build/gt_iaq_otc_sdk/examples/Debug/ExemploOTCSDK.exe -installedDir C:/dev/vcpkg/installed/x64-windows/debug/bin -OutVariable out && cd /D D:\dev\gaintech\build\gt_iaq_otc_sdk\examples && "C:\Program Files\CMake\bin\cmake.exe" -E copy_if_different C:/dev/vcpkg/installed/x64-windows/debug/bin/opencv_world4d.dll C:/dev/vcpkg/installed/x64-windows/debug/bin/opencv_world4d.dll C:/dev/vcpkg/installed/x64-windows/debug/bin/opencv_world4d.dll C:/dev/vcpkg/installed/x64-windows/debug/bin/opencv_world4d.dll C:/dev/vcpkg/installed/x64-windows/debug/bin/opencv_world4d.dll C:/dev/vcpkg/installed/x64-windows/debug/bin/opencv_world4d.dll C:/dev/vcpkg/installed/x64-windows/debug/bin/opencv_world4d.dll C:/dev/vcpkg/installed/x64-windows/debug/bin/opencv_world4d.dll C:/dev/vcpkg/installed/x64-windows/debug/bin/opencv_world4d.dll C:/dev/vcpkg/installed/x64-windows/debug/bin/opencv_world4d.dll C:/dev/vcpkg/installed/x64-windows/debug/bin/opencv_world4d.dll C:/dev/vcpkg/installed/x64-windows/debug/bin/opencv_world4d.dll C:/dev/vcpkg/installed/x64-windows/debug/bin/opencv_world4d.dll C:/dev/vcpkg/installed/x64-windows/debug/bin/opencv_world4d.dll C:/dev/vcpkg/installed/x64-windows/debug/bin/opencv_world4d.dll C:/dev/vcpkg/installed/x64-windows/debug/bin/libprotobufd.dll C:/dev/vcpkg/installed/x64-windows/debug/bin/abseil_dll.dll C:/dev/vcpkg/installed/x64-windows/debug/bin/yaml-cppd.dll "C:/Program Files/Optris GmbH & Co. KG/Thermal Camera SDK/bin/otcsdk.dll" D:/dev/gaintech/build/gt_iaq_otc_sdk/examples/Debug""

The quoting rules on Windows for the cmd shell are notoriously complicated. I guess you could report this as an issue in CMake’s issue tracker, but I’m not sure who would potentially be able to look into it.

Thank you, Craig. I opened an issue as suggested.

If I get any solution, I’ll post it here.