9#include <QtCore/QCommandLineOption>
10#include <QtCore/QCommandLineParser>
12#include <QtCore/QFileInfo>
13#include <QtCore/QCoreApplication>
14#include <QtCore/QJsonDocument>
15#include <QtCore/QJsonObject>
16#include <QtCore/QJsonArray>
17#include <QtCore/QList>
18#include <QtCore/QOperatingSystemVersion>
19#include <QtCore/QSharedPointer>
22#include <QtCore/qt_windows.h>
24#define IMAGE_FILE_MACHINE_ARM64 0xaa64
27#include <QtCore/private/qconfig_p.h>
33#include <unordered_map>
41#define DECLARE_KNOWN_MODULE(name) \
42 static size_t Qt##name ## ModuleId = QtModule::InvalidId
55#define DEFINE_KNOWN_MODULE(name) \
56 m[QLatin1String("Qt6" #name)] = &Qt##name ## ModuleId
60 std::unordered_map<QString, size_t *>
m;
72 const QtModule &
module = qtModuleEntries.moduleById(i);
80#undef DECLARE_KNOWN_MODULE
81#undef DEFINE_KNOWN_MODULE
112 result.append(
"Internal");
121 for (
const auto &pair : pluginInfo.typeMap()) {
124 for (
const QString &plugin : pair.second) {
135 if (xSpec.startsWith(
"win32-"_L1)) {
136 if (xSpec.contains(
"clang-g++"_L1))
138 if (xSpec.contains(
"clang-msvc++"_L1))
140 if (xSpec.contains(
"arm"_L1))
142 if (xSpec.contains(
"G++"_L1))
165 std::wcerr <<
"Warning: both -" << enableOption.names().first()
166 <<
" and -" << disableOption.names().first() <<
" were specified, defaulting to -"
167 << enableOption.names().first() <<
".\n";
224 for (
const QFileInfo &binaryFi : binaries) {
227 return binaryFi.absoluteFilePath();
248 u
"Use specified qmake instead of qmake from PATH. Deprecated, use qtpaths instead."_s,
257 u
"Use specified qtpaths.exe instead of qtpaths.exe from PATH."_s,
266 u
"Verbose level (0-2)."_s,
289 if (parser.
isSet(qmakeOption) && parser.
isSet(qtpathsOption)) {
295 std::wcerr <<
"Warning: -qmake option is deprecated. Use -qtpaths instead.\n";
297 if (parser.
isSet(qtpathsOption) || parser.
isSet(qmakeOption)) {
298 const QString qtpathsArg = parser.
isSet(qtpathsOption) ? parser.
value(qtpathsOption)
299 : parser.
value(qmakeOption);
308 if (!fi.isExecutable()) {
316 if (parser.
isSet(verboseOption)) {
333 using CommandLineOptionPtr = QSharedPointer<QCommandLineOption>;
334 using OptionPtrVector = QList<CommandLineOptionPtr>;
338 "\n\nThe simplest way to use windeployqt is to add the bin directory of your Qt\n"
339 "installation (e.g. <QT_DIR\\bin>) to the PATH variable and then run:\n windeployqt <path-to-app-binary>\n\n"
340 "If your application uses Qt Quick, run:\n windeployqt --qmldir <path-to-app-qml-files> <path-to-app-binary>"_s);
365 u
"Copy translations to path."_s,
381 QStringLiteral(
"Assume release binaries with debug information."));
383 parser->
addOption(releaseWithDebugInfoOption);
394 QStringLiteral(
"Simulation mode. Behave normally, but do not copy/update any files."));
410 QStringLiteral(
"Include in the deployment all relevant plugins by taking into account all soft dependencies."));
411 parser->
addOption(includeSoftPluginsOption);
414 QStringLiteral(
"A comma-separated list of plugin types that are not deployed (qmltooling,generic)."),
416 parser->
addOption(skipPluginTypesOption);
419 QStringLiteral(
"A comma-separated list of plugin types that will be added to deployment (imageformats,iconengines)"),
424 QStringLiteral(
"A comma-separated list of individual plugins that will be added to deployment (scene2d,qjpeg)"),
429 QStringLiteral(
"A comma-separated list of individual plugins that will not be deployed (qsvg,qpdf)"),
443 QStringLiteral(
"Add the given path to the QML module search locations."),
453 QStringLiteral(
"A comma-separated list of languages to deploy (de,fi)."),
463 parser->
addOption(noSystemD3DCompilerOption);
466 QStringLiteral(
"Skip deployment of the system DXC (dxcompiler.dll, dxil.dll)."));
472 parser->
addOption(compilerRunTimeOption);
475 QStringLiteral(
"Do not deploy compiler runtime (Desktop only)."));
476 parser->
addOption(noCompilerRunTimeOption);
483 QStringLiteral(
"Do not deploy the software rasterizer library."));
484 parser->
addOption(suppressSoftwareRasterizerOption);
491 QStringLiteral(
"Deploy openssl plugin but ignore openssl library dependency"));
501 "Print only the names of the files copied.\n"
502 "Available options:\n"
503 " source: absolute path of the source files\n"
504 " target: absolute path of the target files\n"
505 " relative: paths of the target files, relative\n"
506 " to the target directory\n"
507 " mapping: outputs the source and the relative\n"
508 " target, suitable for use within an\n"
509 " Appx mapping file"_L1,
522 bool insightTrackerModuleAvailable =
false;
524 OptionPtrVector enabledModuleOptions;
525 OptionPtrVector disabledModuleOptions;
527 enabledModuleOptions.reserve(qtModulesCount);
528 disabledModuleOptions.reserve(qtModulesCount);
532 if (
name == u
"InsightTracker") {
533 parser->
addOption(deployInsightTrackerOption);
534 insightTrackerModuleAvailable =
true;
538 parser->
addOption(*enabledOption.data());
539 enabledModuleOptions.append(enabledOption);
542 disabledDescription));
543 disabledModuleOptions.append(disabledOption);
544 parser->
addOption(*disabledOption.data());
548 if (parser->
isSet(helpOption))
550 if (parser->
isSet(versionOption))
564 if (parser->
isSet(translationOption))
572 || parser->
isSet(compilerRunTimeOption))
574 if (parser->
isSet(noCompilerRunTimeOption))
585 if (parser->
isSet(skipPluginTypesOption))
588 if (parser->
isSet(addPluginTypesOption))
591 if (parser->
isSet(includePluginsOption))
594 if (parser->
isSet(excludePluginsOption))
597 if (parser->
isSet(releaseWithDebugInfoOption))
598 std::wcerr <<
"Warning: " << releaseWithDebugInfoOption.names().first() <<
" is obsolete.";
611 if (parser->
isSet(deployPdbOption)) {
615 std::wcerr <<
"Warning: --" << deployPdbOption.names().first() <<
" is not supported on this platform.\n";
618 if (parser->
isSet(suppressSoftwareRasterizerOption))
621 if (parser->
isSet(noFFmpegOption))
624 if (parser->
isSet(forceOpenSslOption))
627 if (parser->
isSet(openSslRootOption))
635 if (parser->
isSet(forceOption))
637 if (parser->
isSet(dryRunOption)) {
644 if (insightTrackerModuleAvailable)
648 if (parser->
isSet(*enabledModuleOptions.at(module.id)))
650 if (parser->
isSet(*disabledModuleOptions.at(module.id)))
660 if (parser->
isSet(listOption)) {
676 if (parser->
isSet(jsonOption) || options->
list) {
682 if (posArgs.isEmpty()) {
687 if (parser->
isSet(dirOption))
690 if (parser->
isSet(qmlDirOption))
693 if (parser->
isSet(qmlImportOption))
709 options->
binaries.append(fi.absoluteFilePath());
718 options->
directory = fi.absoluteFilePath();
723 bool multipleDirs =
false;
724 for (
int i = 1;
i < posArgs.size(); ++
i) {
734 for (
const QString &library : libraries)
737 if (!parser->
isSet(dirOption) && fi.absolutePath() != options->
directory)
743 std::wcerr <<
"Warning: using binaries from different directories, deploying to following path: "
744 << options->
directory <<
'\n' <<
"To disable this warning, use the --dir option\n";
755 const qsizetype lastBlank =
s.lastIndexOf(u
' ',
i);
756 if (lastBlank >= 0) {
757 s[lastBlank] = u
'\n';
773 const qsizetype moduleStart =
result.indexOf(
"\n --"_L1 + firstModuleOption);
774 const qsizetype argumentsStart =
result.lastIndexOf(
"\nArguments:"_L1);
775 if (moduleStart >= argumentsStart)
779 "\n\nQt libraries can be added by passing their name (-xml) or removed by passing\n"
780 "the name prepended by --no- (--no-xml). Available libraries:\n"_L1;
783 moduleHelp += u
"\n\n";
785 u
"Qt plugins can be included or excluded individually or by type.\n"
786 u
"To deploy or block plugins individually, use the --include-plugins\n"
787 u
"and --exclude-plugins options (--include-plugins qjpeg,qsvgicon)\n"
788 u
"You can also use the --skip-plugin-types or --add-plugin-types to\n"
789 u
"achieve similar results with entire plugin groups, like imageformats, e.g.\n"
790 u
"(--add-plugin-types imageformats,iconengines). Exclusion always takes\n"
791 u
"precedence over inclusion, and types take precedence over specific plugins.\n"
792 u
"For example, including qjpeg, but skipping imageformats, will NOT deploy qjpeg.\n"
793 u
"\nDetected available plugins:\n";
795 result.replace(moduleStart, argumentsStart - moduleStart, moduleHelp);
804 const QChar version = libName.at(2);
805 return version.isDigit() && (version.toLatin1() -
'0') == QT_VERSION_MAJOR;
811 unsigned *wordSize =
nullptr,
bool *isDebug =
nullptr,
812 unsigned short *machineArch =
nullptr,
813 int *directDependencyCount =
nullptr,
int recursionDepth = 0)
816 if (directDependencyCount)
817 *directDependencyCount = 0;
820 errorMessage->prepend(
"Unable to find dependent libraries of "_L1 +
827 for (
const QString &lib : std::as_const(dependentLibs)) {
835 if (directDependencyCount)
836 *directDependencyCount =
end -
start;
840 nullptr,
nullptr,
nullptr,
nullptr, recursionDepth + 1))
851 m_platform(
platform), m_debugMatchMode(debugMatchMode), m_prefix(prefix) {}
864 const qsizetype lastDot = libraryFileName.lastIndexOf(u
'.') + 1;
867 libraryFileName.replace(lastDot, libraryFileName.size() - lastDot,
"pdb"_L1);
868 return libraryFileName;
887 , m_dllFilter(
platform, debugMatchMode), m_moduleSourcePath(moduleSourcePath)
899 for (
const QString &library : libraries) {
916 if (!moduleSourceDir.
cdUp()) {
920 return moduleSourceDir;
936 const unsigned m_flags;
945 const qsizetype lastSlashPos =
module.lastIndexOf(u'/');
946 if (lastSlashPos > 0)
947 module.remove(0, lastSlashPos + 1);
950 int endPos = infix.isEmpty() ? -1 :
module.lastIndexOf(infix);
952 endPos =
module.indexOf(u'.');
954 module.truncate(endPos);
958 if (module == libraryName
959 || (module.
size() == libraryName.size() + 1 && module.
startsWith(libraryName))) {
963 std::wcerr <<
"Warning: module " <<
qPrintable(module) <<
" could not be found\n";
973 bool deployInsightTrackerPlugin,
bool deployOpenSslPlugin)
975 const QString subDirName = subDir.dirName();
978 std::wcout <<
"Skipping plugin " << plugin <<
" due to skipped plugin type " << subDirName <<
'\n';
981 if (
optVerboseLevel && subDirName == u
"generic" && plugin.contains(u
"qinsighttracker")
982 && !deployInsightTrackerPlugin) {
983 std::wcout <<
"Skipping plugin " << plugin
984 <<
". Use -deploy-insighttracker if you want to use it.\n";
987 if (
optVerboseLevel && subDirName == u
"tls" && plugin.contains(u
"qopensslbackend")
988 && !deployOpenSslPlugin) {
989 std::wcout <<
"Skipping plugin " << plugin
990 <<
". Use -force_openssl or specify -openssl-root if you want to use it.\n";
994 const int dotIndex = plugin.lastIndexOf(u
'.');
1000 const QString pluginName = plugin.first(stripIndex);
1003 std::wcout <<
"Skipping plugin " << plugin <<
" due to exclusion option" <<
'\n';
1008 if (subDirName == u
"platforms"
1015 const QString pluginPath = subDir.absoluteFilePath(plugin);
1019 const bool requiresPlugin = pluginSelections.
includedPlugins.contains(pluginName)
1021 if (!dueToModule && !requiresPlugin)
1027 if (subDirName == u
"designer")
1034 for (
int d = 0;
d < dependentQtLibs.size(); ++
d) {
1035 const qint64 module = qtModule(dependentQtLibs.at(d), infix);
1037 (*pluginNeededQtModules)[module] = 1;
1040 std::wcerr <<
"Warning: Cannot determine dependencies of "
1045 disabledNeededQtModules = *pluginNeededQtModules & disabledQtModules;
1046 if (disabledNeededQtModules.any()) {
1048 std::wcout <<
"Skipping plugin " << plugin
1049 <<
" due to disabled dependencies ("
1061 bool needsTypeForPlugin =
false;
1063 if (pluginInfo.isTypeForPlugin(subDirName, plugin))
1064 needsTypeForPlugin =
true;
1066 return (pluginSelections.
enabledPluginTypes.contains(subDirName) || needsTypeForPlugin);
1073 QString *platformPlugin,
bool deployInsightTrackerPlugin,
1074 bool deployOpenSslPlugin)
1076 if (qtPluginsDirName.isEmpty())
1078 QDir pluginsDir(qtPluginsDirName);
1080 bool missingQtModulesAdded =
false;
1082 for (
const QFileInfo &subDirFi : pluginDirs) {
1083 const QString subDirName = subDirFi.fileName();
1084 const size_t module = qtModuleEntries.moduleIdForPluginType(subDirName);
1087 std::wcerr <<
"No Qt module found for plugin type \"" << subDirName <<
"\".\n";
1091 const bool dueToModule = usedQtModules->test(module);
1092 if (dueToModule ||
needsPluginType(subDirName, pluginInfo, pluginSelections)) {
1093 const DebugMatchMode debugMatchMode = (
module == QtWebEngineCoreModuleId)
1094 ? MatchDebugOrRelease
1096 QDir subDir(subDirFi.absoluteFilePath());
1098 std::wcout <<
"Adding in plugin type " << subDirFi.baseName() <<
" for module: " <<
qtModuleEntries.moduleById(module).name <<
'\n';
1100 const bool isPlatformPlugin = subDirName ==
"platforms"_L1;
1103 for (
const QString &plugin : plugins) {
1106 deployPlugin(plugin, subDir, dueToModule, debugMatchMode, &pluginNeededQtModules,
1107 disabledQtModules, pluginSelections, libraryLocation, infix,
1108 platform, deployInsightTrackerPlugin, deployOpenSslPlugin);
1110 if (isPlatformPlugin && plugin.startsWith(u
"qwindows"))
1111 *platformPlugin = subDir.absoluteFilePath(plugin);
1112 result.append(pluginPath);
1114 const ModuleBitset missingModules = (pluginNeededQtModules & ~*usedQtModules);
1115 if (missingModules.any()) {
1116 *usedQtModules |= missingModules;
1117 missingQtModulesAdded =
true;
1119 std::wcout <<
"Adding " <<
formatQtModules(missingModules).constData()
1120 <<
" for " << plugin <<
" from plugin type: " << subDirName <<
'\n';
1132 std::wcout <<
"Performing additional pass of finding Qt plugins due to updated Qt module list: "
1135 return findQtPlugins(usedQtModules, disabledQtModules, pluginInfo, pluginSelections, qtPluginsDirName,
1136 libraryLocation, infix, debugMatchModeIn,
platform, platformPlugin,
1137 deployInsightTrackerPlugin, deployOpenSslPlugin);
1162 QDir sourceDir(sourcePath);
1166 const QString prefix = qmFi.baseName().
mid(7);
1170 if (prefixes.isEmpty()) {
1171 std::wcerr <<
"Warning: Could not find any translations in "
1180 for (
const QString &prefix : std::as_const(prefixes)) {
1184 const QString targetFilePath = absoluteTarget + u
'/' + targetFile;
1186 options.
json->
addFile(sourcePath + u
'/' + targetFile, absoluteTarget);
1189 if (translationFilters.isEmpty()){
1190 std::wcerr <<
"Warning: translation catalogs are all empty, skipping translation deployment\n";
1194 for (
const QFileInfo &langQmFileFi : langQmFiles) {
1196 options.
json->
addFile(langQmFileFi.absoluteFilePath(),
1202 std::wcout <<
"Creating " << targetFile <<
"...\n";
1203 unsigned long exitCode;
1215 const std::vector<QLatin1StringView> ffmpegHints = {
"avcodec"_L1,
"avformat"_L1,
"avutil"_L1,
1216 "swresample"_L1,
"swscale"_L1 };
1224 if (ffmpegLib.empty()) {
1225 std::wcerr <<
"Warning: Cannot find FFmpeg libraries. Multimedia features will not work as expected.\n";
1227 }
else if (ffmpegLib.size() != 1u) {
1228 std::wcerr <<
"Warning: Multiple versions of FFmpeg libraries found. Multimedia features will not work as expected.\n";
1232 const QChar slash(u
'/');
1233 QFileInfo ffmpegLibPath{ qtBinDir + slash + ffmpegLib.front() };
1234 ffmpegLibs.append(ffmpegLibPath.absoluteFilePath());
1243 const std::vector<QLatin1StringView> libHints = {
"libcrypto"_L1,
"libssl"_L1 };
1244 const QChar slash(u
'/');
1245 const QString openSslBinDir = openSslRootDir + slash +
"bin"_L1;
1254 std::wcerr <<
"Warning: Cannot find openssl libraries.\n";
1256 }
else if (lib.size() != 1u) {
1257 std::wcerr <<
"Warning: Multiple versions of openssl libraries found.\n";
1261 QFileInfo libPath{ openSslBinDir + slash + lib.front() };
1262 result.append(libPath.absoluteFilePath());
1296 const char vcDirVar[] =
"VCINSTALLDIR";
1297 const QChar slash(u
'/');
1299 if (vcRedistDirName.isEmpty()) {
1300 std::wcerr <<
"Warning: Cannot find Visual Studio installation directory, " << vcDirVar
1301 <<
" is not set.\n";
1304 if (!vcRedistDirName.endsWith(slash))
1305 vcRedistDirName.append(slash);
1307 if (!
QFileInfo(vcRedistDirName).isDir()) {
1308 std::wcerr <<
"Warning: Cannot find Visual Studio redist directory, "
1314 QDir(vcRedistDirName)
1324 std::wcerr <<
"Warning: Cannot find Visual Studio redist directory under "
1336 for (
const auto &minGWRuntime : runtimeFilters)
1337 filters.append(minGWRuntime + suffix);
1340 if (dlls.isEmpty()) {
1341 std::wcerr <<
"Warning: Runtime libraries not found in Qt binary folder, defaulting to looking in path\n";
1344 std::wcerr <<
"Warning: Cannot find " << (isClang ?
"Clang" :
"GCC") <<
" installation directory, " << (isClang ?
"clang++" :
"g++") <<
".exe must be in the path\n";
1362 const QStringList minGWRuntimes = {
"*gcc_"_L1,
"*stdc++"_L1,
"*winpthread"_L1 };
1367 const QStringList clangMinGWRuntimes = {
"*unwind"_L1,
"*c++"_L1 };
1375 if (vcRedistDirName.isEmpty())
1379 const QString machineArchString = getArchString(machineArch);
1387 redistFiles.append(dll.absoluteFilePath());
1391 QString releaseRedistDir = vcRedistDirName;
1393 if (!countryCodes.isEmpty())
1394 releaseRedistDir += u
'/' + countryCodes.constFirst();
1395 QFileInfo fi(releaseRedistDir +
"/vc_redist."_L1
1396 + machineArchString +
".exe"_L1);
1398 fi.setFile(releaseRedistDir +
"/vcredist_"_L1
1399 + machineArchString +
".exe"_L1);
1402 redistFiles.append(fi.absoluteFilePath());
1404 if (redistFiles.isEmpty()) {
1405 std::wcerr <<
"Warning: Cannot find Visual Studio " << (isDebug ?
"debug" :
"release")
1409 result.append(redistFiles);
1419static inline int qtVersion(
const QMap<QString, QString> &qtpathsVariables)
1426 return (majorVersion << 16) | (minorVersion << 8) | patchVersion;
1435 std::wcerr <<
"Warning: Could not update " << sourceFileName <<
" :" << *
errorMessage <<
'\n';
1455 std::copy_if(libName.cbegin(), libName.cend(), std::back_inserter(version),
1456 [](
QChar c) { return c.isDigit(); });
1465 const QChar slash = u
'/';
1468 const QString libraryLocation = qtBinDir;
1470 const int version =
qtVersion(qtpathsVariables);
1479 unsigned short machineArch;
1480 int directDependencyCount = 0;
1482 &detectedDebug, &machineArch, &directDependencyCount)) {
1485 for (
int b = 1;
b < options.
binaries.size(); ++
b) {
1487 nullptr,
nullptr,
nullptr)) {
1500 result.isDebug = detectedDebug;
1515 for (
int m = 0;
m < dependentQtLibs.size(); ++
m) {
1516 const qint64 module = qtModule(dependentQtLibs.at(m), infix);
1518 result.directlyUsedQtLibraries[module] = 1;
1521 const bool usesQml =
result.directlyUsedQtLibraries.test(QtQmlModuleId);
1522 const bool usesQuick =
result.directlyUsedQtLibraries.test(QtQuickModuleId);
1523 const bool uses3DQuick =
result.directlyUsedQtLibraries.test(Qt3DQuickModuleId);
1525 && (usesQml || usesQuick || uses3DQuick || (options.
additionalLibraries.test(QtQmlModuleId)));
1529 << wordSize <<
" bit, " << (
result.isDebug ?
"debug" :
"release")
1532 std::wcout <<
" [QML]";
1536 if (dependentQtLibs.isEmpty()) {
1546 for (
const QString &qtLib : qtLibs) {
1548 if (!icuLibs.isEmpty()) {
1552 if (!icuVersion.isEmpty()) {
1554 std::wcout <<
"Adding ICU version " << icuVersion <<
'\n';
1562 if (!
findInPath(icuLibCandidate).isEmpty()) {
1563 icuLib = icuLibCandidate;
1566 icuLibs.push_back(icuLib);
1568 for (
const QString &icuLib : std::as_const(icuLibs)) {
1570 if (icuPath.isEmpty()) {
1574 dependentQtLibs.push_back(icuPath);
1587 qmlImportPaths << qtpathsVariables.value(
QStringLiteral(
"QT_INSTALL_QML"));
1589 if (qmlDirectories.isEmpty()) {
1592 qmlDirectories.append(qmlDirectory);
1594 for (
const QString &qmlDirectory : std::as_const(qmlDirectories)) {
1599 result.directlyUsedQtLibraries.test(QtWidgetsModuleId),
1603 qmlScanResult.append(scanResult);
1605 for (
const QString &plugin : std::as_const(qmlScanResult.plugins)) {
1610 std::wcout <<
"QML imports:\n";
1612 std::wcout <<
" '" << mod.name <<
"' "
1616 std::wcout <<
"QML plugins:\n";
1617 for (
const QString &
p : std::as_const(qmlScanResult.plugins))
1628 for (
int i = 0 ;
i < dependentQtLibs.size(); ++
i) {
1629 const qint64 module = qtModule(dependentQtLibs.at(i), infix);
1631 result.usedQtLibraries[module] = 1;
1633 deployedQtLibraries.push_back(dependentQtLibs.at(
i));
1646 if (openSslLibs.isEmpty()) {
1652 deployedQtLibraries.append(openSslLibs);
1654 const bool deployOpenSslPlugin = options.
forceOpenSslPlugin || !openSslLibs.isEmpty();
1657 &
result.deployedQtLibraries,
1662 libraryLocation, infix, debugMatchMode, options.
platform, &platformPlugin,
1671 deployedQtLibraries.append(library);
1673 qtGuiLibrary = library;
1678 std::wcout <<
"Direct dependencies: " <<
formatQtModules(
result.directlyUsedQtLibraries).constData()
1684 std::wcout <<
"Plugins: " << plugins.join(u
',') <<
'\n';
1686 if (
result.deployedQtLibraries.test(QtGuiModuleId) && platformPlugin.isEmpty()) {
1696 if (softwareRasterizer.
isFile())
1701 if (d3dCompiler.isEmpty()) {
1702 std::wcerr <<
"Warning: Cannot find any version of the d3dcompiler DLL.\n";
1704 deployedQtLibraries.push_back(d3dCompiler);
1709 if (!dxcLibs.isEmpty())
1710 deployedQtLibraries.append(dxcLibs);
1712 std::wcerr <<
"Warning: Cannot find any version of the dxcompiler.dll and dxil.dll.\n";
1729 for (
const QString &qtLib : std::as_const(libraries)) {
1734#if !QT_CONFIG(relocatable)
1756 for (
const QString &plugin : plugins) {
1757 const QString targetDirName = plugin.section(slash, -2, -2);
1758 const QString targetPath =
dir.absoluteFilePath(targetDirName);
1759 if (!
dir.exists(targetDirName)) {
1761 std::wcout <<
"Creating directory " << targetPath <<
".\n";
1782 const QString installPath =
module.installPath(targetPath);
1784 std::wcout <<
"Installing: '" <<
module.name
1785 << "' from " << module.sourcePath << " to "
1786 << QDir::toNativeSeparators(installPath) << '\n';
1791 unsigned qmlDirectoryFileFlags = 0;
1797 qmlDirectoryFileFlags),
1818static bool deployWebProcess(
const QMap<QString, QString> &qtpathsVariables,
const char *binaryName,
1825 + u
'/' + webProcess;
1826 if (!
updateFile(webProcessSource, sourceOptions.directory, sourceOptions.updateFileFlags, sourceOptions.json,
errorMessage))
1828 Options options(sourceOptions);
1839 static const char *installDataFiles[] = {
"icudtl.dat",
1840 "qtwebengine_devtools_resources.pak",
1841 "qtwebengine_resources.pak",
1842 "qtwebengine_resources_100p.pak",
1843 "qtwebengine_resources_200p.pak",
1844 isDebug ?
"v8_context_snapshot.debug.bin"
1845 :
"v8_context_snapshot.bin" };
1848 webEngineProcessName.append(
'd');
1850 std::wcout <<
"Deploying: " << webEngineProcessName.constData() <<
"...\n";
1855 + resourcesSubDir + u
'/';
1859 for (
auto installDataFile : installDataFiles) {
1867 if (!translations.
isDir()) {
1868 std::wcerr <<
"Warning: Cannot find the translation files of the QtWebEngine module at "
1880 if (!enUSpak.exists()) {
1881 std::wcerr <<
"Warning: Cannot find "
1889 return updateFile(enUSpak.absoluteFilePath(), webEngineTranslationsDir,
1904 if (!
path.contains(qtBinPath)) {
1906 path.prepend(qtBinPath);
1923 const QMap<QString, QString> qtpathsVariables =
1926 if (qtpathsVariables.isEmpty() || xSpec.isEmpty()
1927 || !qtpathsVariables.contains(
QStringLiteral(
"QT_INSTALL_BINS"))) {
1928 std::wcerr <<
"Unable to query qtpaths: " <<
errorMessage <<
'\n';
1937 switch (si.wProcessorArchitecture) {
1938 case PROCESSOR_ARCHITECTURE_INTEL:
1939 case PROCESSOR_ARCHITECTURE_IA64:
1940 case PROCESSOR_ARCHITECTURE_AMD64:
1943 case PROCESSOR_ARCHITECTURE_ARM:
1944 case PROCESSOR_ARCHITECTURE_ARM64:
1952 std::wcerr <<
"Unsupported platform " << xSpec <<
'\n';
1958 = qtpathsVariables.value(
QLatin1String(
"QT_INSTALL_ARCHDATA"))
1961 = qtpathsVariables.value(
QLatin1String(
"QT_INSTALL_TRANSLATIONS"));
1981 std::fputs(QT_VERSION_STR
"\n", stdout);
2009 if (
result.deployedQtLibraries.test(QtWebEngineCoreModuleId)) {
2022 delete options.
json;
2023 options.
json =
nullptr;
QStringList operator()(const QDir &dir) const
DllDirectoryFileEntryFunction(Platform platform, DebugMatchMode debugMatchMode, const QString &prefix=QString())
void addFile(const QString &source, const QString &target)
QByteArray toJson() const
QByteArray toList(ListOption option, const QDir &base) const
const char * constData() const noexcept
Returns a pointer to the const data stored in the byte array.
The QCommandLineOption class defines a possible command-line option. \inmodule QtCore.
The QCommandLineParser class provides a means for handling the command line options.
QString value(const QString &name) const
Returns the option value found for the given option name optionName, or an empty string if not found.
bool parse(const QStringList &arguments)
Parses the command line arguments.
void addPositionalArgument(const QString &name, const QString &description, const QString &syntax=QString())
Defines an additional argument to the application, for the benefit of the help text.
QStringList positionalArguments() const
Returns a list of positional arguments.
void setSingleDashWordOptionMode(SingleDashWordOptionMode parsingMode)
Sets the parsing mode to singleDashWordOptionMode.
QStringList values(const QString &name) const
Returns a list of option values found for the given option name optionName, or an empty list if not f...
void setApplicationDescription(const QString &description)
Sets the application description shown by helpText().
bool addOption(const QCommandLineOption &commandLineOption)
Adds the option option to look for while parsing.
QString errorText() const
Returns a translated error text for the user.
bool isSet(const QString &name) const
Checks whether the option name was passed to the application.
QCommandLineOption addVersionOption()
Adds the {-v} / {–version} option, which displays the version string of the application.
QCommandLineOption addHelpOption()
Adds help options to the command-line parser.
static QString applicationDirPath()
Returns the directory that contains the application executable.
static void setApplicationVersion(const QString &version)
static QStringList arguments()
bool cdUp()
Changes directory by moving one directory up from the QDir's current directory.
QFileInfoList entryInfoList(Filters filters=NoFilter, SortFlags sort=NoSort) const
This is an overloaded member function, provided for convenience. It differs from the above function o...
bool exists() const
This is an overloaded member function, provided for convenience. It differs from the above function o...
static QString cleanPath(const QString &path)
Returns path with directory separators normalized (that is, platform-native separators converted to "...
static QString toNativeSeparators(const QString &pathName)
static constexpr QChar listSeparator() noexcept
QString absoluteFilePath() const
bool isFile() const
Returns true if this object points to a file or to a symbolic link to a file.
bool isDir() const
Returns true if this object points to a directory or to a symbolic link to a directory.
QString absolutePath() const
Returns the absolute path of the file system entry this QFileInfo refers to, excluding the entry's na...
QString filePath() const
Returns the path of the file system entry this QFileInfo refers to; the path may be absolute or relat...
static QByteArray encodeName(const QString &fileName)
Converts fileName to an 8-bit encoding that you can use in native APIs.
static QString decodeName(const QByteArray &localFileName)
This does the reverse of QFile::encodeName() using localFileName.
void append(parameter_type t)
iterator find(const T &value)
\macro QT_RESTRICTED_CAST_FROM_ASCII
int toInt(bool *ok=nullptr, int base=10) const
Returns the string converted to an int using base base, which is 10 by default and must be between 2 ...
bool startsWith(const QString &s, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Returns true if the string starts with s; otherwise returns false.
static QString fromLatin1(QByteArrayView ba)
This is an overloaded member function, provided for convenience. It differs from the above function o...
QStringList split(const QString &sep, Qt::SplitBehavior behavior=Qt::KeepEmptyParts, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Splits the string into substrings wherever sep occurs, and returns the list of those strings.
QString mid(qsizetype position, qsizetype n=-1) const &
bool isEmpty() const noexcept
Returns true if the string has no characters; otherwise returns false.
qsizetype size() const noexcept
Returns the number of characters in this string.
void push_back(QChar c)
This is an overloaded member function, provided for convenience. It differs from the above function o...
QString section(QChar sep, qsizetype start, qsizetype end=-1, SectionFlags flags=SectionDefault) const
This function returns a section of the string.
QString toLower() const &
QString & append(QChar c)
QString & prepend(QChar c)
QStringList operator()(const QDir &dir) const
QmlDirectoryFileEntryFunction(const QString &moduleSourcePath, Platform platform, DebugMatchMode debugMatchMode, unsigned flags)
QSet< QString >::iterator it
QList< QVariant > arguments
Combined button and popup list for selecting options.
QList< QString > QStringList
Constructs a string list that contains the given string, str.
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
GLsizei GLsizei GLenum void * binary
GLboolean GLboolean GLboolean b
GLboolean GLboolean GLboolean GLboolean a
[7]
GLenum GLenum GLsizei const GLuint GLboolean enabled
GLint GLint GLint GLint GLint GLint GLint GLbitfield mask
GLsizei const GLchar *const * path
static qreal dot(const QPointF &a, const QPointF &b)
static QString canonicalPath(const QString &rootPath)
#define qPrintable(string)
QLatin1StringView QLatin1String
#define QStringLiteral(str)
bool updateFile(const QString &fileName, const QHash< QString, QString > &replacements)
QString findInPath(const QString &fileName)
static Platform platformFromMkSpec(const QString &xSpec)
static bool isQtModule(const QString &libName)
static QtModuleInfoStore qtModuleEntries
static QString libraryPath(const QString &libraryLocation, const char *name, const QString &infix, Platform platform, bool debug)
static QString lineBreak(QString s)
static QString msgFileDoesNotExist(const QString &file)
static QStringList compilerRunTimeLibs(const QString &qtBinDir, Platform platform, bool isDebug, unsigned short machineArch)
static bool updateLibrary(const QString &sourceFileName, const QString &targetDirectory, const Options &options, QString *errorMessage)
static void assignKnownModuleIds()
static QCommandLineOption createVerboseOption()
static int parseArguments(const QStringList &arguments, QCommandLineParser *parser, Options *options, QString *errorMessage)
static QString moduleNameToOptionName(const QString &moduleName)
static ExlusiveOptionValue parseExclusiveOptions(const QCommandLineParser *parser, const QCommandLineOption &enableOption, const QCommandLineOption &disableOption)
static int qtVersion(const QMap< QString, QString > &qtpathsVariables)
static QStringList translationNameFilters(const ModuleBitset &modules, const QString &prefix)
static QString findBinary(const QString &directory, Platform platform)
static DeployResult deploy(const Options &options, const QMap< QString, QString > &qtpathsVariables, const PluginInformation &pluginInfo, QString *errorMessage)
static int parseEarlyArguments(const QStringList &arguments, Options *options, QString *errorMessage)
static QCommandLineOption createQMakeOption()
static bool deployWebEngineCore(const QMap< QString, QString > &qtpathsVariables, const PluginInformation &pluginInfo, const Options &options, bool isDebug, QString *errorMessage)
static QStringList qmlCacheFileFilters()
static QString pdbFileName(QString libraryFileName)
@ CommandLineVersionRequested
@ CommandLineParseHelpRequested
static QString formatQtPlugins(const PluginInformation &pluginInfo)
#define DECLARE_KNOWN_MODULE(name)
static QCommandLineOption createQtPathsOption()
static bool needsPluginType(const QString &subDirName, const PluginInformation &pluginInfo, const PluginSelections &pluginSelections)
static const char webEngineProcessC[]
static qint64 qtModule(QString module, const QString &infix)
static QString vcRedistDir()
static QString webProcessBinary(const char *binaryName, Platform p)
static QStringList findFFmpegLibs(const QString &qtBinDir, Platform platform)
static QString deployPlugin(const QString &plugin, const QDir &subDir, const bool dueToModule, const DebugMatchMode &debugMatchMode, ModuleBitset *pluginNeededQtModules, const ModuleBitset &disabledQtModules, const PluginSelections &pluginSelections, const QString &libraryLocation, const QString &infix, Platform platform, bool deployInsightTrackerPlugin, bool deployOpenSslPlugin)
static QString helpText(const QCommandLineParser &p, const PluginInformation &pluginInfo)
static bool deployWebProcess(const QMap< QString, QString > &qtpathsVariables, const char *binaryName, const PluginInformation &pluginInfo, const Options &sourceOptions, QString *errorMessage)
static QStringList findMinGWRuntimePaths(const QString &qtBinDir, Platform platform, const QStringList &runtimeFilters)
#define DEFINE_KNOWN_MODULE(name)
#define IMAGE_FILE_MACHINE_ARM64
static QString getIcuVersion(const QString &libName)
static bool findDependentQtLibraries(const QString &qtBinDir, const QString &binary, Platform platform, QString *errorMessage, QStringList *result, unsigned *wordSize=nullptr, bool *isDebug=nullptr, unsigned short *machineArch=nullptr, int *directDependencyCount=nullptr, int recursionDepth=0)
static bool deployTranslations(const QString &sourcePath, const ModuleBitset &usedQtModules, const QString &target, const Options &options, QString *errorMessage)
QStringList findQtPlugins(ModuleBitset *usedQtModules, const ModuleBitset &disabledQtModules, const PluginInformation &pluginInfo, const PluginSelections &pluginSelections, const QString &qtPluginsDirName, const QString &libraryLocation, const QString &infix, DebugMatchMode debugMatchModeIn, Platform platform, QString *platformPlugin, bool deployInsightTrackerPlugin, bool deployOpenSslPlugin)
static QStringList findOpenSslLibraries(const QString &openSslRootDir, Platform platform)
static QString vcDebugRedistDir()
static QByteArray formatQtModules(const ModuleBitset &mask, bool option=false)
bool qputenv(const char *varName, QByteArrayView raw)
Q_CORE_EXPORT QByteArray qgetenv(const char *varName)
std::bitset< ModuleBitsetSize > ModuleBitset
static QString errorMessage(QUrlPrivate::ErrorCode errorCode, const QString &errorSource, qsizetype errorPosition)
const QStringList filters({"Image files (*.png *.xpm *.jpg)", "Text files (*.txt)", "Any files (*)" })
[6]
ModuleBitset usedQtLibraries
ModuleBitset directlyUsedQtLibraries
ModuleBitset deployedQtLibraries
DebugDetection debugDetection
QStringList qmlImportPaths
PluginSelections pluginSelections
QStringList qmlDirectories
QString translationsDirectory
ModuleBitset additionalLibraries
QString openSslRootDirectory
ModuleBitset disabledLibraries
bool deployInsightTrackerPlugin
@ DebugDetectionForceRelease
@ DebugDetectionForceDebug
QStringList includedPlugins
QStringList enabledPluginTypes
QStringList excludedPlugins
QStringList disabledPluginTypes
static constexpr size_t InvalidId
QStringList findDxc(Platform, const QString &, unsigned)
bool readPeExecutable(const QString &, QString *errorMessage, QStringList *, unsigned *, bool *, bool, unsigned short *)
QMap< QString, QString > queryQtPaths(const QString &qtpathsBinary, QString *errorMessage)
QString findD3dCompiler(Platform, const QString &, unsigned)
bool createDirectory(const QString &directory, QString *errorMessage, bool dryRun)
QStringList findSharedLibraries(const QDir &directory, Platform platform, DebugMatchMode debugMatchMode, const QString &prefix)
bool runProcess(const QString &binary, const QStringList &args, const QString &workingDirectory, unsigned long *exitCode, QByteArray *stdOut, QByteArray *stdErr, QString *errorMessage)
bool patchQtCore(const QString &path, QString *errorMessage)
const char * qmakeInfixKey
@ WindowsDesktopMsvcIntel
@ WindowsDesktopClangMinGW
@ WindowsDesktopClangMsvc
bool platformHasDebugSuffix(Platform p)
@ SkipQmlDesignerSpecificsDirectories
static const char windowsSharedLibrarySuffix[]
QStringList findDependentLibraries(const QString &executableFileName, QString *errorMessage)
QString sharedLibrarySuffix()
QString normalizeFileName(const QString &name)