diff --git a/3rdparty/macdeployqt/shared.cpp b/3rdparty/macdeployqt/shared.cpp index 3f27e089e..6ac4b2dc9 100644 --- a/3rdparty/macdeployqt/shared.cpp +++ b/3rdparty/macdeployqt/shared.cpp @@ -39,6 +39,7 @@ #include #include #include +#include #include #include #include @@ -232,7 +233,7 @@ OtoolInfo findDependencyInfo(const QString &binaryPath) return info; } -FrameworkInfo parseOtoolLibraryLine(const QString &line, const QString &appBundlePath, const QSet &rpaths, bool useDebugLibs) +FrameworkInfo parseOtoolLibraryLine(const QString &line, const QString &appBundlePath, const QList &rpaths, bool useDebugLibs) { FrameworkInfo info; QString trimmed = line.trimmed(); @@ -503,7 +504,7 @@ QString findEntitlementsFile(const QString& path) return QString(); } -QList getQtFrameworks(const QList &dependencies, const QString &appBundlePath, const QSet &rpaths, bool useDebugLibs) +QList getQtFrameworks(const QList &dependencies, const QString &appBundlePath, const QList &rpaths, bool useDebugLibs) { QList libraries; for (const DylibInfo &dylibInfo : dependencies) { @@ -543,9 +544,9 @@ QString resolveDyldPrefix(const QString &path, const QString &loaderPath, const return path; } -QSet getBinaryRPaths(const QString &path, bool resolve = true, QString executablePath = QString()) +QList getBinaryRPaths(const QString &path, bool resolve = true, QString executablePath = QString()) { - QSet rpaths; + QList rpaths; QProcess otool; otool.start("otool", QStringList() << "-l" << path); @@ -582,13 +583,15 @@ QSet getBinaryRPaths(const QString &path, bool resolve = true, QString return rpaths; } -QList getQtFrameworks(const QString &path, const QString &appBundlePath, const QSet &rpaths, bool useDebugLibs) +QList getQtFrameworks(const QString &path, const QString &appBundlePath, const QList &rpaths, bool useDebugLibs) { const OtoolInfo info = findDependencyInfo(path); - return getQtFrameworks(info.dependencies, appBundlePath, rpaths + getBinaryRPaths(path), useDebugLibs); + QList allRPaths = rpaths + getBinaryRPaths(path); + allRPaths.removeDuplicates(); + return getQtFrameworks(info.dependencies, appBundlePath, allRPaths, useDebugLibs); } -QList getQtFrameworksForPaths(const QStringList &paths, const QString &appBundlePath, const QSet &rpaths, bool useDebugLibs) +QList getQtFrameworksForPaths(const QStringList &paths, const QString &appBundlePath, const QList &rpaths, bool useDebugLibs) { QList result; QSet existing; @@ -612,7 +615,7 @@ QStringList getBinaryDependencies(const QString executablePath, const auto dependencies = findDependencyInfo(path).dependencies; bool rpathsLoaded = false; - QSet rpaths; + QList rpaths; // return bundle-local dependencies. (those starting with @executable_path) for (const DylibInfo &info : dependencies) { @@ -625,9 +628,9 @@ QStringList getBinaryDependencies(const QString executablePath, if (!rpathsLoaded) { rpaths = getBinaryRPaths(path, true, executablePath); for (const QString &binaryPath : additionalBinariesContainingRpaths) { - QSet binaryRpaths = getBinaryRPaths(binaryPath, true); - rpaths += binaryRpaths; + rpaths += getBinaryRPaths(binaryPath, true); } + rpaths.removeDuplicates(); rpathsLoaded = true; } bool resolved = false; @@ -673,7 +676,7 @@ bool recursiveCopy(const QString &sourcePath, const QString &destinationPath) return true; } -void recursiveCopyAndDeploy(const QString &appBundlePath, const QSet &rpaths, const QString &sourcePath, const QString &destinationPath) +void recursiveCopyAndDeploy(const QString &appBundlePath, const QList &rpaths, const QString &sourcePath, const QString &destinationPath) { QDir().mkpath(destinationPath); @@ -870,7 +873,7 @@ void addRPath(const QString &rpath, const QString &binaryPath) runInstallNameTool(QStringList() << "-add_rpath" << rpath << binaryPath); } -void deployRPaths(const QString &bundlePath, const QSet &rpaths, const QString &binaryPath, bool useLoaderPath) +void deployRPaths(const QString &bundlePath, const QList &rpaths, const QString &binaryPath, bool useLoaderPath) { const QString absFrameworksPath = QFileInfo(bundlePath).absoluteFilePath() + QLatin1String("/Contents/Frameworks"); @@ -878,7 +881,7 @@ void deployRPaths(const QString &bundlePath, const QSet &rpaths, const const QString loaderPathToFrameworks = QLatin1String("@loader_path/") + relativeFrameworkPath; bool rpathToFrameworksFound = false; QStringList args; - QSet binaryRPaths = getBinaryRPaths(binaryPath, false); + QList binaryRPaths = getBinaryRPaths(binaryPath, false); for (const QString &rpath : std::as_const(binaryRPaths)) { if (rpath == "@executable_path/../Frameworks" || rpath == loaderPathToFrameworks) { @@ -905,7 +908,7 @@ void deployRPaths(const QString &bundlePath, const QSet &rpaths, const runInstallNameTool(QStringList() << args << binaryPath); } -void deployRPaths(const QString &bundlePath, const QSet &rpaths, const QStringList &binaryPaths, bool useLoaderPath) +void deployRPaths(const QString &bundlePath, const QList &rpaths, const QStringList &binaryPaths, bool useLoaderPath) { for (const QString &binary : binaryPaths) { deployRPaths(bundlePath, rpaths, binary, useLoaderPath); @@ -973,7 +976,7 @@ DeploymentInfo deployQtFrameworks(QList frameworks, deploymentInfo.useLoaderPath = useLoaderPath; deploymentInfo.isFramework = bundlePath.contains(".framework"); deploymentInfo.isDebug = false; - QSet rpathsUsed; + QList rpathsUsed; while (frameworks.isEmpty() == false) { const FrameworkInfo framework = frameworks.takeFirst(); @@ -998,8 +1001,9 @@ DeploymentInfo deployQtFrameworks(QList frameworks, continue; } - if (!framework.rpathUsed.isEmpty()) - rpathsUsed << framework.rpathUsed; + if (!framework.rpathUsed.isEmpty() && !rpathsUsed.contains(framework.rpathUsed)) { + rpathsUsed.append(framework.rpathUsed); + } // Copy the framework/dylib to the app bundle. const QString deployedBinaryPath = framework.isDylib ? copyDylib(framework, bundlePath) @@ -1026,7 +1030,7 @@ DeploymentInfo deployQtFrameworks(QList frameworks, if (dependency.rpathUsed.isEmpty()) { changeInstallName(bundlePath, dependency, QStringList() << deployedBinaryPath, useLoaderPath); } else { - rpathsUsed << dependency.rpathUsed; + rpathsUsed.append(dependency.rpathUsed); } // Deploy framework if necessary. @@ -1038,6 +1042,7 @@ DeploymentInfo deployQtFrameworks(QList frameworks, deploymentInfo.deployedFrameworks = copiedFrameworks; deployRPaths(bundlePath, rpathsUsed, binaryPaths, useLoaderPath); deploymentInfo.rpathsUsed += rpathsUsed; + deploymentInfo.rpathsUsed.removeDuplicates(); return deploymentInfo; } @@ -1049,12 +1054,14 @@ DeploymentInfo deployQtFrameworks(const QString &appBundlePath, const QStringLis applicationBundle.libraryPaths = findAppLibraries(appBundlePath); QStringList allBinaryPaths = QStringList() << applicationBundle.binaryPath << applicationBundle.libraryPaths << additionalExecutables; - QSet allLibraryPaths = getBinaryRPaths(applicationBundle.binaryPath, true); + QList allLibraryPaths = getBinaryRPaths(applicationBundle.binaryPath, true); #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) - allLibraryPaths.insert(QLibraryInfo::path(QLibraryInfo::LibrariesPath)); + allLibraryPaths.append(QLibraryInfo::path(QLibraryInfo::LibrariesPath)); #else - allLibraryPaths.insert(QLibraryInfo::location(QLibraryInfo::LibrariesPath)); + allLibraryPaths.append(QLibraryInfo::location(QLibraryInfo::LibrariesPath)); #endif + allLibraryPaths.removeDuplicates(); + QList frameworks = getQtFrameworksForPaths(allBinaryPaths, appBundlePath, allLibraryPaths, useDebugLibs); if (frameworks.isEmpty() && !alwaysOwerwriteEnabled) { LogWarning(); @@ -1399,7 +1406,7 @@ void deployPlugins(const QString &appBundlePath, DeploymentInfo deploymentInfo, deployPlugins(applicationBundle, deploymentInfo.pluginPath, pluginDestinationPath, deploymentInfo, useDebugLibs); } -void deployQmlImport(const QString &appBundlePath, const QSet &rpaths, const QString &importSourcePath, const QString &importName) +void deployQmlImport(const QString &appBundlePath, const QList &rpaths, const QString &importSourcePath, const QString &importName) { QString importDestinationPath = appBundlePath + "/Contents/Resources/qml/" + importName; diff --git a/3rdparty/macdeployqt/shared.h b/3rdparty/macdeployqt/shared.h index 15ff08430..48ea24b11 100644 --- a/3rdparty/macdeployqt/shared.h +++ b/3rdparty/macdeployqt/shared.h @@ -62,7 +62,7 @@ public: bool isDebugLibrary() const { - return binaryName.contains(QLatin1String("_debug")); + return binaryName.endsWith(QStringLiteral("_debug")); } }; @@ -101,7 +101,7 @@ public: QString qtPath; QString pluginPath; QStringList deployedFrameworks; - QSet rpathsUsed; + QList rpathsUsed; bool useLoaderPath; bool isFramework; bool isDebug; @@ -112,10 +112,10 @@ public: inline QDebug operator<<(QDebug debug, const ApplicationBundleInfo &info); OtoolInfo findDependencyInfo(const QString &binaryPath); -FrameworkInfo parseOtoolLibraryLine(const QString &line, const QString &appBundlePath, const QSet &rpaths, bool useDebugLibs); +FrameworkInfo parseOtoolLibraryLine(const QString &line, const QString &appBundlePath, const QList &rpaths, bool useDebugLibs); QString findAppBinary(const QString &appBundlePath); -QList getQtFrameworks(const QString &path, const QString &appBundlePath, const QSet &rpaths, bool useDebugLibs); -QList getQtFrameworks(const QStringList &otoolLines, const QString &appBundlePath, const QSet &rpaths, bool useDebugLibs); +QList getQtFrameworks(const QString &path, const QString &appBundlePath, const QList &rpaths, bool useDebugLibs); +QList getQtFrameworks(const QStringList &otoolLines, const QString &appBundlePath, const QList &rpaths, bool useDebugLibs); QString copyFramework(const FrameworkInfo &framework, const QString path); DeploymentInfo deployQtFrameworks(const QString &appBundlePath, const QStringList &additionalExecutables, bool useDebugLibs); DeploymentInfo deployQtFrameworks(QList frameworks,const QString &bundlePath, const QStringList &binaryPaths, bool useDebugLibs, bool useLoaderPath);