#[[ Warning: This module depends on `qmcorecmd` after installation. ]] # if(NOT QMSETUP_CORECMD_EXECUTABLE) message(FATAL_ERROR "QMSETUP_CORECMD_EXECUTABLE not defined. Add find_package(qmsetup) to CMake first.") endif() if(NOT DEFINED QMSETUP_APPLOCAL_DEPS_PATHS) set(QMSETUP_APPLOCAL_DEPS_PATHS) endif() if(NOT DEFINED QMSETUP_APPLOCAL_DEPS_PATHS_DEBUG) set(QMSETUP_APPLOCAL_DEPS_PATHS_DEBUG ${QMSETUP_APPLOCAL_DEPS_PATHS}) endif() if(NOT DEFINED QMSETUP_APPLOCAL_DEPS_PATHS_RELEASE) set(QMSETUP_APPLOCAL_DEPS_PATHS_RELEASE ${QMSETUP_APPLOCAL_DEPS_PATHS_RELEASE}) endif() if(NOT DEFINED QMSETUP_APPLOCAL_DEPS_PATHS_RELWITHDEBINFO) set(QMSETUP_APPLOCAL_DEPS_PATHS_RELWITHDEBINFO ${QMSETUP_APPLOCAL_DEPS_PATHS}) endif() if(NOT DEFINED QMSETUP_APPLOCAL_DEPS_PATHS_MINSIZEREL) set(QMSETUP_APPLOCAL_DEPS_PATHS_MINSIZEREL ${QMSETUP_APPLOCAL_DEPS_PATHS_RELEASE}) endif() include_guard(DIRECTORY) #[[ Record searching paths for Windows Executables, must be called before calling `qm_win_applocal_deps` or `qm_deploy_directory` if your project supports Windows. qm_win_record_deps() ]] # function(qm_win_record_deps _target) if(NOT WIN32) return() endif() set(_paths) get_target_property(_link_libraries ${_target} LINK_LIBRARIES) foreach(_item IN LISTS _link_libraries) if(NOT TARGET ${_item}) continue() endif() get_target_property(_imported ${_item} IMPORTED) if(_imported) get_target_property(_path ${_item} LOCATION) if(NOT _path OR NOT ${_path} MATCHES "\\.dll$") continue() endif() set(_path "$>") else() get_target_property(_type ${_item} TYPE) if(NOT ${_type} MATCHES "SHARED_LIBRARY") continue() endif() set(_path "$") endif() list(APPEND _paths ${_path}) endforeach() if(NOT _paths) return() endif() set(_deps_file "${CMAKE_CURRENT_BINARY_DIR}/${_target}_deps_$.txt") file(GENERATE OUTPUT ${_deps_file} CONTENT "$") set_target_properties(${_target} PROPERTIES QMSETUP_DEPENDENCIES_FILE ${_deps_file}) endfunction() #[[ Automatically copy dependencies for Windows Executables after build. qm_win_applocal_deps( [CUSTOM_TARGET ] [FORCE] [VERBOSE] [EXTRA_SEARCHING_PATHS ] [EXTRA_TARGETS ] [OUTPUT_DIR ] [EXCLUDE ] ) ]] # function(qm_win_applocal_deps _target) if(NOT WIN32) return() endif() set(options FORCE VERBOSE) set(oneValueArgs TARGET CUSTOM_TARGET OUTPUT_DIR) set(multiValueArgs EXTRA_SEARCHING_PATHS EXTRA_TARGETS EXCLUDE) cmake_parse_arguments(FUNC "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) # Get output directory and deploy target set(_out_dir) set(_deploy_target) if(FUNC_CUSTOM_TARGET) set(_deploy_target ${FUNC_CUSTOM_TARGET}) if(NOT TARGET ${_deploy_target}) add_custom_target(${_deploy_target}) endif() else() set(_deploy_target ${_target}) endif() if(FUNC_OUTPUT_DIR) set(_out_dir ${FUNC_OUTPUT_DIR}) else() set(_out_dir "$") endif() if(NOT _out_dir) message(FATAL_ERROR "qm_win_applocal_deps: cannot determine output directory.") endif() # Get dep files set(_dep_files) _qm_win_get_all_dep_files(_dep_files ${_target}) foreach(_item IN LISTS FUNC_EXTRA_TARGETS) _qm_win_get_all_dep_files(_dep_files ${_item}) endforeach() # Prepare command set(_args) if(FUNC_FORCE) list(APPEND _args -f) endif() if(FUNC_VERBOSE) list(APPEND _args -V) endif() # Add extra searching paths foreach(_item IN LISTS FUNC_EXTRA_SEARCHING_PATHS) list(APPEND _args "-L${_item}") endforeach() # Add global extra searching paths if(CMAKE_BUILD_TYPE) string(TOUPPER ${CMAKE_BUILD_TYPE} _build_type_upper) if(QMSETUP_APPLOCAL_DEPS_PATHS_${_build_type_upper}) foreach(_item IN LISTS QMSETUP_APPLOCAL_DEPS_PATHS_${_build_type_upper}) get_filename_component(_item ${_item} ABSOLUTE BASE_DIR ${CMAKE_SOURCE_DIR}) list(APPEND _args "-L${_item}") endforeach() elseif(QMSETUP_APPLOCAL_DEPS_PATHS) foreach(_item IN LISTS QMSETUP_APPLOCAL_DEPS_PATHS) get_filename_component(_item ${_item} ABSOLUTE BASE_DIR ${CMAKE_SOURCE_DIR}) list(APPEND _args "-L${_item}") endforeach() endif() else() foreach(_item IN LISTS QMSETUP_APPLOCAL_DEPS_PATHS) get_filename_component(_item ${_item} ABSOLUTE BASE_DIR ${CMAKE_SOURCE_DIR}) list(APPEND _args "-L${_item}") endforeach() endif() foreach(_item IN LISTS _dep_files) list(APPEND _args "-@${_item}") endforeach() foreach(_item IN LISTS FUNC_EXCLUDE) list(APPEND _args -e ${_item}) endforeach() list(APPEND _args "$") add_custom_command(TARGET ${_deploy_target} POST_BUILD COMMAND ${QMSETUP_CORECMD_EXECUTABLE} deploy ${_args} WORKING_DIRECTORY ${_out_dir} VERBATIM ) endfunction() #[[ Add deploy command when install project, not available in debug mode. qm_deploy_directory( [FORCE] [STANDARD] [VERBOSE] [LIBRARY_DIR ] [EXTRA_PLUGIN_PATHS ...] [EXTRA_SEARCHING_PATHS ...] [PLUGINS ...] [PLUGIN_DIR ] [QML ...] [QML_DIR ] [WIN_TARGETS ...] [COMMENT ] ) PLUGINS: Qt plugins, in format of `/` PLUGIN_DIR: Qt plugins destination EXTRA_PLUGIN_PATHS: Extra Qt plugins searching paths QML: Qt qml directories QML_DIR: Qt qml destination LIBRARY_DIR: Extra library destination EXTRA_SEARCHING_PATHS: Extra library searching paths ]] # function(qm_deploy_directory _install_dir) set(options FORCE STANDARD VERBOSE) set(oneValueArgs LIBRARY_DIR PLUGIN_DIR QML_DIR COMMENT) set(multiValueArgs EXTRA_PLUGIN_PATHS PLUGINS QML WIN_TARGETS EXTRA_SEARCHING_PATHS) cmake_parse_arguments(FUNC "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) # Get qmake if((FUNC_PLUGINS OR FUNC_QML) AND NOT DEFINED QT_QMAKE_EXECUTABLE) if(TARGET Qt${QT_VERSION_MAJOR}::qmake) get_target_property(QT_QMAKE_EXECUTABLE Qt${QT_VERSION_MAJOR}::qmake IMPORTED_LOCATION) elseif((FUNC_PLUGINS AND NOT FUNC_EXTRA_PLUGIN_PATHS) OR FUNC_QML) message(FATAL_ERROR "qm_deploy_directory: qmake not defined. Add find_package(Qt5 COMPONENTS Core) to CMake to enable.") endif() endif() # Set values qm_set_value(_lib_dir FUNC_LIBRARY_DIR "${_install_dir}/${QMSETUP_SHARED_LIBRARY_CATEGORY}") qm_set_value(_plugin_dir FUNC_PLUGIN_DIR "${_install_dir}/plugins") qm_set_value(_qml_dir FUNC_QML_DIR "${_install_dir}/qml") get_filename_component(_lib_dir ${_lib_dir} ABSOLUTE BASE_DIR ${_install_dir}) get_filename_component(_plugin_dir ${_plugin_dir} ABSOLUTE BASE_DIR ${_install_dir}) # Prepare commands set(_args -i "${_install_dir}" -m "${QMSETUP_CORECMD_EXECUTABLE}" --plugindir "${_plugin_dir}" --libdir "${_lib_dir}" --qmldir "${_qml_dir}" ) if(QT_QMAKE_EXECUTABLE) list(APPEND _args --qmake "${QT_QMAKE_EXECUTABLE}") endif() # Add Qt plugins foreach(_item IN LISTS FUNC_PLUGINS) list(APPEND _args --plugin "${_item}") endforeach() # Add QML modules foreach(_item IN LISTS FUNC_QML) list(APPEND _args --qml "${_item}") endforeach() # Add extra plugin paths foreach(_item IN LISTS FUNC_EXTRA_PLUGIN_PATHS) list(APPEND _args --extra "${_item}") endforeach() # Add extra searching paths foreach(_item IN LISTS FUNC_EXTRA_SEARCHING_PATHS) list(APPEND _args -L "${_item}") endforeach() # Add global extra searching paths if(CMAKE_BUILD_TYPE) string(TOUPPER ${CMAKE_BUILD_TYPE} _build_type_upper) if(QMSETUP_APPLOCAL_DEPS_PATHS_${_build_type_upper}) foreach(_item IN LISTS QMSETUP_APPLOCAL_DEPS_PATHS_${_build_type_upper}) get_filename_component(_item ${_item} ABSOLUTE BASE_DIR ${CMAKE_SOURCE_DIR}) list(APPEND _args -L "${_item}") endforeach() elseif(QMSETUP_APPLOCAL_DEPS_PATHS) foreach(_item IN LISTS QMSETUP_APPLOCAL_DEPS_PATHS) get_filename_component(_item ${_item} ABSOLUTE BASE_DIR ${CMAKE_SOURCE_DIR}) list(APPEND _args -L "${_item}") endforeach() endif() else() foreach(_item IN LISTS QMSETUP_APPLOCAL_DEPS_PATHS) get_filename_component(_item ${_item} ABSOLUTE BASE_DIR ${CMAKE_SOURCE_DIR}) list(APPEND _args -L "${_item}") endforeach() endif() if(WIN32) set(_dep_files) if(FUNC_WIN_TARGETS) _qm_win_get_all_dep_files(_dep_files ${FUNC_WIN_TARGETS}) endif() foreach(_item IN LISTS _dep_files) list(APPEND _args -@ "${_item}") endforeach() set(_script_quoted "cmd /c \"${QMSETUP_MODULES_DIR}/scripts/windeps.bat\"") else() set(_script_quoted "bash \"${QMSETUP_MODULES_DIR}/scripts/unixdeps.sh\"") endif() # Add options if(FUNC_FORCE) list(APPEND _args "-f") endif() if(FUNC_STANDARD) list(APPEND _args "-s") endif() if(FUNC_VERBOSE) list(APPEND _args "-V") endif() set(_args_quoted) foreach(_item IN LISTS _args) set(_args_quoted "${_args_quoted}\"${_item}\" ") endforeach() set(_comment_code) if(FUNC_COMMENT) set(_comment_code "message(STATUS \"${FUNC_COMMENT}\")") endif() # Add install command install(CODE " ${_comment_code} execute_process( COMMAND ${_script_quoted} ${_args_quoted} WORKING_DIRECTORY \"${_install_dir}\" COMMAND_ERROR_IS_FATAL ANY ) ") endfunction() # ---------------------------------- # Private functions # ---------------------------------- function(_qm_win_get_all_dep_files _out) # Get searching paths macro(get_recursive_dynamic_dependencies _current_target _result) get_target_property(_deps ${_current_target} LINK_LIBRARIES) if(_deps) foreach(_dep IN LISTS _deps) if(NOT TARGET ${_dep}) continue() endif() get_target_property(_type ${_dep} TYPE) if(_type STREQUAL "SHARED_LIBRARY") list(APPEND ${_result} ${_dep}) endif() get_recursive_dynamic_dependencies(${_dep} ${_result}) endforeach() endif() endmacro() set(_visited_targets ${ARGN}) foreach(_target ${ARGN}) set(_all_deps) get_recursive_dynamic_dependencies(${_target} _all_deps) foreach(_cur_dep IN LISTS _all_deps) if(${_cur_dep} IN_LIST _visited_targets) continue() endif() list(APPEND _visited_targets ${_cur_dep}) endforeach() endforeach() set(_dep_files) foreach(_target IN LISTS _visited_targets) # Add file get_target_property(_file ${_target} QMSETUP_DEPENDENCIES_FILE) if(NOT _file) continue() endif() list(APPEND _dep_files ${_file}) endforeach() set(${_out} ${_dep_files} PARENT_SCOPE) endfunction()