1
0
Fork 0
x64dbg/cmake/deps.cmake

155 lines
5.5 KiB
CMake

if(CMAKE_SCRIPT_MODE_FILE)
set(GUI_DLL "${CMAKE_ARGV3}")
set(DEPS_DIR "${CMAKE_ARGV4}")
set(WINDEPLOYQT "${CMAKE_ARGV5}")
set(EXPECTED_DEPS_HASH "${CMAKE_ARGV6}")
get_filename_component(GUI_DIR "${GUI_DLL}" DIRECTORY)
get_filename_component(WINDEPLOYQT_DIR "${WINDEPLOYQT}" DIRECTORY)
set(DEPS_COPIED_FILE "${GUI_DIR}/.deps_copied")
set(DEPS_HASH_FILE "${GUI_DIR}/.deps_hash")
# Check if we already copied the dependencies for the current Qt/deps state.
if(EXISTS "${DEPS_COPIED_FILE}" AND EXISTS "${DEPS_HASH_FILE}")
file(READ "${DEPS_HASH_FILE}" CURRENT_DEPS_HASH)
string(STRIP "${CURRENT_DEPS_HASH}" CURRENT_DEPS_HASH)
if("${CURRENT_DEPS_HASH}" STREQUAL "${EXPECTED_DEPS_HASH}")
return()
endif()
endif()
# Make windeployqt resilient against globally configured Qt environments.
string(CONCAT SANITIZED_PATH "${WINDEPLOYQT_DIR}" ";" "$ENV{PATH}")
set(ENV{PATH} "${SANITIZED_PATH}")
unset(ENV{QTDIR})
unset(ENV{QT_PLUGIN_PATH})
unset(ENV{QT_QPA_PLATFORM_PLUGIN_PATH})
unset(ENV{QML_IMPORT_PATH})
unset(ENV{QML2_IMPORT_PATH})
message(STATUS "Copying dependencies from ${DEPS_DIR} to ${GUI_DIR}")
execute_process(
COMMAND "${WINDEPLOYQT}" --pdb --no-compiler-runtime --no-translations --no-opengl-sw --force "${GUI_DLL}" --list relative
WORKING_DIRECTORY "${GUI_DIR}"
RESULT_VARIABLE WINDEPLOYQT_RESULT
OUTPUT_VARIABLE DEPS_COPIED
ERROR_VARIABLE WINDEPLOYQT_STDERR
OUTPUT_STRIP_TRAILING_WHITESPACE
ERROR_STRIP_TRAILING_WHITESPACE
)
if(NOT "${WINDEPLOYQT_STDERR}" STREQUAL "")
message(STATUS "${WINDEPLOYQT_STDERR}")
endif()
if(NOT WINDEPLOYQT_RESULT EQUAL 0)
message(FATAL_ERROR "windeployqt failed with exit code ${WINDEPLOYQT_RESULT}")
endif()
# Split the output into lines
string(REGEX REPLACE "\n" ";" DEPS_COPIED "${DEPS_COPIED}")
list(FILTER DEPS_COPIED EXCLUDE REGEX "^$")
foreach(line ${DEPS_COPIED})
message(STATUS "Copying ${line}")
endforeach()
function(copy_dep relfile)
set(DEPS_COPIED ${DEPS_COPIED} ${relfile} PARENT_SCOPE)
set(target_path "${GUI_DIR}/${relfile}")
if(IS_SYMLINK "${target_path}")
message(STATUS "Skipping symlink ${relfile}")
return()
endif()
message(STATUS "Copying ${relfile}")
get_filename_component(reldir "${relfile}" DIRECTORY)
get_filename_component(filename "${relfile}" NAME)
if(reldir)
file(COPY "${DEPS_DIR}/${reldir}/${filename}" DESTINATION "${GUI_DIR}/${reldir}")
else()
file(COPY "${DEPS_DIR}/${filename}" DESTINATION "${GUI_DIR}")
endif()
endfunction()
file(GLOB_RECURSE DEPS RELATIVE "${DEPS_DIR}" "${DEPS_DIR}/*.dll")
list(SORT DEPS)
foreach(DEP ${DEPS})
copy_dep("${DEP}")
endforeach()
list(JOIN DEPS_COPIED "\n" DEPS_COPIED)
file(WRITE "${DEPS_COPIED_FILE}" "${DEPS_COPIED}")
file(WRITE "${DEPS_HASH_FILE}" "${EXPECTED_DEPS_HASH}\n")
return()
endif()
if(NOT WIN32)
message(STATUS "copy_dependencies is only supported on Windows")
return()
endif()
if(NOT TARGET Qt5::windeployqt)
if(Qt5_FOUND AND TARGET Qt5::qmake)
get_target_property(_qt5_qmake_location Qt5::qmake IMPORTED_LOCATION)
execute_process(
COMMAND "${_qt5_qmake_location}" -query QT_INSTALL_PREFIX
RESULT_VARIABLE return_code
OUTPUT_VARIABLE qt5_install_prefix
OUTPUT_STRIP_TRAILING_WHITESPACE
)
set(imported_location "${qt5_install_prefix}/bin/windeployqt.exe")
if(EXISTS ${imported_location})
add_executable(Qt5::windeployqt IMPORTED)
set_target_properties(Qt5::windeployqt PROPERTIES
IMPORTED_LOCATION ${imported_location}
)
endif()
endif()
if(NOT TARGET Qt5::windeployqt)
# Fallback: search for windeployqt on PATH
find_program(_qt5_windeployqt_from_path NAMES windeployqt.exe windeployqt)
if(_qt5_windeployqt_from_path)
add_executable(Qt5::windeployqt IMPORTED)
set_target_properties(Qt5::windeployqt PROPERTIES
IMPORTED_LOCATION ${_qt5_windeployqt_from_path}
)
endif()
endif()
endif()
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
set(DEPS_DIR ${CMAKE_SOURCE_DIR}/deps/x64)
else()
set(DEPS_DIR ${CMAKE_SOURCE_DIR}/deps/x32)
endif()
get_target_property(_qt5_windeployqt_location Qt5::windeployqt IMPORTED_LOCATION)
if(NOT _qt5_windeployqt_location)
message(FATAL_ERROR "Could not locate Qt5::windeployqt. Install Qt with windeployqt and ensure it is discoverable (in PATH or via Qt5::qmake).")
endif()
file(GLOB_RECURSE DEPS_INPUT_DLLS "${DEPS_DIR}/*.dll")
list(SORT DEPS_INPUT_DLLS)
file(SHA256 "${_qt5_windeployqt_location}" WINDEPLOYQT_HASH)
set(DEPS_HASH_INPUT "WINDEPLOYQT=${WINDEPLOYQT_HASH}\n")
foreach(DEP_FILE ${DEPS_INPUT_DLLS})
file(RELATIVE_PATH DEP_RELATIVE "${DEPS_DIR}" "${DEP_FILE}")
file(SHA256 "${DEP_FILE}" DEP_HASH)
string(APPEND DEPS_HASH_INPUT "${DEP_RELATIVE}=${DEP_HASH}\n")
endforeach()
string(SHA256 EXPECTED_DEPS_HASH "${DEPS_HASH_INPUT}")
add_custom_target(deps
COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_LIST_DIR}/deps.cmake $<TARGET_FILE:gui> ${DEPS_DIR} $<TARGET_FILE:Qt5::windeployqt> ${EXPECTED_DEPS_HASH}
)
# Make a rebuild copy the dependencies again
set_target_properties(deps PROPERTIES
ADDITIONAL_CLEAN_FILES "$<TARGET_FILE_DIR:gui>/.deps_copied;$<TARGET_FILE_DIR:gui>/.deps_hash"
)