diff options
author | Thiago Macieira <thiago.macieira@intel.com> | 2018-07-20 09:22:47 -0700 |
---|---|---|
committer | Simon Hausmann <simon.hausmann@qt.io> | 2018-07-27 04:56:14 +0000 |
commit | 447e2e024609a22fe052cf458c27efdef2e3d3eb (patch) | |
tree | f2665cfdea84b9d85044a3221658eb8ce10e7d9a /src | |
parent | 65fd9165162a8498c5bbe71e5372b65770c240b0 (diff) |
Try to load QML cache from CacheLocation if side-by-side fails
This could happen if the .qmlc file is stale or corrupt for some reason.
In that case, we should try to load a cache file from the user's
CacheLocation.
Change-Id: Id2be776c7ae0467c9d9ffffd1543204272a531d1
Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
Diffstat (limited to 'src')
-rw-r--r-- | src/qml/compiler/qv4compileddata.cpp | 44 | ||||
-rw-r--r-- | src/qml/compiler/qv4compileddata_p.h | 4 | ||||
-rw-r--r-- | src/qml/compiler/qv4compiler.cpp | 5 |
3 files changed, 32 insertions, 21 deletions
diff --git a/src/qml/compiler/qv4compileddata.cpp b/src/qml/compiler/qv4compileddata.cpp index 02aee47eea..0c81a5b3c6 100644 --- a/src/qml/compiler/qv4compileddata.cpp +++ b/src/qml/compiler/qv4compileddata.cpp @@ -76,7 +76,18 @@ namespace QV4 { namespace CompiledData { +#if defined(QML_COMPILE_HASH) +# ifdef Q_OS_LINUX +// Place on a separate section on Linux so it's easier to check from outside +// what the hash version is. +__attribute__((section(".qml_compile_hash"))) +# endif +const char qml_compile_hash[48 + 1] = QML_COMPILE_HASH; static_assert(sizeof(Unit::libraryVersionHash) >= QML_COMPILE_HASH_LENGTH + 1, "Compile hash length exceeds reserved size in data structure. Please adjust and bump the format version"); +#else +# error "QML_COMPILE_HASH must be defined for the build of QtDeclarative to ensure version checking for cache files" +#endif + CompilationUnit::CompilationUnit(const Unit *unitData) { @@ -351,26 +362,27 @@ bool CompilationUnit::loadFromDisk(const QUrl &url, const QDateTime &sourceTimeS const QString sourcePath = QQmlFile::urlToLocalFileOrQrc(url); QScopedPointer<CompilationUnitMapper> cacheFile(new CompilationUnitMapper()); - QString cachePath = sourcePath + QLatin1Char('c'); - if (!QFile::exists(cachePath)) - cachePath = localCacheFilePath(url); + const QStringList cachePaths = { sourcePath + QLatin1Char('c'), localCacheFilePath(url) }; + for (const QString &cachePath : cachePaths) { + CompiledData::Unit *mappedUnit = cacheFile->open(cachePath, sourceTimeStamp, errorString); + if (!mappedUnit) + continue; - CompiledData::Unit *mappedUnit = cacheFile->open(cachePath, sourceTimeStamp, errorString); - if (!mappedUnit) - return false; + const Unit * const oldDataPtr = (data && !(data->flags & QV4::CompiledData::Unit::StaticData)) ? data : nullptr; + QScopedValueRollback<const Unit *> dataPtrChange(data, mappedUnit); - const Unit * const oldDataPtr = (data && !(data->flags & QV4::CompiledData::Unit::StaticData)) ? data : nullptr; - QScopedValueRollback<const Unit *> dataPtrChange(data, mappedUnit); + if (data->sourceFileIndex != 0 && sourcePath != QQmlFile::urlToLocalFileOrQrc(stringAt(data->sourceFileIndex))) { + *errorString = QStringLiteral("QML source file has moved to a different location."); + continue; + } - if (data->sourceFileIndex != 0 && sourcePath != QQmlFile::urlToLocalFileOrQrc(stringAt(data->sourceFileIndex))) { - *errorString = QStringLiteral("QML source file has moved to a different location."); - return false; + dataPtrChange.commit(); + free(const_cast<Unit*>(oldDataPtr)); + backingFile.reset(cacheFile.take()); + return true; } - dataPtrChange.commit(); - free(const_cast<Unit*>(oldDataPtr)); - backingFile.reset(cacheFile.take()); - return true; + return false; } void CompilationUnit::linkBackendToEngine(ExecutionEngine *engine) @@ -783,7 +795,7 @@ bool Unit::verifyHeader(QDateTime expectedSourceTimeStamp, QString *errorString) } #if defined(QML_COMPILE_HASH) - if (qstrcmp(QML_COMPILE_HASH, libraryVersionHash) != 0) { + if (qstrcmp(CompiledData::qml_compile_hash, libraryVersionHash) != 0) { *errorString = QStringLiteral("QML library version mismatch. Expected compile hash does not match"); return false; } diff --git a/src/qml/compiler/qv4compileddata_p.h b/src/qml/compiler/qv4compileddata_p.h index c1be00ea27..0ac40d2800 100644 --- a/src/qml/compiler/qv4compileddata_p.h +++ b/src/qml/compiler/qv4compileddata_p.h @@ -752,7 +752,9 @@ struct Import }; static_assert(sizeof(Import) == 24, "Import structure needs to have the expected size to be binary compatible on disk when generated by host compiler and loaded by target"); +enum { QmlCompileHashSpace = 48 }; static const char magic_str[] = "qv4cdata"; +extern const char qml_compile_hash[QmlCompileHashSpace + 1]; struct Unit { @@ -764,7 +766,7 @@ struct Unit quint32_le unitSize; // Size of the Unit and any depending data. // END DO NOT CHANGE THESE FIELDS EVER - char libraryVersionHash[48]; + char libraryVersionHash[QmlCompileHashSpace]; char md5Checksum[16]; // checksum of all bytes following this field. void generateChecksum(); diff --git a/src/qml/compiler/qv4compiler.cpp b/src/qml/compiler/qv4compiler.cpp index f1afad4965..76779fece8 100644 --- a/src/qml/compiler/qv4compiler.cpp +++ b/src/qml/compiler/qv4compiler.cpp @@ -48,9 +48,6 @@ #include <wtf/MathExtras.h> #include <QCryptographicHash> -// generated by qmake: -#include "qml_compile_hash_p.h" - QV4::Compiler::StringTableGenerator::StringTableGenerator() { clear(); @@ -482,7 +479,7 @@ QV4::CompiledData::Unit QV4::Compiler::JSUnitGenerator::generateHeader(QV4::Comp unit.flags |= module->unitFlags; unit.version = QV4_DATA_STRUCTURE_VERSION; unit.qtVersion = QT_VERSION; - qstrcpy(unit.libraryVersionHash, QML_COMPILE_HASH); + qstrcpy(unit.libraryVersionHash, CompiledData::qml_compile_hash); memset(unit.md5Checksum, 0, sizeof(unit.md5Checksum)); memset(unit.dependencyMD5Checksum, 0, sizeof(unit.dependencyMD5Checksum)); |