diff options
Diffstat (limited to 'src/tools')
| -rw-r--r-- | src/tools/macdeployqt/shared/shared.cpp | 27 |
1 files changed, 26 insertions, 1 deletions
diff --git a/src/tools/macdeployqt/shared/shared.cpp b/src/tools/macdeployqt/shared/shared.cpp index 0731fb616ed..7f8590ae894 100644 --- a/src/tools/macdeployqt/shared/shared.cpp +++ b/src/tools/macdeployqt/shared/shared.cpp @@ -1008,6 +1008,31 @@ DeploymentInfo deployQtFrameworks(QList<FrameworkInfo> frameworks, rpathsUsed.append(framework.rpathUsed); } + // To properly find all dependencies of the current framework / library further down in + // getQtFrameworks, we need to get its rpaths, resolve them in the context of its original + // location before it is copied, and add them as candidate rpaths. + // + // This is necessary to handle cases like + // (1) QtNetwork.framework -> (2) libbrotlidec.dylib -> (3) libbrotlicommon.1.dylib + // to correctly resolve the path to (3) when it is referenced as + // '@rpath/libbrotlicommon.1.dylib' and (2) has an LC_RPATH of '@loader_path/../lib', and + // no other absolute rpaths. So the '@loader_path/../lib' will be resolved relative + // to (2)'s original location and its LC_RPATH. + // + // Otherwise we'd only have the Qt prefix and the current bundle app dir as rpath + // candidates, and once (2) is copied into the app bundle, there's no way + // '@rpath/libbrotlicommon.1.dylib' could resolve to the real path on disk from the two + // candidates above. + if (!framework.sourceFilePath.isEmpty()) { + const QList<QString> sourceRPaths = getBinaryRPaths(framework.sourceFilePath, true); + for (const QString &sourceRPath : sourceRPaths) { + const QDir sourceRPathDir(sourceRPath); + if (sourceRPathDir.exists() && !rpathsUsed.contains(sourceRPath)) { + rpathsUsed.append(sourceRPath); + } + } + } + // Copy the framework/dylib to the app bundle. const QString deployedBinaryPath = framework.isDylib ? copyDylib(framework, bundlePath) : copyFramework(framework, bundlePath); @@ -1032,7 +1057,7 @@ DeploymentInfo deployQtFrameworks(QList<FrameworkInfo> frameworks, for (const FrameworkInfo &dependency : dependencies) { if (dependency.rpathUsed.isEmpty()) { changeInstallName(bundlePath, dependency, QStringList() << deployedBinaryPath, useLoaderPath); - } else { + } else if (!rpathsUsed.contains(dependency.rpathUsed)) { rpathsUsed.append(dependency.rpathUsed); } |
