Browse Source

Improved the way Qt files are located

Using 'qmake -query' to get all information explicitly instead of parsing
the output of 'qmake -v' and deriving binary path, plugin path and QML
path from there.

Fixes #28
Fixes #37
master
Thorbjørn Lindeijer 8 years ago
parent
commit
f45c7e3156
  1. 4
      linuxdeployqt/main.cpp
  2. 63
      shared/shared.cpp

4
linuxdeployqt/main.cpp

@ -38,9 +38,10 @@ int main(int argc, char **argv)
QString appBinaryPath; QString appBinaryPath;
if (argc > 1) if (argc > 1) {
appBinaryPath = QString::fromLocal8Bit(argv[1]); appBinaryPath = QString::fromLocal8Bit(argv[1]);
appBinaryPath = QDir::cleanPath(appBinaryPath).trimmed(); appBinaryPath = QDir::cleanPath(appBinaryPath).trimmed();
}
if (argc < 2 || appBinaryPath.startsWith("-")) { if (argc < 2 || appBinaryPath.startsWith("-")) {
qDebug() << "Usage: linuxdeployqt app-binary [options]"; qDebug() << "Usage: linuxdeployqt app-binary [options]";
@ -199,6 +200,7 @@ int main(int argc, char **argv)
} }
if (plugins && !deploymentInfo.qtPath.isEmpty()) { 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); deployPlugins(appDirPath, deploymentInfo);
createQtConf(appDirPath); createQtConf(appDirPath);

63
shared/shared.cpp

@ -56,7 +56,7 @@ bool deployLibrary = false;
using std::cout; using std::cout;
using std::endl; using std::endl;
QString qtPathToBeBundled = ""; QMap<QString,QString> qtToBeBundledInfo;
bool operator==(const LibraryInfo &a, const LibraryInfo &b) bool operator==(const LibraryInfo &a, const LibraryInfo &b)
{ {
@ -645,6 +645,7 @@ DeploymentInfo deployQtLibraries(QList<LibraryInfo> libraries,
QStringList copiedLibraries; QStringList copiedLibraries;
DeploymentInfo deploymentInfo; DeploymentInfo deploymentInfo;
deploymentInfo.useLoaderPath = useLoaderPath; deploymentInfo.useLoaderPath = useLoaderPath;
deploymentInfo.pluginPath = qtToBeBundledInfo.value("QT_INSTALL_PLUGINS");
QSet<QString> rpathsUsed; QSet<QString> rpathsUsed;
while (libraries.isEmpty() == false) { while (libraries.isEmpty() == false) {
@ -699,6 +700,21 @@ DeploymentInfo deployQtLibraries(QList<LibraryInfo> libraries,
return deploymentInfo; return deploymentInfo;
} }
static QString captureOutput(const QString &command)
{
QProcess process;
process.start(command, QIODevice::ReadOnly);
process.waitForFinished();
if (process.exitStatus() != QProcess::NormalExit) {
LogError() << command << "crashed:" << process.readAllStandardError();
} else if (process.exitCode() != 0) {
LogError() << command << "exited with" << process.exitCode() << ":" << process.readAllStandardError();
}
return process.readAllStandardOutput();
}
DeploymentInfo deployQtLibraries(const QString &appDirPath, const QStringList &additionalExecutables) DeploymentInfo deployQtLibraries(const QString &appDirPath, const QStringList &additionalExecutables)
{ {
AppDirInfo applicationBundle; AppDirInfo applicationBundle;
@ -710,33 +726,31 @@ DeploymentInfo deployQtLibraries(const QString &appDirPath, const QStringList &a
// Determine the location of the Qt to be bundled // Determine the location of the Qt to be bundled
LogDebug() << "Using qmake to determine the location of the Qt to be bundled"; LogDebug() << "Using qmake to determine the location of the Qt to be bundled";
QProcess qmake; QString output = captureOutput("qmake -query");
qmake.start("qmake -v");
qmake.waitForFinished();
if (qmake.exitStatus() != QProcess::NormalExit || qmake.exitCode() != 0) {
LogError() << "qmake:" << qmake.readAllStandardError();
}
static const QRegularExpression regexp(QStringLiteral("^Using Qt version .+ in (.+)"));
QString output = qmake.readAllStandardOutput();
QStringList outputLines = output.split("\n", QString::SkipEmptyParts); QStringList outputLines = output.split("\n", QString::SkipEmptyParts);
foreach (QString outputLine, outputLines) { foreach (const QString &outputLine, outputLines) {
LogDebug() << "qmake outputLine:" << outputLine; int colonIndex = outputLine.indexOf(QLatin1Char(':'));
const auto match = regexp.match(outputLine); if (colonIndex != -1) {
if ((match.hasMatch()) and (QFileInfo(match.captured(1)).absoluteDir().exists())) { QString name = outputLine.left(colonIndex);
qtPathToBeBundled = QFileInfo(match.captured(1)).absolutePath(); QString value = outputLine.mid(colonIndex + 1);
LogDebug() << "Qt path determined from qmake:" << qtPathToBeBundled; qtToBeBundledInfo.insert(name, value);
QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
QString oldPath = env.value("LD_LIBRARY_PATH");
QString newPath = qtPathToBeBundled + "/lib" + ":" + 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;
setenv("LD_LIBRARY_PATH",newPath.toUtf8().constData(),1);
} }
} }
if(qtPathToBeBundled == ""){
QString qtLibsPath = qtToBeBundledInfo.value("QT_INSTALL_LIBS");
if (qtLibsPath.isEmpty() || !QFile::exists(qtLibsPath)) {
LogError() << "Qt path could not be determined from qmake on the $PATH"; LogError() << "Qt path could not be determined from qmake on the $PATH";
LogError() << "Make sure you have the correct Qt on your $PATH"; LogError() << "Make sure you have the correct Qt on your $PATH";
LogError() << "You can check this with qmake -v"; LogError() << "You can check this with qmake -v";
} else {
LogDebug() << "Qt libs path determined from qmake:" << qtLibsPath;
QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
QString oldPath = env.value("LD_LIBRARY_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;
setenv("LD_LIBRARY_PATH",newPath.toUtf8().constData(),1);
} }
changeIdentification("$ORIGIN/" + bundleLibraryDirectory, applicationBundle.binaryPath); changeIdentification("$ORIGIN/" + bundleLibraryDirectory, applicationBundle.binaryPath);
@ -952,7 +966,7 @@ bool deployQmlImports(const QString &appDirPath, DeploymentInfo deploymentInfo,
LogNormal() << "Application QML file search path(s) is" << qmlDirs; LogNormal() << "Application QML file search path(s) is" << qmlDirs;
// Use qmlimportscanner from QLibraryInfo::BinariesPath // Use qmlimportscanner from QLibraryInfo::BinariesPath
QString qmlImportScannerPath = QDir::cleanPath(qtPathToBeBundled) + "/bin/qmlimportscanner"; QString qmlImportScannerPath = QDir::cleanPath(qtToBeBundledInfo.value("QT_INSTALL_BINS")) + "/qmlimportscanner";
LogDebug() << "Looking for qmlimportscanner at" << qmlImportScannerPath; LogDebug() << "Looking for qmlimportscanner at" << qmlImportScannerPath;
// Fallback: Look relative to the linuxdeployqt binary // Fallback: Look relative to the linuxdeployqt binary
@ -975,8 +989,7 @@ bool deployQmlImports(const QString &appDirPath, DeploymentInfo deploymentInfo,
argumentList.append("-rootPath"); argumentList.append("-rootPath");
argumentList.append(qmlDir); argumentList.append(qmlDir);
} }
QString qmlImportsPath = QDir::cleanPath(qtPathToBeBundled) + "/qml"; QString qmlImportsPath = qtToBeBundledInfo.value("QT_INSTALL_QML");
// FIXME: Directory layout might be different for system Qt; cannot assume qml/ to always be inside the Qt directory
LogDebug() << "qmlImportsPath candidate:" << qmlImportsPath; LogDebug() << "qmlImportsPath candidate:" << qmlImportsPath;
// Verify that we found a valid qmlImportsPath // Verify that we found a valid qmlImportsPath

Loading…
Cancel
Save