Make deployment of openssl plugin optional

Qt's openssl plugin is dependent on openssl libraries. Users should
make a conscious decision about deployment of the plugin and the
corresponing libraries so deployment of that functionality is now
opt in.

[ChangeLog][Tools][Windeployqt] Deployment of openssl plugins is now
optional. For proper deployment of openssl related functionality pass
in --openssl-root to make sure that openssl libraries are also deployed.

Fixes: QTBUG-117394
Change-Id: Iad43c7666b9af491f7695783b4e23a811256515b
Reviewed-by: Miguel Costa <miguel.costa@qt.io>
This commit is contained in:
Oliver Wolff 2024-03-18 08:54:05 +01:00
parent 505e7ec37d
commit 0cdeecf415

View File

@ -195,6 +195,7 @@ struct Options {
QStringList languages;
QString libraryDirectory;
QString pluginDirectory;
QString openSslRootDirectory;
QString qmlDirectory;
QStringList binaries;
JsonOutput *json = nullptr;
@ -205,6 +206,7 @@ struct Options {
bool patchQt = true;
bool ignoreLibraryErrors = false;
bool deployInsightTrackerPlugin = false;
bool forceOpenSslPlugin = false;
};
// Return binary to be deployed from folder, ignore pre-existing web engine process.
@ -480,6 +482,15 @@ static inline int parseArguments(const QStringList &arguments, QCommandLineParse
QStringLiteral("Do not deploy the FFmpeg libraries."));
parser->addOption(noFFmpegOption);
QCommandLineOption forceOpenSslOption(QStringLiteral("force-openssl"),
QStringLiteral("Deploy openssl plugin but ignore openssl library dependency"));
parser->addOption(forceOpenSslOption);
QCommandLineOption openSslRootOption(QStringLiteral("openssl-root"),
QStringLiteral("Directory containing openSSL libraries."),
QStringLiteral("directory"));
parser->addOption(openSslRootOption);
QCommandLineOption listOption(QStringLiteral("list"),
"Print only the names of the files copied.\n"
@ -604,6 +615,17 @@ static inline int parseArguments(const QStringList &arguments, QCommandLineParse
if (parser->isSet(noFFmpegOption))
options->ffmpeg = false;
if (parser->isSet(forceOpenSslOption))
options->forceOpenSslPlugin = true;
if (parser->isSet(openSslRootOption))
options->openSslRootDirectory = parser->value(openSslRootOption);
if (options->forceOpenSslPlugin && !options->openSslRootDirectory.isEmpty()) {
*errorMessage = QStringLiteral("force-openssl and openssl-root are mutually exclusive");
return CommandLineParseError;
}
if (parser->isSet(forceOption))
options->updateFileFlags |= ForceUpdateFile;
if (parser->isSet(dryRunOption)) {
@ -942,7 +964,7 @@ static QString deployPlugin(const QString &plugin, const QDir &subDir, const boo
const ModuleBitset &disabledQtModules,
const PluginSelections &pluginSelections, const QString &libraryLocation,
const QString &infix, Platform platform,
bool deployInsightTrackerPlugin)
bool deployInsightTrackerPlugin, bool deployOpenSslPlugin)
{
const QString subDirName = subDir.dirName();
// Filter out disabled plugins
@ -956,6 +978,12 @@ static QString deployPlugin(const QString &plugin, const QDir &subDir, const boo
<< ". Use -deploy-insighttracker if you want to use it.\n";
return {};
}
if (optVerboseLevel && subDirName == u"tls" && plugin.contains(u"qopensslbackend")
&& !deployOpenSslPlugin) {
std::wcout << "Skipping plugin " << plugin
<< ". Use -force_openssl or specify -openssl-root if you want to use it.\n";
return {};
}
const int dotIndex = plugin.lastIndexOf(u'.');
// Strip the .dll from the name, and an additional 'd' if it's a debug library with the 'd'
@ -1036,7 +1064,8 @@ QStringList findQtPlugins(ModuleBitset *usedQtModules, const ModuleBitset &disab
const PluginInformation &pluginInfo, const PluginSelections &pluginSelections,
const QString &qtPluginsDirName, const QString &libraryLocation,
const QString &infix, DebugMatchMode debugMatchModeIn, Platform platform,
QString *platformPlugin, bool deployInsightTrackerPlugin)
QString *platformPlugin, bool deployInsightTrackerPlugin,
bool deployOpenSslPlugin)
{
if (qtPluginsDirName.isEmpty())
return QStringList();
@ -1070,7 +1099,7 @@ QStringList findQtPlugins(ModuleBitset *usedQtModules, const ModuleBitset &disab
const QString pluginPath =
deployPlugin(plugin, subDir, dueToModule, debugMatchMode, &pluginNeededQtModules,
disabledQtModules, pluginSelections, libraryLocation, infix,
platform, deployInsightTrackerPlugin);
platform, deployInsightTrackerPlugin, deployOpenSslPlugin);
if (!pluginPath.isEmpty()) {
if (isPlatformPlugin && plugin.startsWith(u"qwindows"))
*platformPlugin = subDir.absoluteFilePath(plugin);
@ -1099,7 +1128,7 @@ QStringList findQtPlugins(ModuleBitset *usedQtModules, const ModuleBitset &disab
}
return findQtPlugins(usedQtModules, disabledQtModules, pluginInfo, pluginSelections, qtPluginsDirName,
libraryLocation, infix, debugMatchModeIn, platform, platformPlugin,
deployInsightTrackerPlugin);
deployInsightTrackerPlugin, deployOpenSslPlugin);
}
return result;
@ -1202,6 +1231,35 @@ static QStringList findFFmpegLibs(const QString &qtBinDir, Platform platform)
return ffmpegLibs;
}
// Find the openssl libraries Qt executables depend on.
static QStringList findOpenSslLibraries(const QString &openSslRootDir, Platform platform)
{
const std::vector<QLatin1StringView> libHints = { "libcrypto"_L1, "libssl"_L1 };
const QChar slash(u'/');
const QString openSslBinDir = openSslRootDir + slash + "bin"_L1;
const QStringList openSslRootLibs =
findSharedLibraries(openSslBinDir, platform, MatchDebugOrRelease, {});
QStringList result;
for (const QLatin1StringView &libHint : libHints) {
const QStringList lib = openSslRootLibs.filter(libHint, Qt::CaseInsensitive);
if (lib.empty()) {
std::wcerr << "Warning: Cannot find openssl libraries.\n";
return {};
} else if (lib.size() != 1u) {
std::wcerr << "Warning: Multiple versions of openssl libraries found.\n";
return {};
}
QFileInfo libPath{ openSslBinDir + slash + lib.front() };
result.append(libPath.absoluteFilePath());
}
return result;
}
struct DeployResult
{
operator bool() const { return success; }
@ -1574,6 +1632,20 @@ static DeployResult deploy(const Options &options, const QMap<QString, QString>
disabled[QtQmlModuleId] = 1;
disabled[QtQuickModuleId] = 1;
}
QStringList openSslLibs;
if (!options.openSslRootDirectory.isEmpty()) {
openSslLibs = findOpenSslLibraries(options.openSslRootDirectory, options.platform);
if (openSslLibs.isEmpty()) {
*errorMessage = QStringLiteral("Unable to find openSSL libraries in ")
+ options.openSslRootDirectory;
return result;
}
deployedQtLibraries.append(openSslLibs);
}
const bool deployOpenSslPlugin = options.forceOpenSslPlugin || !openSslLibs.isEmpty();
const QStringList plugins = findQtPlugins(
&result.deployedQtLibraries,
// For non-QML applications, disable QML to prevent it from being pulled in by the
@ -1581,7 +1653,7 @@ static DeployResult deploy(const Options &options, const QMap<QString, QString>
disabled, pluginInfo,
options.pluginSelections, qtpathsVariables.value(QStringLiteral("QT_INSTALL_PLUGINS")),
libraryLocation, infix, debugMatchMode, options.platform, &platformPlugin,
options.deployInsightTrackerPlugin);
options.deployInsightTrackerPlugin, deployOpenSslPlugin);
// Apply options flags and re-add library names.
QString qtGuiLibrary;