# Определение зависимостей после сборки приложения cmake_minimum_required(VERSION 4.0) set(LIBS_FIND_DIRS "${PREFIX}") set(QT_SHARE_DIR "${PREFIX}") if (CMAKE_SYSTEM_NAME STREQUAL "Windows") if (EXISTS "${PREFIX}/bin") set(LIBS_FIND_DIRS "${PREFIX}/bin") endif() else() if (EXISTS "${PREFIX}/lib") set(LIBS_FIND_DIRS "${PREFIX}/lib") endif() endif() if (EXISTS "${PREFIX}/share/qt${QT_VERSION_MAJOR}") set(QT_SHARE_DIR "${PREFIX}/share/qt${QT_VERSION_MAJOR}") endif() if(TARGET_TYPE STREQUAL "EXECUTABLE") if (EXISTS "${OUTPUT_DIR}/${TARGET_NAME}") set(TARGET_FILE "${OUTPUT_DIR}/${TARGET_NAME}") elseif (EXISTS "${OUTPUT_DIR}/${TARGET_NAME}.exe") set(TARGET_FILE "${OUTPUT_DIR}/${TARGET_NAME}.exe") endif() else() if (EXISTS "${OUTPUT_DIR}/${TARGET_NAME}") set(TARGET_FILE "${OUTPUT_DIR}/${TARGET_NAME}") elseif (EXISTS "${OUTPUT_DIR}/${TARGET_NAME}.dll") set(TARGET_FILE "${OUTPUT_DIR}/${TARGET_NAME}.dll") elseif (EXISTS "${OUTPUT_DIR}/${TARGET_NAME}.so") set(TARGET_FILE "${OUTPUT_DIR}/${TARGET_NAME}.so") endif() endif() message(STATUS "TARGET_FILE: '${TARGET_FILE}'") message(STATUS "LIBS_FIND_DIRS: '${LIBS_FIND_DIRS}'") message(STATUS "OUTPUT_DIR: '${OUTPUT_DIR}'") message(STATUS "QT_VERSION_MAJOR: '${QT_VERSION_MAJOR}'") message(STATUS "Find and copy dependencies. Please, wait...") # functions -------------------------------------------------------------------- # Копирование файла function(safe_copy src dest) # Пытаемся скопировать через execute_process (кросс-платформенно) execute_process( COMMAND ${CMAKE_COMMAND} -E copy_if_different "${src}" "${dest}" RESULT_VARIABLE copy_result ERROR_VARIABLE copy_error OUTPUT_QUIET # Подавляем stdout ) if(NOT copy_result EQUAL 0) message(WARNING "Не удалось скопировать ${src} -> ${dest}: ${copy_error}") return() endif() endfunction() # Отслеживание цепочки ссылок function(get_symlink_chain dep symlink_chain) unset(chain) set(current_dep "${dep}") # 1. Разрешаем основную цепочку симлинков (исходный файл → конечный файл) while(IS_SYMLINK "${current_dep}") execute_process( COMMAND readlink "${current_dep}" OUTPUT_VARIABLE link_target OUTPUT_STRIP_TRAILING_WHITESPACE ) list(INSERT chain 0 "${current_dep}") # Добавляем текущий симлинк в начало get_filename_component(parent_dir "${current_dep}" DIRECTORY) set(current_dep "${parent_dir}/${link_target}") # Переходим по ссылке endwhile() # 2. Добавляем конечный файл в начало цепочки list(INSERT chain 0 "${current_dep}") # 3. Теперь ищем ВСЕ симлинки в этой директории, которые ссылаются на конечный файл if(EXISTS "${current_dep}") get_filename_component(final_file "${current_dep}" REALPATH) # Абсолютный путь конечного файла get_filename_component(parent_dir "${current_dep}" DIRECTORY) # Директория конечного файла # Получаем список всех файлов в этой директории file(GLOB all_files LIST_DIRECTORIES false "${parent_dir}/*") foreach(file IN LISTS all_files) # Если это симлинк, проверяем, ведёт ли он на конечный файл if(IS_SYMLINK "${file}") execute_process( COMMAND readlink -f "${file}" # Абсолютный путь цели симлинка OUTPUT_VARIABLE symlink_target OUTPUT_STRIP_TRAILING_WHITESPACE ) # Если цель симлинка совпадает с конечным файлом, добавляем в цепочку if(symlink_target STREQUAL final_file AND NOT file IN_LIST chain) list(APPEND chain "${file}") endif() endif() endforeach() endif() set(${symlink_chain} "${chain}" PARENT_SCOPE) endfunction() # ------------------------------------------------------------------------------ if (EXISTS "${TARGET_FILE}") # Получаем runtime-зависимости file(GET_RUNTIME_DEPENDENCIES EXECUTABLES ${TARGET_FILE} RESOLVED_DEPENDENCIES_VAR RESOLVED_DEPS UNRESOLVED_DEPENDENCIES_VAR UNRESOLVED_DEPS DIRECTORIES ${LIBS_FIND_DIRS} ) set(USE_SQL OFF) set(USE_PRINT OFF) set(USE_NETWORK OFF) set(USE_SERIALPORT OFF) set(USE_MULTIMEDIA OFF) message(STATUS "\nResolved dependencies copy:\n") foreach(DEP ${RESOLVED_DEPS}) string(FIND "${DEP}" "${LIBS_FIND_DIRS}" POS) if(POS EQUAL 0) if (CMAKE_SYSTEM_NAME STREQUAL "Windows") message(STATUS "${DEP}") file(COPY "${DEP}" DESTINATION "${OUTPUT_DIR}") else () #message(STATUS "${DEP}") #file(COPY "${DEP}" DESTINATION "${OUTPUT_DIR}/system_lib" FOLLOW_SYMLINK_CHAIN) get_symlink_chain("${DEP}" dep_chain) foreach(file IN LISTS dep_chain) message(STATUS "${file}") safe_copy("${file}" "${OUTPUT_DIR}") endforeach() endif() endif() string(FIND "${DEP}" "Qt${QT_VERSION_MAJOR}Sql" POS) if(POS GREATER 0) set(USE_SQL ON) endif() string(FIND "${DEP}" "Qt${QT_VERSION_MAJOR}Print" POS) if(POS GREATER 0) set(USE_PRINT ON) endif() string(FIND "${DEP}" "Qt${QT_VERSION_MAJOR}Network" POS) if(POS GREATER 0) set(USE_NETWORK ON) endif() string(FIND "${DEP}" "Qt${QT_VERSION_MAJOR}Serial" POS) if(POS GREATER 0) set(USE_SERIALPORT ON) endif() string(FIND "${DEP}" "Qt${QT_VERSION_MAJOR}Multimedia" POS) if(POS GREATER 0) set(USE_MULTIMEDIA ON) endif() endforeach() if (EXISTS "${LIBS_FIND_DIRS}/libQt${QT_VERSION_MAJOR}XcbQpa.so") get_symlink_chain("${LIBS_FIND_DIRS}/libQt${QT_VERSION_MAJOR}XcbQpa.so" xcb_chain) foreach(file IN LISTS xcb_chain) message(STATUS "${file}") safe_copy("${file}" "${OUTPUT_DIR}") endforeach() endif() message(STATUS "\nResolved dependencies not copy:\n") foreach(DEP ${RESOLVED_DEPS}) string(FIND "${DEP}" "${LIBS_FIND_DIRS}" POS) if(NOT POS EQUAL 0) message(STATUS "${DEP}") endif() endforeach() message(STATUS "\nUnresolved dependencies:\n") foreach(DEP ${UNRESOLVED_DEPS}) message(STATUS "${DEP}") endforeach() if (EXISTS "${QT_SHARE_DIR}/plugins/platforms") file(COPY "${QT_SHARE_DIR}/plugins/platforms" DESTINATION "${OUTPUT_DIR}") endif() if (EXISTS "${QT_SHARE_DIR}/plugins/platformthemes") file(COPY "${QT_SHARE_DIR}/plugins/platformthemes" DESTINATION "${OUTPUT_DIR}") endif() if (EXISTS "${QT_SHARE_DIR}/plugins/styles") file(COPY "${QT_SHARE_DIR}/plugins/styles" DESTINATION "${OUTPUT_DIR}") endif() if (EXISTS "${QT_SHARE_DIR}/plugins/imageformats") file(COPY "${QT_SHARE_DIR}/plugins/imageformats" DESTINATION "${OUTPUT_DIR}") endif() if (USE_SQL AND (EXISTS "${QT_SHARE_DIR}/plugins/sqldrivers")) file(COPY "${QT_SHARE_DIR}/plugins/sqldrivers" DESTINATION "${OUTPUT_DIR}") endif() if (USE_PRINT AND (EXISTS "${QT_SHARE_DIR}/plugins/printsupport")) file(COPY "${QT_SHARE_DIR}/plugins/printsupport" DESTINATION "${OUTPUT_DIR}") endif() if (USE_NETWORK AND (EXISTS "${QT_SHARE_DIR}/plugins/networkinformation")) file(COPY "${QT_SHARE_DIR}/plugins/networkinformation" DESTINATION "${OUTPUT_DIR}") endif() if (USE_MULTIMEDIA AND (EXISTS "${QT_SHARE_DIR}/plugins/multimedia")) file(COPY "${QT_SHARE_DIR}/plugins/multimedia" DESTINATION "${OUTPUT_DIR}") endif() if (EXISTS "${QT_SHARE_DIR}/translations") file(MAKE_DIRECTORY "${OUTPUT_DIR}/translations") if (EXISTS "${QT_SHARE_DIR}/translations/qtbase_ru.qm") file(COPY "${QT_SHARE_DIR}/translations/qtbase_ru.qm" DESTINATION "${OUTPUT_DIR}/translations") endif() if (EXISTS "${QT_SHARE_DIR}/translations/qtdeclarative_ru.qm") file(COPY "${QT_SHARE_DIR}/translations/qtdeclarative_ru.qm" DESTINATION "${OUTPUT_DIR}/translations") endif() if (USE_SERIALPORT AND (EXISTS "${QT_SHARE_DIR}/translations/qtserialport_ru.qm")) file(COPY "${QT_SHARE_DIR}/translations/qtserialport_ru.qm" DESTINATION "${OUTPUT_DIR}/translations") endif() if (USE_MULTIMEDIA AND (EXISTS "${QT_SHARE_DIR}/translations/qtmultimedia_ru.qm")) file(COPY "${QT_SHARE_DIR}/translations/qtmultimedia_ru.qm" DESTINATION "${OUTPUT_DIR}/translations") endif() endif() else() message(STATUS "'${TARGET_FILE}' not found. Exit.") endif()