aboutsummaryrefslogtreecommitdiffstats
path: root/cmake
diff options
context:
space:
mode:
authorCristian Adam <cristian.adam@qt.io>2020-02-05 19:38:18 +0100
committerAlessandro Portale <alessandro.portale@qt.io>2020-02-06 18:03:33 +0000
commit8d767a3a2139b710f97e3b14553aa98fdae1362f (patch)
treed00d83ca8fe20e4f0fc65bfb9c001f7003471060 /cmake
parentdecb6866b91cb0023ed71f7a5186520a8ce20d03 (diff)
CMake Deployment: Remove Dependencies component
- Install will also copy the dependencies. - Made the dependencies search recursive, not just two steps - Moved install code to a script, not having to escape quotes and dollars Change-Id: I6c5fb19e4094e9dcd4b339d5b90be6e7c5055223 Reviewed-by: Alessandro Portale <alessandro.portale@qt.io>
Diffstat (limited to 'cmake')
-rw-r--r--cmake/CMakeLists.txt101
-rw-r--r--cmake/InstallDependentSharedObjects.cmake.in150
2 files changed, 251 insertions, 0 deletions
diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt
new file mode 100644
index 0000000000..2d2d9f2b1b
--- /dev/null
+++ b/cmake/CMakeLists.txt
@@ -0,0 +1,101 @@
+# Deployment of Qt, Clang, C++ Runtime libraries is being done in this script.
+#
+# It should be included as a subdirectory as last because of CMake's
+# cmake_install.cmake script behviour of including subdirectories at the end
+# of the script, not respecting the order of install commands from CMakeLists.txt
+#
+# This way we are sure that all the binaries have been installed before.
+
+if (CMAKE_VERSION VERSION_GREATER_EQUAL 3.16)
+ get_target_property(moc_binary Qt5::moc IMPORTED_LOCATION)
+ get_filename_component(moc_dir "${moc_binary}" DIRECTORY)
+ get_filename_component(qt5_base_dir "${moc_dir}/../" ABSOLUTE)
+
+ if (MSVC AND NOT CMAKE_BUILD_TYPE STREQUAL "Debug")
+ set(exclusion_mask PATTERN "*d.dll" EXCLUDE)
+ endif()
+
+ if (WIN32)
+ set(qt5_plugin_dest_dir ${IDE_BIN_PATH}/plugins)
+ set(qt5_qml_dest_dir ${IDE_BIN_PATH}/qml)
+ elseif(APPLE)
+ set(qt5_plugin_dest_dir ${IDE_PLUGIN_PATH})
+ set(qt5_qml_dest_dir ${IDE_DATA_PATH}/../Imports/qtquick2)
+ else()
+ set(qt5_plugin_dest_dir ${IDE_LIBRARY_BASE_PATH}/Qt/plugins)
+ set(qt5_qml_dest_dir ${IDE_LIBRARY_BASE_PATH}/Qt/qml)
+ endif()
+
+ foreach(plugin
+ designer iconengines imageformats platforms platformthemes
+ printsupport qmltooling sqldrivers styles)
+ if(NOT EXISTS "${qt5_base_dir}/plugins/${plugin}")
+ continue()
+ endif()
+ install(
+ DIRECTORY "${qt5_base_dir}/plugins/${plugin}"
+ DESTINATION ${qt5_plugin_dest_dir}
+ ${exclusion_mask}
+ )
+ list(APPEND qt5_plugin_directories "${qt5_plugin_dest_dir}/${plugin}")
+ endforeach()
+
+ install(
+ DIRECTORY "${qt5_base_dir}/qml/"
+ DESTINATION ${qt5_qml_dest_dir}
+ PATTERN "qml/*"
+ ${exclusion_mask}
+ )
+
+ install(CODE "
+ function(create_qt_conf location base_dir)
+ get_filename_component(install_prefix \"\${CMAKE_INSTALL_PREFIX}\" ABSOLUTE)
+ file(RELATIVE_PATH qt_conf_binaries
+ \"\${install_prefix}/\${base_dir}\"
+ \"\${install_prefix}/${IDE_BIN_PATH}\"
+ )
+ if (NOT qt_conf_binaries)
+ set(qt_conf_binaries .)
+ endif()
+ file(RELATIVE_PATH qt_conf_plugins
+ \"\${install_prefix}/\${base_dir}\"
+ \"\${install_prefix}/${qt5_plugin_dest_dir}\"
+ )
+ file(RELATIVE_PATH qt_conf_qml
+ \"\${install_prefix}/\${base_dir}\"
+ \"\${install_prefix}/${qt5_qml_dest_dir}\"
+ )
+
+ file(WRITE \"\${CMAKE_INSTALL_PREFIX}/\${location}/qt.conf\"
+ \"[Paths]\n\"
+ \"Binaries=\${qt_conf_binaries}\n\"
+ \"Plugins=\${qt_conf_plugins}\n\"
+ \"Qml2Imports=\${qt_conf_qml}\n\"
+ )
+ endfunction()
+
+ if(APPLE)
+ create_qt_conf(\"${IDE_DATA_PATH}\" \"${IDE_DATA_PATH}/..\")
+ create_qt_conf(\"${IDE_LIBEXEC_PATH}\" \"${IDE_DATA_PATH}/..\")
+ else()
+ create_qt_conf(\"${IDE_APP_PATH}\" \"${IDE_APP_PATH}\")
+ create_qt_conf(\"${IDE_LIBEXEC_PATH}\" \"${IDE_LIBEXEC_PATH}\")
+ endif()
+
+ "
+ )
+
+ # Analyze the binaries and install missing dependencies if they are
+ # found the CMAKE_PREFIX_PATH e.g. Qt, Clang
+ configure_file(InstallDependentSharedObjects.cmake.in InstallDependentSharedObjects.cmake @ONLY)
+ install(SCRIPT ${CMAKE_CURRENT_BINARY_DIR}/InstallDependentSharedObjects.cmake)
+
+ if (MSVC)
+ set(CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS_SKIP ON)
+ include(InstallRequiredsystemLibraries)
+
+ install(PROGRAMS ${CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS}
+ DESTINATION ${IDE_APP_PATH}
+ )
+ endif()
+endif()
diff --git a/cmake/InstallDependentSharedObjects.cmake.in b/cmake/InstallDependentSharedObjects.cmake.in
new file mode 100644
index 0000000000..2149489080
--- /dev/null
+++ b/cmake/InstallDependentSharedObjects.cmake.in
@@ -0,0 +1,150 @@
+if (MINGW AND @CMAKE_CXX_COMPILER_ID@ MATCHES "Clang")
+ set(CMAKE_GET_RUNTIME_DEPENDENCIES_TOOL objdump)
+endif()
+if (WIN32)
+ set(filter_regex PRE_EXCLUDE_REGEXES "api-ms-.*|ext-ms-.*")
+elseif (APPLE)
+ set(filter_regex PRE_EXCLUDE_REGEXES "libiodbc.*|libpq.*")
+endif()
+
+get_filename_component(install_prefix "${CMAKE_INSTALL_PREFIX}" ABSOLUTE)
+
+# Get the dependencies of Qt's plugins
+foreach(plugin @qt5_plugin_directories@)
+ file(GLOB plugin_files "${install_prefix}/${plugin}/*@CMAKE_SHARED_LIBRARY_SUFFIX@")
+ list(APPEND qt5_plugin_files "${plugin_files}")
+endforeach()
+
+# Get the qml module dependencies
+file(GLOB_RECURSE qml_plugin_files "${install_prefix}/@qt5_qml_dest_dir@/*/*@CMAKE_SHARED_LIBRARY_SUFFIX@")
+list(APPEND qt5_plugin_files "${qml_plugin_files}")
+
+set(installed_EXECUTABLES_NOT_PREFIXED "@__QTC_INSTALLED_EXECUTABLES@")
+set(installed_LIBRARIES_NOT_PREFIXED "@__QTC_INSTALLED_LIBRARIES@")
+set(installed_MODULES_NOT_PREFIXED "@__QTC_INSTALLED_PLUGINS@")
+
+foreach(binary_type EXECUTABLES LIBRARIES MODULES)
+ foreach(element IN LISTS installed_${binary_type}_NOT_PREFIXED)
+ if (EXISTS "${install_prefix}/${element}")
+ list(APPEND installed_${binary_type} "${install_prefix}/${element}")
+ endif()
+ endforeach()
+endforeach()
+
+# Install first the dependencies, and continue to install the dependencies
+# of the installed dependencies e.g. libicu for libQt5Core on Linux.
+
+list(LENGTH installed_LIBRARIES installed_libraries_size)
+unset(qt_plugins_installed)
+
+while(installed_libraries_size GREATER 0)
+ foreach(binary_type EXECUTABLES LIBRARIES MODULES)
+ list(LENGTH installed_${binary_type} list_size)
+ if (NOT list_size EQUAL 0)
+ set(${binary_type}_TO_ANALYZE ${binary_type} "${installed_${binary_type}}")
+ else()
+ set(${binary_type}_TO_ANALYZE "")
+ endif()
+ endforeach()
+
+ file(GET_RUNTIME_DEPENDENCIES
+ UNRESOLVED_DEPENDENCIES_VAR unresolved_deps
+ RESOLVED_DEPENDENCIES_VAR resolved_deps
+ CONFLICTING_DEPENDENCIES_PREFIX conflicts
+ ${EXECUTABLES_TO_ANALYZE}
+ ${LIBRARIES_TO_ANALYZE}
+ ${MODULES_TO_ANALYZE}
+ DIRECTORIES
+ "${install_prefix}/@IDE_BIN_PATH@"
+ "${install_prefix}/@IDE_PLUGIN_PATH@"
+ "${install_prefix}/@IDE_LIBRARY_PATH@"
+ "${install_prefix}/@IDE_LIBRARY_BASE_PATH@/Qt/lib"
+ ${filter_regex}
+ )
+
+ # Clear for next step
+ set(installed_EXECUTABLES "")
+ set(installed_LIBRARIES "")
+ set(installed_MODULES "")
+
+ if (NOT qt_plugins_installed)
+ if (WIN32)
+ # Needed by QmlDesigner, QmlProfiler, but they are not referenced directly.
+ list(APPEND unresolved_deps libEGL.dll libGLESv2.dll)
+ endif()
+
+ set(qt_plugins_installed TRUE)
+ set(installed_MODULES "${qt5_plugin_files}")
+ endif()
+
+ list(REMOVE_DUPLICATES unresolved_deps)
+ list(REMOVE_DUPLICATES resolved_deps)
+
+ file(TO_CMAKE_PATH "@CMAKE_PREFIX_PATH@" prefix_path)
+
+ # Add parent link directory paths. Needed for e.g. MinGW choco libstdc++-6.dll
+ if (WIN32)
+ foreach(path "@CMAKE_CXX_IMPLICIT_LINK_DIRECTORIES@")
+ get_filename_component(parent_path "${path}" DIRECTORY)
+ list(APPEND prefix_path "${parent_path}")
+ endforeach()
+ endif()
+
+ # On Linux the Qt libraries might exist in the system, and they are passed
+ # as resolved, therefore scan the resolved dependencies too
+ if (NOT WIN32 AND NOT APPLE)
+ list(APPEND unresolved_deps "${resolved_deps}")
+ endif()
+
+ foreach(so IN LISTS unresolved_deps)
+
+ # Skip the installed dependencies
+ string(FIND "${so}" "${install_prefix}" found_prefix_path)
+ if (NOT found_prefix_path EQUAL -1)
+ continue()
+ endif()
+
+ # On Linux get the name of the resolved Qt dependency, this would come from ldconfig
+ # with the full path on the system
+ if (NOT APPLE AND NOT WIN32)
+ get_filename_component(so "${so}" NAME)
+ endif()
+
+ if (APPLE)
+ string(REPLACE "@rpath/" "" so "${so}")
+ get_filename_component(so_dir "${so}" DIRECTORY)
+ endif()
+
+ message(STATUS "Dependency: ${so}")
+ foreach(p IN LISTS prefix_path)
+ if (WIN32)
+ set(so_src "${p}/bin/${so}")
+ set(so_dest "${install_prefix}/@IDE_BIN_PATH@")
+ elseif(APPLE)
+ set(so_src "${p}/lib/${so}")
+ set(so_dest "${install_prefix}/@IDE_LIBRARY_PATH@/${so_dir}")
+ else()
+ set(so_src "${p}/lib/${so}")
+ if (p STREQUAL "@qt5_base_dir@")
+ set(so_dest "${install_prefix}/@IDE_LIBRARY_BASE_PATH@/Qt/lib")
+ else()
+ set(so_dest "${install_prefix}/@IDE_LIBRARY_PATH@")
+ endif()
+ endif()
+
+ message(STATUS "Looking at: ${so_src}")
+ if (EXISTS "${so_src}")
+ file(INSTALL "${so_src}" DESTINATION "${so_dest}" FOLLOW_SYMLINK_CHAIN)
+ if (APPLE)
+ get_filename_component(so "${so}" NAME)
+ endif()
+ list(APPEND installed_LIBRARIES "${so_dest}/${so}")
+ break()
+ endif()
+
+ endforeach()
+ endforeach()
+
+ list(LENGTH installed_LIBRARIES installed_libraries_size)
+
+endwhile()