Skip to content

Commit

Permalink
Make deployment of openssl plugin optional
Browse files Browse the repository at this point in the history
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 <[email protected]>
  • Loading branch information
owolff committed Mar 21, 2024
1 parent 505e7ec commit 0cdeecf
Showing 1 changed file with 77 additions and 5 deletions.
82 changes: 77 additions & 5 deletions src/tools/windeployqt/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,7 @@ struct Options {
QStringList languages;
QString libraryDirectory;
QString pluginDirectory;
QString openSslRootDirectory;
QString qmlDirectory;
QStringList binaries;
JsonOutput *json = nullptr;
Expand All @@ -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.
Expand Down Expand Up @@ -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"
Expand Down Expand Up @@ -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)) {
Expand Down Expand Up @@ -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
Expand All @@ -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'
Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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; }
Expand Down Expand Up @@ -1574,14 +1632,28 @@ 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
// qtaccessiblequick plugin.
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;
Expand Down

0 comments on commit 0cdeecf

Please sign in to comment.