421 lines
12 KiB
CMake
421 lines
12 KiB
CMake
#[[
|
||
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})
|
||
endif()
|
||
|
||
if(NOT DEFINED QMSETUP_APPLOCAL_DEPS_PATHS_RELWITHDEBINFO)
|
||
set(QMSETUP_APPLOCAL_DEPS_PATHS_RELWITHDEBINFO ${QMSETUP_APPLOCAL_DEPS_PATHS_RELEASE})
|
||
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.
|
||
|
||
WARNING: This function is deprecated.
|
||
|
||
qm_win_record_deps(<target>)
|
||
]] #
|
||
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 "$<TARGET_PROPERTY:${_item},LOCATION_$<CONFIG>>")
|
||
else()
|
||
get_target_property(_type ${_item} TYPE)
|
||
|
||
if(NOT ${_type} MATCHES "SHARED_LIBRARY")
|
||
continue()
|
||
endif()
|
||
|
||
set(_path "$<TARGET_FILE:${_item}>")
|
||
endif()
|
||
|
||
list(APPEND _paths ${_path})
|
||
endforeach()
|
||
|
||
if(NOT _paths)
|
||
return()
|
||
endif()
|
||
|
||
set(_deps_file "${CMAKE_CURRENT_BINARY_DIR}/${_target}_deps_$<CONFIG>.txt")
|
||
file(GENERATE OUTPUT ${_deps_file} CONTENT "$<JOIN:${_paths},\n>")
|
||
set_target_properties(${_target} PROPERTIES QMSETUP_DEPENDENCIES_FILE ${_deps_file})
|
||
endfunction()
|
||
|
||
#[[
|
||
Automatically copy dependencies for Windows Executables after build.
|
||
|
||
qm_win_applocal_deps(<target>
|
||
[CUSTOM_TARGET <target>]
|
||
[FORCE] [VERBOSE]
|
||
[EXTRA_SEARCHING_PATHS <path...>]
|
||
[EXTRA_TARGETS <target...>]
|
||
[OUTPUT_DIR <dir>]
|
||
[EXCLUDE <pattern...>]
|
||
)
|
||
]] #
|
||
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 "$<TARGET_FILE_DIR:${_target}>")
|
||
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 "--linkdirs-file" "${_item}")
|
||
endforeach()
|
||
|
||
foreach(_item IN LISTS FUNC_EXCLUDE)
|
||
list(APPEND _args -e ${_item})
|
||
endforeach()
|
||
|
||
list(APPEND _args "$<TARGET_FILE:${_target}>")
|
||
|
||
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(<install_dir>
|
||
[FORCE] [STANDARD] [VERBOSE]
|
||
[LIBRARY_DIR <dir>]
|
||
[EXTRA_LIBRARIES <path>...]
|
||
[EXTRA_PLUGIN_PATHS <path>...]
|
||
[EXTRA_SEARCHING_PATHS <path>...]
|
||
|
||
[PLUGINS <plugin>...]
|
||
[PLUGIN_DIR <dir>]
|
||
|
||
[QML <qml>...]
|
||
[QML_DIR <dir>]
|
||
|
||
[WIN_TARGETS <target>...]
|
||
|
||
[COMMENT <comment>]
|
||
)
|
||
|
||
PLUGINS: Qt plugins, in format of `<category>/<name>`
|
||
PLUGIN_DIR: Qt plugins destination
|
||
EXTRA_PLUGIN_PATHS: Extra Qt plugins searching paths
|
||
QML: Qt qml directories
|
||
QML_DIR: Qt qml destination
|
||
LIBRARY_DIR: Library destination
|
||
EXTRA_LIBRARIES: Extra library names list to deploy
|
||
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 EXTRA_LIBRARIES)
|
||
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)
|
||
qm_get_executable_location(Qt${QT_VERSION_MAJOR}::qmake _qmake_path)
|
||
set(QT_QMAKE_EXECUTABLE "${_qmake_path}" CACHE FILEPATH "Path to qmake executable" FORCE)
|
||
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")
|
||
|
||
# Prepare commands
|
||
set(_args
|
||
-i "${_install_dir}"
|
||
-m "${QMSETUP_CORECMD_EXECUTABLE}"
|
||
--plugindir "${_plugin_dir}"
|
||
--libdir "${_lib_dir}"
|
||
--qmldir "${_qml_dir}"
|
||
)
|
||
set(_searching_paths)
|
||
|
||
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)
|
||
get_filename_component(_item ${_item} ABSOLUTE)
|
||
list(APPEND _searching_paths ${_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 _searching_paths ${_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 _searching_paths ${_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 _searching_paths ${_item})
|
||
endforeach()
|
||
endif()
|
||
|
||
foreach(_item IN LISTS _searching_paths)
|
||
list(APPEND _args -L "${_item}")
|
||
endforeach()
|
||
|
||
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 "--linkdirs-file" "${_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 extra libraries
|
||
foreach(_item IN LISTS _searching_paths)
|
||
foreach(_lib IN LISTS FUNC_EXTRA_LIBRARIES)
|
||
set(_path "${_item}/${_lib}")
|
||
|
||
if((EXISTS ${_path}) AND(NOT IS_DIRECTORY ${_path}))
|
||
list(APPEND _args --copy ${_path} ${_lib_dir})
|
||
endif()
|
||
endforeach()
|
||
endforeach()
|
||
|
||
# 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() |