diff options
author | Ulf Hermann <[email protected]> | 2025-03-10 08:34:45 +0100 |
---|---|---|
committer | Ulf Hermann <[email protected]> | 2025-03-18 10:53:07 +0100 |
commit | 390c78b394b30d1abdc6268b21dd2a583472bd60 (patch) | |
tree | 3990a9485d60e4ae18949693e434b2eeb4ee0f9b | |
parent | 0675e10429234b43ab96de22181c1970416a42ef (diff) |
QtQml: Drop checks for compile hash and Qt version from the CUs
The data structure version is supposed to encode any incompatible
changes to our compilation unit format. Checking the compile hash and Qt
version in addition is redundant and excessively restrictive.
[ChangeLog][QtQml] You can now use QML code compiled with Qt Quick
Compiler across Qt versions as long as the compilation unit format
hasn't changed between those versions. You cannot rely on the
compilation unit format to stay unchanged under any specific
circumstances. However, we won't change it unnecessarily.
Change-Id: I8c407b505ac7fa952f53fa25bb6d4e7caf0fba0c
Reviewed-by: Fabian Kosmale <[email protected]>
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | cmake/QtDeclarativeSetup.cmake | 53 | ||||
-rw-r--r-- | src/qml/CMakeLists.txt | 1 | ||||
-rw-r--r-- | src/qml/common/qv4compileddata.cpp | 36 | ||||
-rw-r--r-- | src/qml/common/qv4compileddata_p.h | 12 | ||||
-rw-r--r-- | src/qml/compiler/qv4compiler.cpp | 3 | ||||
-rw-r--r-- | tests/auto/qml/qmldiskcache/tst_qmldiskcache.cpp | 17 |
7 files changed, 5 insertions, 118 deletions
diff --git a/.gitignore b/.gitignore index e3756b608c..8a269d3336 100644 --- a/.gitignore +++ b/.gitignore @@ -351,7 +351,6 @@ tests/auto/*/*/*/*.moc src/qml/RegExpJitTables.h src/qml/udis86_itab.c src/qml/udis86_itab.h -src/qml/qml_compile_hash_p.h # Generated HLSL bytecode headers *.hlslh diff --git a/cmake/QtDeclarativeSetup.cmake b/cmake/QtDeclarativeSetup.cmake index b174756343..48ddd3f672 100644 --- a/cmake/QtDeclarativeSetup.cmake +++ b/cmake/QtDeclarativeSetup.cmake @@ -1,59 +1,6 @@ # Copyright (C) 2022 The Qt Company Ltd. # SPDX-License-Identifier: BSD-3-Clause -# Create a header containing a hash that describes this library. For a -# released version of Qt, we'll use the .tag file that is updated by git -# archive with the tree hash. For unreleased versions, we'll do -# "git show -s --format=format:%T" to get the tree hash. If none of this -# works, we use CMake to hash all the files in the src/qml/ directory. -# Skip recreation of the hash when doing a developer build. -function(qt_declarative_write_tag_header target_name) - set(out_file "${CMAKE_CURRENT_BINARY_DIR}/qml_compile_hash_p.h") - if(FEATURE_developer_build AND EXISTS "${out_file}") - target_sources(${target_name} PRIVATE "${out_file}") - set_source_files_properties("${out_file}" PROPERTIES GENERATED TRUE) - return() - endif() - - set(tag_file "${CMAKE_CURRENT_SOURCE_DIR}/../../.tag") - set(tag_contents "") - if(EXISTS "${tag_file}") - file(READ "${tag_file}" tag_contents) - string(STRIP "${tag_contents}" tag_contents) - endif() - find_program(git_path git) - - if(tag_contents AND NOT tag_contents STREQUAL "$Format:%T$") - set(QML_COMPILE_HASH "${tag_contents}") - elseif(git_path AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/../../.git") - execute_process( - COMMAND ${git_path} show -s --format=format:%T HEAD - OUTPUT_VARIABLE QML_COMPILE_HASH - OUTPUT_STRIP_TRAILING_WHITESPACE - WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}") - endif() - string(LENGTH "${QML_COMPILE_HASH}" QML_COMPILE_HASH_LENGTH) - if(QML_COMPILE_HASH_LENGTH EQUAL 0) - set(sources_hash "") - file(GLOB_RECURSE qtqml_source_files "${CMAKE_CURRENT_SOURCE_DIR}/*") - foreach(file IN LISTS qtqml_source_files) - file(SHA1 ${file} file_hash) - string(APPEND sources_hash ${file_hash}) - endforeach() - string(SHA1 QML_COMPILE_HASH "${sources_hash}") - endif() - - string(LENGTH "${QML_COMPILE_HASH}" QML_COMPILE_HASH_LENGTH) - if(QML_COMPILE_HASH_LENGTH GREATER 0) - configure_file("qml_compile_hash_p.h.in" "${out_file}") - else() - message(FATAL_ERROR "QML compile hash is empty! " - "You need either a valid git repository or a non-empty .tag file.") - endif() - target_sources(${target_name} PRIVATE "${out_file}") - set_source_files_properties("${out_file}" PROPERTIES GENERATED TRUE) -endfunction() - # Generate a header file containing a regular expression jit table. function(qt_declarative_generate_reg_exp_jit_tables consuming_target) set(generate_dir "${CMAKE_CURRENT_BINARY_DIR}/.generated") diff --git a/src/qml/CMakeLists.txt b/src/qml/CMakeLists.txt index bd02dd1376..c0ea99b5fa 100644 --- a/src/qml/CMakeLists.txt +++ b/src/qml/CMakeLists.txt @@ -521,7 +521,6 @@ set_source_files_properties(compat/removed_api.cpp # "" #) -qt_declarative_write_tag_header(Qml) set(_qt_qlalr_flags "--no-debug" "--qt") qt_process_qlalr(Qml "${CMAKE_CURRENT_SOURCE_DIR}/parser/qqmljs.g" "${_qt_qlalr_flags}") qt_declarative_generate_reg_exp_jit_tables(Qml) diff --git a/src/qml/common/qv4compileddata.cpp b/src/qml/common/qv4compileddata.cpp index 3959c0c2a5..9ce5f5058f 100644 --- a/src/qml/common/qv4compileddata.cpp +++ b/src/qml/common/qv4compileddata.cpp @@ -4,7 +4,6 @@ #include "qv4compileddata_p.h" #include <private/inlinecomponentutils_p.h> -#include <private/qml_compile_hash_p.h> #include <private/qqmlscriptdata_p.h> #include <private/qqmltypenamecache_p.h> #include <private/qv4resolvedtypereference_p.h> @@ -16,21 +15,6 @@ #include <QtCore/qstandardpaths.h> #include <QtCore/qxpfunctional.h> -static_assert(QV4::CompiledData::QmlCompileHashSpace > QML_COMPILE_HASH_LENGTH); - -#if defined(QML_COMPILE_HASH) && defined(QML_COMPILE_HASH_LENGTH) && QML_COMPILE_HASH_LENGTH > 0 -# 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[QV4::CompiledData::QmlCompileHashSpace] = QML_COMPILE_HASH; -static_assert(sizeof(QV4::CompiledData::Unit::libraryVersionHash) > QML_COMPILE_HASH_LENGTH, - "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 - QT_BEGIN_NAMESPACE namespace QV4 { @@ -50,12 +34,6 @@ bool Unit::verifyHeader(QDateTime expectedSourceTimeStamp, QString *errorString) return false; } - if (qtVersion != quint32(QT_VERSION)) { - *errorString = QString::fromUtf8("Qt version mismatch. Found %1 expected %2") - .arg(qtVersion, 0, 16).arg(QT_VERSION, 0, 16); - return false; - } - if (sourceTimeStamp) { // Files from the resource system do not have any time stamps, so fall back to the application // executable. @@ -69,20 +47,6 @@ bool Unit::verifyHeader(QDateTime expectedSourceTimeStamp, QString *errorString) } } -#if defined(QML_COMPILE_HASH) && defined(QML_COMPILE_HASH_LENGTH) && QML_COMPILE_HASH_LENGTH > 0 - if (qstrncmp(qml_compile_hash, libraryVersionHash, QML_COMPILE_HASH_LENGTH) != 0) { - *errorString = QStringLiteral("QML compile hashes don't match. Found %1 expected %2") - .arg(QString::fromLatin1( - QByteArray(libraryVersionHash, QML_COMPILE_HASH_LENGTH) - .toPercentEncoding()), - QString::fromLatin1( - QByteArray(qml_compile_hash, QML_COMPILE_HASH_LENGTH) - .toPercentEncoding())); - return false; - } -#else -#error "QML_COMPILE_HASH must be defined for the build of QtDeclarative to ensure version checking for cache files" -#endif return true; } diff --git a/src/qml/common/qv4compileddata_p.h b/src/qml/common/qv4compileddata_p.h index 46112c3034..889df101d0 100644 --- a/src/qml/common/qv4compileddata_p.h +++ b/src/qml/common/qv4compileddata_p.h @@ -51,7 +51,7 @@ QT_BEGIN_NAMESPACE // Also change the comment behind the number to describe the latest change. This has the added // benefit that if another patch changes the version too, it will result in a merge conflict, and // not get removed silently. -#define QV4_DATA_STRUCTURE_VERSION 0x44 // added a flag to mark properties as final from QML +#define QV4_DATA_STRUCTURE_VERSION 0x45 // Removed Qt version and compile hash checks class QIODevice; class QQmlTypeNameCache; @@ -1203,7 +1203,6 @@ struct QmlUnit }; static_assert(sizeof(QmlUnit) == 16, "QmlUnit 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"; struct Unit @@ -1211,12 +1210,11 @@ struct Unit // DO NOT CHANGE THESE FIELDS EVER char magic[8]; quint32_le version; - quint32_le qtVersion; - qint64_le sourceTimeStamp; - quint32_le unitSize; // Size of the Unit and any depending data. // END DO NOT CHANGE THESE FIELDS EVER - char libraryVersionHash[QmlCompileHashSpace]; + quint32_le reserved; // For predictable alignment and size. Used to be Qt version. + qint64_le sourceTimeStamp; + quint32_le unitSize; // Size of the Unit and any depending data. char md5Checksum[16]; // checksum of all bytes following this field. char dependencyMD5Checksum[16]; @@ -1387,7 +1385,7 @@ struct Unit bool verifyHeader(QDateTime expectedSourceTimeStamp, QString *errorString) const; }; -static_assert(sizeof(Unit) == 248, "Unit structure needs to have the expected size to be binary compatible on disk when generated by host compiler and loaded by target"); +static_assert(sizeof(Unit) == 200, "Unit structure needs to have the expected size to be binary compatible on disk when generated by host compiler and loaded by target"); struct TypeReference { diff --git a/src/qml/compiler/qv4compiler.cpp b/src/qml/compiler/qv4compiler.cpp index 7a7c8f621b..ad1390a650 100644 --- a/src/qml/compiler/qv4compiler.cpp +++ b/src/qml/compiler/qv4compiler.cpp @@ -9,7 +9,6 @@ #include <private/qv4alloca_p.h> #include <private/qqmljslexer_p.h> #include <private/qqmljsast_p.h> -#include <private/qml_compile_hash_p.h> #include <private/qqmlirbuilder_p.h> #include <QCryptographicHash> #include <QtEndian> @@ -632,8 +631,6 @@ QV4::CompiledData::Unit QV4::Compiler::JSUnitGenerator::generateHeader(QV4::Comp unit.flags = QV4::CompiledData::Unit::IsJavascript; unit.flags |= module->unitFlags; unit.version = QV4_DATA_STRUCTURE_VERSION; - unit.qtVersion = QT_VERSION; - qstrcpy(unit.libraryVersionHash, QML_COMPILE_HASH); memset(unit.md5Checksum, 0, sizeof(unit.md5Checksum)); memset(unit.dependencyMD5Checksum, 0, sizeof(unit.dependencyMD5Checksum)); diff --git a/tests/auto/qml/qmldiskcache/tst_qmldiskcache.cpp b/tests/auto/qml/qmldiskcache/tst_qmldiskcache.cpp index dc7490c18a..a6ea3b2e97 100644 --- a/tests/auto/qml/qmldiskcache/tst_qmldiskcache.cpp +++ b/tests/auto/qml/qmldiskcache/tst_qmldiskcache.cpp @@ -281,11 +281,8 @@ void tst_qmldiskcache::loadLocalAsFallback() QV4::CompiledData::Unit unit = {}; memcpy(unit.magic, QV4::CompiledData::magic_str, sizeof(unit.magic)); unit.version = QV4_DATA_STRUCTURE_VERSION; - unit.qtVersion = QT_VERSION; unit.sourceTimeStamp = testCompiler.mappedFile.fileTime(QFile::FileModificationTime).toMSecsSinceEpoch(); unit.unitSize = ~0U; // make the size a silly number - // write something to the library hash that should cause it not to be loaded - memset(unit.libraryVersionHash, 'z', sizeof(unit.libraryVersionHash)); memset(unit.md5Checksum, 0, sizeof(unit.md5Checksum)); // leave the other fields unset, since they don't matter @@ -428,20 +425,6 @@ void tst_qmldiskcache::basicVersionChecks() testCompiler.clearCache(); QVERIFY2(testCompiler.compile(contents), qPrintable(testCompiler.lastErrorString)); - const QString qtVersionFile = QStringLiteral("qtversion.qml"); - QVERIFY(testCompiler.tweakHeader([](QV4::CompiledData::Unit *header) { - header->qtVersion = 0; - }, qtVersionFile)); - - QVERIFY(!testCompiler.verify(qtVersionFile)); - QCOMPARE(testCompiler.lastErrorString, QString::fromUtf8("Qt version mismatch. Found 0 expected %1").arg(QT_VERSION, 0, 16)); - testCompiler.clearCache(qtVersionFile); - } - - { - testCompiler.clearCache(); - QVERIFY2(testCompiler.compile(contents), qPrintable(testCompiler.lastErrorString)); - const QString versionFile = QStringLiteral("version.qml"); QVERIFY(testCompiler.tweakHeader([](QV4::CompiledData::Unit *header) { header->version = 0; |