summaryrefslogtreecommitdiffstats
path: root/src/tools
diff options
context:
space:
mode:
Diffstat (limited to 'src/tools')
-rw-r--r--src/tools/androiddeployqt/main.cpp309
-rw-r--r--src/tools/bootstrap/bootstrap.pro2
-rw-r--r--src/tools/moc/generator.cpp18
-rw-r--r--src/tools/moc/moc.cpp51
-rw-r--r--src/tools/moc/moc.h5
-rw-r--r--src/tools/moc/preprocessor.cpp10
-rw-r--r--src/tools/qdbuscpp2xml/qdbuscpp2xml.cpp2
-rw-r--r--src/tools/qdbusxml2cpp/qdbusxml2cpp.cpp2
-rw-r--r--src/tools/uic/python/pythonwriteimports.cpp6
9 files changed, 254 insertions, 151 deletions
diff --git a/src/tools/androiddeployqt/main.cpp b/src/tools/androiddeployqt/main.cpp
index 0504432eea..b7e96a0b59 100644
--- a/src/tools/androiddeployqt/main.cpp
+++ b/src/tools/androiddeployqt/main.cpp
@@ -129,7 +129,6 @@ struct Options
, internalSf(false)
, sectionsOnly(false)
, protectedAuthenticationPath(false)
- , jarSigner(false)
, installApk(false)
, uninstallApk(false)
{}
@@ -157,6 +156,7 @@ struct Options
QString sdkPath;
QString sdkBuildToolsVersion;
QString ndkPath;
+ QString ndkVersion;
QString jdkPath;
// Build paths
@@ -174,7 +174,7 @@ struct Options
QString versionName;
QString versionCode;
QByteArray minSdkVersion{"21"};
- QByteArray targetSdkVersion{"28"};
+ QByteArray targetSdkVersion{"31"};
// lib c++ path
QString stdCppPath;
@@ -213,7 +213,6 @@ struct Options
bool internalSf;
bool sectionsOnly;
bool protectedAuthenticationPath;
- bool jarSigner;
QString apkPath;
// Installation information
@@ -343,7 +342,7 @@ QString fileArchitecture(const Options &options, const QString &path)
return {};
}
- readElf = QLatin1String("%1 -needed-libs %2").arg(shellQuote(readElf), shellQuote(path));
+ readElf = QLatin1String("%1 --needed-libs %2").arg(shellQuote(readElf), shellQuote(path));
FILE *readElfCommand = openProcess(readElf);
if (!readElfCommand) {
@@ -422,7 +421,6 @@ Options parseOptions()
} else if (argument.compare(QLatin1String("--aab"), Qt::CaseInsensitive) == 0) {
options.buildAAB = true;
options.build = true;
- options.jarSigner = true;
} else if (!options.buildAAB && argument.compare(QLatin1String("--no-build"), Qt::CaseInsensitive) == 0) {
options.build = false;
} else if (argument.compare(QLatin1String("--install"), Qt::CaseInsensitive) == 0) {
@@ -525,8 +523,6 @@ Options parseOptions()
options.sectionsOnly = true;
} else if (argument.compare(QLatin1String("--protected"), Qt::CaseInsensitive) == 0) {
options.protectedAuthenticationPath = true;
- } else if (argument.compare(QLatin1String("--jarsigner"), Qt::CaseInsensitive) == 0) {
- options.jarSigner = true;
} else if (argument.compare(QLatin1String("--aux-mode"), Qt::CaseInsensitive) == 0) {
options.auxMode = true;
}
@@ -597,8 +593,7 @@ void printHelp()
" --internalsf: Include the .SF file inside the signature block.\n"
" --sectionsonly: Don't compute hash of entire manifest.\n"
" --protected: Keystore has protected authentication path.\n"
- " --jarsigner: Force jarsigner usage, otherwise apksigner will be\n"
- " used if available.\n"
+ " --jarsigner: Deprecated, ignored.\n"
" --jdk <path/to/jdk>: Used to find the jarsigner tool when used\n"
" in combination with the --release argument. By default,\n"
" an attempt is made to detect the tool using the JAVA_HOME and\n"
@@ -894,6 +889,30 @@ bool readInputFile(Options *options)
}
{
+ const QString ndkPropertiesPath = options->ndkPath + QStringLiteral("/source.properties");
+ QFile file(ndkPropertiesPath);
+ if (file.open(QIODevice::ReadOnly | QIODevice::Text)) {
+ const char pkgRevisionKey[] = "Pkg.Revision";
+ while (!file.atEnd()) {
+ const QByteArray line = file.readLine();
+ if (line.startsWith(pkgRevisionKey)) {
+ const QList<QByteArray> parts = line.split('=');
+ if (parts.size() == 2 && parts.at(0).trimmed() == QByteArray(pkgRevisionKey)) {
+ options->ndkVersion = QString::fromLocal8Bit(parts.at(1).trimmed());
+ break;
+ }
+ }
+ }
+ }
+
+ if (options->ndkVersion.isEmpty()) {
+ fprintf(stderr, "Couldn't retrieve the NDK version from \"%s\".\n",
+ qPrintable(ndkPropertiesPath));
+ return false;
+ }
+ }
+
+ {
const QJsonValue toolchainPrefix = jsonObject.value(QLatin1String("toolchain-prefix"));
if (toolchainPrefix.isUndefined()) {
fprintf(stderr, "No toolchain prefix defined in json file.\n");
@@ -986,12 +1005,19 @@ bool readInputFile(Options *options)
}
}
} else {
- auto arch = fileArchitecture(*options, path);
- if (!arch.isEmpty()) {
- options->qtDependencies[arch].append(QtDependency(dependency.toString(), path));
- } else if (options->verbose) {
- fprintf(stderr, "Skipping \"%s\", unknown architecture\n", qPrintable(path));
- fflush(stderr);
+ if (dependency.endsWith(QLatin1String(".so"))) {
+ auto arch = fileArchitecture(*options, path);
+ if (!arch.isEmpty()) {
+ options->qtDependencies[arch].append(QtDependency(dependency.toString(), path));
+ } else if (options->verbose) {
+ fprintf(stderr, "Skipping \"%s\", unknown architecture\n", qPrintable(path));
+ fflush(stderr);
+ }
+ } else {
+ if (dependency.endsWith(QLatin1String(".jar")))
+ options->localJars.append(dependency.toString());
+ for (auto arch : options->architectures.keys())
+ options->qtDependencies[arch].append(QtDependency(dependency.toString(), path));
}
}
}
@@ -1292,25 +1318,19 @@ bool updateLibsXml(Options *options)
if (localLibs.isEmpty()) {
QString plugin;
for (const QtDependency &qtDependency : options->qtDependencies[it.key()]) {
- if (qtDependency.relativePath.endsWith(QLatin1String("libqtforandroid.so"))
- || qtDependency.relativePath.endsWith(QLatin1String("libqtforandroidGL.so"))) {
- if (!plugin.isEmpty() && plugin != qtDependency.relativePath) {
- fprintf(stderr, "Both platform plugins libqtforandroid.so and libqtforandroidGL.so included in package. Please include only one.\n");
- return false;
- }
-
+ if (qtDependency.relativePath.contains(QLatin1String("libplugins_platforms_qtforandroid_")))
plugin = qtDependency.relativePath;
- }
+
if (qtDependency.relativePath.contains(QLatin1String("libQt5OpenGL"))
|| qtDependency.relativePath.contains(QLatin1String("libQt5Quick"))) {
options->usesOpenGL |= true;
- break;
}
}
if (plugin.isEmpty()) {
fflush(stdout);
- fprintf(stderr, "No platform plugin, neither libqtforandroid.so or libqtforandroidGL.so, included in package. Please include one.\n");
+ fprintf(stderr, "No platform plugin (libplugins_platforms_qtforandroid.so) included"
+ " in the deployment. Make sure the app links to Qt Gui library.\n");
fflush(stderr);
return false;
}
@@ -1629,7 +1649,7 @@ QStringList getQtLibsFromElf(const Options &options, const QString &fileName)
return QStringList();
}
- readElf = QLatin1String("%1 -needed-libs %2").arg(shellQuote(readElf), shellQuote(fileName));
+ readElf = QLatin1String("%1 --needed-libs %2").arg(shellQuote(readElf), shellQuote(fileName));
FILE *readElfCommand = openProcess(readElf);
if (!readElfCommand) {
@@ -1801,7 +1821,7 @@ bool scanImports(Options *options, QSet<QString> *usedDependencies)
// The qmlimportscanner sometimes outputs paths that do not exist.
if (!info.exists()) {
if (options->verbose)
- fprintf(stdout, " -- Skipping because file does not exist.\n");
+ fprintf(stdout, " -- Skipping because path does not exist.\n");
continue;
}
@@ -1811,7 +1831,7 @@ bool scanImports(Options *options, QSet<QString> *usedDependencies)
if (absolutePath.startsWith(rootPath)) {
if (options->verbose)
- fprintf(stdout, " -- Skipping because file is in QML root path.\n");
+ fprintf(stdout, " -- Skipping because path is in QML root path.\n");
continue;
}
@@ -2260,9 +2280,9 @@ static GradleProperties readGradleProperties(const QString &path)
if (line.trimmed().startsWith('#'))
continue;
- QList<QByteArray> prop(line.split('='));
- if (prop.size() > 1)
- properties[prop.at(0).trimmed()] = prop.at(1).trimmed();
+ const int idx = line.indexOf('=');
+ if (idx > -1)
+ properties[line.left(idx).trimmed()] = line.mid(idx + 1).trimmed();
}
file.close();
return properties;
@@ -2270,15 +2290,16 @@ static GradleProperties readGradleProperties(const QString &path)
static bool mergeGradleProperties(const QString &path, GradleProperties properties)
{
- QFile::remove(path + QLatin1Char('~'));
- QFile::rename(path, path + QLatin1Char('~'));
+ const QString oldPathStr = path + QLatin1Char('~');
+ QFile::remove(oldPathStr);
+ QFile::rename(path, oldPathStr);
QFile file(path);
if (!file.open(QIODevice::Truncate | QIODevice::WriteOnly | QIODevice::Text)) {
fprintf(stderr, "Can't open file: %s for writing\n", qPrintable(file.fileName()));
return false;
}
- QFile oldFile(path + QLatin1Char('~'));
+ QFile oldFile(oldPathStr);
if (oldFile.open(QIODevice::ReadOnly)) {
while (!oldFile.atEnd()) {
QByteArray line(oldFile.readLine());
@@ -2294,6 +2315,7 @@ static bool mergeGradleProperties(const QString &path, GradleProperties properti
file.write(line);
}
oldFile.close();
+ QFile::remove(oldPathStr);
}
for (GradleProperties::const_iterator it = properties.begin(); it != properties.end(); ++it)
@@ -2324,26 +2346,88 @@ void checkAndWarnGradleLongPaths(const QString &outputDirectory)
}
#endif
+struct GradleFlags {
+ bool setsLegacyPackaging = false;
+ bool usesIntegerCompileSdkVersion = false;
+};
+
+GradleFlags gradleBuildFlags(const QString &path)
+{
+ GradleFlags flags;
+
+ QFile file(path);
+ if (!file.open(QIODevice::ReadOnly))
+ return flags;
+
+ auto isComment = [](const QByteArray &line) {
+ const auto trimmed = line.trimmed();
+ return trimmed.startsWith("//") || trimmed.startsWith('*') || trimmed.startsWith("/*");
+ };
+
+ const auto lines = file.readAll().split('\n');
+ for (const auto &line : lines) {
+ if (isComment(line))
+ continue;
+ if (line.contains("useLegacyPackaging")) {
+ flags.setsLegacyPackaging = true;
+ } else if (line.contains("compileSdkVersion androidCompileSdkVersion.toInteger()")) {
+ flags.usesIntegerCompileSdkVersion = true;
+ }
+ }
+
+ return flags;
+}
+
bool buildAndroidProject(const Options &options)
{
GradleProperties localProperties;
localProperties["sdk.dir"] = QDir::fromNativeSeparators(options.sdkPath).toUtf8();
- localProperties["ndk.dir"] = QDir::fromNativeSeparators(options.ndkPath).toUtf8();
-
- if (!mergeGradleProperties(options.outputDirectory + QLatin1String("local.properties"), localProperties))
+ const QString localPropertiesPath = options.outputDirectory + QLatin1String("local.properties");
+ if (!mergeGradleProperties(localPropertiesPath, localProperties))
return false;
- QString gradlePropertiesPath = options.outputDirectory + QLatin1String("gradle.properties");
+ const QString gradlePropertiesPath = options.outputDirectory + QLatin1String("gradle.properties");
GradleProperties gradleProperties = readGradleProperties(gradlePropertiesPath);
- gradleProperties["android.bundle.enableUncompressedNativeLibs"] = "false";
+
+ const QString gradleBuildFilePath = options.outputDirectory + QLatin1String("build.gradle");
+ GradleFlags gradleFlags = gradleBuildFlags(gradleBuildFilePath);
+ if (!gradleFlags.setsLegacyPackaging)
+ gradleProperties["android.bundle.enableUncompressedNativeLibs"] = "false";
+
gradleProperties["buildDir"] = "build";
gradleProperties["qt5AndroidDir"] = (options.qtInstallDirectory + QLatin1String("/src/android/java")).toUtf8();
- gradleProperties["androidCompileSdkVersion"] = options.androidPlatform.split(QLatin1Char('-')).last().toLocal8Bit();
+
+ QByteArray sdkPlatformVersion;
+ // Provide the integer version only if build.gradle explicitly converts to Integer,
+ // to avoid regression to existing projects that build for sdk platform of form android-xx.
+ if (gradleFlags.usesIntegerCompileSdkVersion) {
+ const QByteArray tmp = options.androidPlatform.split(QLatin1Char('-')).last().toLocal8Bit();
+ bool ok;
+ tmp.toInt(&ok);
+ if (ok) {
+ sdkPlatformVersion = tmp;
+ } else {
+ fprintf(stderr, "Warning: Gradle expects SDK platform version to be an integer, "
+ "but the set version is not convertible to an integer.");
+ }
+ }
+
+ if (sdkPlatformVersion.isEmpty())
+ sdkPlatformVersion = options.androidPlatform.toLocal8Bit();
+
+ gradleProperties["androidCompileSdkVersion"] = sdkPlatformVersion;
gradleProperties["qtMinSdkVersion"] = options.minSdkVersion;
gradleProperties["qtTargetSdkVersion"] = options.targetSdkVersion;
+ gradleProperties["androidNdkVersion"] = options.ndkVersion.toUtf8();
if (gradleProperties["androidBuildToolsVersion"].isEmpty())
gradleProperties["androidBuildToolsVersion"] = options.sdkBuildToolsVersion.toLocal8Bit();
-
+ QString abiList;
+ for (auto it = options.architectures.constBegin(); it != options.architectures.constEnd(); ++it) {
+ if (abiList.size())
+ abiList.append(u",");
+ abiList.append(it.key());
+ }
+ gradleProperties["qtTargetAbiList"] = abiList.toLocal8Bit();// armeabi-v7a or arm64-v8a or ...
if (!mergeGradleProperties(gradlePropertiesPath, gradleProperties))
return false;
@@ -2465,7 +2549,7 @@ QString packagePath(const Options &options, PackageType pt)
path += QLatin1String(".aab");
}
}
- return shellQuote(path);
+ return path;
}
bool installApk(const Options &options)
@@ -2530,7 +2614,7 @@ bool copyStdCpp(Options *options)
return copyFileIfNewer(stdCppPath, destinationFile, *options);
}
-bool jarSignerSignPackage(const Options &options)
+bool signAAB(const Options &options)
{
if (options.verbose)
fprintf(stdout, "Signing Android package.\n");
@@ -2589,12 +2673,13 @@ bool jarSignerSignPackage(const Options &options)
if (options.protectedAuthenticationPath)
jarSignerTool += QLatin1String(" -protected");
- auto signPackage = [&](const QString &file) {
+ auto jarSignPackage = [&](const QString &file) {
fprintf(stdout, "Signing file %s\n", qPrintable(file));
fflush(stdout);
- auto command = jarSignerTool + QLatin1String(" %1 %2")
- .arg(file)
- .arg(shellQuote(options.keyStoreAlias));
+ QString command = jarSignerTool
+ + QLatin1String(" %1 %2")
+ .arg(shellQuote(file))
+ .arg(shellQuote(options.keyStoreAlias));
FILE *jarSignerCommand = openProcess(command);
if (jarSignerCommand == 0) {
@@ -2618,52 +2703,9 @@ bool jarSignerSignPackage(const Options &options)
return true;
};
- if (!signPackage(packagePath(options, UnsignedAPK)))
- return false;
- if (options.buildAAB && !signPackage(packagePath(options, AAB)))
- return false;
-
- QString zipAlignTool = options.sdkPath + QLatin1String("/tools/zipalign");
-#if defined(Q_OS_WIN32)
- zipAlignTool += QLatin1String(".exe");
-#endif
-
- if (!QFile::exists(zipAlignTool)) {
- zipAlignTool = options.sdkPath + QLatin1String("/build-tools/") + options.sdkBuildToolsVersion + QLatin1String("/zipalign");
-#if defined(Q_OS_WIN32)
- zipAlignTool += QLatin1String(".exe");
-#endif
- if (!QFile::exists(zipAlignTool)) {
- fprintf(stderr, "zipalign tool not found: %s\n", qPrintable(zipAlignTool));
- return false;
- }
- }
-
- zipAlignTool = QLatin1String("%1%2 -f 4 %3 %4")
- .arg(shellQuote(zipAlignTool),
- options.verbose ? QLatin1String(" -v") : QLatin1String(),
- packagePath(options, UnsignedAPK),
- packagePath(options, SignedAPK));
-
- FILE *zipAlignCommand = openProcess(zipAlignTool);
- if (zipAlignCommand == 0) {
- fprintf(stderr, "Couldn't run zipalign.\n");
+ if (options.buildAAB && !jarSignPackage(packagePath(options, AAB)))
return false;
- }
-
- char buffer[512];
- while (fgets(buffer, sizeof(buffer), zipAlignCommand) != 0)
- fprintf(stdout, "%s", buffer);
-
- int errorCode = pclose(zipAlignCommand);
- if (errorCode != 0) {
- fprintf(stderr, "zipalign command failed.\n");
- if (!options.verbose)
- fprintf(stderr, " -- Run with --verbose for more information.\n");
- return false;
- }
-
- return QFile::remove(packagePath(options, UnsignedAPK));
+ return true;
}
bool signPackage(const Options &options)
@@ -2672,12 +2714,6 @@ bool signPackage(const Options &options)
#if defined(Q_OS_WIN32)
apksignerTool += QLatin1String(".bat");
#endif
-
- if (options.jarSigner || !QFile::exists(apksignerTool))
- return jarSignerSignPackage(options);
-
- // APKs signed with apksigner must not be changed after they're signed, therefore we need to zipalign it before we sign it.
-
QString zipAlignTool = options.sdkPath + QLatin1String("/tools/zipalign");
#if defined(Q_OS_WIN32)
zipAlignTool += QLatin1String(".exe");
@@ -2694,28 +2730,54 @@ bool signPackage(const Options &options)
}
}
- zipAlignTool = QLatin1String("%1%2 -f 4 %3 %4")
- .arg(shellQuote(zipAlignTool),
- options.verbose ? QLatin1String(" -v") : QLatin1String(),
- packagePath(options, UnsignedAPK),
- packagePath(options, SignedAPK));
+ auto zipalignRunner = [](const QString &zipAlignCommandLine) {
+ FILE *zipAlignCommand = openProcess(zipAlignCommandLine);
+ if (zipAlignCommand == 0) {
+ fprintf(stderr, "Couldn't run zipalign.\n");
+ return false;
+ }
+
+ char buffer[512];
+ while (fgets(buffer, sizeof(buffer), zipAlignCommand) != 0)
+ fprintf(stdout, "%s", buffer);
- FILE *zipAlignCommand = openProcess(zipAlignTool);
- if (zipAlignCommand == 0) {
- fprintf(stderr, "Couldn't run zipalign.\n");
- return false;
- }
+ return pclose(zipAlignCommand) == 0;
+ };
- char buffer[512];
- while (fgets(buffer, sizeof(buffer), zipAlignCommand) != 0)
- fprintf(stdout, "%s", buffer);
+ const QString verifyZipAlignCommandLine =
+ QLatin1String("%1%2 -c 4 %3")
+ .arg(shellQuote(zipAlignTool),
+ options.verbose ? QLatin1String(" -v") : QLatin1String(),
+ shellQuote(packagePath(options, UnsignedAPK)));
- int errorCode = pclose(zipAlignCommand);
- if (errorCode != 0) {
- fprintf(stderr, "zipalign command failed.\n");
- if (!options.verbose)
- fprintf(stderr, " -- Run with --verbose for more information.\n");
- return false;
+ if (zipalignRunner(verifyZipAlignCommandLine)) {
+ if (options.verbose)
+ fprintf(stdout, "APK already aligned, copying it for signing.\n");
+
+ if (QFile::exists(packagePath(options, SignedAPK)))
+ QFile::remove(packagePath(options, SignedAPK));
+
+ if (!QFile::copy(packagePath(options, UnsignedAPK), packagePath(options, SignedAPK))) {
+ fprintf(stderr, "Could not copy unsigned APK.\n");
+ return false;
+ }
+ } else {
+ if (options.verbose)
+ fprintf(stdout, "APK not aligned, aligning it for signing.\n");
+
+ const QString zipAlignCommandLine =
+ QLatin1String("%1%2 -f 4 %3 %4")
+ .arg(shellQuote(zipAlignTool),
+ options.verbose ? QLatin1String(" -v") : QLatin1String(),
+ shellQuote(packagePath(options, UnsignedAPK)),
+ shellQuote(packagePath(options, SignedAPK)));
+
+ if (!zipalignRunner(zipAlignCommandLine)) {
+ fprintf(stderr, "zipalign command failed.\n");
+ if (!options.verbose)
+ fprintf(stderr, " -- Run with --verbose for more information.\n");
+ return false;
+ }
}
QString apkSignerCommandLine = QLatin1String("%1 sign --ks %2")
@@ -2733,8 +2795,7 @@ bool signPackage(const Options &options)
if (options.verbose)
apkSignerCommandLine += QLatin1String(" --verbose");
- apkSignerCommandLine += QLatin1String(" %1")
- .arg(packagePath(options, SignedAPK));
+ apkSignerCommandLine += QLatin1String(" %1").arg(shellQuote(packagePath(options, SignedAPK)));
auto apkSignerRunner = [&] {
FILE *apkSignerCommand = openProcess(apkSignerCommandLine);
@@ -2747,7 +2808,7 @@ bool signPackage(const Options &options)
while (fgets(buffer, sizeof(buffer), apkSignerCommand) != 0)
fprintf(stdout, "%s", buffer);
- errorCode = pclose(apkSignerCommand);
+ int errorCode = pclose(apkSignerCommand);
if (errorCode != 0) {
fprintf(stderr, "apksigner command failed.\n");
if (!options.verbose)
@@ -2761,8 +2822,12 @@ bool signPackage(const Options &options)
if (!apkSignerRunner())
return false;
- apkSignerCommandLine = QLatin1String("%1 verify --verbose %2")
- .arg(shellQuote(apksignerTool), packagePath(options, SignedAPK));
+ apkSignerCommandLine =
+ QLatin1String("%1 verify --verbose %2")
+ .arg(shellQuote(apksignerTool), shellQuote(packagePath(options, SignedAPK)));
+
+ if (options.buildAAB && !signAAB(options))
+ return false;
// Verify the package and remove the unsigned apk
return apkSignerRunner() && QFile::remove(packagePath(options, UnsignedAPK));
diff --git a/src/tools/bootstrap/bootstrap.pro b/src/tools/bootstrap/bootstrap.pro
index c212ccbb6f..24862a07db 100644
--- a/src/tools/bootstrap/bootstrap.pro
+++ b/src/tools/bootstrap/bootstrap.pro
@@ -172,5 +172,7 @@ win32 {
load(qt_module)
+CONFIG -= create_cmake
+
lib.CONFIG = dummy_install
INSTALLS += lib
diff --git a/src/tools/moc/generator.cpp b/src/tools/moc/generator.cpp
index 7264b5bf66..e8b1d2fb6a 100644
--- a/src/tools/moc/generator.cpp
+++ b/src/tools/moc/generator.cpp
@@ -1207,7 +1207,7 @@ void Generator::generateStaticMetacall()
} else {
fprintf(out, " auto *_t = reinterpret_cast<%s *>(_o);\n", cdef->classname.constData());
}
- fprintf(out, " Q_UNUSED(_t)\n");
+ fprintf(out, " (void)_t;\n");
fprintf(out, " switch (_id) {\n");
for (int methodindex = 0; methodindex < methodList.size(); ++methodindex) {
const FunctionDef &f = methodList.at(methodindex);
@@ -1313,7 +1313,7 @@ void Generator::generateStaticMetacall()
fprintf(out, " }\n }\n");
}
if (!anythingUsed)
- fprintf(out, " Q_UNUSED(result);\n");
+ fprintf(out, " (void)result;\n");
fprintf(out, " }");
needElse = true;
}
@@ -1372,7 +1372,7 @@ void Generator::generateStaticMetacall()
} else {
fprintf(out, " auto *_t = reinterpret_cast<%s *>(_o);\n", cdef->classname.constData());
}
- fprintf(out, " Q_UNUSED(_t)\n");
+ fprintf(out, " (void)_t;\n");
if (needTempVarForGet)
fprintf(out, " void *_v = _a[0];\n");
fprintf(out, " switch (_id) {\n");
@@ -1418,7 +1418,7 @@ void Generator::generateStaticMetacall()
} else {
fprintf(out, " auto *_t = reinterpret_cast<%s *>(_o);\n", cdef->classname.constData());
}
- fprintf(out, " Q_UNUSED(_t)\n");
+ fprintf(out, " (void)_t;\n");
fprintf(out, " void *_v = _a[0];\n");
fprintf(out, " switch (_id) {\n");
for (int propindex = 0; propindex < cdef->propertyList.size(); ++propindex) {
@@ -1474,7 +1474,7 @@ void Generator::generateStaticMetacall()
} else {
fprintf(out, " %s *_t = reinterpret_cast<%s *>(_o);\n", cdef->classname.constData(), cdef->classname.constData());
}
- fprintf(out, " Q_UNUSED(_t)\n");
+ fprintf(out, " (void)_t;\n");
fprintf(out, " switch (_id) {\n");
for (int propindex = 0; propindex < cdef->propertyList.size(); ++propindex) {
const PropertyDef &p = cdef->propertyList.at(propindex);
@@ -1499,14 +1499,14 @@ void Generator::generateStaticMetacall()
fprintf(out, "\n");
if (methodList.isEmpty()) {
- fprintf(out, " Q_UNUSED(_o);\n");
+ fprintf(out, " (void)_o;\n");
if (cdef->constructorList.isEmpty() && automaticPropertyMetaTypes.isEmpty() && methodsWithAutomaticTypesHelper(methodList).isEmpty()) {
- fprintf(out, " Q_UNUSED(_id);\n");
- fprintf(out, " Q_UNUSED(_c);\n");
+ fprintf(out, " (void)_id;\n");
+ fprintf(out, " (void)_c;\n");
}
}
if (!isUsed_a)
- fprintf(out, " Q_UNUSED(_a);\n");
+ fprintf(out, " (void)_a;\n");
fprintf(out, "}\n\n");
}
diff --git a/src/tools/moc/moc.cpp b/src/tools/moc/moc.cpp
index edc72f0869..27a68fe9b5 100644
--- a/src/tools/moc/moc.cpp
+++ b/src/tools/moc/moc.cpp
@@ -219,6 +219,7 @@ Type Moc::parseType()
case DOUBLE:
case VOID:
case BOOL:
+ case AUTO:
type.name += lexem();
isVoid |= (lookup(0) == VOID);
break;
@@ -261,6 +262,12 @@ Type Moc::parseType()
return type;
}
+enum class IncludeState {
+ IncludeBegin,
+ IncludeEnd,
+ NoInclude,
+};
+
bool Moc::parseEnum(EnumDef *def)
{
bool isTypdefEnum = false; // typedef enum { ... } Foo;
@@ -281,18 +288,27 @@ bool Moc::parseEnum(EnumDef *def)
}
if (!test(LBRACE))
return false;
- auto handleInclude = [this]() {
- if (test(MOC_INCLUDE_BEGIN))
+ auto handleInclude = [this]() -> IncludeState {
+ bool hadIncludeBegin = false;
+ if (test(MOC_INCLUDE_BEGIN)) {
currentFilenames.push(symbol().unquotedLexem());
+ // we do not return early to handle empty headers in one go
+ hadIncludeBegin = true;
+ }
if (test(NOTOKEN)) {
next(MOC_INCLUDE_END);
currentFilenames.pop();
+ return IncludeState::IncludeEnd;
}
+ if (hadIncludeBegin)
+ return IncludeState::IncludeBegin;
+ else
+ return IncludeState::NoInclude;
};
do {
+ handleInclude();
if (lookup() == RBRACE) // accept trailing comma
break;
- handleInclude();
next(IDENTIFIER);
def->values += lexem();
handleInclude();
@@ -442,15 +458,6 @@ bool Moc::parseFunction(FunctionDef *def, bool inMacro)
scopedFunctionName = tempType.isScoped;
}
- // we don't support references as return types, it's too dangerous
- if (def->type.referenceType == Type::Reference) {
- QByteArray rawName = def->type.rawName;
- def->type = Type("void");
- def->type.rawName = rawName;
- }
-
- def->normalizedType = normalizeType(def->type.name);
-
if (!test(RPAREN)) {
parseFunctionArguments(def);
next(RPAREN);
@@ -473,6 +480,10 @@ bool Moc::parseFunction(FunctionDef *def, bool inMacro)
next(LPAREN);
until(RPAREN);
}
+
+ if (def->type.name == "auto" && test(ARROW))
+ def->type = parseType(); // Parse trailing return-type
+
if (test(SEMIC))
;
else if ((def->inlineCode = test(LBRACE)))
@@ -490,6 +501,22 @@ bool Moc::parseFunction(FunctionDef *def, bool inMacro)
warning(msg.constData());
return false;
}
+
+ QList<QByteArray> typeNameParts = normalizeType(def->type.name).split(' ');
+ if (typeNameParts.contains("auto")) {
+ // We expected a trailing return type but we haven't seen one
+ error("Function declared with auto as return type but missing trailing return type. "
+ "Return type deduction is not supported.");
+ }
+
+ // we don't support references as return types, it's too dangerous
+ if (def->type.referenceType == Type::Reference) {
+ QByteArray rawName = def->type.rawName;
+ def->type = Type("void");
+ def->type.rawName = rawName;
+ }
+
+ def->normalizedType = normalizeType(def->type.name);
return true;
}
diff --git a/src/tools/moc/moc.h b/src/tools/moc/moc.h
index a3e20a061e..531fde70a1 100644
--- a/src/tools/moc/moc.h
+++ b/src/tools/moc/moc.h
@@ -37,7 +37,8 @@
#include <qjsonarray.h>
#include <qjsonobject.h>
#include <stdio.h>
-#include <ctype.h>
+
+#include <private/qtools_p.h>
QT_BEGIN_NAMESPACE
@@ -125,7 +126,7 @@ struct PropertyDef
{
bool stdCppSet() const {
QByteArray s("set");
- s += toupper(name[0]);
+ s += QtMiscUtils::toAsciiUpper(name[0]);
s += name.mid(1);
return (s == write);
}
diff --git a/src/tools/moc/preprocessor.cpp b/src/tools/moc/preprocessor.cpp
index a99b8cc80c..c6e84c0913 100644
--- a/src/tools/moc/preprocessor.cpp
+++ b/src/tools/moc/preprocessor.cpp
@@ -886,7 +886,15 @@ int PP_Expression::multiplicative_expression()
int value = unary_expression();
switch (next()) {
case PP_STAR:
- return value * multiplicative_expression();
+ {
+ // get well behaved overflow behavior by converting to long
+ // and then back to int
+ // NOTE: A conformant preprocessor would need to work intmax_t/
+ // uintmax_t according to [cpp.cond], 19.1 ยง10
+ // But we're not compliant anyway
+ qint64 result = qint64(value) * qint64(multiplicative_expression());
+ return int(result);
+ }
case PP_PERCENT:
{
int remainder = multiplicative_expression();
diff --git a/src/tools/qdbuscpp2xml/qdbuscpp2xml.cpp b/src/tools/qdbuscpp2xml/qdbuscpp2xml.cpp
index 768594efb4..56926ec017 100644
--- a/src/tools/qdbuscpp2xml/qdbuscpp2xml.cpp
+++ b/src/tools/qdbuscpp2xml/qdbuscpp2xml.cpp
@@ -61,7 +61,7 @@ static const char docTypeHeader[] =
#define PROGRAMNAME "qdbuscpp2xml"
#define PROGRAMVERSION "0.2"
-#define PROGRAMCOPYRIGHT "Copyright (C) 2020 The Qt Company Ltd."
+#define PROGRAMCOPYRIGHT "Copyright (C) 2023 The Qt Company Ltd."
static QString outputFile;
static int flags;
diff --git a/src/tools/qdbusxml2cpp/qdbusxml2cpp.cpp b/src/tools/qdbusxml2cpp/qdbusxml2cpp.cpp
index 9825596f3d..d83a79e808 100644
--- a/src/tools/qdbusxml2cpp/qdbusxml2cpp.cpp
+++ b/src/tools/qdbusxml2cpp/qdbusxml2cpp.cpp
@@ -46,7 +46,7 @@
#define PROGRAMNAME "qdbusxml2cpp"
#define PROGRAMVERSION "0.8"
-#define PROGRAMCOPYRIGHT "Copyright (C) 2020 The Qt Company Ltd."
+#define PROGRAMCOPYRIGHT "Copyright (C) 2023 The Qt Company Ltd."
#define ANNOTATION_NO_WAIT "org.freedesktop.DBus.Method.NoReply"
diff --git a/src/tools/uic/python/pythonwriteimports.cpp b/src/tools/uic/python/pythonwriteimports.cpp
index f8d5e96729..b1652874b2 100644
--- a/src/tools/uic/python/pythonwriteimports.cpp
+++ b/src/tools/uic/python/pythonwriteimports.cpp
@@ -39,9 +39,9 @@
QT_BEGIN_NAMESPACE
static const char *standardImports =
-R"I(from PySide2.QtCore import *
-from PySide2.QtGui import *
-from PySide2.QtWidgets import *
+R"I(from PySide2.QtCore import * # type: ignore
+from PySide2.QtGui import * # type: ignore
+from PySide2.QtWidgets import * # type: ignore
)I";
// Change the name of a qrc file "dir/foo.qrc" file to the Python