From d5dd7da3eef45c69957e4b16cc8af83475aa1e99 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Thu, 16 May 2024 09:12:35 -0700 Subject: [PATCH] rcc: add the ability to output copyrights in the output According to gnu.org[1] > When a file is automatically generated from some other file in the > distribution, it is useful for the automatic procedure to copy the > copyright notice and permission notice of the file it is generated > from, if possible. This commit allows us to add copyright notices to the .qrc files themselves and additionally have that be output into the generated .rcc (of which we have a few committed to the repository) [ChangeLog][rcc] The Qt Resource Compiler now accepts a XML tag inside the main entry, which can be used to document the copyright of the resource file itself and other terms of use (even though the file is probably created by a tool like Qt Creator's resource editor). The text of this copyright will be emitted in the generated C++ or Python source code. [1] https://www.gnu.org/prep/maintain/html_node/Copyright-Notices.html Change-Id: If05cb740b64f42eba21efffd17d00417433f1ee9 Reviewed-by: Volker Hilsheimer Reviewed-by: Ahmad Samir --- src/tools/rcc/rcc.cpp | 16 +++ src/tools/rcc/rcc.h | 2 + tests/auto/tools/rcc/data/.gitattributes | 2 + tests/auto/tools/rcc/data/legal/legal.qrc | 10 ++ tests/auto/tools/rcc/data/legal/rcc_legal.cpp | 101 ++++++++++++++++++ tests/auto/tools/rcc/tst_rcc.cpp | 4 + 6 files changed, 135 insertions(+) create mode 100644 tests/auto/tools/rcc/data/.gitattributes create mode 100644 tests/auto/tools/rcc/data/legal/legal.qrc create mode 100644 tests/auto/tools/rcc/data/legal/rcc_legal.cpp diff --git a/src/tools/rcc/rcc.cpp b/src/tools/rcc/rcc.cpp index 0fdba3671d1..a1089914fd2 100644 --- a/src/tools/rcc/rcc.cpp +++ b/src/tools/rcc/rcc.cpp @@ -512,6 +512,12 @@ bool RCCResourceLibrary::interpretResourceFile(QIODevice *inputDevice, reader.raiseError("expected tag"_L1); else tokens.push(RccTag); + } else if (reader.name() == m_strings.TAG_LEGAL) { + if (tokens.isEmpty() || tokens.top() != RccTag) { + reader.raiseError("unexpected tag"_L1); + } else { + m_legal = reader.readElementText().trimmed(); + } } else if (reader.name() == m_strings.TAG_RESOURCE) { if (tokens.isEmpty() || tokens.top() != RccTag) { reader.raiseError("unexpected tag"_L1); @@ -1087,11 +1093,20 @@ void RCCResourceLibrary::writeNumber8(quint64 number) bool RCCResourceLibrary::writeHeader() { + auto writeCopyright = [this](QByteArrayView prefix) { + const QStringList lines = m_legal.split(u'\n', Qt::SkipEmptyParts); + for (const QString &line : lines) { + write(prefix.data(), prefix.size()); + writeString(line.toUtf8().trimmed()); + writeChar('\n'); + } + }; switch (m_format) { case C_Code: case Pass1: writeString("/****************************************************************************\n"); writeString("** Resource object code\n"); + writeCopyright("** "); writeString("**\n"); writeString("** Created by: The Resource Compiler for Qt version "); writeByteArray(QT_VERSION_STR); @@ -1105,6 +1120,7 @@ bool RCCResourceLibrary::writeHeader() break; case Python_Code: writeString("# Resource object code (Python 3)\n"); + writeCopyright("# "); writeString("# Created by: object code\n"); writeString("# Created by: The Resource Compiler for Qt version "); writeByteArray(QT_VERSION_STR); diff --git a/src/tools/rcc/rcc.h b/src/tools/rcc/rcc.h index bfc3503da87..e2ae8c5240e 100644 --- a/src/tools/rcc/rcc.h +++ b/src/tools/rcc/rcc.h @@ -93,6 +93,7 @@ private: const QString TAG_RCC; const QString TAG_RESOURCE; const QString TAG_FILE; + const QString TAG_LEGAL = QLatin1StringView("legal"); const QString ATTRIBUTE_LANG; const QString ATTRIBUTE_PREFIX; const QString ATTRIBUTE_ALIAS; @@ -134,6 +135,7 @@ private: QString m_resourceRoot; QString m_initName; QString m_outputName; + QString m_legal; Format m_format; bool m_verbose; CompressionAlgorithm m_compressionAlgo; diff --git a/tests/auto/tools/rcc/data/.gitattributes b/tests/auto/tools/rcc/data/.gitattributes new file mode 100644 index 00000000000..89d6e8fe1c7 --- /dev/null +++ b/tests/auto/tools/rcc/data/.gitattributes @@ -0,0 +1,2 @@ +# Keep parentdir.txt with LF line endings +parentdir.txt -text diff --git a/tests/auto/tools/rcc/data/legal/legal.qrc b/tests/auto/tools/rcc/data/legal/legal.qrc new file mode 100644 index 00000000000..5eb7f584165 --- /dev/null +++ b/tests/auto/tools/rcc/data/legal/legal.qrc @@ -0,0 +1,10 @@ + + + + Copyright (C) 2024 Intel Corporation. + SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + + + ../parentdir.txt + + diff --git a/tests/auto/tools/rcc/data/legal/rcc_legal.cpp b/tests/auto/tools/rcc/data/legal/rcc_legal.cpp new file mode 100644 index 00000000000..7522e1b34ff --- /dev/null +++ b/tests/auto/tools/rcc/data/legal/rcc_legal.cpp @@ -0,0 +1,101 @@ +/**************************************************************************** +** Resource object code +** Copyright (C) 2024 Intel Corporation. +** SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only +** +** Created by: The Resource Compiler for Qt version 6.8.0 +** +** WARNING! All changes made in this file will be lost! +*****************************************************************************/ + +#ifdef _MSC_VER +// disable informational message "function ... selected for automatic inline expansion" +#pragma warning (disable: 4711) +#endif + +static const unsigned char qt_resource_data[] = { + // parentdir.txt + 0x0,0x0,0x0,0x1a, + 0x61, + 0x62,0x63,0x64,0x65,0x66,0x67,0x69,0x68,0x6b,0x6c,0x6d,0x6e,0x6f,0x70,0x71,0x72, + 0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0xa, + +}; + +static const unsigned char qt_resource_name[] = { + // parentdir.txt + 0x0,0xd, + 0x6,0x14,0xd1,0x74, + 0x0,0x70, + 0x0,0x61,0x0,0x72,0x0,0x65,0x0,0x6e,0x0,0x74,0x0,0x64,0x0,0x69,0x0,0x72,0x0,0x2e,0x0,0x74,0x0,0x78,0x0,0x74, + +}; + +static const unsigned char qt_resource_struct[] = { + // : + 0x0,0x0,0x0,0x0,0x0,0x2,0x0,0x0,0x0,0x1,0x0,0x0,0x0,0x1, +0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + // :/parentdir.txt + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x0,0x0,0x0, +TIMESTAMP:../parentdir.txt + +}; + +#ifdef QT_NAMESPACE +# define QT_RCC_PREPEND_NAMESPACE(name) ::QT_NAMESPACE::name +# define QT_RCC_MANGLE_NAMESPACE0(x) x +# define QT_RCC_MANGLE_NAMESPACE1(a, b) a##_##b +# define QT_RCC_MANGLE_NAMESPACE2(a, b) QT_RCC_MANGLE_NAMESPACE1(a,b) +# define QT_RCC_MANGLE_NAMESPACE(name) QT_RCC_MANGLE_NAMESPACE2( \ + QT_RCC_MANGLE_NAMESPACE0(name), QT_RCC_MANGLE_NAMESPACE0(QT_NAMESPACE)) +#else +# define QT_RCC_PREPEND_NAMESPACE(name) name +# define QT_RCC_MANGLE_NAMESPACE(name) name +#endif + +#if defined(QT_INLINE_NAMESPACE) +inline namespace QT_NAMESPACE { +#elif defined(QT_NAMESPACE) +namespace QT_NAMESPACE { +#endif + +bool qRegisterResourceData(int, const unsigned char *, const unsigned char *, const unsigned char *); +bool qUnregisterResourceData(int, const unsigned char *, const unsigned char *, const unsigned char *); + +#ifdef QT_NAMESPACE +} +#endif + +int QT_RCC_MANGLE_NAMESPACE(qInitResources)(); +int QT_RCC_MANGLE_NAMESPACE(qInitResources)() +{ + int version = 3; + QT_RCC_PREPEND_NAMESPACE(qRegisterResourceData) + (version, qt_resource_struct, qt_resource_name, qt_resource_data); + return 1; +} + +int QT_RCC_MANGLE_NAMESPACE(qCleanupResources)(); +int QT_RCC_MANGLE_NAMESPACE(qCleanupResources)() +{ + int version = 3; + QT_RCC_PREPEND_NAMESPACE(qUnregisterResourceData) + (version, qt_resource_struct, qt_resource_name, qt_resource_data); + return 1; +} + +#ifdef __clang__ +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wexit-time-destructors" +#endif + +namespace { + struct initializer { + initializer() { QT_RCC_MANGLE_NAMESPACE(qInitResources)(); } + ~initializer() { QT_RCC_MANGLE_NAMESPACE(qCleanupResources)(); } + } dummy; +} + +#ifdef __clang__ +# pragma clang diagnostic pop +#endif diff --git a/tests/auto/tools/rcc/tst_rcc.cpp b/tests/auto/tools/rcc/tst_rcc.cpp index 88a6e17e2f2..af4a992d5cf 100644 --- a/tests/auto/tools/rcc/tst_rcc.cpp +++ b/tests/auto/tools/rcc/tst_rcc.cpp @@ -1,5 +1,6 @@ // Copyright (C) 2012 Giuseppe D'Angelo // Copyright (C) 2016 The Qt Company Ltd. +// Copyright (C) 2024 Intel Corporation. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include @@ -148,6 +149,9 @@ void tst_rcc::rcc_data() QTest::newRow("size-1") << sizesPath << "size-1.qrc" << "size-1.expected"; QTest::newRow("size-2-0-35-1") << sizesPath << "size-2-0-35-1.qrc" << (sizeof(size_t) == 8 ? "size-2-0-35-1.expected" : "size-2-0-35-1.expected32"); + + QTest::newRow("legal") << m_dataPath + QLatin1StringView("/legal") + << "legal.qrc" << "rcc_legal.cpp"; } static QStringList readLinesFromFile(const QString &fileName,