From 967372c975fcaea5c2ef4e8a5950fb60bab10e6c Mon Sep 17 00:00:00 2001
From: Oswald Buddenhagen <oswald.buddenhagen@theqtcompany.com>
Date: Fri, 5 Jun 2015 17:45:47 +0200
Subject: [PATCH] sanitize qt rpath handling, in particular on mac

the addition of qt's rpath belongs into qt.prf - even on mac.
so consolidate the two implementations.
as a nice "side effect", we get relative rpaths also on linux.
another "side effect" is that we don't unnecessarily add the qt rpath to
qt modules also on linux.

the qt rpath addition mechanism should not be responsible for setting
the policy who gets a relative rpath, so move the logic to higher-level
callers.

Change-Id: I52e8fe2e8279e7b1ac25fae758867a5cb1cafcf8
Reviewed-by: Joerg Bornemann <joerg.bornemann@theqtcompany.com>
Reviewed-by: Oswald Buddenhagen <oswald.buddenhagen@theqtcompany.com>
---
 mkspecs/features/mac/default_post.prf    | 25 ------------------------
 mkspecs/features/qt.prf                  | 22 +++++++++++++++++++--
 mkspecs/features/qt_app.prf              |  1 +
 mkspecs/features/qt_example_installs.prf |  2 ++
 mkspecs/features/qt_module.prf           |  2 ++
 mkspecs/features/qt_plugin.prf           |  2 ++
 6 files changed, 27 insertions(+), 27 deletions(-)

diff --git a/mkspecs/features/mac/default_post.prf b/mkspecs/features/mac/default_post.prf
index 7100717b78f..30960e66ddc 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 36ec32f9829..9eeb1bd76c8 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 0f83fd7270e..b446ed1cd1b 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 9c0026fbd07..a6449049813 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 5206691a179..3c0526055c0 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 17748e518a2..220f11bd755 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)
 
-- 
GitLab