diff --git a/mkspecs/features/mac/default_post.prf b/mkspecs/features/mac/default_post.prf
index 7100717b78fabe8c8fcbd2cb0f219b596ea5620e..30960e66ddcc0146817cebc6847061ebff482b05 100644
--- a/mkspecs/features/mac/default_post.prf
+++ b/mkspecs/features/mac/default_post.prf
@@ -22,31 +22,6 @@ qt {
             QMAKE_LFLAGS   += -stdlib=libstdc++
         }
     }
-    # If Qt was built with shared libraries with rpath support and project does
-    # not specify own rpaths (including empty list) add one pointing to Qt
-    # libraries. This applies only to apps, since all loaded libraries inherit
-    # rpaths from current process executable.
-    else:!if(host_build:force_bootstrap):equals(TEMPLATE, app):!defined(QMAKE_RPATHDIR, var):contains(QT_CONFIG, rpath) {
-        # If app is expected to be installed into the Qt prefix build, use
-        # relative path, so all SDK tools and examples work when relocated.
-        prefix_build:defined(target.path, var):\
-            contains(target.path, "$$re_escape($$[QT_INSTALL_PREFIX])/.*"):\
-            # Tests are an exception, since they are launched in their build not
-            # install location by CI, so we cannot use relative rpaths there.
-            !contains(target.path, "$$re_escape($$[QT_INSTALL_TESTS])/.*") {
-            app_bundle {
-                ios:  binpath = $$target.path/$${TARGET}.app
-                else: binpath = $$target.path/$${TARGET}.app/Contents/MacOS
-            } else {
-                binpath = $$target.path
-            }
-            QMAKE_RPATHDIR = @loader_path/$$relative_path($$[QT_INSTALL_LIBS], $$binpath)
-            unset(binpath)
-        } else {
-             # Otherwise, use absolute path to Qt libraries
-             QMAKE_RPATHDIR = $$[QT_INSTALL_LIBS]
-        }
-    }
 }
 
 macx-xcode:!isEmpty(QMAKE_XCODE_DEBUG_INFORMATION_FORMAT) {
diff --git a/mkspecs/features/qt.prf b/mkspecs/features/qt.prf
index 36ec32f9829d6f3b499c7e9797622b9798a0d49f..9eeb1bd76c8682c0b091a269b830131b4dea51ab 100644
--- a/mkspecs/features/qt.prf
+++ b/mkspecs/features/qt.prf
@@ -59,9 +59,27 @@ qt_module_deps = $$QT $$QT_PRIVATE
 qt_module_deps = $$replace(qt_module_deps, -private$, _private)
 qt_module_deps = $$resolve_depends(qt_module_deps, "QT.")
 
-!static:contains(QT_CONFIG, rpath):!contains(QT_CONFIG, static):!contains(QT_CONFIG, qt_framework):\
+!no_qt_rpath:!static:contains(QT_CONFIG, rpath):!contains(QT_CONFIG, static):\
         contains(qt_module_deps, core) {
-    QMAKE_RPATHDIR += $$[QT_INSTALL_LIBS/dev]
+    relative_qt_rpath:defined(target.path, var) {
+        mac {
+            if(equals(TEMPLATE, app):app_bundle)|\
+                    if(equals(TEMPLATE, lib):plugin:plugin_bundle) {
+                ios:  binpath = $$target.path/$${TARGET}.app
+                else: binpath = $$target.path/$${TARGET}.app/Contents/MacOS
+            } else: equals(TEMPLATE, lib):!plugin:lib_bundle {
+                binpath = $$target.path/$${TARGET}.framework/Versions/Current
+            } else {
+                binpath = $$target.path
+            }
+            QMAKE_RPATHDIR += @loader_path/$$relative_path($$[QT_INSTALL_LIBS], $$binpath)
+        } else {
+            QMAKE_LFLAGS += -Wl,-z,origin
+            QMAKE_RPATHDIR += $ORIGIN/$$relative_path($$[QT_INSTALL_LIBS], $$target.path)
+        }
+    } else {
+        QMAKE_RPATHDIR += $$[QT_INSTALL_LIBS/dev]
+    }
 }
 
 # static builds: link qml import plugins into the app.
diff --git a/mkspecs/features/qt_app.prf b/mkspecs/features/qt_app.prf
index 0f83fd7270e9ebdbcd88701a3901cef3c229581b..b446ed1cd1b7f9cc781327c317fc707f329c2c9f 100644
--- a/mkspecs/features/qt_app.prf
+++ b/mkspecs/features/qt_app.prf
@@ -30,6 +30,7 @@ host_build:force_bootstrap {
 } else {
     !build_pass:contains(QT_CONFIG, debug_and_release):contains(QT_CONFIG, build_all): CONFIG += release
     target.path = $$[QT_INSTALL_BINS]
+    CONFIG += relative_qt_rpath  # Qt's tools and apps should be relocatable
 }
 INSTALLS += target
 
diff --git a/mkspecs/features/qt_example_installs.prf b/mkspecs/features/qt_example_installs.prf
index 9c0026fbd079002322d9613329f460fa7c065923..a6449049813f562bbb48d82e8852f16b889b3509 100644
--- a/mkspecs/features/qt_example_installs.prf
+++ b/mkspecs/features/qt_example_installs.prf
@@ -101,5 +101,7 @@ probase = $$relative_path($$_PRO_FILE_PWD_, $$dirname(_QMAKE_CONF_)/examples)
         SOURCES =
         OBJECTIVE_SOURCES =
         INSTALLS -= target
+    } else {
+        CONFIG += relative_qt_rpath  # Examples built as part of Qt should be relocatable
     }
 }
diff --git a/mkspecs/features/qt_module.prf b/mkspecs/features/qt_module.prf
index 5206691a17949eab630632f05d0f91d0e56d27b6..3c0526055c0d86903f72298f2208a8d85b4f7bce 100644
--- a/mkspecs/features/qt_module.prf
+++ b/mkspecs/features/qt_module.prf
@@ -42,6 +42,8 @@ host_build {
     }
 }
 
+CONFIG += relative_qt_rpath  # Qt libraries should be relocatable
+
 ucmodule = $$upper($$MODULE)
 
 isEmpty(MODULE_INCNAME): MODULE_INCNAME = $$TARGET
diff --git a/mkspecs/features/qt_plugin.prf b/mkspecs/features/qt_plugin.prf
index 17748e518a2dd200ae67205def00923e85b76159..220f11bd7554289bff380318b98c3be026747b8e 100644
--- a/mkspecs/features/qt_plugin.prf
+++ b/mkspecs/features/qt_plugin.prf
@@ -30,6 +30,8 @@ tool_plugin {
     contains(QT_CONFIG, build_all):CONFIG += build_all
 }
 
+CONFIG += relative_qt_rpath  # Qt's plugins should be relocatable
+
 CONFIG(static, static|shared)|prefix_build {
     isEmpty(MODULE): MODULE = $$basename(TARGET)