if(NOT DEFINED APP_EXE OR NOT DEFINED APP_OUT_DIR) message(FATAL_ERROR "APP_EXE and APP_OUT_DIR must be set") endif() if(NOT EXISTS "${APP_EXE}") message(FATAL_ERROR "Executable not found: ${APP_EXE}") endif() set(_search_dirs "") if((NOT DEFINED TOOLCHAIN_BIN_DIR OR TOOLCHAIN_BIN_DIR STREQUAL "") AND EXISTS "${APP_OUT_DIR}/CMakeCache.txt") file( STRINGS "${APP_OUT_DIR}/CMakeCache.txt" _compiler_line REGEX "^CMAKE_CXX_COMPILER:FILEPATH=" LIMIT_COUNT 1 ) if(_compiler_line) string(REPLACE "CMAKE_CXX_COMPILER:FILEPATH=" "" TOOLCHAIN_BIN_DIR "${_compiler_line}") get_filename_component(TOOLCHAIN_BIN_DIR "${TOOLCHAIN_BIN_DIR}" DIRECTORY) endif() endif() if(DEFINED TOOLCHAIN_BIN_DIR AND NOT TOOLCHAIN_BIN_DIR STREQUAL "" AND EXISTS "${TOOLCHAIN_BIN_DIR}") list(APPEND _search_dirs "${TOOLCHAIN_BIN_DIR}") endif() if(NOT DEFINED TOOLCHAIN_BIN_DIR OR TOOLCHAIN_BIN_DIR STREQUAL "" OR NOT EXISTS "${TOOLCHAIN_BIN_DIR}") message(FATAL_ERROR "TOOLCHAIN_BIN_DIR is required and must exist") endif() file(TO_CMAKE_PATH "${TOOLCHAIN_BIN_DIR}" _toolchain_bin_dir_norm) string(TOLOWER "${_toolchain_bin_dir_norm}" _toolchain_bin_dir_norm_lower) function(_literal_to_case_insensitive_regex _literal _out_var) string(LENGTH "${_literal}" _len) if(_len EQUAL 0) set(${_out_var} "" PARENT_SCOPE) return() endif() set(_regex "") math(EXPR _last "${_len} - 1") foreach(_i RANGE 0 ${_last}) string(SUBSTRING "${_literal}" ${_i} 1 _ch) if(_ch MATCHES "[A-Za-z]") string(TOUPPER "${_ch}" _up) string(TOLOWER "${_ch}" _lo) string(APPEND _regex "[${_up}${_lo}]") elseif(_ch STREQUAL ".") string(APPEND _regex "\\\\.") else() string(APPEND _regex "${_ch}") endif() endforeach() set(${_out_var} "${_regex}" PARENT_SCOPE) endfunction() set(_pre_exclude_regexes "^api-ms-win-.*" "^ext-ms-.*" ) set(_windows_system_dlls "KERNEL32.dll" "USER32.dll" "GDI32.dll" "SHELL32.dll" "WINMM.dll" "OPENGL32.dll" "ADVAPI32.dll" "OLE32.dll" "OLEAUT32.dll" "COMDLG32.dll" "WS2_32.dll" "SECUR32.dll" "NTDLL.dll" ) foreach(_dll IN LISTS _windows_system_dlls) _literal_to_case_insensitive_regex("${_dll}" _dll_regex) list(APPEND _pre_exclude_regexes "(^|.*[/\\\\])${_dll_regex}$") endforeach() file(GET_RUNTIME_DEPENDENCIES EXECUTABLES "${APP_EXE}" RESOLVED_DEPENDENCIES_VAR _resolved_deps UNRESOLVED_DEPENDENCIES_VAR _unresolved_deps CONFLICTING_DEPENDENCIES_PREFIX _conflicting_deps DIRECTORIES ${_search_dirs} PRE_EXCLUDE_REGEXES ${_pre_exclude_regexes} POST_EXCLUDE_REGEXES ".*[/\\\\]Windows[/\\\\]System32[/\\\\].*" ) if(_unresolved_deps) message(STATUS "Unresolved runtime dependencies: ${_unresolved_deps}") endif() if(_conflicting_deps_FILENAMES) message(STATUS "Conflicting runtime dependency names: ${_conflicting_deps_FILENAMES}") endif() foreach(_dep IN LISTS _resolved_deps) file(TO_CMAKE_PATH "${_dep}" _dep_norm) string(TOLOWER "${_dep_norm}" _dep_norm_lower) if(NOT _dep_norm_lower MATCHES "^${_toolchain_bin_dir_norm_lower}/") continue() endif() get_filename_component(_name "${_dep}" NAME) if(_name STREQUAL "") continue() endif() execute_process( COMMAND "${CMAKE_COMMAND}" -E copy_if_different "${_dep}" "${APP_OUT_DIR}/${_name}" RESULT_VARIABLE _copy_rc ) if(NOT _copy_rc EQUAL 0) message(FATAL_ERROR "Failed to copy runtime dependency: ${_dep}") endif() endforeach()