diff options
Diffstat (limited to 'src/libs/installer/qtpatchoperation.cpp')
-rw-r--r-- | src/libs/installer/qtpatchoperation.cpp | 186 |
1 files changed, 149 insertions, 37 deletions
diff --git a/src/libs/installer/qtpatchoperation.cpp b/src/libs/installer/qtpatchoperation.cpp index 9699219ec..e9fbb65c5 100644 --- a/src/libs/installer/qtpatchoperation.cpp +++ b/src/libs/installer/qtpatchoperation.cpp @@ -111,7 +111,10 @@ static QHash<QByteArray, QByteArray> generatePatchValueHash(const QByteArray &ne replaceHash.insert( QByteArray("qt_trnspath=%1").replace("%1", oldValue), QByteArray("qt_trnspath=%1/translations").replace("%1/", newQtPath + nativeSeperator)); - // This must not be patched. Commenting out to fix QTSDK-429 + // This must not be patched! + // On desktop there should be a correct default path (for example "/etc/xdg"), + // but on some other targets you need to use "-sysconfdir </your/default/config/path" + // while building Qt to get a correct QT_INSTALL_CONFIGURATION value // oldValue = qmakeValueHash.value(QLatin1String("QT_INSTALL_CONFIGURATION")); // replaceMap.insert( QByteArray("qt_stngpath=%1").replace("%1", oldValue), // QByteArray("qt_stngpath=%1").replace("%1", newQtPath)); @@ -142,6 +145,10 @@ static QHash<QByteArray, QByteArray> generatePatchValueHash(const QByteArray &ne replaceHash.insert(QByteArray("qt_hdatpath=%1").replace("%1", oldValue), QByteArray("qt_hdatpath=%1/").replace("%1/", newQtPath)); + oldValue = qmakeValueHash.value(QLatin1String("QT_HOST_LIBS")); + replaceHash.insert(QByteArray("qt_hlibpath=%1").replace("%1", oldValue), + QByteArray("qt_hlibpath=%1/lib").replace("%1/", newQtPath + nativeSeperator)); + return replaceHash; } @@ -160,16 +167,34 @@ bool QtPatchOperation::performOperation() // 1. type // 2. new/target qtpath // 3. version if greather Qt4 + // optional QmakeOutputInstallerKey=<used_installer_value> // the possible 2 argument case is here to support old syntax - if (arguments().count() < 2 || arguments().count() > 3) { + if (arguments().count() < 2 && arguments().count() > 4) { setError(InvalidArguments); setErrorString(tr("Invalid arguments in %0: %1 arguments given, %2 expected%3.") - .arg(name()).arg(arguments().count()).arg(tr("exactly 3"), QLatin1String(""))); + .arg(name()).arg(arguments().count()).arg(tr("3 or 4"), QLatin1String(""))); return false; } - QString type = arguments().at(0); + QStringList args = arguments(); + QString qmakeOutputInstallerKey; + QStringList filteredQmakeOutputInstallerKey = args.filter(QLatin1String("QmakeOutputInstallerKey="), + Qt::CaseInsensitive); + PackageManagerCore *const core = value(QLatin1String("installer")).value<PackageManagerCore*>(); + if (!filteredQmakeOutputInstallerKey.isEmpty()) { + if (!core) { + setError(UserDefinedError); + setErrorString(tr("Needed installer object in \"%1\" operation is empty.").arg(name())); + return false; + } + QString qmakeOutputInstallerKeyArgument = filteredQmakeOutputInstallerKey.at(0); + qmakeOutputInstallerKey = qmakeOutputInstallerKeyArgument; + qmakeOutputInstallerKey.replace(QLatin1String("QmakeOutputInstallerKey="), QString(), Qt::CaseInsensitive); + args.removeAll(qmakeOutputInstallerKeyArgument); + } + + QString type = args.at(0); bool isPlatformSupported = type.contains(QLatin1String("linux"), Qt::CaseInsensitive) || type.contains(QLatin1String("windows"), Qt::CaseInsensitive) || type.contains(QLatin1String("mac"), Qt::CaseInsensitive); @@ -180,31 +205,42 @@ bool QtPatchOperation::performOperation() return false; } - const QString newQtPathStr = QDir::toNativeSeparators(arguments().at(1)); - const QByteArray newQtPath = newQtPathStr.toUtf8(); + if (core && !filteredQmakeOutputInstallerKey.isEmpty() && core->value(qmakeOutputInstallerKey).isEmpty()) { + setError(UserDefinedError); + setErrorString(tr("Could not find the needed QmakeOutputInstallerKey(%1) value on the installer " + "object. The ConsumeOutput operation on the valid qmake needs to be called first.").arg( + qmakeOutputInstallerKey)); + return false; + } + const QString newQtPathStr = QDir::toNativeSeparators(args.at(1)); + const QByteArray newQtPath = newQtPathStr.toUtf8(); QString qmakePath = QString::fromUtf8(newQtPath) + QLatin1String("/bin/qmake"); #ifdef Q_OS_WIN qmakePath = qmakePath + QLatin1String(".exe"); #endif - if (!QFile::exists(qmakePath)) { - setError(UserDefinedError); - setErrorString(tr("QMake from the current Qt version \n(%1)is not existing. Please file a bugreport " - "with this dialog at https://bugreports.qt-project.org.").arg(QDir::toNativeSeparators(qmakePath))); - return false; + QHash<QString, QByteArray> qmakeValueHash; + if (core && !core->value(qmakeOutputInstallerKey).isEmpty()) { + qmakeValueHash = QtPatch::readQmakeOutput(core->value(qmakeOutputInstallerKey).toLatin1()); + } else { + if (!QFile::exists(qmakePath)) { + setError(UserDefinedError); + setErrorString(tr("QMake from the current Qt version \n(%1)is not existing. Please file a bugreport " + "with this dialog at https://bugreports.qt-project.org.").arg(QDir::toNativeSeparators(qmakePath))); + return false; + } + QByteArray qmakeOutput; + qmakeValueHash = QtPatch::qmakeValues(qmakePath, &qmakeOutput); + if (qmakeValueHash.isEmpty()) { + setError(UserDefinedError); + setErrorString(tr("The output of \n%1 -query\nis not parseable. Please file a bugreport with this " + "dialog https://bugreports.qt-project.org.\noutput: \"%2\"").arg(QDir::toNativeSeparators(qmakePath), + QString::fromUtf8(qmakeOutput))); + return false; + } } - QByteArray qmakeOutput; - QHash<QString, QByteArray> qmakeValueHash = QtPatch::qmakeValues(qmakePath, &qmakeOutput); - - if (qmakeValueHash.isEmpty()) { - setError(UserDefinedError); - setErrorString(tr("The output of \n%1 -query\nis not parseable. Please file a bugreport with this " - "dialog https://bugreports.qt-project.org.\noutput: \"%2\"").arg(QDir::toNativeSeparators(qmakePath), - QString::fromUtf8(qmakeOutput))); - return false; - } const QByteArray oldQtPath = qmakeValueHash.value(QLatin1String("QT_INSTALL_PREFIX")); bool oldQtPathFromQMakeIsEmpty = oldQtPath.isEmpty(); @@ -218,19 +254,97 @@ bool QtPatchOperation::performOperation() } #ifdef Q_OS_MAC - // just try to patch here at the beginning to keep the unpatched qmake if mac install_names_tool fails - MacReplaceInstallNamesOperation operation; - operation.setArguments(QStringList() - //can not use the old path which is wrong in the webkit case - //<< QString::fromUtf8(oldQtPath) - << QLatin1String("/lib/Qt") // search string - << newQtPathStr + QLatin1String("/lib/Qt") //replace string - << newQtPathStr //where - ); - if (!operation.performOperation()) { - setError(operation.error()); - setErrorString(operation.errorString()); - return false; + // looking for /lib/Qt wasn't enough for all libs and frameworks, + // at the Qt4 case we had for example: /lib/libQtCLucene* and /lib/phonon* + // so now we find every possible replace string inside dynlib dependencies + // and we reduce it to few as possible search strings + QStringList possibleSearchStringList; + QDirIterator dirIterator(newQtPathStr + QLatin1String("/lib/")); + while (dirIterator.hasNext()) { + const QString possibleSearchString = QString(dirIterator.next()).remove(newQtPathStr); + const QFileInfo fileInfo = dirIterator.fileInfo(); + if (fileInfo.isSymLink()) + continue; + if (fileInfo.isDir()) { + if (possibleSearchString.endsWith(QLatin1String(".framework"))) + possibleSearchStringList.append(possibleSearchString); + else + continue; + } + if (possibleSearchString.endsWith(QLatin1String(".dylib"))) + possibleSearchStringList.append(possibleSearchString); + } + + // now we have this in possibleSearchStringList at Qt 4.8.6 +// "/lib/libQtCLucene.4.8.6.dylib" +// "/lib/libQtCLucene_debug.4.8.6.dylib" +// "/lib/phonon.framework" +// "/lib/QtCore.framework" +// "/lib/QtDeclarative.framework" +// "/lib/QtDesigner.framework" +// "/lib/QtDesignerComponents.framework" +// "/lib/QtGui.framework" +// "/lib/QtHelp.framework" +// "/lib/QtMultimedia.framework" +// "/lib/QtNetwork.framework" +// "/lib/QtOpenGL.framework" +// "/lib/QtScript.framework" +// "/lib/QtScriptTools.framework" +// "/lib/QtSql.framework" +// "/lib/QtSvg.framework" +// "/lib/QtTest.framework" +// "/lib/QtWebKit.framework" +// "/lib/QtXml.framework" +// "/lib/QtXmlPatterns.framework" + + // so then we reduce the possible filter strings as much as possible + QStringList searchStringList; + + // as the minimal search string use the subdirector lib + one letter from the name + int minFilterLength = QString(QLatin1String("/lib/")).length() + 1; + + while (!possibleSearchStringList.isEmpty()) { + QString firstSearchString = possibleSearchStringList.first(); + int filterLength = minFilterLength; + int lastFilterCount = 0; + QString lastFilterString; + // now filter as long as we find something more then 1 + for (; filterLength < firstSearchString.length(); ++filterLength) { + QString filterString(firstSearchString.left(filterLength)); + QStringList filteredStringList(possibleSearchStringList.filter(filterString)); + // found a valid filter + if (lastFilterCount > filteredStringList.count()) { + possibleSearchStringList = QList<QString>::fromSet(possibleSearchStringList.toSet() - + possibleSearchStringList.filter(lastFilterString).toSet()); + searchStringList.append(lastFilterString); + break; + } else if (lastFilterCount == 1){ //in case there is only one we can use the complete name + possibleSearchStringList = QList<QString>::fromSet(possibleSearchStringList.toSet() - + possibleSearchStringList.filter(firstSearchString).toSet()); + searchStringList.append(firstSearchString); + break; + } else { + lastFilterCount = possibleSearchStringList.filter(filterString).count(); + lastFilterString = filterString; + } + } + } + + // in the tested Qt 4.8.6 case we have searchStringList ("/lib/libQtCLucene", "/lib/Qt", "/lib/phonon") + foreach (const QString &searchString, searchStringList) { + MacReplaceInstallNamesOperation operation; + operation.setArguments(QStringList() + //can not use the old path which is wrong in the webkit case + //<< QString::fromUtf8(oldQtPath) + << searchString + << newQtPathStr + searchString //replace string + << newQtPathStr //where + ); + if (!operation.performOperation()) { + setError(operation.error()); + setErrorString(operation.errorString()); + return false; + } } #endif @@ -239,13 +353,11 @@ bool QtPatchOperation::performOperation() fileName = QString::fromLatin1(":/files-to-patch-windows"); else if (type == QLatin1String("linux")) fileName = QString::fromLatin1(":/files-to-patch-linux"); - else if (type == QLatin1String("linux-emb-arm")) - fileName = QString::fromLatin1(":/files-to-patch-linux-emb-arm"); else if (type == QLatin1String("mac")) fileName = QString::fromLatin1(":/files-to-patch-macx"); QFile patchFileListFile(fileName); - QString version = arguments().value(2).toLower(); + QString version = args.value(2).toLower(); if (!version.isEmpty()) patchFileListFile.setFileName(fileName + QLatin1Char('-') + version); |