3#include <QCoreApplication> 
   15#include <QDirIterator> 
   16#include <QLibraryInfo> 
   17#include <QJsonDocument> 
   21#include <QRegularExpression> 
   25#include <CoreFoundation/CoreFoundation.h> 
   46    return ((
a.frameworkPath == 
b.frameworkPath) && (
a.binaryPath == 
b.binaryPath));
 
   51    debug << 
"Framework name" << 
info.frameworkName << 
"\n";
 
   52    debug << 
"Framework directory" << 
info.frameworkDirectory << 
"\n";
 
   53    debug << 
"Framework path" << 
info.frameworkPath << 
"\n";
 
   54    debug << 
"Binary directory" << 
info.binaryDirectory << 
"\n";
 
   55    debug << 
"Binary name" << 
info.binaryName << 
"\n";
 
   56    debug << 
"Binary path" << 
info.binaryPath << 
"\n";
 
   57    debug << 
"Version" << 
info.version << 
"\n";
 
   58    debug << 
"Install name" << 
info.installName << 
"\n";
 
   59    debug << 
"Deployed install name" << 
info.deployedInstallName << 
"\n";
 
   60    debug << 
"Source file Path" << 
info.sourceFilePath << 
"\n";
 
   61    debug << 
"Framework Destination Directory (relative to bundle)" << 
info.frameworkDestinationDirectory << 
"\n";
 
   62    debug << 
"Binary Destination Directory (relative to bundle)" << 
info.binaryDestinationDirectory << 
"\n";
 
   72    debug << 
"Binary path" << 
info.binaryPath << 
"\n";
 
   73    debug << 
"Additional libraries" << 
info.libraryPaths << 
"\n";
 
   83            qDebug() << 
"File exists, skip copy:" << to;
 
  102            LogError() << 
"Failed to set u+w permissions on target file: " << to;
 
  108        LogError() << 
"file copy failed from" << from;
 
  117        if (
QFile(link).symLinkTarget().isEmpty())
 
  118            LogError() << link << 
"exists but it's a file.";
 
  120            LogNormal() << 
"Symlink exists, skipping:" << link;
 
  127        LogError() << 
"failed to symlink" << link;
 
  137    QFile infoPlist(infoPlistPath);
 
  149    info.binaryPath = binaryPath;
 
  152    LogDebug() << 
" inspecting" << binaryPath;
 
  154    otool.start(
"otool", 
QStringList() << 
"-L" << binaryPath);
 
  155    otool.waitForFinished();
 
  157    if (otool.exitStatus() != QProcess::NormalExit || otool.exitCode() != 0) {
 
  158        LogError() << otool.readAllStandardError();
 
  163        "^\\t(.+) \\(compatibility version (\\d+\\.\\d+\\.\\d+), " 
  164        "current version (\\d+\\.\\d+\\.\\d+)(, weak|, reexport)?\\)$"));
 
  168    if (outputLines.size() < 2) {
 
  173    outputLines.removeFirst(); 
 
  175        const auto match = regexp.
match(outputLines.first());
 
  176        if (
match.hasMatch()) {
 
  179                info.installName = installname;
 
  182                outputLines.removeFirst();
 
  184                info.installName = binaryPath;
 
  187            LogDebug() << 
"Could not parse otool output line:" << outputLines.first();
 
  188            outputLines.removeFirst();
 
  192    for (
const QString &outputLine : outputLines) {
 
  194        if (
match.hasMatch()) {
 
  195            if (
match.captured(1) == 
info.installName)
 
  201            info.dependencies << dylib;
 
  203            LogDebug() << 
"Could not parse otool output line:" << outputLine;
 
  227        bool foundInsideBundle = 
false;
 
  228        for (
const QString &rpath : std::as_const(rpaths)) {
 
  231            if (!appBundlePath.
isEmpty()) {
 
  234                        foundInsideBundle = 
true;
 
  239                        foundInsideBundle = 
true;
 
  252        if (!rpaths.
isEmpty() && !foundInsideBundle) {
 
  253            LogError() << 
"Cannot resolve rpath" << trimmed;
 
  259    enum State {QtPath, FrameworkName, DylibName, 
Version, FrameworkBinary, 
End};
 
  264    QString suffix = useDebugLibs ? 
"_debug" : 
"";
 
  268    while (part < parts.count()) {
 
  269        const QString currentPart = parts.at(part).simplified();
 
  271        if (currentPart == 
"")
 
  274        if (
state == QtPath) {
 
  276            if (part < parts.count() && parts.at(part).contains(
".dylib")) {
 
  280            } 
else if (part < parts.count() && parts.at(part).endsWith(
".framework")) {
 
  282                state = FrameworkName;
 
  284            } 
else if (trimmed.
startsWith(
"/") == 
false) {      
 
  286                partsCopy.removeLast();
 
  288                    if (!
path.endsWith(
"/"))
 
  292                        info.frameworkDirectory = 
path + partsCopy.join(u
'/');
 
  296                if (currentPart.
contains(
".framework")) {
 
  297                    if (
info.frameworkDirectory.isEmpty())
 
  298                        info.frameworkDirectory = 
"/Library/Frameworks/" + partsCopy.join(u
'/');
 
  299                    if (!
info.frameworkDirectory.endsWith(
"/"))
 
  300                        info.frameworkDirectory += 
"/";
 
  301                    state = FrameworkName;
 
  304                } 
else if (currentPart.
contains(
".dylib")) {
 
  305                    if (
info.frameworkDirectory.isEmpty())
 
  306                        info.frameworkDirectory = 
"/usr/lib/" + partsCopy.join(u
'/');
 
  307                    if (!
info.frameworkDirectory.endsWith(
"/"))
 
  308                        info.frameworkDirectory += 
"/";
 
  314            qtPath += (currentPart + 
"/");
 
  316        } 
if (
state == FrameworkName) {
 
  320            info.isDylib = 
false;
 
  321            info.frameworkName = currentPart;
 
  325        } 
if (
state == DylibName) {
 
  330            info.deployedInstallName = 
"@executable_path/../Frameworks/" + 
info.binaryName;
 
  331            info.frameworkPath = 
info.frameworkDirectory + 
info.binaryName;
 
  332            info.sourceFilePath = 
info.frameworkPath;
 
  334            info.binaryDestinationDirectory = 
info.frameworkDestinationDirectory;
 
  335            info.binaryDirectory = 
info.frameworkDirectory;
 
  336            info.binaryPath = 
info.frameworkPath;
 
  341            info.version = currentPart;
 
  342            info.binaryDirectory = 
"Versions/" + 
info.version;
 
  343            info.frameworkPath = 
info.frameworkDirectory + 
info.frameworkName;
 
  345            info.binaryDestinationDirectory = 
info.frameworkDestinationDirectory + 
"/" + 
info.binaryDirectory;
 
  346            state = FrameworkBinary;
 
  347        } 
else if (
state == FrameworkBinary) {
 
  348            info.binaryName = currentPart.
contains(suffix) ? currentPart : currentPart + suffix;
 
  349            info.binaryPath = 
"/" + 
info.binaryDirectory + 
"/" + 
info.binaryName;
 
  350            info.deployedInstallName = 
"@executable_path/../Frameworks/" + 
info.frameworkName + 
info.binaryPath;
 
  351            info.sourceFilePath = 
info.frameworkPath + 
info.binaryPath;
 
  360        if (
info.installName.startsWith(
"@rpath/"))
 
  361            info.deployedInstallName = 
info.installName;
 
  372    CFStringRef bundlePath = appBundlePath.toCFString();
 
  373    CFURLRef bundleURL = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, bundlePath,
 
  374                                                       kCFURLPOSIXPathStyle, 
true);
 
  375    CFRelease(bundlePath);
 
  376    CFBundleRef 
bundle = CFBundleCreate(kCFAllocatorDefault, bundleURL);
 
  378        CFURLRef executableURL = CFBundleCopyExecutableURL(
bundle);
 
  380            CFURLRef absoluteExecutableURL = CFURLCopyAbsoluteURL(executableURL);
 
  381            if (absoluteExecutableURL) {
 
  382                CFStringRef executablePath = CFURLCopyFileSystemPath(absoluteExecutableURL,
 
  383                                                                     kCFURLPOSIXPathStyle);
 
  384                if (executablePath) {
 
  385                    binaryPath = QString::fromCFString(executablePath);
 
  386                    CFRelease(executablePath);
 
  388                CFRelease(absoluteExecutableURL);
 
  390            CFRelease(executableURL);
 
  394    CFRelease(bundleURL);
 
  399    LogError() << 
"Could not find bundle binary for" << appBundlePath;
 
  409    QString searchPath = appBundlePath + 
"/Contents/Frameworks/";
 
  412    while (
iter.hasNext()) {
 
  414        frameworks << 
iter.fileInfo().fileName();
 
  423    QString searchPath = appBundlePath + 
"/Contents/Frameworks/";
 
  426    while (
iter.hasNext()) {
 
  428        frameworks << 
iter.fileInfo().filePath();
 
  440    while (
iter.hasNext()) {
 
  454    while (
iter.hasNext()) {
 
  456        if (
iter.fileInfo().isSymLink())
 
  469    while (
iter.hasNext()) {
 
  471        if (
iter.fileInfo().isSymLink())
 
  475        return iter.fileInfo().absoluteFilePath();
 
  484    for (
const DylibInfo &dylibInfo : dependencies) {
 
  486        if (
info.frameworkName.isEmpty() == 
false) {
 
  497    if (
path.startsWith(
"@")) {
 
  527    otool.waitForFinished();
 
  529    if (otool.exitCode() != 0) {
 
  530        LogError() << otool.readAllStandardError();
 
  533    if (resolve && executablePath.isEmpty()) {
 
  534      executablePath = 
path;
 
  540    for (
auto i = outputLines.cbegin(), 
end = outputLines.cend(); 
i != 
end; ++
i) {
 
  541        if (
i->contains(
"cmd LC_RPATH") && ++
i != 
end &&
 
  542            i->contains(
"cmdsize") && ++
i != 
end) {
 
  544            int pathStart = rpathCmd.
indexOf(
"path ");
 
  545            int pathEnd = rpathCmd.
indexOf(
" (");
 
  546            if (pathStart >= 0 && pathEnd >= 0 && pathStart < pathEnd) {
 
  547                QString rpath = rpathCmd.
mid(pathStart + 5, pathEnd - pathStart - 5);
 
  564    allRPaths.removeDuplicates();
 
  591    bool rpathsLoaded = 
false;
 
  597        if (trimmedLine.
startsWith(
"@executable_path/")) {
 
  601        } 
else if (trimmedLine.
startsWith(
"@rpath/")) {
 
  604                foreach (
const QString &binaryPath, additionalBinariesContainingRpaths)
 
  606                rpaths.removeDuplicates();
 
  609            bool resolved = 
false;
 
  610            for (
const QString &rpath : std::as_const(rpaths)) {
 
  619            if (!resolved && !rpaths.
isEmpty()) {
 
  620                LogError() << 
"Cannot resolve rpath" << trimmedLine;
 
  633    if (!
QDir(sourcePath).exists())
 
  637    LogNormal() << 
"copy:" << sourcePath << destinationPath;
 
  640    const bool hasValidRegExp = ignoreRegExp.isValid() && ignoreRegExp.pattern().length() > 0;
 
  642        if (hasValidRegExp && ignoreRegExp.match(
file).hasMatch())
 
  644        const QString fileSourcePath = sourcePath + 
"/" + 
file;
 
  645        const QString fileDestinationPath = destinationPath + 
"/" + 
file;
 
  660    LogNormal() << 
"copy:" << sourcePath << destinationPath;
 
  661    const bool isDwarfPath = sourcePath.
endsWith(
"DWARF");
 
  665        const QString fileSourcePath = sourcePath + u
'/' + 
file;
 
  667        if (
file.endsWith(
"_debug.dylib")) {
 
  683            QString fileDestinationPath = fileDestinationDir + 
file;
 
  686            QString linkDestinationPath = destinationPath + u
'/' + 
file;
 
  691            for (
int i = 0; 
i < cdupCount - 2; ++
i)
 
  698                bool useDebugLibs = 
false;
 
  699                bool useLoaderPath = 
false;
 
  704            QString fileDestinationPath = destinationPath + u
'/' + 
file;
 
  725    QString dylibDestinationBinaryPath = dylibDestinationDirectory + u
'/' + framework.
binaryName;
 
  728    if (!
QDir().mkpath(dylibDestinationDirectory)) {
 
  729        LogError() << 
"could not create destination directory" << dylibDestinationDirectory;
 
  735        return dylibDestinationBinaryPath;
 
  739    return dylibDestinationBinaryPath;
 
  752    QString frameworkBinaryDestinationDirectory = frameworkDestinationDirectory + u
'/' + framework.
binaryDirectory;
 
  753    QString frameworkDestinationBinaryPath = frameworkBinaryDestinationDirectory + u
'/' + framework.
binaryName;
 
  760    if (!
QDir().mkpath(frameworkBinaryDestinationDirectory)) {
 
  761        LogError() << 
"could not create destination directory" << frameworkBinaryDestinationDirectory;
 
  775    const QString resourcesDestinationPath = frameworkDestinationDirectory + 
"/Versions/" + framework.
version + 
"/Resources";
 
  780    const QString librariesDestinationPath = frameworkDestinationDirectory + 
"/Versions/" + framework.
version + 
"/Libraries";
 
  781    bool createdLibraries = 
recursiveCopy(librariesSourcePath, librariesDestinationPath);
 
  783    const QString helpersDestinationPath = frameworkDestinationDirectory + 
"/Versions/" + framework.
version + 
"/Helpers";
 
  784    bool createdHelpers = 
recursiveCopy(helpersSourcePath, helpersDestinationPath);
 
  792    linkFilePrintStatus(
"Versions/Current/Resources", frameworkDestinationDirectory + 
"/Resources");
 
  793    if (createdLibraries)
 
  794        linkFilePrintStatus(
"Versions/Current/Libraries", frameworkDestinationDirectory + 
"/Libraries");
 
  796        linkFilePrintStatus(
"Versions/Current/Helpers", frameworkDestinationDirectory + 
"/Helpers");
 
  802    const QString correctInfoPlistPath = frameworkDestinationDirectory + 
"/Resources/Info.plist";
 
  807    return frameworkDestinationBinaryPath;
 
  812    QProcess installNametool;
 
  813    installNametool.start(
"install_name_tool", options);
 
  814    installNametool.waitForFinished();
 
  815    if (installNametool.exitCode() != 0) {
 
  816        LogError() << installNametool.readAllStandardError();
 
  817        LogError() << installNametool.readAllStandardOutput();
 
  823    LogDebug() << 
"Using install_name_tool:";
 
  824    LogDebug() << 
" change identification in" << binaryPath;
 
  835            deployedInstallName = 
"@loader_path/"_L1
 
  845        if (!canonicalInstallName.
isEmpty() && canonicalInstallName != framework.
installName) {
 
  849            if (innerDependency != canonicalInstallName && innerDependency != framework.
installName) {
 
  864            + 
"/Contents/Frameworks"_L1;
 
  866    const QString loaderPathToFrameworks = 
"@loader_path/"_L1 + relativeFrameworkPath;
 
  867    bool rpathToFrameworksFound = 
false;
 
  870    for (
const QString &rpath : std::as_const(binaryRPaths)) {
 
  871        if (rpath == 
"@executable_path/../Frameworks" ||
 
  872                rpath == loaderPathToFrameworks) {
 
  873            rpathToFrameworksFound = 
true;
 
  878                args << 
"-delete_rpath" << rpath;
 
  884    if (!rpathToFrameworksFound) {
 
  885        if (!useLoaderPath) {
 
  886            args << 
"-add_rpath" << 
"@executable_path/../Frameworks";
 
  888            args << 
"-add_rpath" << loaderPathToFrameworks;
 
  891    LogDebug() << 
"Using install_name_tool:";
 
  892    LogDebug() << 
" change rpaths in" << binaryPath;
 
  906    LogDebug() << 
"Using install_name_tool:";
 
  908    LogDebug() << 
" change reference" << oldName;
 
  919    LogDebug() << 
" stripped" << binaryPath;
 
  921    strip.start(
"strip", 
QStringList() << 
"-x" << binaryPath);
 
  922    strip.waitForFinished();
 
  923    if (strip.exitCode() != 0) {
 
  924        LogError() << strip.readAllStandardError();
 
  925        LogError() << strip.readAllStandardOutput();
 
  943        + 
".[0-9]+.dylib"_L1);
 
  959    LogNormal() << 
"Deploying Qt frameworks found inside:" << binaryPaths;
 
  964    deploymentInfo.
isDebug = 
false;
 
  967    while (frameworks.
isEmpty() == 
false) {
 
  997        if (deployedBinaryPath.
isNull())
 
 1011            if (dependency.rpathUsed.isEmpty()) {
 
 1014                rpathsUsed.
append(dependency.rpathUsed);
 
 1018            if (copiedFrameworks.contains(dependency.frameworkName) == 
false && frameworks.
contains(dependency) == 
false) {
 
 1019                frameworks.
append(dependency);
 
 1024    deployRPaths(bundlePath, rpathsUsed, binaryPaths, useLoaderPath);
 
 1026    deploymentInfo.
rpathsUsed.removeDuplicates();
 
 1027    return deploymentInfo;
 
 1033   applicationBundle.
path = appBundlePath;
 
 1037                                                 << additionalExecutables;
 
 1041   allLibraryPaths.removeDuplicates();
 
 1046        LogWarning() << 
"Could not find any external Qt frameworks to deploy in" << appBundlePath;
 
 1047        LogWarning() << 
"Perhaps macdeployqt was already used on" << appBundlePath << 
"?";
 
 1048        LogWarning() << 
"If so, you will need to rebuild" << appBundlePath << 
"before trying again.";
 
 1051       return deployQtFrameworks(frameworks, applicationBundle.
path, allBinaryPaths, useDebugLibs, !additionalExecutables.isEmpty());
 
 1058    for (
const QString &framework : deployedFrameworks) {
 
 1061            Q_ASSERT(framework.length() >= 16);
 
 1063            const int lengthOfLibInfix = framework.length() - 16;
 
 1064            if (lengthOfLibInfix)
 
 1065                libInfix = framework.
mid(6, lengthOfLibInfix);
 
 1075    LogNormal() << 
"Deploying plugins from" << pluginSourcePath;
 
 1083    const auto addPlugins = [&pluginSourcePath,&pluginList,useDebugLibs](
const QString &subDirectory,
 
 1084            const std::function<bool(
QString)> &
predicate = std::function<bool(QString)>()) {
 
 1087        for (
const QString &lib : libs) {
 
 1088            if (lib.endsWith(
QStringLiteral(
"_debug.dylib")) != useDebugLibs)
 
 1091                pluginList.append(subDirectory + u
'/' + lib);
 
 1119    const bool usesSvg = deploymentInfo.
containsModule(
"Svg", libInfix);
 
 1142                LogWarning() << 
"Plugin" << lib << 
"uses private API and is not Mac App store compliant.";
 
 1156                LogWarning() << 
"Plugin" << lib << 
"uses QtWebEngine and is not Mac App store compliant.";
 
 1166    static const std::map<QString, std::vector<QString>> 
map {
 
 1175    for (
const auto &
it : 
map) {
 
 1177            for (
const auto &pluginType : 
it.second) {
 
 1178                addPlugins(pluginType);
 
 1183    for (
const QString &plugin : pluginList) {
 
 1184        QString sourcePath = pluginSourcePath + 
"/" + plugin;
 
 1185        const QString destinationPath = pluginDestinationPath + 
"/" + plugin;
 
 1201                          "Plugins = PlugIns\n" 
 1202                          "Imports = Resources/qml\n" 
 1203                          "QmlImports = Resources/qml\n";
 
 1205    QString filePath = appBundlePath + 
"/Contents/Resources/";
 
 1214        LogWarning() << 
"To make sure the plugins are loaded from the correct location,";
 
 1215        LogWarning() << 
"please make sure qt.conf contains the following lines:";
 
 1224        LogNormal() << 
"This file sets the plugin search path to" << appBundlePath + 
"/Contents/PlugIns";
 
 1231    applicationBundle.
path = appBundlePath;
 
 1234    const QString pluginDestinationPath = appBundlePath + 
"/" + 
"Contents/PlugIns";
 
 1235    deployPlugins(applicationBundle, deploymentInfo.
pluginPath, pluginDestinationPath, deploymentInfo, useDebugLibs);
 
 1240    QString importDestinationPath = appBundlePath + 
"/Contents/Resources/qml/" + importName;
 
 1244    if (
QDir().exists(importDestinationPath))
 
 1254    QString path1 = import1[
"path"].toString();
 
 1255    QString path2 = import2[
"path"].toString();
 
 1256    return path1 < path2;
 
 1263    LogNormal() << 
"Deploying QML imports ";
 
 1264    LogNormal() << 
"Application QML file path(s) is" << qmlDirs;
 
 1265    LogNormal() << 
"QML module search path(s) is" << qmlImportPaths;
 
 1268    QString qmlImportScannerPath =
 
 1270                + 
"/qmlimportscanner");
 
 1278        LogError() << 
"qmlimportscanner not found at" << qmlImportScannerPath;
 
 1279        LogError() << 
"Rebuild qtdeclarative/tools/qmlimportscanner";
 
 1286    for (
const QString &qmlDir : qmlDirs) {
 
 1287        argumentList.append(
"-rootPath");
 
 1288        argumentList.append(qmlDir);
 
 1290    for (
const QString &importPath : qmlImportPaths)
 
 1291        argumentList << 
"-importPath" << importPath;
 
 1293    argumentList.append( 
"-importPath");
 
 1294    argumentList.append(qmlImportsPath);
 
 1297    QProcess qmlImportScanner;
 
 1298    qmlImportScanner.start(qmlImportScannerPath, argumentList);
 
 1299    if (!qmlImportScanner.waitForStarted()) {
 
 1300        LogError() << 
"Could not start qmlimpoortscanner. Process error is" << qmlImportScanner.errorString();
 
 1303    qmlImportScanner.waitForFinished(-1);
 
 1306    qmlImportScanner.setReadChannel(QProcess::StandardError);
 
 1307    QByteArray errors = qmlImportScanner.readAll();
 
 1309        LogWarning() << 
"QML file parse error (deployment will continue):";
 
 1314    qmlImportScanner.setReadChannel(QProcess::StandardOutput);
 
 1315    QByteArray json = qmlImportScanner.readAll();
 
 1318        LogError() << 
"qmlimportscanner output error. Expected json array, got:";
 
 1339        if (
name.isEmpty() || 
path.isEmpty()) {
 
 1340            LogNormal() << 
"  Skip import: name or path is empty";
 
 1348            LogNormal() << 
"  Skip non-module import";
 
 1356        name.replace(u
'.', u
'/');
 
 1357        int secondTolast = 
path.length() - 2;
 
 1373    QString codeSignLogMessage = 
"codesign";
 
 1375        codeSignLogMessage += 
", enable hardened runtime";
 
 1377        codeSignLogMessage += 
", include secure timestamp";
 
 1378    LogNormal() << codeSignLogMessage << filePath;
 
 1380    QStringList codeSignOptions = { 
"--preserve-metadata=identifier,entitlements", 
"--force", 
"-s",
 
 1381                                    identity, filePath };
 
 1383        codeSignOptions << 
"-o" << 
"runtime";
 
 1386        codeSignOptions << 
"--timestamp";
 
 1392    codesign.start(
"codesign", codeSignOptions);
 
 1397        LogError() << 
"Codesign signing error:";
 
 1416    LogNormal() << 
"Signing" << appBundlePath << 
"with identity" << identity;
 
 1425    QString rootBinariesPath = appBundleAbsolutePath + 
"/Contents/MacOS/";
 
 1429        pendingBinaries.
push(binaryPath);
 
 1430        pendingBinariesSet.
insert(binaryPath);
 
 1431        additionalBinariesContainingRpaths.
append(binaryPath);
 
 1434    bool getAbsoltuePath = 
true;
 
 1443    for (
const QString &frameworkPath : frameworkPaths) {
 
 1448        while (helpersIterator.
hasNext()) {
 
 1449            helpersIterator.
next();
 
 1452            for (
const QString &innerBundleName : innerBundleNames)
 
 1454                                                 helpersPath + 
"/" + innerBundleName,
 
 1455                                                 additionalBinariesContainingRpaths);
 
 1461        while (librariesIterator.
hasNext()) {
 
 1462            librariesIterator.
next();
 
 1473    while (!pendingBinaries.
isEmpty()) {
 
 1480                                                         additionalBinariesContainingRpaths);
 
 1481        dependencies = 
QSet<QString>(dependencies.begin(), dependencies.end())
 
 1483            .subtract(pendingBinariesSet)
 
 1486        if (!dependencies.isEmpty()) {
 
 1489            int dependenciesSkipped = 0;
 
 1490            for (
const QString &dependency : std::as_const(dependencies)) {
 
 1495                if (!dependency.startsWith(appBundleAbsolutePath)) {
 
 1496                    ++dependenciesSkipped;
 
 1497                    LogNormal() << 
"Skipping outside dependency: " << dependency;
 
 1500                pendingBinaries.
push(dependency);
 
 1501                pendingBinariesSet.
insert(dependency);
 
 1506            if (dependenciesSkipped == dependencies.size()) {
 
 1507                pendingBinaries.
pop();
 
 1522    LogNormal() << 
"Finished codesigning " << appBundlePath << 
"with identity" << identity;
 
 1530        LogError() << 
"codesign verification error:";
 
 1536    return signedBinaries;
 
 1545    QString appBaseName = appBundlePath;
 
 1546    appBaseName.
chop(4); 
 
 1548    QString dmgName = appBaseName + 
".dmg";
 
 1556        LogNormal() << 
"Disk image already exists, skipping .dmg creation for" << dmg.
fileName();
 
 1558        LogNormal() << 
"Creating disk image (.dmg) for" << appBundlePath;
 
 1561    LogNormal() << 
"Image will use" << filesystemType;
 
 1565            << 
"create" << dmgName
 
 1566            << 
"-srcfolder" << appBundlePath
 
 1567            << 
"-format" << 
"UDZO" 
 1568            << 
"-fs" << filesystemType
 
 1569            << 
"-volname" << appBaseName;
 
 1572    hdutil.start(
"hdiutil", options);
 
 1573    hdutil.waitForFinished(-1);
 
 1574    if (hdutil.exitCode() != 0) {
 
 1575        LogError() << 
"Bundle creation error:" << hdutil.readAllStandardError();
 
 1583    if (parts.count() < 2) {
 
 1584        LogError() << 
"fixupFramework: Unexpected framework name" << frameworkName;
 
 1598    addRPath(
"@loader_path/../../Contents/Frameworks/", frameworkBinary);
 
QStringList deployedFrameworks
bool containsModule(const QString &module, const QString &libInFix) const
QList< QString > rpathsUsed
QVersionNumber compatibilityVersion
QVersionNumber currentVersion
QString frameworkDirectory
QString binaryDestinationDirectory
bool isDebugLibrary() const
QString frameworkDestinationDirectory
QString deployedInstallName
bool contains(QByteArrayView a) const noexcept
bool startsWith(QByteArrayView other) const noexcept
constexpr QByteArrayView mid(qsizetype pos, qsizetype n=-1) const
constexpr bool isEmpty() const noexcept
bool isEmpty() const noexcept
Returns true if the byte array has size 0; otherwise returns false.
static QString applicationDirPath()
Returns the directory that contains the application executable.
The QDirIterator class provides an iterator for directory entrylists.
bool hasNext() const
Returns true if there is at least one more entry in the directory; otherwise, false is returned.
QString next()
Advances the iterator to the next entry, and returns the file path of this new entry.
QString filePath() const
Returns the full file path for the current directory entry.
QStringList entryList(Filters filters=NoFilter, SortFlags sort=NoSort) const
This is an overloaded member function, provided for convenience. It differs from the above function o...
static bool isAbsolutePath(const QString &path)
Returns true if path is absolute; returns false if it is relative.
bool mkpath(const QString &dirPath) const
Creates the directory path dirPath.
static QString cleanPath(const QString &path)
Returns path with directory separators normalized (that is, platform-native separators converted to "...
QString relativeFilePath(const QString &fileName) const
Returns the path to fileName relative to the directory.
static QString currentPath()
Returns the absolute path of the application's current directory.
void close() override
Calls QFileDevice::flush() and closes the file.
\inmodule QtCore \reentrant
QString fileName() const
Returns the name of the file, excluding the path.
QString absoluteFilePath() const
Returns an absolute path including the file name.
QString canonicalPath() const
Returns the file's path canonical path (excluding the file name), i.e.
QString canonicalFilePath() const
Returns the canonical path including the file name, i.e.
QDir absoluteDir() const
Returns the file's absolute path as a QDir object.
QString path() const
Returns the file's path.
bool exists() const
Returns true if the file exists; otherwise returns false.
bool open(OpenMode flags) override
Opens the file using OpenMode mode, returning true if successful; otherwise false.
bool setPermissions(Permissions permissionSpec) override
Sets the permissions for the file to the permissions specified.
bool link(const QString &newName)
Creates a link named linkName that points to the file currently specified by fileName().
bool copy(const QString &newName)
Copies the file named fileName() to newName.
bool remove()
Removes the file specified by fileName().
QString fileName() const override
Returns the name set by setFileName() or to the QFile constructors.
Permissions permissions() const override
\reimp
bool exists() const
This is an overloaded member function, provided for convenience. It differs from the above function o...
QByteArray readAll()
Reads all remaining data from the device, and returns it as a byte array.
qint64 write(const char *data, qint64 len)
Writes at most maxSize bytes of data from data to the device.
QVariantList toVariantList() const
Converts this object to a QVariantList.
\inmodule QtCore\reentrant
bool isArray() const
Returns true if the document contains an array.
QJsonArray array() const
Returns the QJsonArray contained in the document.
static QJsonDocument fromJson(const QByteArray &json, QJsonParseError *error=nullptr)
Parses json as a UTF-8 encoded JSON document, and creates a QJsonDocument from it.
static QString path(LibraryPath p)
bool isEmpty() const noexcept
qsizetype length() const noexcept
void append(parameter_type t)
\inmodule QtCore \reentrant
QRegularExpressionMatch match(const QString &subject, qsizetype offset=0, MatchType matchType=NormalMatch, MatchOptions matchOptions=NoMatchOption) const
Attempts to match the regular expression against the given subject string, starting at the position o...
bool remove(const T &value)
bool contains(const T &value) const
iterator insert(const T &value)
QSet< T > & subtract(const QSet< T > &other)
T pop()
Removes the top item from the stack and returns it.
void push(const T &t)
Adds element t to the top of the stack.
\macro QT_RESTRICTED_CAST_FROM_ASCII
bool startsWith(const QString &s, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Returns true if the string starts with s; otherwise returns false.
void chop(qsizetype n)
Removes n characters from the end of the string.
static QString fromLatin1(QByteArrayView ba)
This is an overloaded member function, provided for convenience. It differs from the above function o...
QStringList split(const QString &sep, Qt::SplitBehavior behavior=Qt::KeepEmptyParts, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Splits the string into substrings wherever sep occurs, and returns the list of those strings.
bool isNull() const
Returns true if this string is null; otherwise returns false.
QString mid(qsizetype position, qsizetype n=-1) const
Returns a string that contains n characters of this string, starting at the specified position index.
QString simplified() const &
bool endsWith(const QString &s, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Returns true if the string ends with s; otherwise returns false.
bool isEmpty() const
Returns true if the string has no characters; otherwise returns false.
qsizetype count(QChar c, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
bool contains(QChar c, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
QString & append(QChar c)
static QString static QString qsizetype indexOf(QChar c, qsizetype from=0, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
QString trimmed() const &
QString & prepend(QChar c)
qsizetype length() const
Returns the number of characters in this string.
static Q_CORE_EXPORT QVersionNumber fromString(QAnyStringView string, qsizetype *suffixIndex=nullptr)
QMap< QString, QString > map
[6]
QSet< QString >::iterator it
DBusConnection const char DBusError DBusBusType DBusError return DBusConnection DBusHandleMessageFunction void DBusFreeFunction return DBusConnection return DBusConnection return const char DBusError return DBusConnection DBusMessage dbus_uint32_t return DBusConnection dbus_bool_t DBusConnection DBusAddWatchFunction DBusRemoveWatchFunction DBusWatchToggledFunction void DBusFreeFunction return DBusConnection DBusDispatchStatusFunction void DBusFreeFunction DBusTimeout return DBusTimeout return DBusWatch return DBusWatch unsigned int return DBusError const DBusError return const DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessageIter * iter
GLint GLfloat GLfloat GLfloat v2
GLsizei GLsizei GLenum void * binary
GLboolean GLboolean GLboolean b
GLboolean GLboolean GLboolean GLboolean a
[7]
GLenum GLuint GLenum GLsizei length
GLsizei const GLuint * paths
GLsizei const GLchar *const  * path
static QString absolutePath(const QString &path)
#define QStringLiteral(str)
static bool match(const uchar *found, uint foundLen, const char *target, uint targetLen)
QT_BEGIN_NAMESPACE typedef uchar * output
bool recursiveCopy(const QString &sourcePath, const QString &destinationPath, const QRegularExpression &ignoreRegExp=QRegularExpression())
QSet< QString > codesignBundle(const QString &identity, const QString &appBundlePath, QList< QString > additionalBinariesContainingRpaths)
void addRPath(const QString &rpath, const QString &binaryPath)
void codesignFile(const QString &identity, const QString &filePath)
QStringList getBinaryDependencies(const QString executablePath, const QString &path, const QList< QString > &additionalBinariesContainingRpaths)
bool deployQmlImports(const QString &appBundlePath, DeploymentInfo deploymentInfo, QStringList &qmlDirs, QStringList &qmlImportPaths)
QString extraEntitlements
QStringList librarySearchPath
void createQtConf(const QString &appBundlePath)
const QString bundleFrameworkDirectory
void runStrip(const QString &binaryPath)
void fixupFramework(const QString &frameworkName)
QString findAppBinary(const QString &appBundlePath)
QStringList findAppBundleFiles(const QString &appBundlePath, bool absolutePath=false)
static bool importLessThan(const QVariant &v1, const QVariant &v2)
bool operator==(const FrameworkInfo &a, const FrameworkInfo &b)
QList< FrameworkInfo > getQtFrameworksForPaths(const QStringList &paths, const QString &appBundlePath, const QList< QString > &rpaths, bool useDebugLibs)
bool copyFilePrintStatus(const QString &from, const QString &to)
void deployRPaths(const QString &bundlePath, const QList< QString > &rpaths, const QString &binaryPath, bool useLoaderPath)
QString getLibInfix(const QStringList &deployedFrameworks)
QList< QString > getBinaryRPaths(const QString &path, bool resolve=true, QString executablePath=QString())
void patch_debugInInfoPlist(const QString &infoPlistPath)
void changeIdentification(const QString &id, const QString &binaryPath)
OtoolInfo findDependencyInfo(const QString &binaryPath)
void createDiskImage(const QString &appBundlePath, const QString &filesystemType)
void runInstallNameTool(QStringList options)
QList< FrameworkInfo > getQtFrameworks(const QList< DylibInfo > &dependencies, const QString &appBundlePath, const QList< QString > &rpaths, bool useDebugLibs)
QString copyFramework(const FrameworkInfo &framework, const QString path)
void stripAppBinary(const QString &bundlePath)
QStringList findAppFrameworkPaths(const QString &appBundlePath)
bool alwaysOwerwriteEnabled
void deployPlugins(const ApplicationBundleInfo &appBundleInfo, const QString &pluginSourcePath, const QString pluginDestinationPath, DeploymentInfo deploymentInfo, bool useDebugLibs)
void deployQmlImport(const QString &appBundlePath, const QList< QString > &rpaths, const QString &importSourcePath, const QString &importName)
DeploymentInfo deployQtFrameworks(QList< FrameworkInfo > frameworks, const QString &bundlePath, const QStringList &binaryPaths, bool useDebugLibs, bool useLoaderPath)
void recursiveCopyAndDeploy(const QString &appBundlePath, const QList< QString > &rpaths, const QString &sourcePath, const QString &destinationPath)
QString resolveDyldPrefix(const QString &path, const QString &loaderPath, const QString &executablePath)
bool linkFilePrintStatus(const QString &file, const QString &link)
QStringList findAppFrameworkNames(const QString &appBundlePath)
void changeInstallName(const QString &bundlePath, const FrameworkInfo &framework, const QStringList &binaryPaths, bool useLoaderPath)
QString findEntitlementsFile(const QString &path)
void codesign(const QString &identity, const QString &appBundlePath)
QString copyDylib(const FrameworkInfo &framework, const QString path)
QStringList findAppLibraries(const QString &appBundlePath)
FrameworkInfo parseOtoolLibraryLine(const QString &line, const QString &appBundlePath, const QList< QString > &rpaths, bool useDebugLibs)
QDebug operator<<(QDebug debug, const FrameworkInfo &info)
QFileInfo info(fileName)
[8]
bool contains(const AT &t) const noexcept