diff options
Diffstat (limited to 'src/tools/macdeployqt/shared/shared.cpp')
-rw-r--r-- | src/tools/macdeployqt/shared/shared.cpp | 73 |
1 files changed, 49 insertions, 24 deletions
diff --git a/src/tools/macdeployqt/shared/shared.cpp b/src/tools/macdeployqt/shared/shared.cpp index 5abc0281c6..6ff269b36d 100644 --- a/src/tools/macdeployqt/shared/shared.cpp +++ b/src/tools/macdeployqt/shared/shared.cpp @@ -152,7 +152,7 @@ OtoolInfo findDependencyInfo(const QString &binaryPath) LogDebug() << " inspecting" << binaryPath; QProcess otool; otool.start("otool", QStringList() << "-L" << binaryPath); - otool.waitForFinished(); + otool.waitForFinished(-1); if (otool.exitStatus() != QProcess::NormalExit || otool.exitCode() != 0) { LogError() << otool.readAllStandardError(); @@ -161,7 +161,7 @@ OtoolInfo findDependencyInfo(const QString &binaryPath) static const QRegularExpression regexp(QStringLiteral( "^\\t(.+) \\(compatibility version (\\d+\\.\\d+\\.\\d+), " - "current version (\\d+\\.\\d+\\.\\d+)(, weak)?\\)$")); + "current version (\\d+\\.\\d+\\.\\d+)(, weak|, reexport)?\\)$")); QString output = otool.readAllStandardOutput(); QStringList outputLines = output.split("\n", Qt::SkipEmptyParts); @@ -172,7 +172,7 @@ OtoolInfo findDependencyInfo(const QString &binaryPath) outputLines.removeFirst(); // remove line containing the binary path if (binaryPath.contains(".framework/") || binaryPath.endsWith(".dylib")) { - const auto match = regexp.match(outputLines.first()); + const auto match = regexp.match(outputLines.constFirst()); if (match.hasMatch()) { QString installname = match.captured(1); if (QFileInfo(binaryPath).fileName() == QFileInfo(installname).fileName()) { @@ -184,7 +184,7 @@ OtoolInfo findDependencyInfo(const QString &binaryPath) info.installName = binaryPath; } } else { - LogDebug() << "Could not parse otool output line:" << outputLines.first(); + LogDebug() << "Could not parse otool output line:" << outputLines.constFirst(); outputLines.removeFirst(); } } @@ -435,7 +435,7 @@ QStringList findAppLibraries(const QString &appBundlePath) { QStringList result; // dylibs - QDirIterator iter(appBundlePath, QStringList() << QString::fromLatin1("*.dylib"), + QDirIterator iter(appBundlePath, QStringList() << QString::fromLatin1("*.dylib") << QString::fromLatin1("*.so"), QDir::Files | QDir::NoSymLinks, QDirIterator::Subdirectories); while (iter.hasNext()) { iter.next(); @@ -598,10 +598,14 @@ QStringList getBinaryDependencies(const QString executablePath, QString binary = QDir::cleanPath(executablePath + trimmedLine.mid(QStringLiteral("@executable_path/").length())); if (binary != path) binaries.append(binary); + } else if (trimmedLine.startsWith("@loader_path/")) { + QString binary = QDir::cleanPath(QFileInfo(path).path() + "/" + trimmedLine.mid(QStringLiteral("@loader_path/").length())); + if (binary != path) + binaries.append(binary); } else if (trimmedLine.startsWith("@rpath/")) { if (!rpathsLoaded) { rpaths = getBinaryRPaths(path, true, executablePath); - foreach (const QString &binaryPath, additionalBinariesContainingRpaths) + for (const QString &binaryPath : additionalBinariesContainingRpaths) rpaths += getBinaryRPaths(binaryPath, true); rpaths.removeDuplicates(); rpathsLoaded = true; @@ -627,22 +631,27 @@ QStringList getBinaryDependencies(const QString executablePath, } // copies everything _inside_ sourcePath to destinationPath -bool recursiveCopy(const QString &sourcePath, const QString &destinationPath) +bool recursiveCopy(const QString &sourcePath, const QString &destinationPath, + const QRegularExpression &ignoreRegExp = QRegularExpression()) { - if (!QDir(sourcePath).exists()) + const QDir sourceDir(sourcePath); + if (!sourceDir.exists()) return false; QDir().mkpath(destinationPath); LogNormal() << "copy:" << sourcePath << destinationPath; - QStringList files = QDir(sourcePath).entryList(QStringList() << "*", QDir::Files | QDir::NoDotAndDotDot); + const QStringList files = sourceDir.entryList(QStringList() << "*", QDir::Files | QDir::NoDotAndDotDot); + const bool hasValidRegExp = ignoreRegExp.isValid() && ignoreRegExp.pattern().length() > 0; for (const QString &file : files) { + if (hasValidRegExp && ignoreRegExp.match(file).hasMatch()) + continue; const QString fileSourcePath = sourcePath + "/" + file; const QString fileDestinationPath = destinationPath + "/" + file; copyFilePrintStatus(fileSourcePath, fileDestinationPath); } - QStringList subdirs = QDir(sourcePath).entryList(QStringList() << "*", QDir::Dirs | QDir::NoDotAndDotDot); + const QStringList subdirs = sourceDir.entryList(QStringList() << "*", QDir::Dirs | QDir::NoDotAndDotDot); for (const QString &dir : subdirs) { recursiveCopy(sourcePath + "/" + dir, destinationPath + "/" + dir); } @@ -656,7 +665,9 @@ void recursiveCopyAndDeploy(const QString &appBundlePath, const QList<QString> & LogNormal() << "copy:" << sourcePath << destinationPath; const bool isDwarfPath = sourcePath.endsWith("DWARF"); - QStringList files = QDir(sourcePath).entryList(QStringList() << QStringLiteral("*"), QDir::Files | QDir::NoDotAndDotDot); + const QDir sourceDir(sourcePath); + + const QStringList files = sourceDir.entryList(QStringList() << QStringLiteral("*"), QDir::Files | QDir::NoDotAndDotDot); for (const QString &file : files) { const QString fileSourcePath = sourcePath + u'/' + file; @@ -702,7 +713,7 @@ void recursiveCopyAndDeploy(const QString &appBundlePath, const QList<QString> & } } - QStringList subdirs = QDir(sourcePath).entryList(QStringList() << QStringLiteral("*"), QDir::Dirs | QDir::NoDotAndDotDot); + const QStringList subdirs = sourceDir.entryList(QStringList() << QStringLiteral("*"), QDir::Dirs | QDir::NoDotAndDotDot); for (const QString &dir : subdirs) { recursiveCopyAndDeploy(appBundlePath, rpaths, sourcePath + u'/' + dir, destinationPath + u'/' + dir); } @@ -768,14 +779,16 @@ QString copyFramework(const FrameworkInfo &framework, const QString path) // Copy Resources/, Libraries/ and Helpers/ const QString resourcesSourcePath = framework.frameworkPath + "/Resources"; - const QString resourcesDestianationPath = frameworkDestinationDirectory + "/Versions/" + framework.version + "/Resources"; - recursiveCopy(resourcesSourcePath, resourcesDestianationPath); + const QString resourcesDestinationPath = frameworkDestinationDirectory + "/Versions/" + framework.version + "/Resources"; + // Ignore *.prl files that are in the Resources directory + recursiveCopy(resourcesSourcePath, resourcesDestinationPath, + QRegularExpression("\\A(?:[^/]*\\.prl)\\z")); const QString librariesSourcePath = framework.frameworkPath + "/Libraries"; - const QString librariesDestianationPath = frameworkDestinationDirectory + "/Versions/" + framework.version + "/Libraries"; - bool createdLibraries = recursiveCopy(librariesSourcePath, librariesDestianationPath); + const QString librariesDestinationPath = frameworkDestinationDirectory + "/Versions/" + framework.version + "/Libraries"; + bool createdLibraries = recursiveCopy(librariesSourcePath, librariesDestinationPath); const QString helpersSourcePath = framework.frameworkPath + "/Helpers"; - const QString helpersDestianationPath = frameworkDestinationDirectory + "/Versions/" + framework.version + "/Helpers"; - bool createdHelpers = recursiveCopy(helpersSourcePath, helpersDestianationPath); + const QString helpersDestinationPath = frameworkDestinationDirectory + "/Versions/" + framework.version + "/Helpers"; + bool createdHelpers = recursiveCopy(helpersSourcePath, helpersDestinationPath); // Create symlink structure. Links at the framework root point to Versions/Current/ // which again points to the actual version: @@ -834,9 +847,15 @@ void changeInstallName(const QString &bundlePath, const FrameworkInfo &framework changeInstallName(framework.installName, deployedInstallName, binary); // Workaround for the case when the library ID name is a symlink, while the dependencies // specified using the canonical path to the library (QTBUG-56814) - QString canonicalInstallName = QFileInfo(framework.installName).canonicalFilePath(); + QFileInfo fileInfo= QFileInfo(framework.installName); + QString canonicalInstallName = fileInfo.canonicalFilePath(); if (!canonicalInstallName.isEmpty() && canonicalInstallName != framework.installName) { changeInstallName(canonicalInstallName, deployedInstallName, binary); + // some libraries' inner dependencies (such as ffmpeg, nettle) use symbol link (QTBUG-100093) + QString innerDependency = fileInfo.canonicalPath() + "/" + fileInfo.fileName(); + if (innerDependency != canonicalInstallName && innerDependency != framework.installName) { + changeInstallName(innerDependency, deployedInstallName, binary); + } } } } @@ -862,7 +881,8 @@ void deployRPaths(const QString &bundlePath, const QList<QString> &rpaths, const continue; } if (rpaths.contains(resolveDyldPrefix(rpath, binaryPath, binaryPath))) { - args << "-delete_rpath" << rpath; + if (!args.contains(rpath)) + args << "-delete_rpath" << rpath; } } if (!args.length()) { @@ -924,12 +944,15 @@ bool DeploymentInfo::containsModule(const QString &module, const QString &libInF if (deployedFrameworks.contains("Qt"_L1 + module + libInFix + ".framework"_L1)) return true; // Check for dylib - const QRegularExpression dylibRegExp("libQt[0-9]+"_L1 + module + libInFix + ".[0-9]+.dylib"_L1); + const QRegularExpression dylibRegExp("libQt[0-9]+"_L1 + + module + libInFix + + (isDebug ? "_debug" : "") + + ".[0-9]+.dylib"_L1); return deployedFrameworks.filter(dylibRegExp).size() > 0; } /* - Deploys the the listed frameworks listed into an app bundle. + Deploys the listed frameworks into an app bundle. The frameworks are searched for dependencies, which are also deployed. (deploying Qt3Support will also deploy QtNetwork and QtSql for example.) Returns a DeploymentInfo structure containing the Qt path used and a @@ -1094,8 +1117,10 @@ void deployPlugins(const ApplicationBundleInfo &appBundleInfo, const QString &pl const QString libInfix = getLibInfix(deploymentInfo.deployedFrameworks); // Network - if (deploymentInfo.containsModule("Network", libInfix)) + if (deploymentInfo.containsModule("Network", libInfix)) { addPlugins(QStringLiteral("tls")); + addPlugins(QStringLiteral("networkinformation")); + } // All image formats (svg if QtSvg is used) const bool usesSvg = deploymentInfo.containsModule("Svg", libInfix); @@ -1146,7 +1171,7 @@ void deployPlugins(const ApplicationBundleInfo &appBundleInfo, const QString &pl } static const std::map<QString, std::vector<QString>> map { - {QStringLiteral("Multimedia"), {QStringLiteral("mediaservice"), QStringLiteral("audio")}}, + {QStringLiteral("Multimedia"), {QStringLiteral("multimedia")}}, {QStringLiteral("3DRender"), {QStringLiteral("sceneparsers"), QStringLiteral("geometryloaders"), QStringLiteral("renderers")}}, {QStringLiteral("3DQuickRender"), {QStringLiteral("renderplugins")}}, {QStringLiteral("Positioning"), {QStringLiteral("position")}}, |