Files
FrameAssistant/cmake/bundle-install.cmake.in
T
matzmanandClaude Opus 5.5 b823ff321e Bundled builds: ship Qt WebEngine (helper process, resources)
When a bundled library is Qt WebEngine, the bundler also installs
QtWebEngineProcess (plus its libraries) to libexec/, the resources and
the en-US/de locales, and points qt.conf at them. The cross image unpacks
the arm64 QtWebEngineProcess (its package can't be co-installed with the
amd64 one). Experiment for DSH-1: the Frame's system WebEngine (6.7.0,
built against FFmpeg 6) can't be loaded.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 22:35:09 +02:00

203 lines
8.3 KiB
CMake

# 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 "$<TARGET_FILE:Qt6::qmlimportscanner>" -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")