# Generated from cmake/bundle-install.cmake.in by vrdash_bundle_qt(). Runs at install time, # once for all dashboard executables. cmake_policy(VERSION 3.22) get_filename_component(prefix "$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}" ABSOLUTE) set(executables "") foreach(name @executables@) list(APPEND executables "${prefix}/@CMAKE_INSTALL_BINDIR@/${name}") endforeach() set(libdir "${prefix}/@CMAKE_INSTALL_LIBDIR@") set(plugindir "${prefix}/plugins") set(qmldir "${prefix}/qml") set(qt_plugins "@QT6_INSTALL_PREFIX@/@QT6_INSTALL_PLUGINS@") set(qt_qml "@QT6_INSTALL_PREFIX@/@QT6_INSTALL_QML@") set(patchelf "@VRDASH_PATCHELF@") set(exclude "@bundle_exclude@") set(webengine_process "@webengine_process@") set(webengine_resources "@webengine_resources@") set(webengine_locales "@webengine_locales@") message(STATUS "Bundling Qt into ${prefix}") # --- QML modules the UI imports (transitively) ------------------------------------------- set(modules "") foreach(root @qml_dirs@) execute_process( COMMAND "$" -rootPath "${root}" -importPath "${qt_qml}" OUTPUT_VARIABLE imports_json RESULT_VARIABLE result) if(NOT result EQUAL 0) message(FATAL_ERROR "qmlimportscanner failed on ${root} (${result})") endif() string(JSON count LENGTH "${imports_json}") if(count EQUAL 0) continue() endif() math(EXPR last "${count} - 1") foreach(i RANGE ${last}) string(JSON type ERROR_VARIABLE err GET "${imports_json}" ${i} type) string(JSON path ERROR_VARIABLE err GET "${imports_json}" ${i} path) if(type STREQUAL "module" AND path AND path MATCHES "^${qt_qml}/") list(APPEND modules "${path}") endif() endforeach() endforeach() list(REMOVE_DUPLICATES modules) set(qml_plugins "") foreach(module IN LISTS modules) file(RELATIVE_PATH rel "${qt_qml}" "${module}") # Only the module's own files; submodules are listed separately if they are needed. file(GLOB files LIST_DIRECTORIES false "${module}/*") file(INSTALL ${files} DESTINATION "${qmldir}/${rel}" FOLLOW_SYMLINK_CHAIN) file(GLOB so_files "${qmldir}/${rel}/*.so") list(APPEND qml_plugins ${so_files}) endforeach() # --- Qt plugins -------------------------------------------------------------------------- set(qt_plugin_files "") foreach(pattern @VRDASH_BUNDLE_PLUGINS@) file(GLOB files "${qt_plugins}/${pattern}") foreach(file IN LISTS files) file(RELATIVE_PATH rel "${qt_plugins}" "${file}") get_filename_component(dir "${rel}" DIRECTORY) file(INSTALL "${file}" DESTINATION "${plugindir}/${dir}") list(APPEND qt_plugin_files "${plugindir}/${rel}") endforeach() endforeach() # --- Shared libraries needed by executable + plugins -------------------------------------- set(CMAKE_GET_RUNTIME_DEPENDENCIES_PLATFORM "linux+elf") set(CMAKE_GET_RUNTIME_DEPENDENCIES_TOOL "objdump") set(CMAKE_GET_RUNTIME_DEPENDENCIES_COMMAND "@objdump@") file(GET_RUNTIME_DEPENDENCIES EXECUTABLES ${executables} MODULES ${qt_plugin_files} ${qml_plugins} DIRECTORIES "@qt_libdir@" "${libdir}" PRE_EXCLUDE_REGEXES ${exclude} # matched against DT_NEEDED names POST_EXCLUDE_REGEXES "^${libdir}/" RESOLVED_DEPENDENCIES_VAR resolved UNRESOLVED_DEPENDENCIES_VAR unresolved) # --- Qt WebEngine: helper process (and its libraries), resources, locales ---------------- # Only if a dashboard uses it. Found through qt.conf (LibraryExecutables, Data, # Translations; written below). set(helper_executables "") if(resolved MATCHES "libQt6WebEngineCore") message(STATUS "Bundling Qt WebEngine (${webengine_process})") file(INSTALL "${webengine_process}" DESTINATION "${prefix}/libexec" FOLLOW_SYMLINK_CHAIN) list(APPEND helper_executables "${prefix}/libexec/QtWebEngineProcess") file(GET_RUNTIME_DEPENDENCIES EXECUTABLES ${helper_executables} DIRECTORIES "@qt_libdir@" "${libdir}" PRE_EXCLUDE_REGEXES ${exclude} POST_EXCLUDE_REGEXES "^${libdir}/" RESOLVED_DEPENDENCIES_VAR helper_resolved UNRESOLVED_DEPENDENCIES_VAR helper_unresolved) list(APPEND resolved ${helper_resolved}) list(APPEND unresolved ${helper_unresolved}) list(REMOVE_DUPLICATES resolved) list(REMOVE_DUPLICATES unresolved) file(GLOB files LIST_DIRECTORIES false "${webengine_resources}/*") file(INSTALL ${files} DESTINATION "${prefix}/resources") foreach(locale @VRDASH_WEBENGINE_LOCALES@) file(INSTALL "${webengine_locales}/${locale}.pak" DESTINATION "${prefix}/translations/qtwebengine_locales") endforeach() endif() if(unresolved) message(WARNING "Unresolved (expected on target system): ${unresolved}") endif() file(INSTALL ${resolved} DESTINATION "${libdir}" FOLLOW_SYMLINK_CHAIN) # --- Relative RPATHs ------------------------------------------------------------------------ # DT_RUNPATH of the executable does not apply to transitive dependencies, so every bundled # ELF file needs its own path back to lib/. function(set_rpath file rpath) execute_process(COMMAND "${patchelf}" --set-rpath "${rpath}" "${file}" RESULT_VARIABLE rc) if(NOT rc EQUAL 0) message(FATAL_ERROR "patchelf failed on ${file}") endif() endfunction() file(GLOB bundled_libs "${libdir}/*.so*") foreach(lib IN LISTS bundled_libs) if(NOT IS_SYMLINK "${lib}") set_rpath("${lib}" "\$ORIGIN") endif() endforeach() foreach(file IN LISTS qt_plugin_files qml_plugins helper_executables) get_filename_component(dir "${file}" DIRECTORY) file(RELATIVE_PATH rel "${dir}" "${libdir}") set_rpath("${file}" "\$ORIGIN/${rel}") endforeach() # --- License files of everything bundled ---------------------------------------------- # Bundled libraries come from Debian packages: ship each package's copyright file and # the common license texts they reference (LGPL/GPL/...), as their licenses require. find_program(dpkg dpkg) if(dpkg) set(docdir "${prefix}/@CMAKE_INSTALL_DOCDIR@/third-party") set(packages "") foreach(file IN LISTS resolved qt_plugin_files qml_plugins helper_executables) # Ask dpkg about the original file: map installed plugins back, resolve # symlinks and /lib -> /usr/lib (usrmerge: packages register /usr paths). string(REPLACE "${plugindir}" "${qt_plugins}" original "${file}") string(REPLACE "${qmldir}" "${qt_qml}" original "${original}") if(file STREQUAL "${prefix}/libexec/QtWebEngineProcess") set(original "${webengine_process}") endif() file(REAL_PATH "${original}" original) execute_process(COMMAND "${dpkg}" -S "${original}" OUTPUT_VARIABLE owner ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE) string(REGEX REPLACE ":.*" "" owner "${owner}") if(owner) list(APPEND packages "${owner}") endif() endforeach() list(REMOVE_DUPLICATES packages) set(licenses "") foreach(package IN LISTS packages) set(copyright "/usr/share/doc/${package}/copyright") if(EXISTS "${copyright}") file(INSTALL "${copyright}" DESTINATION "${docdir}" RENAME "${package}.copyright" FOLLOW_SYMLINK_CHAIN) file(STRINGS "${copyright}" refs REGEX "/usr/share/common-licenses/[A-Za-z0-9.+-]+") foreach(ref IN LISTS refs) string(REGEX MATCHALL "/usr/share/common-licenses/[A-Za-z0-9.+-]+" paths "${ref}") list(APPEND licenses ${paths}) endforeach() endif() endforeach() list(REMOVE_DUPLICATES licenses) foreach(license IN LISTS licenses) string(REGEX REPLACE "[.]$" "" license "${license}") if(EXISTS "${license}") file(INSTALL "${license}" DESTINATION "${docdir}/common-licenses" FOLLOW_SYMLINK_CHAIN) endif() endforeach() list(LENGTH packages n_packages) message(STATUS "Collected copyright files of ${n_packages} Debian packages") else() message(WARNING "dpkg not found: license files of bundled libraries not collected") endif() file(WRITE "${prefix}/@CMAKE_INSTALL_BINDIR@/qt.conf" "[Paths] Prefix = .. Libraries = @CMAKE_INSTALL_LIBDIR@ Plugins = plugins QmlImports = qml LibraryExecutables = libexec Data = . Translations = translations ") list(LENGTH resolved n_libs) list(LENGTH modules n_modules) list(LENGTH qt_plugin_files n_plugins) message(STATUS "Bundled ${n_libs} libraries, ${n_plugins} Qt plugins, ${n_modules} QML modules")