diff options
Diffstat (limited to 'cmake/QtRpathHelpers.cmake')
-rw-r--r-- | cmake/QtRpathHelpers.cmake | 133 |
1 files changed, 133 insertions, 0 deletions
diff --git a/cmake/QtRpathHelpers.cmake b/cmake/QtRpathHelpers.cmake new file mode 100644 index 0000000000..eeb837df8f --- /dev/null +++ b/cmake/QtRpathHelpers.cmake @@ -0,0 +1,133 @@ +function(qt_compute_relative_rpath_base rpath install_location out_var) + set(install_lib_dir_absolute "${CMAKE_INSTALL_PREFIX}/${INSTALL_LIBDIR}") + get_filename_component(rpath_absolute "${rpath}" + ABSOLUTE BASE_DIR "${install_lib_dir_absolute}") + + if(NOT IS_ABSOLUTE) + set(install_location_absolute "${CMAKE_INSTALL_PREFIX}/${install_location}") + endif() + # Compute relative rpath from where the target will be installed, to the place where libraries + # will be placed (INSTALL_LIBDIR). + file(RELATIVE_PATH rpath_relative "${install_location_absolute}" "${rpath_absolute}") + + if("${rpath_relative}" STREQUAL "") + # file(RELATIVE_PATH) returns an empty string if the given absolute paths are equal + set(rpath_relative ".") + endif() + + # Prepend $ORIGIN / @loader_path style tokens (qmake's QMAKE_REL_RPATH_BASE), to make the + # relative rpaths work. qmake does this automatically when generating a project, so it wasn't + # needed in the .prf files, but for CMake we need to prepend them ourselves. + if(APPLE) + set(rpath_rel_base "@loader_path") + elseif(LINUX) + set(rpath_rel_base "$ORIGIN") + else() + message(WARNING "No known RPATH_REL_BASE for target platform.") + set(rpath_rel_base "NO_KNOWN_RPATH_REL_BASE") + endif() + + if(rpath_relative STREQUAL ".") + set(rpath_relative "${rpath_rel_base}") + else() + set(rpath_relative "${rpath_rel_base}/${rpath_relative}") + endif() + + set("${out_var}" "${rpath_relative}" PARENT_SCOPE) +endfunction() + +# Applies necessary rpaths to a target upon target installation. +# No-op when targeting Windows, Android, or non-prefix builds. +# +# If no RELATIVE_RPATH option is given, embeds an absolute path rpath to ${INSTALL_LIBDIR}. +# If RELATIVE_RPATH is given, the INSTALL_PATH value is to compute the relative path from +# ${INSTALL_LIBDIR} to wherever the target will be installed (the value of INSTALL_PATH). +# It's the equivalent of qmake's relative_qt_rpath. +# INSTALL_PATH is used to implement the equivalent of qmake's $$qtRelativeRPathBase(). +# +# A cache variable QT_DISABLE_RPATH can be set to disable embedding any rpaths when installing. +function(qt_apply_rpaths) + # No rpath support for win32 and android. Also no need to apply rpaths when doing a non-prefix + # build. + if(NOT QT_WILL_INSTALL OR WIN32 OR ANDROID) + return() + endif() + + # Rpaths xplicitly disabled (like for uikit), equivalent to qmake's no_qt_rpath. + if(QT_DISABLE_RPATH) + return() + endif() + + qt_parse_all_arguments(arg "qt_apply_rpaths" "RELATIVE_RPATH" "TARGET;INSTALL_PATH" "" ${ARGN}) + if(NOT arg_TARGET) + message(FATAL_ERRO "No target given to qt_apply_rpaths.") + else() + set(target "${arg_TARGET}") + endif() + + # If a target is not built (which can happen for tools when crosscompiling, we shouldn't try + # to apply properties. + if(NOT TARGET "${target}") + return() + endif() + + # Protect against interface libraries. + get_target_property(target_type "${target}" TYPE) + if (target_type STREQUAL "INTERFACE_LIBRARY") + return() + endif() + + if(NOT arg_INSTALL_PATH) + message(FATAL_ERROR "No INSTALL_PATH given to qt_apply_rpaths.") + endif() + + set(rpaths "") + + # Modify the install path to contain the nested structure of a framework. + get_target_property(is_framework "${target}" FRAMEWORK) + if(is_framework) + if(UIKIT) + # Shallow framework + string(APPEND arg_INSTALL_PATH "/Qt${target}.framework") + else() + # Full framework + string(APPEND arg_INSTALL_PATH "/Qt${target}.framework/Versions/Current") + endif() + endif() + + # Same but for an app bundle. + get_target_property(is_bundle "${target}" MACOSX_BUNDLE) + if(is_bundle AND NOT is_framework) + if(UIKIT) + # Shallow bundle + string(APPEND arg_INSTALL_PATH "/${target}.app") + else() + # Full bundle + string(APPEND arg_INSTALL_PATH "/${target}.app/Contents/MacOS") + endif() + endif() + + # Somewhat similar to mkspecs/features/qt.prf + if(arg_RELATIVE_RPATH) + qt_compute_relative_rpath_base( + "${_default_install_rpath}" "${arg_INSTALL_PATH}" relative_rpath) + list(APPEND rpaths "${relative_rpath}") + else() + list(APPEND rpaths "${_default_install_rpath}") + endif() + + # Somewhat similar to mkspecs/features/qt_build_extra.prf. + foreach(rpath ${QT_EXTRA_RPATHS}) + if(IS_ABSOLUTE) + list(APPEND rpaths "${rpath}") + else() + qt_compute_relative_rpath_base("${rpath}" "${arg_INSTALL_PATH}" relative_rpath) + list(APPEND rpaths "${relative_rpath}") + endif() + endforeach() + + if(rpaths) + list(REMOVE_DUPLICATES rpaths) + set_property(TARGET "${target}" APPEND PROPERTY INSTALL_RPATH ${rpaths}) + endif() +endfunction() |