aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorUlf Hermann <[email protected]>2025-03-10 08:34:45 +0100
committerUlf Hermann <[email protected]>2025-03-18 10:53:07 +0100
commit390c78b394b30d1abdc6268b21dd2a583472bd60 (patch)
tree3990a9485d60e4ae18949693e434b2eeb4ee0f9b
parent0675e10429234b43ab96de22181c1970416a42ef (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--.gitignore1
-rw-r--r--cmake/QtDeclarativeSetup.cmake53
-rw-r--r--src/qml/CMakeLists.txt1
-rw-r--r--src/qml/common/qv4compileddata.cpp36
-rw-r--r--src/qml/common/qv4compileddata_p.h12
-rw-r--r--src/qml/compiler/qv4compiler.cpp3
-rw-r--r--tests/auto/qml/qmldiskcache/tst_qmldiskcache.cpp17
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;