abf7239541
This works around linking issues when doing yocto non-prefix Qt builds, because CMake does not add -rpath-link flags even though it probably should. Task-number: QTBUG-86533 Change-Id: Iaaf246ac71ca05d9369ceb6eb9c4a1e206c42839 Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Joerg Bornemann <joerg.bornemann@qt.io>
139 lines
5.0 KiB
CMake
139 lines
5.0 KiB
CMake
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(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_ERROR "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)
|
|
if(QT_WILL_INSTALL)
|
|
set(prop_name "INSTALL_RPATH")
|
|
else()
|
|
set(prop_name "BUILD_RPATH")
|
|
endif()
|
|
set_property(TARGET "${target}" APPEND PROPERTY "${prop_name}" ${rpaths})
|
|
endif()
|
|
endfunction()
|