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