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 <legal> XML tag
inside the main <RCC> 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 <volker.hilsheimer@qt.io>
Reviewed-by: Ahmad Samir <a.samirh78@gmail.com>
This commit is contained in:
Thiago Macieira 2024-05-16 09:12:35 -07:00
parent 24b1e52a1a
commit d5dd7da3ee
6 changed files with 135 additions and 0 deletions

View File

@ -512,6 +512,12 @@ bool RCCResourceLibrary::interpretResourceFile(QIODevice *inputDevice,
reader.raiseError("expected <RCC> tag"_L1);
else
tokens.push(RccTag);
} else if (reader.name() == m_strings.TAG_LEGAL) {
if (tokens.isEmpty() || tokens.top() != RccTag) {
reader.raiseError("unexpected <legal> 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 <RESOURCE> 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);

View File

@ -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;

View File

@ -0,0 +1,2 @@
# Keep parentdir.txt with LF line endings
parentdir.txt -text

View File

@ -0,0 +1,10 @@
<!DOCTYPE RCC>
<RCC version="1.0">
<legal>
Copyright (C) 2024 Intel Corporation.
SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
</legal>
<qresource>
<file>../parentdir.txt</file>
</qresource>
</RCC>

View File

@ -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

View File

@ -1,5 +1,6 @@
// Copyright (C) 2012 Giuseppe D'Angelo <dangelog@gmail.com>
// Copyright (C) 2016 The Qt Company Ltd.
// Copyright (C) 2024 Intel Corporation.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QTest>
@ -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,