From caf561457d09a942bf0789f3e7ebc3870714a65f Mon Sep 17 00:00:00 2001 From: Rangi <35663410+Rangi42@users.noreply.github.com> Date: Wed, 24 Jun 2026 17:53:11 -0400 Subject: [PATCH] Warn about CMake <3.27 for Windows-targeted builds (#1989) We only use `$`` when cross-compiling for MinGW on Linux, so the relevant block is now wrapped in `if(WIN32)` so a user can more easily lower the `cmake_minimum_required` version. --- src/CMakeLists.txt | 62 +++++++++++++++++++++++++--------------------- 1 file changed, 34 insertions(+), 28 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 0c808877..a55713ef 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -118,32 +118,38 @@ add_custom_command(TARGET rgbgfx POST_BUILD COMMENT "Copying rgbgfx's DLLs" COMMAND ${CMAKE_COMMAND} -E copy -t $ $ COMMAND_EXPAND_LISTS VERBATIM) -# On Windows, you don't link against DLLs directly, but against an import library for that DLL. -# This leads to, sometimes, the DLL being stored in a directory far away from the import library itself! -set(DLL_SEARCH_DIRS CACHE PATH "List of directories in which DLLs will be searched") -cmake_path(CONVERT "${DLL_SEARCH_DIRS}" TO_CMAKE_PATH_LIST search_dirs NORMALIZE) -# TODO: we've only tested this with MinGW, but it may not work with other uses of the variable. -# Anyone who knows how to handle this better, feel free to submit a patch! -if(DEFINED CMAKE_FIND_ROOT_PATH) - list(APPEND search_dirs "${CMAKE_FIND_ROOT_PATH}/bin") +if(WIN32) + # CMake 3.27 is required for `$`, but is only needed when cross-compiling for MinGW. + if(CMAKE_VERSION VERSION_LESS "3.27") + message(WARNING "CMake 3.27 or higher is required for `\$` inside `install(CODE)`") + endif() + # On Windows, you don't link against DLLs directly, but against an import library for that DLL. + # This leads to, sometimes, the DLL being stored in a directory far away from the import library itself! + set(DLL_SEARCH_DIRS CACHE PATH "List of directories in which DLLs will be searched") + cmake_path(CONVERT "${DLL_SEARCH_DIRS}" TO_CMAKE_PATH_LIST search_dirs NORMALIZE) + # TODO: we've only tested this with MinGW, but it may not work with other uses of the variable. + # Anyone who knows how to handle this better, feel free to submit a patch! + if(DEFINED CMAKE_FIND_ROOT_PATH) + list(APPEND search_dirs "${CMAKE_FIND_ROOT_PATH}/bin") + endif() + # Escape the search paths in a form that makes them suitable for splatting into the CMake install script. + list(TRANSFORM search_dirs REPLACE "([\\$\"])" "\\\\1") # Neutralize escapes and variable refs... + list(TRANSFORM search_dirs REPLACE "^(.+)\$" "\"\\1\"") # ...and quote each argument. + list(JOIN search_dirs " " search_dirs_splat) + # This is a modified version of the install code generated by + # `install(TARGETS rgbgfx RUNTIME_DEPENDENCIES)`. + # Unfortunately, that `install(TARGETS)` is outright not supported when cross-compiling, + # and working around that has CMake fail to resolve the DLL locations with MinGW, + # due to not specifying any `DIRECTORIES` and the system search path being ineffective. + install(CODE "\ + file(GET_RUNTIME_DEPENDENCIES + RESOLVED_DEPENDENCIES_VAR rgbgfx_deps + EXECUTABLES \"$\" + DIRECTORIES ${search_dirs_splat} \"$\" \"$\" + PRE_EXCLUDE_REGEXES \"^kernel32\\\\.dll$\" \"^msvcrt.?.?\\\\.dll\" \"^api-ms-win-.*\\\\.dll$\") + foreach(rgbgfx_dep IN LISTS rgbgfx_deps) + file(INSTALL DESTINATION \"$/${CMAKE_INSTALL_BINDIR}\" TYPE SHARED_LIBRARY FILES \${rgbgfx_dep} + FOLLOW_SYMLINK_CHAIN) + endforeach()" + COMPONENT shared-libs EXCLUDE_FROM_ALL) # Most platforms install those separately. endif() -# Escape the search paths in a form that makes them suitable for splatting into the CMake install script. -list(TRANSFORM search_dirs REPLACE "([\\$\"])" "\\\\1") # Neutralize escapes and variable refs... -list(TRANSFORM search_dirs REPLACE "^(.+)\$" "\"\\1\"") # ...and quote each argument. -list(JOIN search_dirs " " search_dirs_splat) -# This is a modified version of the install code generated by -# `install(TARGETS rgbgfx RUNTIME_DEPENDENCIES)`. -# Unfortunately, that `install(TARGETS)` is outright not supported when cross-compiling, -# and working around that has CMake fail to resolve the DLL locations with MinGW, -# due to not specifying any `DIRECTORIES` and the system search path being ineffective. -install(CODE "\ -file(GET_RUNTIME_DEPENDENCIES - RESOLVED_DEPENDENCIES_VAR rgbgfx_deps - EXECUTABLES \"$\" - DIRECTORIES ${search_dirs_splat} \"$\" \"$\" - PRE_EXCLUDE_REGEXES \"^kernel32\\\\.dll$\" \"^msvcrt.?.?\\\\.dll\" \"^api-ms-win-.*\\\\.dll$\") - foreach(rgbgfx_dep IN LISTS rgbgfx_deps) - file(INSTALL DESTINATION \"$/${CMAKE_INSTALL_BINDIR}\" TYPE SHARED_LIBRARY FILES \${rgbgfx_dep} - FOLLOW_SYMLINK_CHAIN) - endforeach()" - COMPONENT shared-libs EXCLUDE_FROM_ALL) # Most platforms install those separately.