Skip to content

Commit 4fe76cc

Browse files
Add MSYS2 runtime dependency deployment
Introduce a CMake helper to deploy MSYS2/MinGW runtime DLLs discovered via ldd and cygpath. Added cmake/packaging/windows_runtime_deps.cmake which requires SUNSHINE_RUNTIME_TARGET and SUNSHINE_RUNTIME_OUTPUT_DIR, uses ldd to enumerate dependencies, converts MSYS paths with cygpath, copies needed DLLs into the output dir, and recursively processes newly copied DLLs. Hooked this script into existing packaging: qt.cmake's deploy function now invokes the script for the given target, and windows.cmake runs it after windeployqt and fails the build on errors. This ensures MSYS2 runtime DLLs reported by ldd are bundled with the application.
1 parent cb8984a commit 4fe76cc

3 files changed

Lines changed: 113 additions & 0 deletions

File tree

cmake/packaging/qt.cmake

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,10 @@ function(sunshine_deploy_qt_runtime target_name deploy_tool)
3838
${ARGN}
3939
--dir "$<TARGET_FILE_DIR:${target_name}>"
4040
"$<TARGET_FILE:${target_name}>"
41+
COMMAND "${CMAKE_COMMAND}"
42+
"-DSUNSHINE_RUNTIME_TARGET=$<TARGET_FILE:${target_name}>"
43+
"-DSUNSHINE_RUNTIME_OUTPUT_DIR=$<TARGET_FILE_DIR:${target_name}>"
44+
-P "${CMAKE_CURRENT_FUNCTION_LIST_DIR}/windows_runtime_deps.cmake"
4145
COMMENT "Deploying Qt runtime for ${target_name}"
4246
VERBATIM)
4347
endfunction()

cmake/packaging/windows.cmake

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,17 @@ if(SUNSHINE_ENABLE_TRAY)
3737
if(NOT _qt_deploy_result EQUAL 0)
3838
message(FATAL_ERROR \"windeployqt failed: \${_qt_deploy_result}\")
3939
endif()
40+
41+
execute_process(
42+
COMMAND \"${CMAKE_COMMAND}\"
43+
\"-DSUNSHINE_RUNTIME_TARGET=\${_qt_deploy_dir}/sunshine.exe\"
44+
\"-DSUNSHINE_RUNTIME_OUTPUT_DIR=\${_qt_deploy_dir}\"
45+
-P \"${CMAKE_MODULE_PATH}/packaging/windows_runtime_deps.cmake\"
46+
RESULT_VARIABLE _runtime_deploy_result
47+
)
48+
if(NOT _runtime_deploy_result EQUAL 0)
49+
message(FATAL_ERROR \"Runtime dependency deployment failed: \${_runtime_deploy_result}\")
50+
endif()
4051
" COMPONENT application)
4152
endif()
4253

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
# Deploy MSYS2 runtime DLLs that are reported by ldd for a Windows binary.
2+
3+
if(NOT DEFINED SUNSHINE_RUNTIME_TARGET)
4+
message(FATAL_ERROR "SUNSHINE_RUNTIME_TARGET is required")
5+
endif()
6+
7+
if(NOT DEFINED SUNSHINE_RUNTIME_OUTPUT_DIR)
8+
message(FATAL_ERROR "SUNSHINE_RUNTIME_OUTPUT_DIR is required")
9+
endif()
10+
11+
string(REGEX REPLACE "^\"|\"$" "" SUNSHINE_RUNTIME_TARGET "${SUNSHINE_RUNTIME_TARGET}")
12+
string(REGEX REPLACE "^\"|\"$" "" SUNSHINE_RUNTIME_OUTPUT_DIR "${SUNSHINE_RUNTIME_OUTPUT_DIR}")
13+
14+
find_program(SUNSHINE_LDD_EXECUTABLE ldd)
15+
if(NOT SUNSHINE_LDD_EXECUTABLE)
16+
message(FATAL_ERROR "ldd is required to deploy MSYS2 runtime dependencies")
17+
endif()
18+
19+
find_program(SUNSHINE_CYGPATH_EXECUTABLE cygpath)
20+
if(NOT SUNSHINE_CYGPATH_EXECUTABLE)
21+
message(FATAL_ERROR "cygpath is required to deploy MSYS2 runtime dependencies")
22+
endif()
23+
24+
function(sunshine_msys_path_to_cmake msys_path out_var)
25+
execute_process(
26+
COMMAND "${SUNSHINE_CYGPATH_EXECUTABLE}" -m "${msys_path}"
27+
OUTPUT_VARIABLE _cmake_path
28+
ERROR_VARIABLE _cygpath_error
29+
RESULT_VARIABLE _cygpath_result
30+
OUTPUT_STRIP_TRAILING_WHITESPACE)
31+
if(NOT _cygpath_result EQUAL 0)
32+
message(FATAL_ERROR "cygpath failed for ${msys_path}: ${_cygpath_error}")
33+
endif()
34+
35+
set(${out_var} "${_cmake_path}" PARENT_SCOPE)
36+
endfunction()
37+
38+
function(sunshine_copy_msys_dependency msys_path output_dir out_path)
39+
sunshine_msys_path_to_cmake("${msys_path}" _source_path)
40+
get_filename_component(_dll_name "${_source_path}" NAME)
41+
set(_deployed_path "${output_dir}/${_dll_name}")
42+
43+
if(NOT EXISTS "${_deployed_path}")
44+
execute_process(
45+
COMMAND "${CMAKE_COMMAND}" -E copy_if_different
46+
"${_source_path}"
47+
"${_deployed_path}"
48+
ERROR_VARIABLE _copy_error
49+
RESULT_VARIABLE _copy_result)
50+
if(NOT _copy_result EQUAL 0)
51+
message(FATAL_ERROR "Failed to copy ${_source_path}: ${_copy_error}")
52+
endif()
53+
endif()
54+
55+
set(${out_path} "${_deployed_path}" PARENT_SCOPE)
56+
endfunction()
57+
58+
file(GLOB_RECURSE _deployed_dlls
59+
LIST_DIRECTORIES false
60+
"${SUNSHINE_RUNTIME_OUTPUT_DIR}/*.dll")
61+
62+
set(_pending "${SUNSHINE_RUNTIME_TARGET}" ${_deployed_dlls})
63+
set(_processed "")
64+
65+
while(_pending)
66+
list(POP_FRONT _pending _runtime_binary)
67+
list(FIND _processed "${_runtime_binary}" _processed_index)
68+
if(NOT _processed_index EQUAL -1)
69+
continue()
70+
endif()
71+
72+
list(APPEND _processed "${_runtime_binary}")
73+
74+
execute_process(
75+
COMMAND "${SUNSHINE_LDD_EXECUTABLE}" "${_runtime_binary}"
76+
OUTPUT_VARIABLE _ldd_output
77+
ERROR_VARIABLE _ldd_error
78+
RESULT_VARIABLE _ldd_result)
79+
if(NOT _ldd_result EQUAL 0)
80+
message(FATAL_ERROR "ldd failed for ${_runtime_binary}: ${_ldd_error}")
81+
endif()
82+
83+
string(REGEX MATCHALL "[^\r\n]+" _ldd_lines "${_ldd_output}")
84+
foreach(_ldd_line IN LISTS _ldd_lines)
85+
if(_ldd_line MATCHES "=>[ \t]+not[ \t]+found")
86+
message(FATAL_ERROR "Runtime dependency not found: ${_ldd_line}")
87+
endif()
88+
89+
if(_ldd_line MATCHES "=>[ \t]+(/(clangarm64|clang64|mingw32|mingw64|ucrt64)/bin/[^ \t\r\n]+\\.dll)")
90+
sunshine_copy_msys_dependency("${CMAKE_MATCH_1}" "${SUNSHINE_RUNTIME_OUTPUT_DIR}" _deployed_dll)
91+
list(FIND _processed "${_deployed_dll}" _deployed_processed_index)
92+
list(FIND _pending "${_deployed_dll}" _deployed_pending_index)
93+
if(_deployed_processed_index EQUAL -1 AND _deployed_pending_index EQUAL -1)
94+
list(APPEND _pending "${_deployed_dll}")
95+
endif()
96+
endif()
97+
endforeach()
98+
endwhile()

0 commit comments

Comments
 (0)