From ba06d5a8fb2f8417f406b3bba8c3ccc927bfc38e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=96mer=20G=C3=B6kta=C5=9F?= Date: Sat, 12 Oct 2024 18:37:25 +0300 Subject: [PATCH] Small adjustments made ClangFormat added Code style updated Version bumped --- .clang-format | 270 ++++++++++ .gitignore | 6 +- CMakeLists.txt | 2 +- main.cpp | 244 +++++---- shared.cpp | 1311 +++++++++++++++++++++++++++--------------------- shared.h | 89 ++-- 6 files changed, 1231 insertions(+), 691 deletions(-) create mode 100644 .clang-format mode change 100644 => 100755 .gitignore diff --git a/.clang-format b/.clang-format new file mode 100644 index 00000000..03b02771 --- /dev/null +++ b/.clang-format @@ -0,0 +1,270 @@ +# yaml-language-server: $schema=https://json.schemastore.org/clang-format.json +--- +Language: Cpp +AccessModifierOffset: -4 +AlignAfterOpenBracket: Align +AlignArrayOfStructures: None +AlignConsecutiveAssignments: + Enabled: false + AcrossEmptyLines: false + AcrossComments: false + AlignCompound: false + PadOperators: false +AlignConsecutiveBitFields: + Enabled: false + AcrossEmptyLines: false + AcrossComments: false + AlignCompound: false + PadOperators: false +AlignConsecutiveDeclarations: + Enabled: false + AcrossEmptyLines: false + AcrossComments: false + AlignCompound: false + PadOperators: false +AlignConsecutiveMacros: + Enabled: false + AcrossEmptyLines: false + AcrossComments: false + AlignCompound: false + PadOperators: false +AlignConsecutiveShortCaseStatements: + Enabled: false + AcrossEmptyLines: false + AcrossComments: false + AlignCaseColons: false +AlignEscapedNewlines: DontAlign +AlignOperands: Align +AlignTrailingComments: + Kind: Always + OverEmptyLines: 0 +AllowAllArgumentsOnNextLine: true +AllowAllParametersOfDeclarationOnNextLine: true +AllowShortBlocksOnASingleLine: Never +AllowShortCaseLabelsOnASingleLine: false +AllowShortEnumsOnASingleLine: true +AllowShortFunctionsOnASingleLine: Inline +AllowShortIfStatementsOnASingleLine: Never +AllowShortLambdasOnASingleLine: All +AllowShortLoopsOnASingleLine: false +AlwaysBreakAfterDefinitionReturnType: None +AlwaysBreakAfterReturnType: None +AlwaysBreakBeforeMultilineStrings: false +AlwaysBreakTemplateDeclarations: Yes +AttributeMacros: + - __capability +BinPackArguments: false +BinPackParameters: false +BitFieldColonSpacing: Both +BraceWrapping: + AfterCaseLabel: false + AfterClass: true + AfterControlStatement: Never + AfterEnum: false + AfterExternBlock: false + AfterFunction: true + AfterNamespace: false + AfterObjCDeclaration: false + AfterStruct: true + AfterUnion: false + BeforeCatch: false + BeforeElse: false + BeforeLambdaBody: false + BeforeWhile: false + IndentBraces: false + SplitEmptyFunction: false + SplitEmptyRecord: false + SplitEmptyNamespace: false +BreakAfterAttributes: Never +BreakAfterJavaFieldAnnotations: false +BreakArrays: true +BreakBeforeBinaryOperators: All +BreakBeforeConceptDeclarations: Always +BreakBeforeBraces: Custom +BreakBeforeInlineASMColon: OnlyMultiline +BreakBeforeTernaryOperators: true +BreakConstructorInitializers: BeforeComma +BreakInheritanceList: BeforeColon +BreakStringLiterals: true +ColumnLimit: 88 +CommentPragmas: '^ IWYU pragma:' +CompactNamespaces: false +ConstructorInitializerIndentWidth: 4 +ContinuationIndentWidth: 4 +Cpp11BracedListStyle: true +DerivePointerAlignment: false +DisableFormat: false +EmptyLineAfterAccessModifier: Never +EmptyLineBeforeAccessModifier: LogicalBlock +ExperimentalAutoDetectBinPacking: false +FixNamespaceComments: true +ForEachMacros: + - forever + - foreach + - Q_FOREACH + - BOOST_FOREACH +IfMacros: + - KJ_IF_MAYBE +IncludeBlocks: Preserve +IncludeCategories: + - Regex: '^ #include #include -#include #include #include +#include #include #include #include -#include int main(int argc, char* argv[]) { @@ -28,7 +28,7 @@ int main(int argc, char* argv[]) // print version statement std::stringstream version; - version << APP_NAME << " v" APP_VERSION ; + version << APP_NAME << " v" APP_VERSION; qInfo().noquote() << QString::fromStdString(version.str()); bool plugins = true; @@ -57,7 +57,7 @@ int main(int argc, char* argv[]) // Due to the structure of the argument parser, we have to check all arguments at first to check whether the user // wants to get the version only // TODO: replace argument parser with position independent, less error prone version - for (int i = 0; i < argc; i++ ) { + for (int i = 0; i < argc; i++) { QString argument = argv[i]; if (argument == "-version" || argument == "-V" || argument == "--version") { // can just exit normally, version has been printed above @@ -91,7 +91,7 @@ int main(int argc, char* argv[]) LogDebug() << "Argument found:" << argument; int index = argument.indexOf("="); bool ok = false; - int number = argument.mid(index+1).toInt(&ok); + int number = argument.mid(index + 1).toInt(&ok); if (!ok) LogError() << "Could not parse verbose level"; else @@ -102,14 +102,14 @@ int main(int argc, char* argv[]) if (index == -1) LogError() << "Missing executable folder path"; else - additionalExecutablesDir << argument.mid(index+1); + additionalExecutablesDir << argument.mid(index + 1); } else if (argument.startsWith(QByteArray("-executable"))) { LogDebug() << "Argument found:" << argument; int index = argument.indexOf('='); if (index == -1) LogError() << "Missing executable path"; else - additionalExecutables << argument.mid(index+1); + additionalExecutables << argument.mid(index + 1); } else if (argument.startsWith(QByteArray("-qmldir"))) { LogDebug() << "Argument found:" << argument; qmldirArgumentUsed = true; @@ -117,14 +117,14 @@ int main(int argc, char* argv[]) if (index == -1) LogError() << "Missing qml directory path"; else - qmlDirs << argument.mid(index+1); + qmlDirs << argument.mid(index + 1); } else if (argument.startsWith(QByteArray("-qmlimport"))) { LogDebug() << "Argument found:" << argument; int index = argument.indexOf('='); if (index == -1) LogError() << "Missing qml import path"; else - qmlImportPaths << argument.mid(index+1); + qmlImportPaths << argument.mid(index + 1); } else if (argument.startsWith("-no-copy-copyright-files")) { LogDebug() << "Argument found:" << argument; copyCopyrightFiles = false; @@ -134,7 +134,7 @@ int main(int argc, char* argv[]) } else if (argument.startsWith("-qmake=")) { LogDebug() << "Argument found:" << argument; int index = argument.indexOf("="); - qmakeExecutable = argument.mid(index+1); + qmakeExecutable = argument.mid(index + 1); } else if (argument == QByteArray("-no-translations")) { LogDebug() << "Argument found:" << argument; skipTranslations = true; @@ -153,13 +153,14 @@ int main(int argc, char* argv[]) } else if (argument.startsWith("-updateinformation=")) { LogDebug() << "Argument found:" << argument; int index = argument.indexOf("="); - updateInformation = QString(argument.mid(index+1)); + updateInformation = QString(argument.mid(index + 1)); } else if (argument.startsWith("-qtlibinfix=")) { LogDebug() << "Argument found:" << argument; int index = argument.indexOf("="); - qtLibInfix = QString(argument.mid(index+1)); + qtLibInfix = QString(argument.mid(index + 1)); } else if (argument.startsWith("--")) { - LogError() << "Error: arguments must not start with --, only -:" << argument << "\n"; + LogError() << "Error: arguments must not start with --, only -:" << argument + << "\n"; return EXIT_FAILURE; } else { LogError() << "Unknown argument:" << argument << "\n"; @@ -168,11 +169,14 @@ int main(int argc, char* argv[]) } // Warn about use of new glibc - const char *glcv = gnu_get_libc_version (); - if (strverscmp (glcv, "2.32") >= 0) { - qInfo() << "WARNING: The host system is too new (glibc > 2.31). To ensure compatibility with older systems,"; - qInfo() << " please consider running this tool on an older mainstream Linux distribution. This will"; - qInfo() << " allow the resulting bundle to work on most Linux distributions, including the older ones."; + const char* glcv = gnu_get_libc_version(); + if (strverscmp(glcv, "2.32") >= 0) { + qInfo() << "WARNING: The host system is too new (glibc > 2.31). To ensure " + "compatibility with older systems,"; + qInfo() << " please consider running this tool on an older mainstream " + "Linux distribution. This will"; + qInfo() << " allow the resulting bundle to work on most Linux " + "distributions, including the older ones."; } if (argc < 2 || (firstArgument.startsWith("-"))) { @@ -180,39 +184,54 @@ int main(int argc, char* argv[]) qInfo() << "Usage:" << APP_NAME << " [options]"; qInfo() << ""; qInfo() << "Options:"; - qInfo() << " -always-overwrite : Copy files even if the target file exists."; - qInfo() << " -appimage : Create an AppImage (implies -bundle-non-qt-libs)."; - qInfo() << " -bundle-non-qt-libs : Also bundle non-core, non-Qt libraries."; - qInfo() << " -bundle-everything : Bundle everything including system libraries."; - qInfo() << " -exclude-libs= : List of libraries which should be excluded,"; + qInfo() << " -always-overwrite : Copy files even if the target file " + "exists."; + qInfo() << " -appimage : Create an AppImage (implies " + "-bundle-non-qt-libs)."; + qInfo() + << " -bundle-non-qt-libs : Also bundle non-core, non-Qt libraries."; + qInfo() << " -bundle-everything : Bundle everything including system " + "libraries."; + qInfo() << " -exclude-libs= : List of libraries which should be " + "excluded,"; qInfo() << " separated by comma."; - qInfo() << " -ignore-glob= : Glob pattern relative to appdir to ignore when"; + qInfo() << " -ignore-glob= : Glob pattern relative to appdir to " + "ignore when"; qInfo() << " searching for libraries."; - qInfo() << " -executable= : Let the given executable use the deployed libraries"; + qInfo() << " -executable= : Let the given executable use the " + "deployed libraries"; qInfo() << " too"; - qInfo() << " -executable-dir= : Let all the executables in the folder (recursive) use"; + qInfo() << " -executable-dir= : Let all the executables in the " + "folder (recursive) use"; qInfo() << " the deployed libraries too"; - qInfo() << " -extra-plugins= : List of extra plugins which should be deployed,"; + qInfo() << " -extra-plugins= : List of extra plugins which should " + "be deployed,"; qInfo() << " separated by comma."; qInfo() << " -no-copy-copyright-files : Skip deployment of copyright files."; qInfo() << " -no-plugins : Skip plugin deployment."; qInfo() << " -no-strip : Don't run 'strip' on the binaries."; qInfo() << " -no-translations : Skip deployment of translations."; qInfo() << " -qmake= : The qmake executable to use."; - qInfo() << " -qmldir= : Scan for QML imports in the given path."; - qInfo() << " -qmlimport= : Add the given path to QML module search locations."; + qInfo() + << " -qmldir= : Scan for QML imports in the given path."; + qInfo() << " -qmlimport= : Add the given path to QML module " + "search locations."; qInfo() << " -show-exclude-libs : Print exclude libraries list."; - qInfo() << " -verbose=<0-3> : 0 = no output, 1 = error/warning (default),"; + qInfo() << " -verbose=<0-3> : 0 = no output, 1 = error/warning " + "(default),"; qInfo() << " 2 = normal, 3 = debug."; - qInfo() << " -updateinformation= : Embed update information STRING; if zsyncmake is installed, generate zsync file"; - qInfo() << " -qtlibinfix= : Adapt the .so search if your Qt distribution has infix."; + qInfo() << " -updateinformation= : Embed update " + "information STRING; if zsyncmake is installed, generate zsync file"; + qInfo() << " -qtlibinfix= : Adapt the .so search if your Qt " + "distribution has infix."; qInfo() << " -version : Print version statement and exit."; qInfo() << ""; qInfo() << APP_NAME << "takes an application as input and makes it"; qInfo() << "self-contained by copying in the Qt libraries and plugins that"; qInfo() << "the application uses."; qInfo() << ""; - qInfo() << "By default it deploys the Qt instance that qmake on the $PATH points to."; + qInfo() << "By default it deploys the Qt instance that qmake on the $PATH " + "points to."; qInfo() << "The '-qmake' option can be used to point to the qmake executable"; qInfo() << "to be used instead."; qInfo() << ""; @@ -240,57 +259,80 @@ int main(int argc, char* argv[]) qDebug() << "Desktop file as first argument:" << firstArgument; /* Check if the desktop file really exists */ - if (! QFile::exists(firstArgument)) { + if (!QFile::exists(firstArgument)) { LogError() << "Desktop file in first argument does not exist!"; return EXIT_FAILURE; } - QSettings * settings = 0; + QSettings* settings = 0; settings = new QSettings(firstArgument, QSettings::IniFormat); - desktopExecEntry = settings->value("Desktop Entry/Exec", "r").toString().split(' ').first().split('/').last().trimmed(); + desktopExecEntry = settings->value("Desktop Entry/Exec", "r") + .toString() + .split(' ') + .first() + .split('/') + .last() + .trimmed(); qDebug() << "desktopExecEntry:" << desktopExecEntry; desktopFile = firstArgument; - desktopIconEntry = settings->value("Desktop Entry/Icon", "r").toString().split(' ').first(); + desktopIconEntry = settings->value("Desktop Entry/Icon", "r") + .toString() + .split(' ') + .first(); qDebug() << "desktopIconEntry:" << desktopIconEntry; - QString candidateBin = QDir::cleanPath(QFileInfo(firstArgument).absolutePath() + desktopExecEntry); // Not FHS-like + QString candidateBin = QDir::cleanPath( + QFileInfo(firstArgument).absolutePath() + + desktopExecEntry); // Not FHS-like /* Search directory for an executable with the name in the Exec= key */ QString directoryToBeSearched; - directoryToBeSearched = QDir::cleanPath(QFileInfo(firstArgument).absolutePath()); + directoryToBeSearched = QDir::cleanPath( + QFileInfo(firstArgument).absolutePath()); QDirIterator it(directoryToBeSearched, QDirIterator::Subdirectories); while (it.hasNext()) { it.next(); - if((it.fileName() == desktopExecEntry) && (it.fileInfo().isFile()) && (it.fileInfo().isExecutable())) { - qDebug() << "Found binary from desktop file:" << it.fileInfo().canonicalFilePath(); + if ((it.fileName() == desktopExecEntry) && (it.fileInfo().isFile()) + && (it.fileInfo().isExecutable())) { + qDebug() << "Found binary from desktop file:" + << it.fileInfo().canonicalFilePath(); appBinaryPath = it.fileInfo().absoluteFilePath(); break; } } /* Only if we could not find it below the directory in which the desktop file resides, search above */ - if(appBinaryPath == "") { - if(QFileInfo(QDir::cleanPath(QFileInfo(firstArgument).absolutePath() + "/../../bin/" + desktopExecEntry)).exists()) { - directoryToBeSearched = QDir::cleanPath(QFileInfo(firstArgument).absolutePath() + "/../../"); + if (appBinaryPath == "") { + if (QFile::exists( + QDir::cleanPath(QFileInfo(firstArgument).absolutePath() + + "/../../bin/" + desktopExecEntry))) { + directoryToBeSearched = QDir::cleanPath( + QFileInfo(firstArgument).absolutePath() + "/../../"); } else { - directoryToBeSearched = QDir::cleanPath(QFileInfo(firstArgument).absolutePath() + "/../"); + directoryToBeSearched = QDir::cleanPath( + QFileInfo(firstArgument).absolutePath() + "/../"); } QDirIterator it2(directoryToBeSearched, QDirIterator::Subdirectories); while (it2.hasNext()) { it2.next(); - if((it2.fileName() == desktopExecEntry) && (it2.fileInfo().isFile()) && (it2.fileInfo().isExecutable())) { - qDebug() << "Found binary from desktop file:" << it2.fileInfo().canonicalFilePath(); + if ((it2.fileName() == desktopExecEntry) + && (it2.fileInfo().isFile()) + && (it2.fileInfo().isExecutable())) { + qDebug() << "Found binary from desktop file:" + << it2.fileInfo().canonicalFilePath(); appBinaryPath = it2.fileInfo().absoluteFilePath(); break; } } } - if(appBinaryPath == "") { - if((QFileInfo(candidateBin).isFile()) && (QFileInfo(candidateBin).isExecutable())) { + if (appBinaryPath == "") { + if ((QFileInfo(candidateBin).isFile()) + && (QFileInfo(candidateBin).isExecutable())) { appBinaryPath = QFileInfo(candidateBin).absoluteFilePath(); } else { - LogError() << "Could not determine the path to the executable based on the desktop file\n"; + LogError() << "Could not determine the path to the executable " + "based on the desktop file\n"; return EXIT_FAILURE; } } @@ -336,15 +378,15 @@ int main(int argc, char* argv[]) QString appDirPath; QString relativeBinPath; - if(fhsLikeMode == false) { + if (fhsLikeMode == false) { appDirPath = appDir; relativeBinPath = appName; } else { appDirPath = QDir::cleanPath(fhsPrefix + "/../"); - QString relativePrefix = fhsPrefix.replace(appDirPath+"/", ""); + QString relativePrefix = fhsPrefix.replace(appDirPath + "/", ""); relativeBinPath = relativePrefix + "/bin/" + appName; } - if(appDirPath == "/") { + if (appDirPath == "/") { LogError() << "'/' is not a valid AppDir. Please refer to the documentation."; LogError() << "Consider adding INSTALL_ROOT or DESTDIR to your install steps."; return EXIT_FAILURE; @@ -353,7 +395,7 @@ int main(int argc, char* argv[]) qDebug() << "relativeBinPath:" << relativeBinPath; QFile appRun(appDirPath + "/AppRun"); - if(appRun.exists()) { + if (appRun.exists()) { qDebug() << "Keeping existing AppRun"; } else { if (!QFile::copy(QCoreApplication::applicationDirPath() + "/../../AppRun", @@ -363,15 +405,17 @@ int main(int argc, char* argv[]) } /* Copy the desktop file in place, into the top level of the AppDir */ - if(desktopFile != "") { - QString destination = QDir::cleanPath(appDirPath + "/" + QFileInfo(desktopFile).fileName()); - if(QFileInfo(destination).exists() == false) { + if (desktopFile != "") { + QString destination = QDir::cleanPath(appDirPath + "/" + + QFileInfo(desktopFile).fileName()); + if (QFile::exists(destination) == false) { if (QFile::copy(desktopFile, destination)) { qDebug() << "Copied" << desktopFile << "to" << destination; } } - if(QFileInfo(destination).isFile() == false) { - LogError() << destination << "does not exist and could not be copied there\n"; + if (QFileInfo(destination).isFile() == false) { + LogError() << destination + << "does not exist and could not be copied there\n"; return EXIT_FAILURE; } } @@ -379,22 +423,34 @@ int main(int argc, char* argv[]) /* To make an AppDir, we need to find the icon and copy it in place */ QStringList candidates; QString iconToBeUsed = ""; - if(desktopIconEntry != "") { + if (desktopIconEntry != "") { QDirIterator it3(appDirPath, QDirIterator::Subdirectories); while (it3.hasNext()) { it3.next(); - if((it3.fileName().startsWith(desktopIconEntry)) && ((it3.fileName().endsWith(".png")) || (it3.fileName().endsWith(".svg")) || (it3.fileName().endsWith(".svgz")) || (it3.fileName().endsWith(".xpm")))) { + if ((it3.fileName().startsWith(desktopIconEntry)) + && ((it3.fileName().endsWith(".png")) + || (it3.fileName().endsWith(".svg")) + || (it3.fileName().endsWith(".svgz")) + || (it3.fileName().endsWith(".xpm")))) { candidates.append(it3.filePath()); } } qDebug() << "Found icons from desktop file:" << candidates; /* Select the main icon from the candidates */ - if(candidates.length() == 1) { + if (candidates.length() == 1) { iconToBeUsed = candidates.at(0); // The only choice - } else if(candidates.length() > 1) { - const QStringList iconPriorities{"256", "128", "svg", "svgz", "512", "1024", "64", "48", "xpm"}; - foreach (const QString &iconPriority, iconPriorities) { + } else if (candidates.length() > 1) { + const QStringList iconPriorities{"256", + "128", + "svg", + "svgz", + "512", + "1024", + "64", + "48", + "xpm"}; + foreach (const QString& iconPriority, iconPriorities) { const auto filteredCandidates = candidates.filter(iconPriority); if (!filteredCandidates.isEmpty()) { iconToBeUsed = filteredCandidates.first(); @@ -404,37 +460,43 @@ int main(int argc, char* argv[]) } /* Copy in place */ - if(iconToBeUsed != "") { + if (iconToBeUsed != "") { /* Check if there is already an icon and only if there is not, copy it to the AppDir. * As per the ROX AppDir spec, also copying to .DirIcon. */ QString preExistingToplevelIcon = ""; - if(QFileInfo(appDirPath + "/" + desktopIconEntry + ".xpm").exists() == true) { + if (QFile::exists(appDirPath + "/" + desktopIconEntry + ".xpm") == true) { preExistingToplevelIcon = appDirPath + "/" + desktopIconEntry + ".xpm"; - if(QFileInfo(appDirPath + "/.DirIcon").exists() == false) QFile::copy(preExistingToplevelIcon, appDirPath + "/.DirIcon"); + if (QFile::exists(appDirPath + "/.DirIcon") == false) + QFile::copy(preExistingToplevelIcon, appDirPath + "/.DirIcon"); } - if(QFileInfo(appDirPath + "/" + desktopIconEntry + ".svgz").exists() == true) { + if (QFile::exists(appDirPath + "/" + desktopIconEntry + ".svgz") == true) { preExistingToplevelIcon = appDirPath + "/" + desktopIconEntry + ".svgz"; - if(QFileInfo(appDirPath + "/.DirIcon").exists() == false) QFile::copy(preExistingToplevelIcon, appDirPath + "/.DirIcon"); + if (QFile::exists(appDirPath + "/.DirIcon") == false) + QFile::copy(preExistingToplevelIcon, appDirPath + "/.DirIcon"); } - if(QFileInfo(appDirPath + "/" + desktopIconEntry + ".svg").exists() == true) { + if (QFile::exists(appDirPath + "/" + desktopIconEntry + ".svg") == true) { preExistingToplevelIcon = appDirPath + "/" + desktopIconEntry + ".svg"; - if(QFileInfo(appDirPath + "/.DirIcon").exists() == false) QFile::copy(preExistingToplevelIcon, appDirPath + "/.DirIcon"); + if (QFile::exists(appDirPath + "/.DirIcon") == false) + QFile::copy(preExistingToplevelIcon, appDirPath + "/.DirIcon"); } - if(QFileInfo(appDirPath + "/" + desktopIconEntry + ".png").exists() == true) { + if (QFile::exists(appDirPath + "/" + desktopIconEntry + ".png") == true) { preExistingToplevelIcon = appDirPath + "/" + desktopIconEntry + ".png"; - if(QFileInfo(appDirPath + "/.DirIcon").exists() == false) QFile::copy(preExistingToplevelIcon, appDirPath + "/.DirIcon"); + if (QFile::exists(appDirPath + "/.DirIcon") == false) + QFile::copy(preExistingToplevelIcon, appDirPath + "/.DirIcon"); } - if(preExistingToplevelIcon != "") { + if (preExistingToplevelIcon != "") { qDebug() << "preExistingToplevelIcon:" << preExistingToplevelIcon; } else { qDebug() << "iconToBeUsed:" << iconToBeUsed; - QString targetIconPath = appDirPath + "/" + QFileInfo(iconToBeUsed).fileName(); + QString targetIconPath = appDirPath + "/" + + QFileInfo(iconToBeUsed).fileName(); if (QFile::copy(iconToBeUsed, targetIconPath)) { qDebug() << "Copied" << iconToBeUsed << "to" << targetIconPath; QFile::copy(targetIconPath, appDirPath + "/.DirIcon"); } else { - LogError() << "Could not copy" << iconToBeUsed << "to" << targetIconPath << "\n"; + LogError() << "Could not copy" << iconToBeUsed << "to" + << targetIconPath << "\n"; exit(1); } } @@ -442,26 +504,29 @@ int main(int argc, char* argv[]) } if (appimage) { - if(checkAppImagePrerequisites(appDirPath) == false) { + if (checkAppImagePrerequisites(appDirPath) == false) { LogError() << "checkAppImagePrerequisites failed\n"; return EXIT_FAILURE; } } // recurse folders for additional executables - for(const auto& folder : additionalExecutablesDir) { - QString directoryToBeSearched = QDir::cleanPath(QFileInfo(folder).absolutePath()); - QDirIterator it(directoryToBeSearched, QDirIterator::Subdirectories); - while (it.hasNext()) { - it.next(); - if((it.fileInfo().isFile()) && (it.fileInfo().isExecutable())){ - qDebug() << "Found additional executable:" << it.fileInfo().canonicalFilePath(); - additionalExecutables << it.fileInfo().absoluteFilePath(); + for (const auto& folder : additionalExecutablesDir) { + QString directoryToBeSearched = QDir::cleanPath( + QFileInfo(folder).absolutePath()); + QDirIterator it(directoryToBeSearched, QDirIterator::Subdirectories); + while (it.hasNext()) { + it.next(); + if ((it.fileInfo().isFile()) && (it.fileInfo().isExecutable())) { + qDebug() << "Found additional executable:" + << it.fileInfo().canonicalFilePath(); + additionalExecutables << it.fileInfo().absoluteFilePath(); + } } - } } - DeploymentInfo deploymentInfo = deployQtLibraries(appDirPath, additionalExecutables, + DeploymentInfo deploymentInfo = deployQtLibraries(appDirPath, + additionalExecutables, qmakeExecutable); // Convenience: Look for .qml files in the current directoty if no -qmldir specified. @@ -487,7 +552,8 @@ int main(int argc, char* argv[]) if (plugins && !deploymentInfo.qtPath.isEmpty()) { if (deploymentInfo.pluginPath.isEmpty()) - deploymentInfo.pluginPath = QDir::cleanPath(deploymentInfo.qtPath + "/../plugins"); + deploymentInfo.pluginPath = QDir::cleanPath(deploymentInfo.qtPath + + "/../plugins"); deployPlugins(appDirPath, deploymentInfo); createQtConf(appDirPath); } diff --git a/shared.cpp b/shared.cpp index 8a712130..51d5a466 100644 --- a/shared.cpp +++ b/shared.cpp @@ -3,76 +3,74 @@ #include #include -#include #include #include -#include +#include #include #include -#include #include +#include +#include #include #include #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) -# define QSTRING_SPLIT_BEHAVIOR_NAMESPACE QString +#define QSTRING_SPLIT_BEHAVIOR_NAMESPACE QString #else -# define QSTRING_SPLIT_BEHAVIOR_NAMESPACE Qt +#define QSTRING_SPLIT_BEHAVIOR_NAMESPACE Qt #endif -QStringList excludedLibraries { - "ld-linux.so.2", - "ld-linux-x86-64.so.2", - "libanl.so.1", - "libasound.so.2", - "libBrokenLocale.so.1", - "libcidn.so.1", - "libcom_err.so.2", - "libc.so.6", - "libdl.so.2", - "libdrm.so.2", - "libEGL.so.1", - "libexpat.so.1", - "libfontconfig.so.1", - "libfreetype.so.6", - "libfribidi.so.0", - "libgbm.so.1", - "libgcc_s.so.1", - "libglapi.so.0", - "libGLdispatch.so.0", - "libGL.so.1", - "libGLX.so.0", - "libgmp.so.10", - "libgpg-error.so.0", - "libharfbuzz.so.0", - "libICE.so.6", - "libjack.so.0", - "libm.so.6", - "libmvec.so.1", - "libnss_compat.so.2", - "libnss_dns.so.2", - "libnss_files.so.2", - "libnss_hesiod.so.2", - "libnss_nisplus.so.2", - "libnss_nis.so.2", - "libOpenGL.so.0", - "libp11-kit.so.0", - "libpthread.so.0", - "libresolv.so.2", - "librt.so.1", - "libSM.so.6", - "libstdc++.so.6", - "libthai.so.0", - "libthread_db.so.1", - "libusb-1.0.so.0", - "libutil.so.1", - "libuuid.so.1", - "libX11.so.6", - "libxcb-dri2.so.0", - "libxcb-dri3.so.0", - "libxcb.so.1", - "libz.so.1" -}; +QStringList excludedLibraries{"ld-linux.so.2", + "ld-linux-x86-64.so.2", + "libanl.so.1", + "libasound.so.2", + "libBrokenLocale.so.1", + "libcidn.so.1", + "libcom_err.so.2", + "libc.so.6", + "libdl.so.2", + "libdrm.so.2", + "libEGL.so.1", + "libexpat.so.1", + "libfontconfig.so.1", + "libfreetype.so.6", + "libfribidi.so.0", + "libgbm.so.1", + "libgcc_s.so.1", + "libglapi.so.0", + "libGLdispatch.so.0", + "libGL.so.1", + "libGLX.so.0", + "libgmp.so.10", + "libgpg-error.so.0", + "libharfbuzz.so.0", + "libICE.so.6", + "libjack.so.0", + "libm.so.6", + "libmvec.so.1", + "libnss_compat.so.2", + "libnss_dns.so.2", + "libnss_files.so.2", + "libnss_hesiod.so.2", + "libnss_nisplus.so.2", + "libnss_nis.so.2", + "libOpenGL.so.0", + "libp11-kit.so.0", + "libpthread.so.0", + "libresolv.so.2", + "librt.so.1", + "libSM.so.6", + "libstdc++.so.6", + "libthai.so.0", + "libthread_db.so.1", + "libusb-1.0.so.0", + "libutil.so.1", + "libuuid.so.1", + "libX11.so.6", + "libxcb-dri2.so.0", + "libxcb-dri3.so.0", + "libxcb.so.1", + "libz.so.1"}; QString appBinaryPath; bool runStripEnabled = true; bool bundleAllButBlacklistedLibs = false; @@ -84,7 +82,8 @@ QStringList librarySearchPath; bool appstoreCompliant = false; int logLevel = 1; int qtDetected = 0; -bool qtDetectionComplete = 0; // As long as Qt is not detected yet, ldd may encounter "not found" messages, continue anyway +bool qtDetectionComplete + = 0; // As long as Qt is not detected yet, ldd may encounter "not found" messages, continue anyway bool deployLibrary = false; QStringList extraQtPlugins; QStringList ignoreGlob; @@ -95,63 +94,63 @@ QString qtLibInfix; using std::cout; using std::endl; -static QMap qtToBeBundledInfo; +static QMap qtToBeBundledInfo; enum Qt5Module #if defined(Q_COMPILER_CLASS_ENUM) : quint64 #endif { - Qt5BluetoothModule = 0x0000000000000001, - Qt5CLuceneModule = 0x0000000000000002, - Qt5ConcurrentModule = 0x0000000000000004, - Qt5CoreModule = 0x0000000000000008, - Qt5DeclarativeModule = 0x0000000000000010, - Qt5DesignerComponents = 0x0000000000000020, - Qt5DesignerModule = 0x0000000000000040, - Qt5GuiModule = 0x0000000000000080, - Qt5CluceneModule = 0x0000000000000100, - Qt5HelpModule = 0x0000000000000200, - Qt5MultimediaModule = 0x0000000000000400, + Qt5BluetoothModule = 0x0000000000000001, + Qt5CLuceneModule = 0x0000000000000002, + Qt5ConcurrentModule = 0x0000000000000004, + Qt5CoreModule = 0x0000000000000008, + Qt5DeclarativeModule = 0x0000000000000010, + Qt5DesignerComponents = 0x0000000000000020, + Qt5DesignerModule = 0x0000000000000040, + Qt5GuiModule = 0x0000000000000080, + Qt5CluceneModule = 0x0000000000000100, + Qt5HelpModule = 0x0000000000000200, + Qt5MultimediaModule = 0x0000000000000400, Qt5MultimediaWidgetsModule = 0x0000000000000800, - Qt5MultimediaQuickModule = 0x0000000000001000, - Qt5NetworkModule = 0x0000000000002000, - Qt5NfcModule = 0x0000000000004000, - Qt5OpenGLModule = 0x0000000000008000, - Qt5PositioningModule = 0x0000000000010000, - Qt5PrintSupportModule = 0x0000000000020000, - Qt5QmlModule = 0x0000000000040000, - Qt5QuickModule = 0x0000000000080000, - Qt5QuickParticlesModule = 0x0000000000100000, - Qt5ScriptModule = 0x0000000000200000, - Qt5ScriptToolsModule = 0x0000000000400000, - Qt5SensorsModule = 0x0000000000800000, - Qt5SerialPortModule = 0x0000000001000000, - Qt5SqlModule = 0x0000000002000000, - Qt5SvgModule = 0x0000000004000000, - Qt5TestModule = 0x0000000008000000, - Qt5WidgetsModule = 0x0000000010000000, - Qt5WinExtrasModule = 0x0000000020000000, - Qt5XmlModule = 0x0000000040000000, - Qt5XmlPatternsModule = 0x0000000080000000, - Qt5WebKitModule = 0x0000000100000000, - Qt5WebKitWidgetsModule = 0x0000000200000000, - Qt5QuickWidgetsModule = 0x0000000400000000, - Qt5WebSocketsModule = 0x0000000800000000, - Qt5EnginioModule = 0x0000001000000000, - Qt5WebEngineCoreModule = 0x0000002000000000, - Qt5WebEngineModule = 0x0000004000000000, - Qt5WebEngineWidgetsModule = 0x0000008000000000, - Qt5QmlToolingModule = 0x0000010000000000, - Qt53DCoreModule = 0x0000020000000000, - Qt53DRendererModule = 0x0000040000000000, - Qt53DQuickModule = 0x0000080000000000, - Qt53DQuickRendererModule = 0x0000100000000000, - Qt53DInputModule = 0x0000200000000000, - Qt5LocationModule = 0x0000400000000000, - Qt5WebChannelModule = 0x0000800000000000, - Qt5TextToSpeechModule = 0x0001000000000000, - Qt5SerialBusModule = 0x0002000000000000 + Qt5MultimediaQuickModule = 0x0000000000001000, + Qt5NetworkModule = 0x0000000000002000, + Qt5NfcModule = 0x0000000000004000, + Qt5OpenGLModule = 0x0000000000008000, + Qt5PositioningModule = 0x0000000000010000, + Qt5PrintSupportModule = 0x0000000000020000, + Qt5QmlModule = 0x0000000000040000, + Qt5QuickModule = 0x0000000000080000, + Qt5QuickParticlesModule = 0x0000000000100000, + Qt5ScriptModule = 0x0000000000200000, + Qt5ScriptToolsModule = 0x0000000000400000, + Qt5SensorsModule = 0x0000000000800000, + Qt5SerialPortModule = 0x0000000001000000, + Qt5SqlModule = 0x0000000002000000, + Qt5SvgModule = 0x0000000004000000, + Qt5TestModule = 0x0000000008000000, + Qt5WidgetsModule = 0x0000000010000000, + Qt5WinExtrasModule = 0x0000000020000000, + Qt5XmlModule = 0x0000000040000000, + Qt5XmlPatternsModule = 0x0000000080000000, + Qt5WebKitModule = 0x0000000100000000, + Qt5WebKitWidgetsModule = 0x0000000200000000, + Qt5QuickWidgetsModule = 0x0000000400000000, + Qt5WebSocketsModule = 0x0000000800000000, + Qt5EnginioModule = 0x0000001000000000, + Qt5WebEngineCoreModule = 0x0000002000000000, + Qt5WebEngineModule = 0x0000004000000000, + Qt5WebEngineWidgetsModule = 0x0000008000000000, + Qt5QmlToolingModule = 0x0000010000000000, + Qt53DCoreModule = 0x0000020000000000, + Qt53DRendererModule = 0x0000040000000000, + Qt53DQuickModule = 0x0000080000000000, + Qt53DQuickRendererModule = 0x0000100000000000, + Qt53DInputModule = 0x0000200000000000, + Qt5LocationModule = 0x0000400000000000, + Qt5WebChannelModule = 0x0000800000000000, + Qt5TextToSpeechModule = 0x0001000000000000, + Qt5SerialBusModule = 0x0002000000000000 }; enum Qt6Module @@ -159,174 +158,185 @@ enum Qt6Module : quint64 #endif { - Qt6BluetoothModule = 0x0000000000000001, - Qt6ConcurrentModule = 0x0000000000000002, - Qt6CoreModule = 0x0000000000000004, - Qt6DeclarativeModule = 0x0000000000000008, - Qt6DesignerComponents = 0x0000000000000010, - Qt6DesignerModule = 0x0000000000000020, - Qt6GuiModule = 0x0000000000000040, - Qt6HelpModule = 0x0000000000000080, - Qt6MultimediaModule = 0x0000000000000100, + Qt6BluetoothModule = 0x0000000000000001, + Qt6ConcurrentModule = 0x0000000000000002, + Qt6CoreModule = 0x0000000000000004, + Qt6DeclarativeModule = 0x0000000000000008, + Qt6DesignerComponents = 0x0000000000000010, + Qt6DesignerModule = 0x0000000000000020, + Qt6GuiModule = 0x0000000000000040, + Qt6HelpModule = 0x0000000000000080, + Qt6MultimediaModule = 0x0000000000000100, Qt6MultimediaWidgetsModule = 0x0000000000000200, - Qt6MultimediaQuickModule = 0x0000000000000400, - Qt6NetworkModule = 0x0000000000000800, - Qt6NfcModule = 0x0000000000001000, - Qt6OpenGLModule = 0x0000000000002000, - Qt6OpenGLWidgetsModule = 0x0000000000004000, - Qt6PositioningModule = 0x0000000000008000, - Qt6PrintSupportModule = 0x0000000000010000, - Qt6QmlModule = 0x0000000000020000, - Qt6QuickModule = 0x0000000000040000, - Qt6QuickParticlesModule = 0x0000000000080000, - Qt6ScriptModule = 0x0000000000100000, - Qt6ScriptToolsModule = 0x0000000000200000, - Qt6SensorsModule = 0x0000000000400000, - Qt6SerialPortModule = 0x0000000000800000, - Qt6SqlModule = 0x0000000001000000, - Qt6SvgModule = 0x0000000002000000, - Qt6SvgWidgetsModule = 0x0000000004000000, - Qt6TestModule = 0x0000000008000000, - Qt6WidgetsModule = 0x0000000010000000, - Qt6WinExtrasModule = 0x0000000020000000, - Qt6XmlModule = 0x0000000040000000, - Qt6QuickWidgetsModule = 0x0000000100000000, - Qt6WebSocketsModule = 0x0000000200000000, - Qt6WebEngineCoreModule = 0x0000000800000000, - Qt6WebEngineModule = 0x0000001000000000, - Qt6WebEngineWidgetsModule = 0x0000002000000000, - Qt6QmlToolingModule = 0x0000004000000000, - Qt63DCoreModule = 0x0000008000000000, - Qt63DRendererModule = 0x0000010000000000, - Qt63DQuickModule = 0x0000020000000000, - Qt63DQuickRendererModule = 0x0000040000000000, - Qt63DInputModule = 0x0000080000000000, - Qt6LocationModule = 0x0000100000000000, - Qt6WebChannelModule = 0x0000200000000000, - Qt6TextToSpeechModule = 0x0000400000000000, - Qt6SerialBusModule = 0x0000800000000000, - Qt6GamePadModule = 0x0001000000000000, - Qt63DAnimationModule = 0x0002000000000000, - Qt6WebViewModule = 0x0004000000000000, - Qt63DExtrasModule = 0x0008000000000000, - Qt6ShaderToolsModule = 0x0010000000000000 + Qt6MultimediaQuickModule = 0x0000000000000400, + Qt6NetworkModule = 0x0000000000000800, + Qt6NfcModule = 0x0000000000001000, + Qt6OpenGLModule = 0x0000000000002000, + Qt6OpenGLWidgetsModule = 0x0000000000004000, + Qt6PositioningModule = 0x0000000000008000, + Qt6PrintSupportModule = 0x0000000000010000, + Qt6QmlModule = 0x0000000000020000, + Qt6QuickModule = 0x0000000000040000, + Qt6QuickParticlesModule = 0x0000000000080000, + Qt6ScriptModule = 0x0000000000100000, + Qt6ScriptToolsModule = 0x0000000000200000, + Qt6SensorsModule = 0x0000000000400000, + Qt6SerialPortModule = 0x0000000000800000, + Qt6SqlModule = 0x0000000001000000, + Qt6SvgModule = 0x0000000002000000, + Qt6SvgWidgetsModule = 0x0000000004000000, + Qt6TestModule = 0x0000000008000000, + Qt6WidgetsModule = 0x0000000010000000, + Qt6WinExtrasModule = 0x0000000020000000, + Qt6XmlModule = 0x0000000040000000, + Qt6QuickWidgetsModule = 0x0000000100000000, + Qt6WebSocketsModule = 0x0000000200000000, + Qt6WebEngineCoreModule = 0x0000000800000000, + Qt6WebEngineModule = 0x0000001000000000, + Qt6WebEngineWidgetsModule = 0x0000002000000000, + Qt6QmlToolingModule = 0x0000004000000000, + Qt63DCoreModule = 0x0000008000000000, + Qt63DRendererModule = 0x0000010000000000, + Qt63DQuickModule = 0x0000020000000000, + Qt63DQuickRendererModule = 0x0000040000000000, + Qt63DInputModule = 0x0000080000000000, + Qt6LocationModule = 0x0000100000000000, + Qt6WebChannelModule = 0x0000200000000000, + Qt6TextToSpeechModule = 0x0000400000000000, + Qt6SerialBusModule = 0x0000800000000000, + Qt6GamePadModule = 0x0001000000000000, + Qt63DAnimationModule = 0x0002000000000000, + Qt6WebViewModule = 0x0004000000000000, + Qt63DExtrasModule = 0x0008000000000000, + Qt6ShaderToolsModule = 0x0010000000000000 }; -struct QtModuleEntry { +struct QtModuleEntry +{ quint64 module; - const char *option; - const char *libraryName; - const char *translation; + const char* option; + const char* libraryName; + const char* translation; }; -static QtModuleEntry *qtModuleEntries; +static QtModuleEntry* qtModuleEntries; static size_t qtModuleEntriesCount; -static QtModuleEntry qt5ModuleEntries[] = { - { Qt5BluetoothModule, "bluetooth", "Qt5Bluetooth", nullptr }, - { Qt5CLuceneModule, "clucene", "Qt5CLucene", "qt_help" }, - { Qt5ConcurrentModule, "concurrent", "Qt5Concurrent", "qtbase" }, - { Qt5CoreModule, "core", "Qt5Core", "qtbase" }, - { Qt5DeclarativeModule, "declarative", "Qt5Declarative", "qtquick1" }, - { Qt5DesignerModule, "designer", "Qt5Designer", nullptr }, - { Qt5DesignerComponents, "designercomponents", "Qt5DesignerComponents", nullptr }, - { Qt5EnginioModule, "enginio", "Enginio", nullptr }, - { Qt5GuiModule, "gui", "Qt5Gui", "qtbase" }, - { Qt5HelpModule, "qthelp", "Qt5Help", "qt_help" }, - { Qt5MultimediaModule, "multimedia", "Qt5Multimedia", "qtmultimedia" }, - { Qt5MultimediaWidgetsModule, "multimediawidgets", "Qt5MultimediaWidgets", "qtmultimedia" }, - { Qt5MultimediaQuickModule, "multimediaquick", "Qt5MultimediaQuick_p", "qtmultimedia" }, - { Qt5NetworkModule, "network", "Qt5Network", "qtbase" }, - { Qt5NfcModule, "nfc", "Qt5Nfc", nullptr }, - { Qt5OpenGLModule, "opengl", "Qt5OpenGL", nullptr }, - { Qt5PositioningModule, "positioning", "Qt5Positioning", nullptr }, - { Qt5PrintSupportModule, "printsupport", "Qt5PrintSupport", nullptr }, - { Qt5QmlModule, "qml", "Qt5Qml", "qtdeclarative" }, - { Qt5QmlToolingModule, "qmltooling", "qmltooling", nullptr }, - { Qt5QuickModule, "quick", "Qt5Quick", "qtdeclarative" }, - { Qt5QuickParticlesModule, "quickparticles", "Qt5QuickParticles", nullptr }, - { Qt5QuickWidgetsModule, "quickwidgets", "Qt5QuickWidgets", nullptr }, - { Qt5ScriptModule, "script", "Qt5Script", "qtscript" }, - { Qt5ScriptToolsModule, "scripttools", "Qt5ScriptTools", "qtscript" }, - { Qt5SensorsModule, "sensors", "Qt5Sensors", nullptr }, - { Qt5SerialPortModule, "serialport", "Qt5SerialPort", "qtserialport" }, - { Qt5SqlModule, "sql", "Qt5Sql", "qtbase" }, - { Qt5SvgModule, "svg", "Qt5Svg", nullptr }, - { Qt5TestModule, "test", "Qt5Test", "qtbase" }, - { Qt5WebKitModule, "webkit", "Qt5WebKit", nullptr }, - { Qt5WebKitWidgetsModule, "webkitwidgets", "Qt5WebKitWidgets", nullptr }, - { Qt5WebSocketsModule, "websockets", "Qt5WebSockets", "qtwebsockets" }, - { Qt5WidgetsModule, "widgets", "Qt5Widgets", "qtbase" }, - { Qt5WinExtrasModule, "winextras", "Qt5WinExtras", nullptr }, - { Qt5XmlModule, "xml", "Qt5Xml", "qtbase" }, - { Qt5XmlPatternsModule, "xmlpatterns", "Qt5XmlPatterns", "qtxmlpatterns" }, - { Qt5WebEngineCoreModule, "webenginecore", "Qt5WebEngineCore", nullptr }, - { Qt5WebEngineModule, "webengine", "Qt5WebEngine", "qtwebengine" }, - { Qt5WebEngineWidgetsModule, "webenginewidgets", "Qt5WebEngineWidgets", nullptr }, - { Qt53DCoreModule, "3dcore", "Qt53DCore", nullptr }, - { Qt53DRendererModule, "3drenderer", "Qt53DRenderer", nullptr }, - { Qt53DQuickModule, "3dquick", "Qt53DQuick", nullptr }, - { Qt53DQuickRendererModule, "3dquickrenderer", "Qt53DQuickRenderer", nullptr }, - { Qt53DInputModule, "3dinput", "Qt53DInput", nullptr }, - { Qt5LocationModule, "geoservices", "Qt5Location", nullptr }, - { Qt5WebChannelModule, "webchannel", "Qt5WebChannel", nullptr }, - { Qt5TextToSpeechModule, "texttospeech", "Qt5TextToSpeech", nullptr }, - { Qt5SerialBusModule, "serialbus", "Qt5SerialBus", nullptr } -}; - -static QtModuleEntry qt6ModuleEntries[] = { - { Qt6BluetoothModule, "bluetooth", "Qt6Bluetooth", nullptr }, - { Qt6ConcurrentModule, "concurrent", "Qt6Concurrent", "qtbase" }, - { Qt6CoreModule, "core", "Qt6Core", "qtbase" }, - { Qt6DeclarativeModule, "declarative", "Qt6Declarative", "qtquick1" }, - { Qt6DesignerModule, "designer", "Qt6Designer", nullptr }, - { Qt6DesignerComponents, "designercomponents", "Qt6DesignerComponents", nullptr }, - { Qt6GamePadModule, "gamepad", "Qt6Gamepad", nullptr }, - { Qt6GuiModule, "gui", "Qt6Gui", "qtbase" }, - { Qt6HelpModule, "qthelp", "Qt6Help", "qt_help" }, - { Qt6MultimediaModule, "multimedia", "Qt6Multimedia", "qtmultimedia" }, - { Qt6MultimediaWidgetsModule, "multimediawidgets", "Qt6MultimediaWidgets", "qtmultimedia" }, - { Qt6MultimediaQuickModule, "multimediaquick", "Qt6MultimediaQuick_p", "qtmultimedia" }, - { Qt6NetworkModule, "network", "Qt6Network", "qtbase" }, - { Qt6NfcModule, "nfc", "Qt6Nfc", nullptr }, - { Qt6OpenGLModule, "opengl", "Qt6OpenGL", nullptr }, - { Qt6OpenGLWidgetsModule, "openglwidgets", "Qt6OpenGLWidgets", nullptr }, - { Qt6PositioningModule, "positioning", "Qt6Positioning", nullptr }, - { Qt6PrintSupportModule, "printsupport", "Qt6PrintSupport", nullptr }, - { Qt6QmlModule, "qml", "Qt6Qml", "qtdeclarative" }, - { Qt6QmlToolingModule, "qmltooling", "qmltooling", nullptr }, - { Qt6QuickModule, "quick", "Qt6Quick", "qtdeclarative" }, - { Qt6QuickParticlesModule, "quickparticles", "Qt6QuickParticles", nullptr }, - { Qt6QuickWidgetsModule, "quickwidgets", "Qt6QuickWidgets", nullptr }, - { Qt6ScriptModule, "script", "Qt6Script", "qtscript" }, - { Qt6ScriptToolsModule, "scripttools", "Qt6ScriptTools", "qtscript" }, - { Qt6SensorsModule, "sensors", "Qt6Sensors", nullptr }, - { Qt6SerialPortModule, "serialport", "Qt6SerialPort", "qtserialport" }, - { Qt6SqlModule, "sql", "Qt6Sql", "qtbase" }, - { Qt6SvgModule, "svg", "Qt6Svg", nullptr }, - { Qt6SvgWidgetsModule, "svgwidgets", "Qt6SvgWidgets", nullptr }, - { Qt6TestModule, "test", "Qt6Test", "qtbase" }, - { Qt6WebSocketsModule, "websockets", "Qt6WebSockets", nullptr }, - { Qt6WidgetsModule, "widgets", "Qt6Widgets", "qtbase" }, - { Qt6WinExtrasModule, "winextras", "Qt6WinExtras", nullptr }, - { Qt6XmlModule, "xml", "Qt6Xml", "qtbase" }, - { Qt6WebEngineCoreModule, "webenginecore", "Qt6WebEngineCore", nullptr }, - { Qt6WebEngineModule, "webengine", "Qt6WebEngine", "qtwebengine" }, - { Qt6WebEngineWidgetsModule, "webenginewidgets", "Qt6WebEngineWidgets", nullptr }, - { Qt63DCoreModule, "3dcore", "Qt63DCore", nullptr }, - { Qt63DRendererModule, "3drenderer", "Qt63DRender", nullptr }, - { Qt63DQuickModule, "3dquick", "Qt63DQuick", nullptr }, - { Qt63DQuickRendererModule, "3dquickrenderer", "Qt63DQuickRender", nullptr }, - { Qt63DInputModule, "3dinput", "Qt63DInput", nullptr }, - { Qt63DAnimationModule, "3danimation", "Qt63DAnimation", nullptr }, - { Qt63DExtrasModule, "3dextras", "Qt63DExtras", nullptr }, - { Qt6LocationModule, "geoservices", "Qt6Location", nullptr }, - { Qt6WebChannelModule, "webchannel", "Qt6WebChannel", nullptr }, - { Qt6TextToSpeechModule, "texttospeech", "Qt6TextToSpeech", nullptr }, - { Qt6SerialBusModule, "serialbus", "Qt6SerialBus", nullptr }, - { Qt6WebViewModule, "webview", "Qt6WebView", nullptr }, - { Qt6ShaderToolsModule, "shadertools", "Qt6ShaderTools", nullptr } -}; +static QtModuleEntry qt5ModuleEntries[] + = {{Qt5BluetoothModule, "bluetooth", "Qt5Bluetooth", nullptr}, + {Qt5CLuceneModule, "clucene", "Qt5CLucene", "qt_help"}, + {Qt5ConcurrentModule, "concurrent", "Qt5Concurrent", "qtbase"}, + {Qt5CoreModule, "core", "Qt5Core", "qtbase"}, + {Qt5DeclarativeModule, "declarative", "Qt5Declarative", "qtquick1"}, + {Qt5DesignerModule, "designer", "Qt5Designer", nullptr}, + {Qt5DesignerComponents, "designercomponents", "Qt5DesignerComponents", nullptr}, + {Qt5EnginioModule, "enginio", "Enginio", nullptr}, + {Qt5GuiModule, "gui", "Qt5Gui", "qtbase"}, + {Qt5HelpModule, "qthelp", "Qt5Help", "qt_help"}, + {Qt5MultimediaModule, "multimedia", "Qt5Multimedia", "qtmultimedia"}, + {Qt5MultimediaWidgetsModule, + "multimediawidgets", + "Qt5MultimediaWidgets", + "qtmultimedia"}, + {Qt5MultimediaQuickModule, + "multimediaquick", + "Qt5MultimediaQuick_p", + "qtmultimedia"}, + {Qt5NetworkModule, "network", "Qt5Network", "qtbase"}, + {Qt5NfcModule, "nfc", "Qt5Nfc", nullptr}, + {Qt5OpenGLModule, "opengl", "Qt5OpenGL", nullptr}, + {Qt5PositioningModule, "positioning", "Qt5Positioning", nullptr}, + {Qt5PrintSupportModule, "printsupport", "Qt5PrintSupport", nullptr}, + {Qt5QmlModule, "qml", "Qt5Qml", "qtdeclarative"}, + {Qt5QmlToolingModule, "qmltooling", "qmltooling", nullptr}, + {Qt5QuickModule, "quick", "Qt5Quick", "qtdeclarative"}, + {Qt5QuickParticlesModule, "quickparticles", "Qt5QuickParticles", nullptr}, + {Qt5QuickWidgetsModule, "quickwidgets", "Qt5QuickWidgets", nullptr}, + {Qt5ScriptModule, "script", "Qt5Script", "qtscript"}, + {Qt5ScriptToolsModule, "scripttools", "Qt5ScriptTools", "qtscript"}, + {Qt5SensorsModule, "sensors", "Qt5Sensors", nullptr}, + {Qt5SerialPortModule, "serialport", "Qt5SerialPort", "qtserialport"}, + {Qt5SqlModule, "sql", "Qt5Sql", "qtbase"}, + {Qt5SvgModule, "svg", "Qt5Svg", nullptr}, + {Qt5TestModule, "test", "Qt5Test", "qtbase"}, + {Qt5WebKitModule, "webkit", "Qt5WebKit", nullptr}, + {Qt5WebKitWidgetsModule, "webkitwidgets", "Qt5WebKitWidgets", nullptr}, + {Qt5WebSocketsModule, "websockets", "Qt5WebSockets", "qtwebsockets"}, + {Qt5WidgetsModule, "widgets", "Qt5Widgets", "qtbase"}, + {Qt5WinExtrasModule, "winextras", "Qt5WinExtras", nullptr}, + {Qt5XmlModule, "xml", "Qt5Xml", "qtbase"}, + {Qt5XmlPatternsModule, "xmlpatterns", "Qt5XmlPatterns", "qtxmlpatterns"}, + {Qt5WebEngineCoreModule, "webenginecore", "Qt5WebEngineCore", nullptr}, + {Qt5WebEngineModule, "webengine", "Qt5WebEngine", "qtwebengine"}, + {Qt5WebEngineWidgetsModule, "webenginewidgets", "Qt5WebEngineWidgets", nullptr}, + {Qt53DCoreModule, "3dcore", "Qt53DCore", nullptr}, + {Qt53DRendererModule, "3drenderer", "Qt53DRenderer", nullptr}, + {Qt53DQuickModule, "3dquick", "Qt53DQuick", nullptr}, + {Qt53DQuickRendererModule, "3dquickrenderer", "Qt53DQuickRenderer", nullptr}, + {Qt53DInputModule, "3dinput", "Qt53DInput", nullptr}, + {Qt5LocationModule, "geoservices", "Qt5Location", nullptr}, + {Qt5WebChannelModule, "webchannel", "Qt5WebChannel", nullptr}, + {Qt5TextToSpeechModule, "texttospeech", "Qt5TextToSpeech", nullptr}, + {Qt5SerialBusModule, "serialbus", "Qt5SerialBus", nullptr}}; + +static QtModuleEntry qt6ModuleEntries[] + = {{Qt6BluetoothModule, "bluetooth", "Qt6Bluetooth", nullptr}, + {Qt6ConcurrentModule, "concurrent", "Qt6Concurrent", "qtbase"}, + {Qt6CoreModule, "core", "Qt6Core", "qtbase"}, + {Qt6DeclarativeModule, "declarative", "Qt6Declarative", "qtquick1"}, + {Qt6DesignerModule, "designer", "Qt6Designer", nullptr}, + {Qt6DesignerComponents, "designercomponents", "Qt6DesignerComponents", nullptr}, + {Qt6GamePadModule, "gamepad", "Qt6Gamepad", nullptr}, + {Qt6GuiModule, "gui", "Qt6Gui", "qtbase"}, + {Qt6HelpModule, "qthelp", "Qt6Help", "qt_help"}, + {Qt6MultimediaModule, "multimedia", "Qt6Multimedia", "qtmultimedia"}, + {Qt6MultimediaWidgetsModule, + "multimediawidgets", + "Qt6MultimediaWidgets", + "qtmultimedia"}, + {Qt6MultimediaQuickModule, + "multimediaquick", + "Qt6MultimediaQuick_p", + "qtmultimedia"}, + {Qt6NetworkModule, "network", "Qt6Network", "qtbase"}, + {Qt6NfcModule, "nfc", "Qt6Nfc", nullptr}, + {Qt6OpenGLModule, "opengl", "Qt6OpenGL", nullptr}, + {Qt6OpenGLWidgetsModule, "openglwidgets", "Qt6OpenGLWidgets", nullptr}, + {Qt6PositioningModule, "positioning", "Qt6Positioning", nullptr}, + {Qt6PrintSupportModule, "printsupport", "Qt6PrintSupport", nullptr}, + {Qt6QmlModule, "qml", "Qt6Qml", "qtdeclarative"}, + {Qt6QmlToolingModule, "qmltooling", "qmltooling", nullptr}, + {Qt6QuickModule, "quick", "Qt6Quick", "qtdeclarative"}, + {Qt6QuickParticlesModule, "quickparticles", "Qt6QuickParticles", nullptr}, + {Qt6QuickWidgetsModule, "quickwidgets", "Qt6QuickWidgets", nullptr}, + {Qt6ScriptModule, "script", "Qt6Script", "qtscript"}, + {Qt6ScriptToolsModule, "scripttools", "Qt6ScriptTools", "qtscript"}, + {Qt6SensorsModule, "sensors", "Qt6Sensors", nullptr}, + {Qt6SerialPortModule, "serialport", "Qt6SerialPort", "qtserialport"}, + {Qt6SqlModule, "sql", "Qt6Sql", "qtbase"}, + {Qt6SvgModule, "svg", "Qt6Svg", nullptr}, + {Qt6SvgWidgetsModule, "svgwidgets", "Qt6SvgWidgets", nullptr}, + {Qt6TestModule, "test", "Qt6Test", "qtbase"}, + {Qt6WebSocketsModule, "websockets", "Qt6WebSockets", nullptr}, + {Qt6WidgetsModule, "widgets", "Qt6Widgets", "qtbase"}, + {Qt6WinExtrasModule, "winextras", "Qt6WinExtras", nullptr}, + {Qt6XmlModule, "xml", "Qt6Xml", "qtbase"}, + {Qt6WebEngineCoreModule, "webenginecore", "Qt6WebEngineCore", nullptr}, + {Qt6WebEngineModule, "webengine", "Qt6WebEngine", "qtwebengine"}, + {Qt6WebEngineWidgetsModule, "webenginewidgets", "Qt6WebEngineWidgets", nullptr}, + {Qt63DCoreModule, "3dcore", "Qt63DCore", nullptr}, + {Qt63DRendererModule, "3drenderer", "Qt63DRender", nullptr}, + {Qt63DQuickModule, "3dquick", "Qt63DQuick", nullptr}, + {Qt63DQuickRendererModule, "3dquickrenderer", "Qt63DQuickRender", nullptr}, + {Qt63DInputModule, "3dinput", "Qt63DInput", nullptr}, + {Qt63DAnimationModule, "3danimation", "Qt63DAnimation", nullptr}, + {Qt63DExtrasModule, "3dextras", "Qt63DExtras", nullptr}, + {Qt6LocationModule, "geoservices", "Qt6Location", nullptr}, + {Qt6WebChannelModule, "webchannel", "Qt6WebChannel", nullptr}, + {Qt6TextToSpeechModule, "texttospeech", "Qt6TextToSpeech", nullptr}, + {Qt6SerialBusModule, "serialbus", "Qt6SerialBus", nullptr}, + {Qt6WebViewModule, "webview", "Qt6WebView", nullptr}, + {Qt6ShaderToolsModule, "shadertools", "Qt6ShaderTools", nullptr}}; QProcessEnvironment systemEnvironment() { @@ -340,18 +350,18 @@ QProcessEnvironment systemEnvironment() env.insert("GSETTINGS_SCHEMA_DIR", env.value("SYS_GSETTINGS_SCHEMA_DIR")); env.insert("QT_PLUGIN_PATH", env.value("SYS_QT_PLUGIN_PATH")); return env; - } (); + }(); return env; } static QProcessEnvironment lddEnvironment(systemEnvironment()); -bool operator==(const LibraryInfo &a, const LibraryInfo &b) +bool operator==(const LibraryInfo& a, const LibraryInfo& b) { return ((a.libraryPath == b.libraryPath) && (a.binaryPath == b.binaryPath)); } -QDebug operator<<(QDebug debug, const LibraryInfo &info) +QDebug operator<<(QDebug debug, const LibraryInfo& info) { debug << "Library name" << info.libraryName << "\n"; debug << "Library directory" << info.libraryDirectory << "\n"; @@ -363,15 +373,17 @@ QDebug operator<<(QDebug debug, const LibraryInfo &info) debug << "Install name" << info.installName << "\n"; debug << "Deployed install name" << info.deployedInstallName << "\n"; debug << "Source file Path" << info.sourceFilePath << "\n"; - debug << "Library Destination Directory (relative to bundle)" << info.libraryDestinationDirectory << "\n"; - debug << "Binary Destination Directory (relative to bundle)" << info.binaryDestinationDirectory << "\n"; + debug << "Library Destination Directory (relative to bundle)" + << info.libraryDestinationDirectory << "\n"; + debug << "Binary Destination Directory (relative to bundle)" + << info.binaryDestinationDirectory << "\n"; return debug; } static QString bundleLibraryDirectory; -inline QDebug operator<<(QDebug debug, const AppDirInfo &info) +inline QDebug operator<<(QDebug debug, const AppDirInfo& info) { debug << "Application bundle path" << info.path << "\n"; debug << "Binary path" << info.binaryPath << "\n"; @@ -379,20 +391,22 @@ inline QDebug operator<<(QDebug debug, const AppDirInfo &info) return debug; } -bool copyFilePrintStatus(const QString &frm, const QString &trm) +bool copyFilePrintStatus(const QString& frm, const QString& trm) { QString from(frm); - QString to (trm); + QString to(trm); - from.replace(QRegularExpression(R"([\\\/]+)"), "/"); - to .replace(QRegularExpression(R"([\\\/]+)"), "/"); + static QRegularExpression exp(R"([\\\/]+)"); + from.replace(exp, "/"); + to.replace(exp, "/"); from = QFileInfo(from).canonicalFilePath(); if (QFile(to).exists()) { if (alwaysOwerwriteEnabled && QFileInfo(to) != QFileInfo(from)) { QFile(to).remove(); } else { - LogDebug() << QFileInfo(to).fileName() << "already exists at target location"; + LogDebug() << QFileInfo(to).fileName() + << "already exists at target location"; return true; } } @@ -428,8 +442,8 @@ bool copyFilePrintStatus(const QString &frm, const QString &trm) } } -bool copyCopyrightFile(QString libPath) { - +bool copyCopyrightFile(QString libPath) +{ /* When deploying files (e.g., libraries) from the * system, then try to also deploy their copyright file. * This is currently only implemented for dpkg-based, @@ -443,14 +457,14 @@ bool copyCopyrightFile(QString libPath) { QString dpkgPath; dpkgPath = QStandardPaths::findExecutable("dpkg"); - if(dpkgPath == "") { + if (dpkgPath == "") { LogNormal() << "dpkg not found, hence not deploying copyright files"; return false; } QString dpkgQueryPath; dpkgQueryPath = QStandardPaths::findExecutable("dpkg-query"); - if(dpkgQueryPath == "") { + if (dpkgQueryPath == "") { LogNormal() << "dpkg-query not found, hence not deploying copyright files"; return false; } @@ -466,7 +480,8 @@ bool copyCopyrightFile(QString libPath) { myProcess.start(dpkgPath, arguments); myProcess.waitForFinished(); QString strOut = myProcess.readAllStandardOutput().split(':')[0]; - if(strOut == "") return false; + if (strOut == "") + return false; /* Find out the copyright file in that package */ arguments << "-L" << strOut; @@ -474,10 +489,12 @@ bool copyCopyrightFile(QString libPath) { myProcess.waitForFinished(); strOut = myProcess.readAllStandardOutput(); - QStringList outputLines = strOut.split("\n", QSTRING_SPLIT_BEHAVIOR_NAMESPACE::SkipEmptyParts); + QStringList outputLines + = strOut.split("\n", QSTRING_SPLIT_BEHAVIOR_NAMESPACE::SkipEmptyParts); foreach (QString outputLine, outputLines) { - if((outputLine.contains("usr/share/doc")) && (outputLine.contains("/copyright")) && (outputLine.contains(" "))) { + if ((outputLine.contains("usr/share/doc")) + && (outputLine.contains("/copyright")) && (outputLine.contains(" "))) { // copyrightFilePath = outputLine.split(' ')[1]; // This is not working on multiarch systems; see https://github.com/probonopd/linuxdeployqt/issues/184#issuecomment-345293540 QStringList parts = outputLine.split(' '); copyrightFilePath = parts[parts.size() - 1]; // Grab last element @@ -485,26 +502,30 @@ bool copyCopyrightFile(QString libPath) { } } - if(copyrightFilePath == "") return false; + if (copyrightFilePath == "") + return false; LogDebug() << "copyrightFilePath:" << copyrightFilePath; /* Where should we copy this file to? We are assuming the Debian-like path contains * the name of the package like so: copyrightFilePath: "/usr/share/doc/libpcre3/copyright" * this assumption is most likely only true for Debian-like systems */ - QString packageName = copyrightFilePath.split("/")[copyrightFilePath.split("/").length()-2]; + QString packageName = copyrightFilePath.split( + "/")[copyrightFilePath.split("/").length() - 2]; QString copyrightFileTargetPath; - if(fhsLikeMode) { - copyrightFileTargetPath = QDir::cleanPath(appBinaryPath + "/../../share/doc/" + packageName + "/copyright"); + if (fhsLikeMode) { + copyrightFileTargetPath = QDir::cleanPath(appBinaryPath + "/../../share/doc/" + + packageName + "/copyright"); } else { - copyrightFileTargetPath = QDir::cleanPath(appBinaryPath + "/../doc/" + packageName + "/copyright"); + copyrightFileTargetPath = QDir::cleanPath(appBinaryPath + "/../doc/" + + packageName + "/copyright"); } /* Do the actual copying */ - return(copyFilePrintStatus(copyrightFilePath, copyrightFileTargetPath)); + return (copyFilePrintStatus(copyrightFilePath, copyrightFileTargetPath)); } -LddInfo findDependencyInfo(const QString &binaryPath) +LddInfo findDependencyInfo(const QString& binaryPath) { LddInfo info; info.binaryPath = binaryPath; @@ -524,7 +545,8 @@ LddInfo findDependencyInfo(const QString &binaryPath) static const QRegularExpression regexp(QStringLiteral("^.+ => (.+) \\(")); QString output = ldd.readAllStandardOutput(); - QStringList outputLines = output.split("\n", QSTRING_SPLIT_BEHAVIOR_NAMESPACE::SkipEmptyParts); + QStringList outputLines + = output.split("\n", QSTRING_SPLIT_BEHAVIOR_NAMESPACE::SkipEmptyParts); if (outputLines.size() < 2) { if ((output.contains("statically linked") == false)) { LogError() << "Could not parse ldd output under 2 lines:" << output; @@ -533,31 +555,33 @@ LddInfo findDependencyInfo(const QString &binaryPath) } foreach (QString outputLine, outputLines) { - - if (outputLine.contains("libQt6")) { - qtDetected = 6; - qtModuleEntries = qt6ModuleEntries; - qtModuleEntriesCount = sizeof(qt6ModuleEntries) / sizeof(qt6ModuleEntries[0]); - } - if(outputLine.contains("libQt5")){ - qtDetected = 5; - qtModuleEntries = qt5ModuleEntries; - qtModuleEntriesCount = sizeof(qt5ModuleEntries) / sizeof(qt5ModuleEntries[0]); - } - if(outputLine.contains("libQtCore.so.4")){ - qtDetected = 4; - } + if (outputLine.contains("libQt6")) { + qtDetected = 6; + qtModuleEntries = qt6ModuleEntries; + qtModuleEntriesCount = sizeof(qt6ModuleEntries) + / sizeof(qt6ModuleEntries[0]); + } + if (outputLine.contains("libQt5")) { + qtDetected = 5; + qtModuleEntries = qt5ModuleEntries; + qtModuleEntriesCount = sizeof(qt5ModuleEntries) + / sizeof(qt5ModuleEntries[0]); + } + if (outputLine.contains("libQtCore.so.4")) { + qtDetected = 4; + } // LogDebug() << "ldd outputLine:" << outputLine; if ((outputLine.contains("not found")) && (qtDetectionComplete == 1)) { LogError() << "ldd outputLine:" << outputLine.replace("\t", ""); LogError() << "for binary:" << binaryPath; - LogError() << "Please ensure that all libraries can be found by ldd. Aborting."; + LogError() + << "Please ensure that all libraries can be found by ldd. Aborting."; exit(1); } } - foreach (const QString &outputLine, outputLines) { + foreach (const QString& outputLine, outputLines) { const QRegularExpressionMatch match = regexp.match(outputLine); if (match.hasMatch()) { DylibInfo dylib; @@ -570,18 +594,21 @@ LddInfo findDependencyInfo(const QString &binaryPath) return info; } -int containsHowOften(const QStringList& haystack, const QString& needle) { +int containsHowOften(const QStringList& haystack, const QString& needle) +{ return haystack.filter(needle).length(); } -LibraryInfo parseLddLibraryLine(const QString &line, const QString &appDirPath, const QSet &rpaths) +LibraryInfo parseLddLibraryLine(const QString& line, + const QString& appDirPath, + const QSet& rpaths) { - (void)rpaths; + (void) rpaths; - if(fhsLikeMode == false) { - bundleLibraryDirectory= "lib"; // relative to bundle + if (fhsLikeMode == false) { + bundleLibraryDirectory = "lib"; // relative to bundle } else { - QString relativePrefix = fhsPrefix.replace(appDirPath+"/", ""); + QString relativePrefix = fhsPrefix.replace(appDirPath + "/", ""); bundleLibraryDirectory = relativePrefix + "/lib/"; } LogDebug() << "bundleLibraryDirectory:" << bundleLibraryDirectory; @@ -594,16 +621,17 @@ LibraryInfo parseLddLibraryLine(const QString &line, const QString &appDirPath, if (trimmed.isEmpty()) return info; - if(!bundleEverything) { - if(bundleAllButBlacklistedLibs) { + if (!bundleEverything) { + if (bundleAllButBlacklistedLibs) { /* Bundle every lib including the low-level ones except those that are explicitly blacklisted. This is more suitable for bundling in a way that is portable between different distributions and target systems. Along the way, this also takes care of non-Qt libraries. */ LogDebug() << "Excluded Libraries:" << excludedLibraries; - if (! trimmed.contains("libicu")) { - if (containsHowOften(excludedLibraries, QFileInfo(trimmed).completeBaseName())) { + if (!trimmed.contains("libicu")) { + if (containsHowOften(excludedLibraries, + QFileInfo(trimmed).completeBaseName())) { LogDebug() << "Skipping blacklisted" << trimmed; return info; } @@ -617,7 +645,8 @@ LibraryInfo parseLddLibraryLine(const QString &line, const QString &appDirPath, Qt from ppas. Hence we make sure libicu is always bundled since it cannot be assumed to be on target sytems */ // Manual make of Qt deploys it to /usr/local/Qt-x.x.x so we cannot remove this path just like that, so let's allow known libs of Qt. - if (!trimmed.contains("libicu") && !trimmed.contains("lib/libQt") && !trimmed.contains("lib/libqgsttools")) { + if (!trimmed.contains("libicu") && !trimmed.contains("lib/libQt") + && !trimmed.contains("lib/libqgsttools")) { if ((trimmed.startsWith("/usr") or (trimmed.startsWith("/lib")))) { return info; } @@ -625,7 +654,7 @@ LibraryInfo parseLddLibraryLine(const QString &line, const QString &appDirPath, } } - enum State {QtPath, LibraryName, Version, End}; + enum State { QtPath, LibraryName, Version, End }; State state = QtPath; int part = 0; QString name; @@ -635,7 +664,7 @@ LibraryInfo parseLddLibraryLine(const QString &line, const QString &appDirPath, // Split the line into [Qt-path]/lib/qt[Module].library/Versions/[Version]/ QStringList parts = trimmed.split("/"); while (part < parts.count()) { - const QString currentPart = parts.at(part).simplified() ; + const QString currentPart = parts.at(part).simplified(); ++part; if (currentPart == "") continue; @@ -643,11 +672,13 @@ LibraryInfo parseLddLibraryLine(const QString &line, const QString &appDirPath, if (state == QtPath) { // Check for library name part if (part < parts.count() && parts.at(part).contains(".so")) { - info.libraryDirectory += "/" + (qtPath + currentPart + "/").simplified(); + info.libraryDirectory += "/" + + (qtPath + currentPart + "/").simplified(); LogDebug() << "info.libraryDirectory:" << info.libraryDirectory; state = LibraryName; continue; - } else if (trimmed.startsWith("/") == false) { // If the line does not contain a full path, the app is using a binary Qt package. + } else if (trimmed.startsWith("/") + == false) { // If the line does not contain a full path, the app is using a binary Qt package. QStringList partsCopy = parts; partsCopy.removeLast(); foreach (QString path, librarySearchPath) { @@ -673,13 +704,15 @@ LibraryInfo parseLddLibraryLine(const QString &line, const QString &appDirPath, name = currentPart; info.isDylib = true; info.libraryName = name; - info.binaryName = name.left(name.indexOf('.')) + suffix + name.mid(name.indexOf('.')); + info.binaryName = name.left(name.indexOf('.')) + suffix + + name.mid(name.indexOf('.')); info.deployedInstallName = "$ORIGIN"; // + info.binaryName; info.libraryPath = info.libraryDirectory + info.binaryName; info.sourceFilePath = info.libraryPath; if (info.libraryPath.contains(appDirPath)) // leave libs that are already in the appdir in their current location - info.libraryDestinationDirectory = QDir(appDirPath).relativeFilePath(info.libraryDirectory); + info.libraryDestinationDirectory + = QDir(appDirPath).relativeFilePath(info.libraryDirectory); else info.libraryDestinationDirectory = bundleLibraryDirectory + "/"; info.binaryDestinationDirectory = info.libraryDestinationDirectory; @@ -702,11 +735,11 @@ LibraryInfo parseLddLibraryLine(const QString &line, const QString &appDirPath, return info; } -QStringList findAppLibraries(const QString &appDirPath) +QStringList findAppLibraries(const QString& appDirPath) { QStringList ignoreGlobAbs; QDir appDir(appDirPath); - foreach (const QString &glob, ignoreGlob) { + foreach (const QString& glob, ignoreGlob) { QString globAbs = appDir.filePath(glob); LogDebug() << "Ignoring libraries matching" << globAbs; ignoreGlobAbs += globAbs; @@ -714,8 +747,11 @@ QStringList findAppLibraries(const QString &appDirPath) QStringList result; // .so, .so.* - QDirIterator iter(appDirPath, QStringList() << QString::fromLatin1("*.so") << QString::fromLatin1("*.so.*"), - QDir::Files, QDirIterator::Subdirectories); + QDirIterator iter(appDirPath, + QStringList() << QString::fromLatin1("*.so") + << QString::fromLatin1("*.so.*"), + QDir::Files, + QDirIterator::Subdirectories); while (iter.hasNext()) { iter.next(); @@ -727,10 +763,12 @@ QStringList findAppLibraries(const QString &appDirPath) return result; } -QList getQtLibraries(const QList &dependencies, const QString &appDirPath, const QSet &rpaths) +QList getQtLibraries(const QList& dependencies, + const QString& appDirPath, + const QSet& rpaths) { QList libraries; - foreach (const DylibInfo &dylibInfo, dependencies) { + foreach (const DylibInfo& dylibInfo, dependencies) { LibraryInfo info = parseLddLibraryLine(dylibInfo.binaryPath, appDirPath, rpaths); if (info.libraryName.isEmpty() == false) { LogDebug() << "Adding library:"; @@ -742,7 +780,9 @@ QList getQtLibraries(const QList &dependencies, const QS } // TODO: Switch the following to using patchelf -QSet getBinaryRPaths(const QString &path, bool resolve = true, QString executablePath = QString()) +QSet getBinaryRPaths(const QString& path, + bool resolve = true, + QString executablePath = QString()) { QSet rpaths; @@ -751,11 +791,12 @@ QSet getBinaryRPaths(const QString &path, bool resolve = true, QString objdump.start("objdump", QStringList() << "-x" << path); if (!objdump.waitForStarted()) { - if(objdump.errorString().contains("execvp: No such file or directory")) { + if (objdump.errorString().contains("execvp: No such file or directory")) { LogError() << "Could not start objdump."; LogError() << "Make sure it is installed on your $PATH."; } else { - LogError() << "Could not start objdump. Process error is" << objdump.errorString(); + LogError() << "Could not start objdump. Process error is" + << objdump.errorString(); } exit(1); } @@ -777,10 +818,10 @@ QSet getBinaryRPaths(const QString &path, bool resolve = true, QString while (i.hasNext()) { if (i.next().contains("RUNPATH") && i.hasNext()) { i.previous(); - const QString &rpathCmd = i.next(); + const QString& rpathCmd = i.next(); int pathStart = rpathCmd.indexOf("RUNPATH"); if (pathStart >= 0) { - QString rpath = rpathCmd.mid(pathStart+8).trimmed(); + QString rpath = rpathCmd.mid(pathStart + 8).trimmed(); LogDebug() << "rpath:" << rpath; rpaths << rpath; } @@ -790,21 +831,24 @@ QSet getBinaryRPaths(const QString &path, bool resolve = true, QString return rpaths; } -QList getQtLibraries(const QString &path, const QString &appDirPath, const QSet &rpaths) +QList getQtLibraries(const QString& path, + const QString& appDirPath, + const QSet& rpaths) { const LddInfo info = findDependencyInfo(path); return getQtLibraries(info.dependencies, appDirPath, rpaths + getBinaryRPaths(path)); } -QList getQtLibrariesForPaths(const QStringList &paths, const QString &appDirPath, const QSet &rpaths) +QList getQtLibrariesForPaths(const QStringList& paths, + const QString& appDirPath, + const QSet& rpaths) { QList result; QSet existing; - foreach (const QString &path, paths) { - if (!excludedLibraries.contains(QFileInfo(path).baseName())) - { - foreach (const LibraryInfo &info, getQtLibraries(path, appDirPath, rpaths)) { + foreach (const QString& path, paths) { + if (!excludedLibraries.contains(QFileInfo(path).baseName())) { + foreach (const LibraryInfo& info, getQtLibraries(path, appDirPath, rpaths)) { if (!existing.contains(info.libraryPath)) { // avoid duplicates existing.insert(info.libraryPath); result << info; @@ -816,7 +860,7 @@ QList getQtLibrariesForPaths(const QStringList &paths, const QStrin } // copies everything _inside_ sourcePath to destinationPath -bool recursiveCopy(const QString &sourcePath, const QString &destinationPath) +bool recursiveCopy(const QString& sourcePath, const QString& destinationPath) { if (!QDir(sourcePath).exists()) return false; @@ -824,7 +868,9 @@ bool recursiveCopy(const QString &sourcePath, const QString &destinationPath) LogNormal() << "copy:" << sourcePath << destinationPath; - QStringList files = QDir(sourcePath).entryList(QStringList() << "*", QDir::Files | QDir::NoDotAndDotDot); + QStringList files = QDir(sourcePath) + .entryList(QStringList() << "*", + QDir::Files | QDir::NoDotAndDotDot); foreach (QString file, files) { const QString fileSourcePath = sourcePath + "/" + file; const QString fileDestinationPath = destinationPath + "/" + file; @@ -833,20 +879,27 @@ bool recursiveCopy(const QString &sourcePath, const QString &destinationPath) copyCopyrightFile(fileSourcePath); } - QStringList subdirs = QDir(sourcePath).entryList(QStringList() << "*", QDir::Dirs | QDir::NoDotAndDotDot); + QStringList subdirs = QDir(sourcePath) + .entryList(QStringList() << "*", + QDir::Dirs | QDir::NoDotAndDotDot); foreach (QString dir, subdirs) { recursiveCopy(sourcePath + "/" + dir, destinationPath + "/" + dir); } return true; } -void recursiveCopyAndDeploy(const QString &appDirPath, const QSet &rpaths, const QString &sourcePath, const QString &destinationPath) +void recursiveCopyAndDeploy(const QString& appDirPath, + const QSet& rpaths, + const QString& sourcePath, + const QString& destinationPath) { QDir().mkpath(destinationPath); LogNormal() << "copy:" << sourcePath << destinationPath; - QStringList files = QDir(sourcePath).entryList(QStringList() << QStringLiteral("*"), QDir::Files | QDir::NoDotAndDotDot); + QStringList files = QDir(sourcePath) + .entryList(QStringList() << QStringLiteral("*"), + QDir::Files | QDir::NoDotAndDotDot); foreach (QString file, files) { const QString fileSourcePath = sourcePath + QLatin1Char('/') + file; @@ -855,37 +908,48 @@ void recursiveCopyAndDeploy(const QString &appDirPath, const QSet &rpat LogDebug() << "copyCopyrightFile:" << fileSourcePath; copyCopyrightFile(fileSourcePath); - if(fileDestinationPath.endsWith(".so")) { - + if (fileDestinationPath.endsWith(".so")) { LogDebug() << "Deploying .so in QML import" << fileSourcePath; runStrip(fileDestinationPath); // Find out the relative path to the lib/ directory and set it as the rpath // FIXME: remove code duplication - the next few lines exist elsewhere already - if(fhsLikeMode == false) { - bundleLibraryDirectory= "lib"; // relative to bundle + if (fhsLikeMode == false) { + bundleLibraryDirectory = "lib"; // relative to bundle } else { - QString relativePrefix = fhsPrefix.replace(appDirPath+"/", ""); + QString relativePrefix = fhsPrefix.replace(appDirPath + "/", ""); bundleLibraryDirectory = relativePrefix + "/lib/"; } QDir dir(QFileInfo(fileDestinationPath).canonicalFilePath()); - QString relativePath = dir.relativeFilePath(appDirPath + "/" + bundleLibraryDirectory); + QString relativePath = dir.relativeFilePath(appDirPath + "/" + + bundleLibraryDirectory); relativePath.remove(0, 3); // remove initial '../' - changeIdentification("$ORIGIN:$ORIGIN/" + relativePath, QFileInfo(fileDestinationPath).canonicalFilePath()); - - QList libraries = getQtLibraries(fileSourcePath, appDirPath, QSet()); - deployQtLibraries(libraries, appDirPath, QStringList() << destinationPath, false); + changeIdentification("$ORIGIN:$ORIGIN/" + relativePath, + QFileInfo(fileDestinationPath).canonicalFilePath()); + + QList libraries = getQtLibraries(fileSourcePath, + appDirPath, + QSet()); + deployQtLibraries(libraries, + appDirPath, + QStringList() << destinationPath, + false); } } - QStringList subdirs = QDir(sourcePath).entryList(QStringList() << QStringLiteral("*"), QDir::Dirs | QDir::NoDotAndDotDot); + QStringList subdirs = QDir(sourcePath) + .entryList(QStringList() << QStringLiteral("*"), + QDir::Dirs | QDir::NoDotAndDotDot); foreach (QString dir, subdirs) { - recursiveCopyAndDeploy(appDirPath, rpaths, sourcePath + QLatin1Char('/') + dir, destinationPath + QLatin1Char('/') + dir); + recursiveCopyAndDeploy(appDirPath, + rpaths, + sourcePath + QLatin1Char('/') + dir, + destinationPath + QLatin1Char('/') + dir); } } -QString copyDylib(const LibraryInfo &library, const QString path) +QString copyDylib(const LibraryInfo& library, const QString path) { if (!QFile::exists(library.sourceFilePath)) { LogError() << "no file at" << library.sourceFilePath; @@ -894,17 +958,20 @@ QString copyDylib(const LibraryInfo &library, const QString path) // Construct destination paths. The full path typically looks like // MyApp.app/Contents/Libraries/libfoo.dylib - QString dylibDestinationDirectory = path + QLatin1Char('/') + library.libraryDestinationDirectory; - QString dylibDestinationBinaryPath = dylibDestinationDirectory + QLatin1Char('/') + library.binaryName; + QString dylibDestinationDirectory = path + QLatin1Char('/') + + library.libraryDestinationDirectory; + QString dylibDestinationBinaryPath = dylibDestinationDirectory + QLatin1Char('/') + + library.binaryName; // Create destination directory if (!QDir().mkpath(dylibDestinationDirectory)) { - LogError() << "could not create destination directory" << dylibDestinationDirectory; + LogError() << "could not create destination directory" + << dylibDestinationDirectory; return QString(); } // Retrun if the dylib has aleardy been deployed - if (QFileInfo(dylibDestinationBinaryPath).exists() && !alwaysOwerwriteEnabled) + if (QFile::exists(dylibDestinationBinaryPath) && !alwaysOwerwriteEnabled) return dylibDestinationBinaryPath; // Copy dylib binary @@ -920,46 +987,52 @@ QString runPatchelf(QStringList options) LogDebug() << "options:" << options; patchelftool.start("patchelf", options); if (!patchelftool.waitForStarted()) { - LogError() << "Could not start patchelf tool. Process error is" << patchelftool.errorString(); + LogError() << "Could not start patchelf tool. Process error is" + << patchelftool.errorString(); exit(1); } patchelftool.waitForFinished(); if (patchelftool.exitCode() != 0) { LogError() << "runPatchelf:" << patchelftool.readAllStandardError(); } - return(patchelftool.readAllStandardOutput().trimmed()); + return (patchelftool.readAllStandardOutput().trimmed()); } -bool patchQtCore(const QString &, const QString &, const QString &) +bool patchQtCore(const QString&, const QString&, const QString&) { return true; } -void changeIdentification(const QString &id, const QString &binaryPath) +void changeIdentification(const QString& id, const QString& binaryPath) { LogNormal() << "Checking rpath in" << binaryPath; - QString oldRpath = runPatchelf(QStringList() << "--print-rpath" << binaryPath).trimmed(); + QString oldRpath + = runPatchelf(QStringList() << "--print-rpath" << binaryPath).trimmed(); LogDebug() << "oldRpath:" << oldRpath; if (oldRpath.startsWith("/")) { - LogDebug() << "Old rpath in" << binaryPath << "starts with /, hence adding it to LD_LIBRARY_PATH"; + LogDebug() << "Old rpath in" << binaryPath + << "starts with /, hence adding it to LD_LIBRARY_PATH"; // FIXME: Split along ":" characters, check each one, only append to LD_LIBRARY_PATH if not already there QString oldPath = lddEnvironment.value("LD_LIBRARY_PATH"); if (not oldPath.contains(oldRpath)) { - QString newPath = oldRpath + ":" + oldPath; // FIXME: If we use a ldd replacement, we still need to observe this path + QString newPath + = oldRpath + ":" + + oldPath; // FIXME: If we use a ldd replacement, we still need to observe this path // FIXME: Directory layout might be different for system Qt; cannot assume lib/ to always be inside the Qt directory LogDebug() << "Added to LD_LIBRARY_PATH:" << newPath; lddEnvironment.insert("LD_LIBRARY_PATH", newPath); } } - QStringList rpath = oldRpath.split(":", QSTRING_SPLIT_BEHAVIOR_NAMESPACE::SkipEmptyParts); + QStringList rpath = oldRpath.split(":", + QSTRING_SPLIT_BEHAVIOR_NAMESPACE::SkipEmptyParts); rpath.prepend(id.trimmed()); rpath.removeDuplicates(); - foreach(QString path, QStringList(rpath)) { + foreach (QString path, QStringList(rpath)) { // remove any non-relative path that would point outside the package - if (!path.startsWith("$ORIGIN")) - { - LogNormal() << "Removing absolute rpath of " << path << " in " << binaryPath; + if (!path.startsWith("$ORIGIN")) { + LogNormal() << "Removing absolute rpath of " << path << " in " + << binaryPath; rpath.removeAll(path); } } @@ -977,7 +1050,7 @@ void changeIdentification(const QString &id, const QString &binaryPath) /* https://codereview.qt-project.org/gitweb?p=qt/qttools.git;a=blob_plain;f=src/windeployqt/utils.cpp;h=e89496ea1f371ed86f6937284c1c801daf576572;hb=7be81b804da102b374c2089aac38353a0383c254 * Search for "qt_prfxpath=" in a path, and replace it with "qt_prfxpath=." or "qt_prfxpath=.." */ - if(fhsLikeMode == true) { + if (fhsLikeMode == true) { patchQtCore(binaryPath, "qt_prfxpath", ".."); } else { patchQtCore(binaryPath, "qt_prfxpath", "."); @@ -1000,7 +1073,9 @@ void changeIdentification(const QString &id, const QString &binaryPath) patchQtCore(binaryPath, "qt_hpfxpath", "."); patchQtCore(binaryPath, "qt_hbinpath", "bin"); patchQtCore(binaryPath, "qt_hdatpath", "."); - patchQtCore(binaryPath, "qt_stngpath", "."); // e.g., /opt/qt53/etc/xdg; does it load Trolltech.conf from there? + patchQtCore(binaryPath, + "qt_stngpath", + "."); // e.g., /opt/qt53/etc/xdg; does it load Trolltech.conf from there? /* Qt on Arch Linux comes with more hardcoded paths * https://github.com/probonopd/linuxdeployqt/issues/98 @@ -1016,10 +1091,9 @@ void changeIdentification(const QString &id, const QString &binaryPath) patchString(binaryPath, "share/doc/qt/examples", "examples"); */ } - } -void runStrip(const QString &binaryPath) +void runStrip(const QString& binaryPath) { if (runStripEnabled == false) return; @@ -1033,14 +1107,19 @@ void runStrip(const QString &binaryPath) QProcess patchelfread; patchelfread.start("patchelf", QStringList() << "--print-rpath" << resolvedPath); if (!patchelfread.waitForStarted()) { - LogError() << "Could not start patchelf. Process error is" << patchelfread.errorString(); + LogError() << "Could not start patchelf. Process error is" + << patchelfread.errorString(); // exit(1); // Do not exit because this could be a script that patchelf can't work on } patchelfread.waitForFinished(); if (patchelfread.exitCode() != 0) { - LogError() << "Error reading rpath with patchelf" << QFileInfo(resolvedPath).completeBaseName() << ":" << patchelfread.readAllStandardError(); - LogError() << "Error reading rpath with patchelf" << QFileInfo(resolvedPath).completeBaseName() << ":" << patchelfread.readAllStandardOutput(); + LogError() << "Error reading rpath with patchelf" + << QFileInfo(resolvedPath).completeBaseName() << ":" + << patchelfread.readAllStandardError(); + LogError() << "Error reading rpath with patchelf" + << QFileInfo(resolvedPath).completeBaseName() << ":" + << patchelfread.readAllStandardOutput(); exit(1); } @@ -1060,11 +1139,12 @@ void runStrip(const QString &binaryPath) strip.setProcessEnvironment(stripEnv); strip.start("strip", QStringList() << resolvedPath); if (!strip.waitForStarted()) { - if(strip.errorString().contains("execvp: No such file or directory")) { + if (strip.errorString().contains("execvp: No such file or directory")) { LogError() << "Could not start strip."; LogError() << "Make sure it is installed on your $PATH."; } else { - LogError() << "Could not start strip. Process error is" << strip.errorString(); + LogError() << "Could not start strip. Process error is" + << strip.errorString(); } exit(1); } @@ -1074,18 +1154,20 @@ void runStrip(const QString &binaryPath) return; if (strip.readAllStandardError().contains("Not enough room for program headers")) { - LogNormal() << QFileInfo(resolvedPath).completeBaseName() << "already stripped."; + LogNormal() << QFileInfo(resolvedPath).completeBaseName() + << "already stripped."; } else { - LogError() << "Error stripping" << QFileInfo(resolvedPath).completeBaseName() << ":" << strip.readAllStandardError(); - LogError() << "Error stripping" << QFileInfo(resolvedPath).completeBaseName() << ":" << strip.readAllStandardOutput(); + LogError() << "Error stripping" << QFileInfo(resolvedPath).completeBaseName() + << ":" << strip.readAllStandardError(); + LogError() << "Error stripping" << QFileInfo(resolvedPath).completeBaseName() + << ":" << strip.readAllStandardOutput(); exit(1); } - } -void stripAppBinary(const QString &bundlePath) +void stripAppBinary(const QString& bundlePath) { - (void)bundlePath; + (void) bundlePath; runStrip(appBinaryPath); } @@ -1098,7 +1180,8 @@ void stripAppBinary(const QString &bundlePath) a list of actually deployed libraries. */ DeploymentInfo deployQtLibraries(QList libraries, - const QString &bundlePath, const QStringList &binaryPaths, + const QString& bundlePath, + const QStringList& binaryPaths, bool useLoaderPath) { LogNormal() << "Deploying the following libraries:" << binaryPaths; @@ -1113,17 +1196,20 @@ DeploymentInfo deployQtLibraries(QList libraries, const LibraryInfo library = libraries.takeFirst(); copiedLibraries.append(library.libraryName); - if(library.libraryName.contains("libQt") and library.libraryName.contains("Core" + qtLibInfix + ".so")) { - LogNormal() << "Setting deploymentInfo.qtPath to:" << library.libraryDirectory; + if (library.libraryName.contains("libQt") + and library.libraryName.contains("Core" + qtLibInfix + ".so")) { + LogNormal() << "Setting deploymentInfo.qtPath to:" + << library.libraryDirectory; deploymentInfo.qtPath = library.libraryDirectory; } - if(library.libraryName.contains("libQt") and library.libraryName.contains("Widgets" + qtLibInfix + ".so")) { + if (library.libraryName.contains("libQt") + and library.libraryName.contains("Widgets" + qtLibInfix + ".so")) { deploymentInfo.requiresQtWidgetsLibrary = true; } if (library.libraryDirectory.startsWith(bundlePath)) { - LogNormal() << library.libraryName << "already at target location"; + LogNormal() << library.libraryName << "already at target location"; } if (library.rpathUsed.isEmpty() != true) { @@ -1139,11 +1225,14 @@ DeploymentInfo deployQtLibraries(QList libraries, runStrip(deployedBinaryPath); if (!library.rpathUsed.length()) { - changeIdentification(library.deployedInstallName, QFileInfo(deployedBinaryPath).canonicalFilePath()); + changeIdentification(library.deployedInstallName, + QFileInfo(deployedBinaryPath).canonicalFilePath()); } // Check for library dependencies - QList dependencies = getQtLibraries(deployedBinaryPath, bundlePath, rpathsUsed); + QList dependencies = getQtLibraries(deployedBinaryPath, + bundlePath, + rpathsUsed); foreach (LibraryInfo dependency, dependencies) { if (dependency.rpathUsed.isEmpty() != true) { @@ -1151,7 +1240,8 @@ DeploymentInfo deployQtLibraries(QList libraries, } // Deploy library if necessary. - if (copiedLibraries.contains(dependency.libraryName) == false && libraries.contains(dependency) == false) { + if (copiedLibraries.contains(dependency.libraryName) == false + && libraries.contains(dependency) == false) { libraries.append(dependency); } } @@ -1163,7 +1253,7 @@ DeploymentInfo deployQtLibraries(QList libraries, return deploymentInfo; } -static QString runQmake(const QString &command) +static QString runQmake(const QString& command) { QProcess process; process.setProcessEnvironment(systemEnvironment()); @@ -1177,13 +1267,16 @@ static QString runQmake(const QString &command) if (process.exitStatus() != QProcess::NormalExit) { LogError() << command << "crashed:" << process.readAllStandardError(); } else if (process.exitCode() != 0) { - LogError() << command << "exited with" << process.exitCode() << ":" << process.readAllStandardError(); + LogError() << command << "exited with" << process.exitCode() << ":" + << process.readAllStandardError(); } return process.readAllStandardOutput(); } -DeploymentInfo deployQtLibraries(const QString &appDirPath, const QStringList &additionalExecutables, const QString& qmake) +DeploymentInfo deployQtLibraries(const QString& appDirPath, + const QStringList& additionalExecutables, + const QString& qmake) { AppDirInfo applicationBundle; @@ -1195,45 +1288,44 @@ DeploymentInfo deployQtLibraries(const QString &appDirPath, const QStringList &a // Find out whether Qt is a dependency of the application to be bundled LddInfo lddInfo = findDependencyInfo(appBinaryPath); - if(qtDetected != 0) { - + if (qtDetected != 0) { // Determine the location of the Qt to be bundled LogDebug() << "Using qmake to determine the location of the Qt to be bundled"; // Use the qmake executable passed in by the user: QString qmakePath = qmake; - if (qmakePath.isEmpty()) { - // Try to find qmake in the same path as the executable - QString path = QCoreApplication::applicationDirPath(); - qmakePath = QStandardPaths::findExecutable("qmake", QStringList(path)); - } - if (qmakePath.isEmpty()) { - // Try to find a version specific qmake first - // openSUSE has qmake for Qt 4 and qmake-qt5 for Qt 5 - // Qt 4 on Fedora comes with suffix -qt4 - // http://www.geopsy.org/wiki/index.php/Installing_Qt_binary_packages - // Starting from Fedora 34, the package qt6-qtbase-devel provides - // qmake-qt6 - qDebug() << "qmakePath 3=" << qmakePath; - if (qtDetected == 6) { - qmakePath = QStandardPaths::findExecutable("qmake-qt6"); - LogDebug() << "qmake 6"; - } else if (qtDetected == 5) { - qmakePath = QStandardPaths::findExecutable("qmake-qt5"); - LogDebug() << "qmake 5"; - } else if(qtDetected == 4){ - qmakePath = QStandardPaths::findExecutable("qmake-qt4"); - LogDebug() << "qmake 4"; - } - - if(qmakePath.isEmpty()) { + if (qmakePath.isEmpty()) { + // Try to find qmake in the same path as the executable + QString path = QCoreApplication::applicationDirPath(); + qmakePath = QStandardPaths::findExecutable("qmake", QStringList(path)); + } + if (qmakePath.isEmpty()) { + // Try to find a version specific qmake first + // openSUSE has qmake for Qt 4 and qmake-qt5 for Qt 5 + // Qt 4 on Fedora comes with suffix -qt4 + // http://www.geopsy.org/wiki/index.php/Installing_Qt_binary_packages + // Starting from Fedora 34, the package qt6-qtbase-devel provides + // qmake-qt6 + qDebug() << "qmakePath 3=" << qmakePath; + if (qtDetected == 6) { + qmakePath = QStandardPaths::findExecutable("qmake-qt6"); + LogDebug() << "qmake 6"; + } else if (qtDetected == 5) { + qmakePath = QStandardPaths::findExecutable("qmake-qt5"); + LogDebug() << "qmake 5"; + } else if (qtDetected == 4) { + qmakePath = QStandardPaths::findExecutable("qmake-qt4"); + LogDebug() << "qmake 4"; + } + + if (qmakePath.isEmpty()) { // The upstream name of the binary is "qmake", for Qt 4 and Qt 5 qmakePath = QStandardPaths::findExecutable("qmake"); } } - if(qmakePath.isEmpty()) { + if (qmakePath.isEmpty()) { LogError() << "qmake not found on the $PATH"; exit(1); } @@ -1242,8 +1334,9 @@ DeploymentInfo deployQtLibraries(const QString &appDirPath, const QStringList &a QString output = runQmake(qmakePath + " -query"); LogDebug() << "-query output from qmake:" << output; - QStringList outputLines = output.split("\n", QSTRING_SPLIT_BEHAVIOR_NAMESPACE::SkipEmptyParts); - foreach (const QString &outputLine, outputLines) { + QStringList outputLines + = output.split("\n", QSTRING_SPLIT_BEHAVIOR_NAMESPACE::SkipEmptyParts); + foreach (const QString& outputLine, outputLines) { int colonIndex = outputLine.indexOf(QLatin1Char(':')); if (colonIndex != -1) { QString name = outputLine.left(colonIndex); @@ -1262,7 +1355,9 @@ DeploymentInfo deployQtLibraries(const QString &appDirPath, const QStringList &a } else { LogDebug() << "Qt libs path determined from qmake:" << qtLibsPath; QString oldPath = lddEnvironment.value("LD_LIBRARY_PATH"); - QString newPath = qtLibsPath + ":" + oldPath; // FIXME: If we use a ldd replacement, we still need to observe this path + QString newPath + = qtLibsPath + ":" + + oldPath; // FIXME: If we use a ldd replacement, we still need to observe this path // FIXME: Directory layout might be different for system Qt; cannot assume lib/ to always be inside the Qt directory LogDebug() << "Changed LD_LIBRARY_PATH:" << newPath; lddEnvironment.insert("LD_LIBRARY_PATH", newPath); @@ -1273,17 +1368,23 @@ DeploymentInfo deployQtLibraries(const QString &appDirPath, const QStringList &a qtDetectionComplete = 1; QString libraryPath; - if(fhsLikeMode == false) { - libraryPath = QFileInfo(applicationBundle.binaryPath).dir().filePath("lib/" + bundleLibraryDirectory); + if (fhsLikeMode == false) { + libraryPath = QFileInfo(applicationBundle.binaryPath) + .dir() + .filePath("lib/" + bundleLibraryDirectory); } else { - libraryPath = QFileInfo(applicationBundle.binaryPath).dir().filePath("../lib/" + bundleLibraryDirectory); + libraryPath = QFileInfo(applicationBundle.binaryPath) + .dir() + .filePath("../lib/" + bundleLibraryDirectory); } /* Make ldd detect pre-existing libraries in the AppDir. * TODO: Consider searching the AppDir for .so* files outside of libraryPath * and warning about them not being taken into consideration */ QString oldPath = lddEnvironment.value("LD_LIBRARY_PATH"); - QString newPath = libraryPath + ":" + oldPath; // FIXME: If we use a ldd replacement, we still need to observe this path + QString newPath + = libraryPath + ":" + + oldPath; // FIXME: If we use a ldd replacement, we still need to observe this path LogDebug() << "Changed LD_LIBRARY_PATH:" << newPath; lddEnvironment.insert("LD_LIBRARY_PATH", newPath); @@ -1292,7 +1393,8 @@ DeploymentInfo deployQtLibraries(const QString &appDirPath, const QStringList &a LogDebug() << "additionalExecutables:" << additionalExecutables; - QStringList allBinaryPaths = QStringList() << applicationBundle.binaryPath << applicationBundle.libraryPaths + QStringList allBinaryPaths = QStringList() << applicationBundle.binaryPath + << applicationBundle.libraryPaths << additionalExecutables; LogDebug() << "allBinaryPaths:" << allBinaryPaths; @@ -1300,39 +1402,59 @@ DeploymentInfo deployQtLibraries(const QString &appDirPath, const QStringList &a allRPaths.insert(QLibraryInfo::path(QLibraryInfo::LibrariesPath)); LogDebug() << "allRPaths:" << allRPaths; - QList libraries = getQtLibrariesForPaths(allBinaryPaths, appDirPath, allRPaths); + QList libraries = getQtLibrariesForPaths(allBinaryPaths, + appDirPath, + allRPaths); DeploymentInfo depInfo; if (libraries.isEmpty() && !alwaysOwerwriteEnabled) { - LogWarning() << "Could not find any external Qt libraries to deploy in" << appDirPath; - LogWarning() << "Perhaps linuxdeployqt was already used on" << appDirPath << "?"; - LogWarning() << "If so, you will need to rebuild" << appDirPath << "before trying again."; - LogWarning() << "Or ldd does not find the external Qt libraries but sees the system ones."; - LogWarning() << "If so, you will need to set LD_LIBRARY_PATH to the directory containing the external Qt libraries before trying again."; + LogWarning() << "Could not find any external Qt libraries to deploy in" + << appDirPath; + LogWarning() << "Perhaps linuxdeployqt was already used on" << appDirPath + << "?"; + LogWarning() << "If so, you will need to rebuild" << appDirPath + << "before trying again."; + LogWarning() << "Or ldd does not find the external Qt libraries but sees the " + "system ones."; + LogWarning() << "If so, you will need to set LD_LIBRARY_PATH to the directory " + "containing the external Qt libraries before trying again."; LogWarning() << "FIXME: https://github.com/probonopd/linuxdeployqt/issues/2"; } else { - depInfo = deployQtLibraries(libraries, applicationBundle.path, allBinaryPaths, !additionalExecutables.isEmpty()); + depInfo = deployQtLibraries(libraries, + applicationBundle.path, + allBinaryPaths, + !additionalExecutables.isEmpty()); } - foreach (const QString &executable, QStringList() << applicationBundle.binaryPath << additionalExecutables) { - changeIdentification("$ORIGIN/" + QFileInfo(executable).dir().relativeFilePath(libraryPath), QFileInfo(executable).canonicalFilePath()); + foreach (const QString& executable, + QStringList() << applicationBundle.binaryPath << additionalExecutables) { + changeIdentification("$ORIGIN/" + + QFileInfo(executable) + .dir() + .relativeFilePath(libraryPath), + QFileInfo(executable).canonicalFilePath()); } return depInfo; } -static void appendPluginToList(const QString pluginSourcePath, const QString pluginName, QStringList &pluginList) +static void appendPluginToList(const QString pluginSourcePath, + const QString pluginName, + QStringList& pluginList) { - QStringList plugins = QDir(pluginSourcePath + "/" + pluginName).entryList(QStringList() << QStringLiteral("*.so")); - foreach (const QString &plugin, plugins) { + QStringList plugins = QDir(pluginSourcePath + "/" + pluginName) + .entryList(QStringList() << QStringLiteral("*.so")); + foreach (const QString& plugin, plugins) { pluginList.append(pluginName + "/" + plugin); } } // All Qt 6 plugins are bases on windeployqt code for Qt 6.3.1, see // https://github.com/qt/qtbase/blob/8483dcde90f40cdfd0a0ec4245b03610b46b6cae/src/tools/windeployqt/main.cpp#L835-L869 -void deployPlugins(const AppDirInfo &appDirInfo, const QString &pluginSourcePath, - const QString pluginDestinationPath, DeploymentInfo deploymentInfo) +void deployPlugins(const AppDirInfo& appDirInfo, + const QString& pluginSourcePath, + const QString pluginDestinationPath, + DeploymentInfo deploymentInfo) { LogNormal() << "Deploying plugins from" << pluginSourcePath; @@ -1342,7 +1464,9 @@ void deployPlugins(const AppDirInfo &appDirInfo, const QString &pluginSourcePath // Plugin white list: QStringList pluginList; - LogDebug() << "deploymentInfo.deployedLibraries before attempting to bundle required plugins:" << deploymentInfo.deployedLibraries; + LogDebug() << "deploymentInfo.deployedLibraries before attempting to bundle " + "required plugins:" + << deploymentInfo.deployedLibraries; // Platform plugin: if (containsHowOften(deploymentInfo.deployedLibraries, "libQt5Gui") @@ -1350,8 +1474,10 @@ void deployPlugins(const AppDirInfo &appDirInfo, const QString &pluginSourcePath LogDebug() << "libQt5Gui/libQt6Gui detected"; pluginList.append("platforms/libqxcb.so"); // Platform plugin contexts - apparently needed to enter special characters - QStringList platformPluginContexts = QDir(pluginSourcePath + QStringLiteral("/platforminputcontexts")).entryList(QStringList() << QStringLiteral("*.so")); - foreach (const QString &plugin, platformPluginContexts) { + QStringList platformPluginContexts + = QDir(pluginSourcePath + QStringLiteral("/platforminputcontexts")) + .entryList(QStringList() << QStringLiteral("*.so")); + foreach (const QString& plugin, platformPluginContexts) { pluginList.append(QStringLiteral("platforminputcontexts/") + plugin); } // Platform themes - make Qt look more native e.g., on Gtk+ 3 (if available in Qt installation) @@ -1391,13 +1517,14 @@ void deployPlugins(const AppDirInfo &appDirInfo, const QString &pluginSourcePath // pluginList.append("iconengines"); // pluginList.append("imageformats"); // TODO: Need to traverse the directories and add each contained plugin individually - QStringList extraQtPluginDirs = { "iconengines", "imageformats" }; - foreach (const QString &plugin, extraQtPluginDirs) { + QStringList extraQtPluginDirs = {"iconengines", "imageformats"}; + foreach (const QString& plugin, extraQtPluginDirs) { QDir pluginDirectory(pluginSourcePath + "/" + plugin); if (pluginDirectory.exists()) { //If it is a plugin directory we will deploy the entire directory - QStringList plugins = pluginDirectory.entryList(QStringList() << QStringLiteral("*.so")); - foreach (const QString &pluginFile, plugins) { + QStringList plugins = pluginDirectory.entryList( + QStringList() << QStringLiteral("*.so")); + foreach (const QString& pluginFile, plugins) { pluginList.append(plugin + "/" + pluginFile); LogDebug() << plugin + "/" + pluginFile << "appended"; } @@ -1413,12 +1540,12 @@ void deployPlugins(const AppDirInfo &appDirInfo, const QString &pluginSourcePath // Platform OpenGL context if ((containsHowOften(deploymentInfo.deployedLibraries, "libQt5OpenGL")) - or (containsHowOften(deploymentInfo.deployedLibraries, "libQt6OpenGL")) - or (containsHowOften(deploymentInfo.deployedLibraries, "libQt5Gui")) - or (containsHowOften(deploymentInfo.deployedLibraries, "libQt6Gui")) - or (containsHowOften(deploymentInfo.deployedLibraries, "libQt5XcbQpa")) - or (containsHowOften(deploymentInfo.deployedLibraries, "libQt6XcbQpa")) - or (containsHowOften(deploymentInfo.deployedLibraries, "libxcb-glx"))) { + or (containsHowOften(deploymentInfo.deployedLibraries, "libQt6OpenGL")) + or (containsHowOften(deploymentInfo.deployedLibraries, "libQt5Gui")) + or (containsHowOften(deploymentInfo.deployedLibraries, "libQt6Gui")) + or (containsHowOften(deploymentInfo.deployedLibraries, "libQt5XcbQpa")) + or (containsHowOften(deploymentInfo.deployedLibraries, "libQt6XcbQpa")) + or (containsHowOften(deploymentInfo.deployedLibraries, "libxcb-glx"))) { appendPluginToList(pluginSourcePath, "xcbglintegrations", pluginList); } @@ -1539,7 +1666,7 @@ void deployPlugins(const AppDirInfo &appDirInfo, const QString &pluginSourcePath QString dstLibexec; QString dstResources; QString dstTranslations; - if(fhsLikeMode) { + if (fhsLikeMode) { QFileInfo qfi(appDirInfo.binaryPath); QString qtTargetDir = qfi.absoluteDir().absolutePath() + "/../"; dstLibexec = qtTargetDir + "/libexec"; @@ -1560,17 +1687,24 @@ void deployPlugins(const AppDirInfo &appDirInfo, const QString &pluginSourcePath // put qt.conf file next to browser process so it can also make use of our local Qt resources createQtConfForQtWebEngineProcess(dstLibexec); // Resources: - sourcePath = QDir::cleanPath(qtDataPath + "/resources/qtwebengine_resources.pak"); + sourcePath = QDir::cleanPath(qtDataPath + + "/resources/qtwebengine_resources.pak"); destinationPath = QDir::cleanPath(dstResources + "/qtwebengine_resources.pak"); copyFilePrintStatus(sourcePath, destinationPath); - sourcePath = QDir::cleanPath(qtDataPath + "/resources/qtwebengine_devtools_resources.pak"); - destinationPath = QDir::cleanPath(dstResources + "/qtwebengine_devtools_resources.pak"); + sourcePath = QDir::cleanPath(qtDataPath + + "/resources/qtwebengine_devtools_resources.pak"); + destinationPath = QDir::cleanPath(dstResources + + "/qtwebengine_devtools_resources.pak"); copyFilePrintStatus(sourcePath, destinationPath); - sourcePath = QDir::cleanPath(qtDataPath + "/resources/qtwebengine_resources_100p.pak"); - destinationPath = QDir::cleanPath(dstResources + "/qtwebengine_resources_100p.pak"); + sourcePath = QDir::cleanPath(qtDataPath + + "/resources/qtwebengine_resources_100p.pak"); + destinationPath = QDir::cleanPath(dstResources + + "/qtwebengine_resources_100p.pak"); copyFilePrintStatus(sourcePath, destinationPath); - sourcePath = QDir::cleanPath(qtDataPath + "/resources/qtwebengine_resources_200p.pak"); - destinationPath = QDir::cleanPath(dstResources + "/qtwebengine_resources_200p.pak"); + sourcePath = QDir::cleanPath(qtDataPath + + "/resources/qtwebengine_resources_200p.pak"); + destinationPath = QDir::cleanPath(dstResources + + "/qtwebengine_resources_200p.pak"); copyFilePrintStatus(sourcePath, destinationPath); sourcePath = QDir::cleanPath(qtDataPath + "/resources/icudtl.dat"); destinationPath = QDir::cleanPath(dstResources + "/icudtl.dat"); @@ -1583,55 +1717,61 @@ void deployPlugins(const AppDirInfo &appDirInfo, const QString &pluginSourcePath if (!extraQtPlugins.isEmpty()) { LogNormal() << "Deploying extra plugins."; - foreach (const QString &plugin, extraQtPlugins) { + foreach (const QString& plugin, extraQtPlugins) { QDir pluginDirectory(pluginSourcePath + "/" + plugin); if (pluginDirectory.exists()) { //If it is a plugin directory we will deploy the entire directory - QStringList plugins = pluginDirectory.entryList(QStringList() << QStringLiteral("*.so")); - foreach (const QString &pluginFile, plugins) { + QStringList plugins = pluginDirectory.entryList( + QStringList() << QStringLiteral("*.so")); + foreach (const QString& pluginFile, plugins) { pluginList.append(plugin + "/" + pluginFile); LogDebug() << plugin + "/" + pluginFile << "appended"; } - } - else { + } else { //If it isn't a directory we asume it is an explicit plugin and we will try to deploy that if (!pluginList.contains(plugin)) { if (QFile::exists(pluginSourcePath + "/" + plugin)) { pluginList.append(plugin); LogDebug() << plugin << "appended"; + } else { + LogWarning() << "The plugin" << pluginSourcePath + "/" + plugin + << "could not be found. Please check spelling and " + "try again!"; } - else { - LogWarning() <<"The plugin" << pluginSourcePath + "/" + plugin << "could not be found. Please check spelling and try again!"; - } - } - else { - LogDebug() << "The plugin" << plugin << "was already deployed." ; + } else { + LogDebug() << "The plugin" << plugin << "was already deployed."; } } } } - LogNormal() << "pluginList after having detected hopefully all required plugins:" << pluginList; + LogNormal() << "pluginList after having detected hopefully all required plugins:" + << pluginList; - foreach (const QString &plugin, pluginList) { + foreach (const QString& plugin, pluginList) { sourcePath = pluginSourcePath + "/" + plugin; destinationPath = pluginDestinationPath + "/" + plugin; - if(!excludedLibraries.contains(QFileInfo(sourcePath).baseName())) - { + if (!excludedLibraries.contains(QFileInfo(sourcePath).baseName())) { QDir dir; dir.mkpath(QFileInfo(destinationPath).path()); - QList libraries = getQtLibraries(sourcePath, appDirInfo.path, deploymentInfo.rpathsUsed); + QList libraries = getQtLibraries(sourcePath, + appDirInfo.path, + deploymentInfo.rpathsUsed); LogDebug() << "Deploying plugin" << sourcePath; if (copyFilePrintStatus(sourcePath, destinationPath)) { runStrip(destinationPath); - deployQtLibraries(libraries, appDirInfo.path, QStringList() << destinationPath, deploymentInfo.useLoaderPath); + deployQtLibraries(libraries, + appDirInfo.path, + QStringList() << destinationPath, + deploymentInfo.useLoaderPath); /* See whether this makes any difference */ // Find out the relative path to the lib/ directory and set it as the rpath QDir dir(destinationPath); - QString relativePath = dir.relativeFilePath(appDirInfo.path + "/" + libraries[0].libraryDestinationDirectory); + QString relativePath = dir.relativeFilePath( + appDirInfo.path + "/" + libraries[0].libraryDestinationDirectory); relativePath.remove(0, 3); // remove initial '../' - changeIdentification("$ORIGIN/" + relativePath, QFileInfo(destinationPath).canonicalFilePath()); - + changeIdentification("$ORIGIN/" + relativePath, + QFileInfo(destinationPath).canonicalFilePath()); } LogDebug() << "copyCopyrightFile:" << sourcePath; copyCopyrightFile(sourcePath); @@ -1639,18 +1779,19 @@ void deployPlugins(const AppDirInfo &appDirInfo, const QString &pluginSourcePath } } -void createQtConf(const QString &appDirPath) +void createQtConf(const QString& appDirPath) { // See, https://doc.qt.io/qt-6/qt-conf.html#overriding-paths - QByteArray contents = fhsLikeMode ? "[Paths]\nPrefix = ../" : "[Paths]\nPrefix = ./"; - QString filePath = appDirPath + "/"; // Is picked up when placed next to the main executable + QByteArray contents = fhsLikeMode ? "[Paths]\nPrefix = ../" + : "[Paths]\nPrefix = ./"; + QString filePath = appDirPath + + "/"; // Is picked up when placed next to the main executable QString fileName = QDir::cleanPath(appBinaryPath + "/../qt.conf"); QDir().mkpath(filePath); QFile qtconf(fileName); if (qtconf.exists() && !alwaysOwerwriteEnabled) { - LogWarning() << fileName << "already exists, will not overwrite."; return; } @@ -1661,7 +1802,7 @@ void createQtConf(const QString &appDirPath) } } -void createQtConfForQtWebEngineProcess(const QString &appDirPath) +void createQtConfForQtWebEngineProcess(const QString& appDirPath) { QByteArray contents = "[Paths]\n" "Prefix = ../\n"; @@ -1678,36 +1819,44 @@ void createQtConfForQtWebEngineProcess(const QString &appDirPath) qtconf.open(QIODevice::WriteOnly); if (qtconf.write(contents) != -1) { - LogNormal() << "Created configuration file for Qt WebEngine process:" << fileName; - LogNormal() << "This file sets the prefix option to parent directory of browser process executable"; + LogNormal() << "Created configuration file for Qt WebEngine process:" + << fileName; + LogNormal() << "This file sets the prefix option to parent directory of " + "browser process executable"; } } -void deployPlugins(const QString &appDirPath, DeploymentInfo deploymentInfo) +void deployPlugins(const QString& appDirPath, DeploymentInfo deploymentInfo) { AppDirInfo applicationBundle; applicationBundle.path = appDirPath; applicationBundle.binaryPath = appBinaryPath; QString pluginDestinationPath; - if(fhsLikeMode) { + if (fhsLikeMode) { QFileInfo qfi(applicationBundle.binaryPath); QString qtTargetDir = qfi.absoluteDir().absolutePath() + "/../"; pluginDestinationPath = qtTargetDir + "/plugins"; } else { pluginDestinationPath = appDirPath + "/" + "plugins"; } - deployPlugins(applicationBundle, deploymentInfo.pluginPath, pluginDestinationPath, deploymentInfo); + deployPlugins(applicationBundle, + deploymentInfo.pluginPath, + pluginDestinationPath, + deploymentInfo); } -void deployQmlImport(const QString &appDirPath, const QSet &rpaths, const QString &importSourcePath, const QString &importName) +void deployQmlImport(const QString& appDirPath, + const QSet& rpaths, + const QString& importSourcePath, + const QString& importName) { AppDirInfo applicationBundle; applicationBundle.path = appDirPath; applicationBundle.binaryPath = appBinaryPath; QString importDestinationPath; - if(fhsLikeMode) { + if (fhsLikeMode) { QFileInfo qfi(applicationBundle.binaryPath); QString qtTargetDir = qfi.absoluteDir().absolutePath() + "/../"; importDestinationPath = qtTargetDir + "/qml/" + importName; @@ -1723,7 +1872,7 @@ void deployQmlImport(const QString &appDirPath, const QSet &rpaths, con QDir destDir(importDestinationPath); if (destDir.exists()) { destDir.setFilter(QDir::Files | QDir::NoDotAndDotDot); - if(destDir.entryInfoList().length() > 0) + if (destDir.entryInfoList().length() > 0) return; } @@ -1731,9 +1880,12 @@ void deployQmlImport(const QString &appDirPath, const QSet &rpaths, con } // Scan qml files in qmldirs for import statements, deploy used imports from Qml2ImportsPath to ./qml. -bool deployQmlImports(const QString &appDirPath, DeploymentInfo deploymentInfo, QStringList &qmlDirs, QStringList &qmlImportPaths) +bool deployQmlImports(const QString& appDirPath, + DeploymentInfo deploymentInfo, + QStringList& qmlDirs, + QStringList& qmlImportPaths) { - if(!qtDetected) { + if (!qtDetected) { LogDebug() << "Skipping QML imports since no Qt detected"; return false; } @@ -1744,19 +1896,26 @@ bool deployQmlImports(const QString &appDirPath, DeploymentInfo deploymentInfo, LogNormal() << "QML module search path(s) is" << qmlImportPaths; // Use qmlimportscanner from QLibraryInfo::BinariesPath - QString qmlImportScannerPath = QDir::cleanPath(qtToBeBundledInfo.value("QT_INSTALL_BINS")) + "/qmlimportscanner"; + QString qmlImportScannerPath = QDir::cleanPath( + qtToBeBundledInfo.value("QT_INSTALL_BINS")) + + "/qmlimportscanner"; LogDebug() << "Looking for qmlimportscanner at" << qmlImportScannerPath; // The location of qmlimportscanner has changed starting from Qt 6 if (!QFile(qmlImportScannerPath).exists()) { - qmlImportScannerPath = QDir::cleanPath(qtToBeBundledInfo.value("QT_INSTALL_LIBEXECS")) + "/qmlimportscanner"; - LogDebug() << "Fallback, looking for Qt 6 qmlimportscanner at" << qmlImportScannerPath; + qmlImportScannerPath = QDir::cleanPath( + qtToBeBundledInfo.value("QT_INSTALL_LIBEXECS")) + + "/qmlimportscanner"; + LogDebug() << "Fallback, looking for Qt 6 qmlimportscanner at" + << qmlImportScannerPath; } // Fallback: Look relative to the linuxdeployqt binary if (!QFile(qmlImportScannerPath).exists()) { - qmlImportScannerPath = QCoreApplication::applicationDirPath() + "/qmlimportscanner"; - LogDebug() << "Fallback, looking for qmlimportscanner at" << qmlImportScannerPath; + qmlImportScannerPath = QCoreApplication::applicationDirPath() + + "/qmlimportscanner"; + LogDebug() << "Fallback, looking for qmlimportscanner at" + << qmlImportScannerPath; } // Verify that we found a qmlimportscanner binary @@ -1769,20 +1928,21 @@ bool deployQmlImports(const QString &appDirPath, DeploymentInfo deploymentInfo, // build argument list for qmlimportsanner: "-rootPath foo/ -rootPath bar/ -importPath path/to/qt/qml" // ("rootPath" points to a directory containing app qml, "importPath" is where the Qt imports are installed) QStringList argumentList; - foreach (const QString &qmlDir, qmlDirs) { + foreach (const QString& qmlDir, qmlDirs) { argumentList.append("-rootPath"); argumentList.append(qmlDir); } - foreach (const QString &importPath, qmlImportPaths) { + foreach (const QString& importPath, qmlImportPaths) { argumentList.append("-importPath"); argumentList.append(importPath); } - argumentList.append( "-importPath"); + argumentList.append("-importPath"); argumentList.append(qtToBeBundledInfo.value("QT_INSTALL_QML")); - LogDebug() << "qmlImportsPath (QT_INSTALL_QML):" << qtToBeBundledInfo.value("QT_INSTALL_QML"); + LogDebug() << "qmlImportsPath (QT_INSTALL_QML):" + << qtToBeBundledInfo.value("QT_INSTALL_QML"); // run qmlimportscanner QProcess qmlImportScanner; @@ -1790,7 +1950,8 @@ bool deployQmlImports(const QString &appDirPath, DeploymentInfo deploymentInfo, LogDebug() << qmlImportScannerPath << argumentList; qmlImportScanner.start(qmlImportScannerPath, argumentList); if (!qmlImportScanner.waitForStarted()) { - LogError() << "Could not start qmlimportscanner. Process error is" << qmlImportScanner.errorString(); + LogError() << "Could not start qmlimportscanner. Process error is" + << qmlImportScanner.errorString(); return false; } qmlImportScanner.waitForFinished(); @@ -1816,7 +1977,7 @@ bool deployQmlImports(const QString &appDirPath, DeploymentInfo deploymentInfo, bool qtQuickContolsInUse = false; // condition for QtQuick.PrivateWidgets below // deploy each import - foreach (const QJsonValue &importValue, doc.array()) { + foreach (const QJsonValue& importValue, doc.array()) { if (!importValue.isObject()) continue; @@ -1870,53 +2031,65 @@ bool deployQmlImports(const QString &appDirPath, DeploymentInfo deploymentInfo, if (deploymentInfo.requiresQtWidgetsLibrary && qtQuickContolsInUse) { LogNormal() << "Deploying QML import QtQuick/PrivateWidgets"; QString name = "QtQuick/PrivateWidgets"; - QString path = qtToBeBundledInfo.value("QT_INSTALL_QML") + QLatin1Char('/') + name; + QString path = qtToBeBundledInfo.value("QT_INSTALL_QML") + QLatin1Char('/') + + name; deployQmlImport(appDirPath, deploymentInfo.rpathsUsed, path, name); LogNormal() << ""; } return true; } -void changeQtLibraries(const QList libraries, const QStringList &binaryPaths, const QString &absoluteQtPath) +void changeQtLibraries(const QList /*libraries*/, + const QStringList& binaryPaths, + const QString& absoluteQtPath) { LogNormal() << "Changing" << binaryPaths << "to link against"; LogNormal() << "Qt in" << absoluteQtPath; - QString finalQtPath = absoluteQtPath; + // QString finalQtPath = absoluteQtPath; - finalQtPath += "/lib/"; + // finalQtPath += "/lib/"; - foreach (LibraryInfo library, libraries) { - const QString oldBinaryId = library.installName; - const QString newBinaryId = finalQtPath + library.libraryName + library.binaryPath; - } + // foreach (LibraryInfo library, libraries) { + // const QString oldBinaryId = library.installName; + // const QString newBinaryId = finalQtPath + library.libraryName + // + library.binaryPath; + // } } -void changeQtLibraries(const QString appPath, const QString &qtPath) +void changeQtLibraries(const QString appPath, const QString& qtPath) { const QStringList libraryPaths = findAppLibraries(appPath); - const QList libraries = getQtLibrariesForPaths(QStringList() << appBinaryPath << libraryPaths, appPath, getBinaryRPaths(appBinaryPath, true)); + const QList libraries + = getQtLibrariesForPaths(QStringList() << appBinaryPath << libraryPaths, + appPath, + getBinaryRPaths(appBinaryPath, true)); if (libraries.isEmpty()) { - - LogWarning() << "Could not find any _external_ Qt libraries to change in" << appPath; + LogWarning() << "Could not find any _external_ Qt libraries to change in" + << appPath; return; } else { const QString absoluteQtPath = QDir(qtPath).absolutePath(); - changeQtLibraries(libraries, QStringList() << appBinaryPath << libraryPaths, absoluteQtPath); + changeQtLibraries(libraries, + QStringList() << appBinaryPath << libraryPaths, + absoluteQtPath); } } -bool checkAppImagePrerequisites(const QString &appDirPath) +bool checkAppImagePrerequisites(const QString& appDirPath) { - if(fhsLikeMode == true) { + if (fhsLikeMode == true) { /* In FHS-like mode, we assume that there will be a desktop file * and icon file that appimagetool will be able to pick up */ return true; } - QDirIterator iter(appDirPath, QStringList() << QString::fromLatin1("*.desktop"), - QDir::Files, QDirIterator::Subdirectories); + QDirIterator iter(appDirPath, + QStringList() << QString::fromLatin1("*.desktop"), + QDir::Files, + QDirIterator::Subdirectories); if (!iter.hasNext()) { - LogError() << "Desktop file missing, creating a default one (you will probably want to edit it)"; + LogError() << "Desktop file missing, creating a default one (you will probably " + "want to edit it)"; QFile file(appDirPath + "/default.desktop"); file.open(QIODevice::WriteOnly | QIODevice::Text); QTextStream out(&file); @@ -1931,10 +2104,13 @@ bool checkAppImagePrerequisites(const QString &appDirPath) } // TODO: Compare whether the icon filename matches the Icon= entry without ending in the *.desktop file above - QDirIterator iter2(appDirPath, QStringList() << QString::fromLatin1("*.png"), - QDir::Files, QDirIterator::Subdirectories); + QDirIterator iter2(appDirPath, + QStringList() << QString::fromLatin1("*.png"), + QDir::Files, + QDirIterator::Subdirectories); if (!iter2.hasNext()) { - LogError() << "Icon file missing, creating a default one (you will probably want to edit it)"; + LogError() << "Icon file missing, creating a default one (you will probably " + "want to edit it)"; QFile file2(appDirPath + "/default.png"); file2.open(QIODevice::WriteOnly | QIODevice::Text); QTextStream out2(&file2); @@ -1945,13 +2121,14 @@ bool checkAppImagePrerequisites(const QString &appDirPath) return true; } -int createAppImage(const QString &appDirPath) +int createAppImage(const QString& appDirPath) { QString updateInfoArgument; if (!updateInformation.isEmpty()) updateInfoArgument = QString("-u '%1'").arg(updateInformation); - QString appImageCommand = "appimagetool -v '" + appDirPath + "' -n " + updateInfoArgument; + QString appImageCommand = "appimagetool -v '" + appDirPath + "' -n " + + updateInfoArgument; LogNormal() << appImageCommand; int ret = system(appImageCommand.toUtf8().constData()); LogNormal() << "ret" << ret; @@ -1959,18 +2136,18 @@ int createAppImage(const QString &appDirPath) return WEXITSTATUS(ret); } -void findUsedModules(DeploymentInfo &info) +void findUsedModules(DeploymentInfo& info) { LogDebug() << "Creating mask of used modules"; - const QStringList &libraries = info.deployedLibraries; + const QStringList& libraries = info.deployedLibraries; for (size_t i = 0; i < qtModuleEntriesCount; ++i) { - QtModuleEntry &entry = qtModuleEntries[i]; + QtModuleEntry& entry = qtModuleEntries[i]; const QString name = QLatin1String(qtModuleEntries[i].libraryName); bool found = false; - foreach (const QString &library, libraries) { + foreach (const QString& library, libraries) { if (library.contains(name, Qt::CaseInsensitive)) { LogDebug() << "Found dependency:" << name; found = true; @@ -1984,12 +2161,13 @@ void findUsedModules(DeploymentInfo &info) } } -void deployTranslations(const QString &appDirPath, quint64 usedQtModules) +void deployTranslations(const QString& appDirPath, quint64 usedQtModules) { LogDebug() << "Deploying translations..."; QString qtTranslationsPath = qtToBeBundledInfo.value("QT_INSTALL_TRANSLATIONS"); if (qtTranslationsPath.isEmpty() || !QFile::exists(qtTranslationsPath)) { - LogDebug() << "Qt translations path could not be determined, maybe there are no translations?"; + LogDebug() << "Qt translations path could not be determined, maybe there are " + "no translations?"; return; } @@ -2003,7 +2181,8 @@ void deployTranslations(const QString &appDirPath, quint64 usedQtModules) translationsDirPath = appRoot + QStringLiteral("/translations"); } - LogNormal() << "Using" << translationsDirPath << "as translations directory for App"; + LogNormal() << "Using" << translationsDirPath + << "as translations directory for App"; LogNormal() << "Using" << qtTranslationsPath << " to search for Qt translations"; QFileInfo fi(translationsDirPath); @@ -2020,13 +2199,13 @@ void deployTranslations(const QString &appDirPath, quint64 usedQtModules) } } -QStringList translationNameFilters(quint64 modules, const QString &prefix) +QStringList translationNameFilters(quint64 modules, const QString& prefix) { QStringList result; for (size_t i = 0; i < qtModuleEntriesCount; ++i) { if ((qtModuleEntries[i].module & modules) && qtModuleEntries[i].translation) { - const QString name = QLatin1String(qtModuleEntries[i].translation) + - QLatin1Char('_') + prefix + QStringLiteral(".qm"); + const QString name = QLatin1String(qtModuleEntries[i].translation) + + QLatin1Char('_') + prefix + QStringLiteral(".qm"); if (!result.contains(name)) result.push_back(name); } @@ -2035,7 +2214,9 @@ QStringList translationNameFilters(quint64 modules, const QString &prefix) return result; } -bool deployTranslations(const QString &sourcePath, const QString &target, quint64 usedQtModules) +bool deployTranslations(const QString& sourcePath, + const QString& target, + quint64 usedQtModules) { LogDebug() << "Translations target is" << target; @@ -2049,15 +2230,16 @@ bool deployTranslations(const QString &sourcePath, const QString &target, quint6 prefixes.push_back(qmFile); } if (prefixes.isEmpty()) { - LogError() << "Could not find any translations in " - << sourcePath << " (developer build?)"; + LogError() << "Could not find any translations in " << sourcePath + << " (developer build?)"; return true; } // Run lconvert to concatenate all files into a single named "qt_.qm" in the application folder // Use QT_INSTALL_TRANSLATIONS as working directory to keep the command line short. const QString absoluteTarget = QFileInfo(target).absoluteFilePath(); - QString lconvertPath = QDir::cleanPath(qtToBeBundledInfo.value("QT_INSTALL_BINS")) + "/lconvert"; + QString lconvertPath = QDir::cleanPath(qtToBeBundledInfo.value("QT_INSTALL_BINS")) + + "/lconvert"; LogDebug() << "Looking for lconvert at" << lconvertPath; // Fallback: Look relative to the linuxdeployqt binary @@ -2075,14 +2257,17 @@ bool deployTranslations(const QString &sourcePath, const QString &target, quint6 LogNormal() << "Found lconvert at" << lconvertPath; QStringList arguments; - foreach (const QString &prefix, prefixes) { + foreach (const QString& prefix, prefixes) { arguments.clear(); - const QString targetFile = QStringLiteral("qt_") + prefix + QStringLiteral(".qm"); + const QString targetFile = QStringLiteral("qt_") + prefix + + QStringLiteral(".qm"); arguments.append(QStringLiteral("-o")); - const QString currentTargetFile = absoluteTarget + QLatin1Char('/') + targetFile; + const QString currentTargetFile = absoluteTarget + QLatin1Char('/') + + targetFile; arguments.append(currentTargetFile); - foreach (const QFileInfo &qmFileInfo, sourceDir.entryInfoList(translationNameFilters(usedQtModules, prefix))) + foreach (const QFileInfo& qmFileInfo, + sourceDir.entryInfoList(translationNameFilters(usedQtModules, prefix))) arguments.append(qmFileInfo.absoluteFilePath()); LogNormal() << "Creating " << currentTargetFile << "..."; diff --git a/shared.h b/shared.h index 1732454a..8a944993 100644 --- a/shared.h +++ b/shared.h @@ -1,10 +1,9 @@ -#ifndef SHARED_H -#define SHARED_H +#pragma once -#include -#include #include #include +#include +#include extern int logLevel; #define LogError() if (logLevel < 0) {} else qDebug() << "ERROR:" @@ -54,8 +53,8 @@ class LddInfo QList dependencies; }; -bool operator==(const LibraryInfo &a, const LibraryInfo &b); -QDebug operator<<(QDebug debug, const LibraryInfo &info); +bool operator==(const LibraryInfo& a, const LibraryInfo& b); +QDebug operator<<(QDebug debug, const LibraryInfo& info); class AppDirInfo { @@ -78,36 +77,52 @@ class DeploymentInfo bool requiresQtWidgetsLibrary; }; -inline QDebug operator<<(QDebug debug, const AppDirInfo &info); - -void changeQtLibraries(const QString appPath, const QString &qtPath); -void changeQtLibraries(const QList libraries, const QStringList &binaryPaths, const QString &qtPath); +inline QDebug operator<<(QDebug debug, const AppDirInfo& info); -LddInfo findDependencyInfo(const QString &binaryPath); -LibraryInfo parseLddLibraryLine(const QString &line, const QString &appDirPath, const QSet &rpaths); -QString findAppBinary(const QString &appDirPath); -QList getQtLibraries(const QString &path, const QString &appDirPath, const QSet &rpaths); -QList getQtLibraries(const QStringList &lddLines, const QString &appDirPath, const QSet &rpaths); -QString copyLibrary(const LibraryInfo &library, const QString path); -DeploymentInfo deployQtLibraries(const QString &appDirPath, - const QStringList &additionalExecutables, - const QString &qmake); -DeploymentInfo deployQtLibraries(QList libraries,const QString &bundlePath, const QStringList &binaryPaths, bool useLoaderPath); -void createQtConf(const QString &appDirPath); -void createQtConfForQtWebEngineProcess(const QString &appDirPath); -void deployPlugins(const QString &appDirPath, DeploymentInfo deploymentInfo); -bool deployQmlImports(const QString &appDirPath, DeploymentInfo deploymentInfo, QStringList &qmlDirs, QStringList &qmlImportPaths); -void changeIdentification(const QString &id, const QString &binaryPath); -void changeInstallName(const QString &oldName, const QString &newName, const QString &binaryPath); -void runStrip(const QString &binaryPath); -void stripAppBinary(const QString &bundlePath); -QString findAppBinary(const QString &appDirPath); -QStringList findAppLibraries(const QString &appDirPath); -bool patchQtCore(const QString &path, const QString &variable, const QString &value); -int createAppImage(const QString &appBundlePath); -bool checkAppImagePrerequisites(const QString &appBundlePath); -void findUsedModules(DeploymentInfo &info); -void deployTranslations(const QString &appDirPath, quint64 usedQtModules); -bool deployTranslations(const QString &sourcePath, const QString &target, quint64 usedQtModules); +void changeQtLibraries(const QString appPath, const QString& qtPath); +void changeQtLibraries(const QList libraries, + const QStringList& binaryPaths, + const QString& qtPath); -#endif // SHARED_H +LddInfo findDependencyInfo(const QString& binaryPath); +LibraryInfo parseLddLibraryLine(const QString& line, + const QString& appDirPath, + const QSet& rpaths); +QString findAppBinary(const QString& appDirPath); +QList getQtLibraries(const QString& path, + const QString& appDirPath, + const QSet& rpaths); +QList getQtLibraries(const QStringList& lddLines, + const QString& appDirPath, + const QSet& rpaths); +QString copyLibrary(const LibraryInfo& library, const QString path); +DeploymentInfo deployQtLibraries(const QString& appDirPath, + const QStringList& additionalExecutables, + const QString& qmake); +DeploymentInfo deployQtLibraries(QList libraries, + const QString& bundlePath, + const QStringList& binaryPaths, + bool useLoaderPath); +void createQtConf(const QString& appDirPath); +void createQtConfForQtWebEngineProcess(const QString& appDirPath); +void deployPlugins(const QString& appDirPath, DeploymentInfo deploymentInfo); +bool deployQmlImports(const QString& appDirPath, + DeploymentInfo deploymentInfo, + QStringList& qmlDirs, + QStringList& qmlImportPaths); +void changeIdentification(const QString& id, const QString& binaryPath); +void changeInstallName(const QString& oldName, + const QString& newName, + const QString& binaryPath); +void runStrip(const QString& binaryPath); +void stripAppBinary(const QString& bundlePath); +QString findAppBinary(const QString& appDirPath); +QStringList findAppLibraries(const QString& appDirPath); +bool patchQtCore(const QString& path, const QString& variable, const QString& value); +int createAppImage(const QString& appBundlePath); +bool checkAppImagePrerequisites(const QString& appBundlePath); +void findUsedModules(DeploymentInfo& info); +void deployTranslations(const QString& appDirPath, quint64 usedQtModules); +bool deployTranslations(const QString& sourcePath, + const QString& target, + quint64 usedQtModules);