diff options
Diffstat (limited to 'src')
243 files changed, 23698 insertions, 380 deletions
diff --git a/src/app/qbs-setup-toolchains/clangclprobe.cpp b/src/app/qbs-setup-toolchains/clangclprobe.cpp index 5c2a87731..816d28546 100644 --- a/src/app/qbs-setup-toolchains/clangclprobe.cpp +++ b/src/app/qbs-setup-toolchains/clangclprobe.cpp @@ -60,9 +60,9 @@ using qbs::Internal::Tr; namespace { -QString getToolchainInstallPath(const QString &compilerFilePath) +QString getToolchainInstallPath(const QFileInfo &compiler) { - return QFileInfo(compilerFilePath).path(); // 1 level up + return compiler.path(); // 1 level up } Profile createProfileHelper( @@ -159,19 +159,19 @@ QString findClangCl() } // namespace -void createClangClProfile( - const QString &profileName, const QString &compilerFilePath, Settings *settings) +void createClangClProfile(const QFileInfo &compiler, Settings *settings, + const QString &profileName) { const auto compilerName = QStringLiteral("clang-cl"); const auto vcvarsallPath = findCompatibleVcsarsallBat(); if (vcvarsallPath.isEmpty()) { qbsWarning() << Tr::tr("%1 requires installed Visual Studio 2017 or newer, but none was found.") - .arg(compilerName); + .arg(compilerName); return; } - const auto toolchainInstallPath = getToolchainInstallPath(compilerFilePath); + const auto toolchainInstallPath = getToolchainInstallPath(compiler); const auto hostArch = QString::fromStdString(HostOsInfo::hostOSArchitecture()); createProfileHelper(settings, profileName, toolchainInstallPath, vcvarsallPath, hostArch); } @@ -184,12 +184,12 @@ void clangClProbe(Settings *settings, QList<Profile> &profiles) { const auto compilerName = QStringLiteral("clang-cl"); qbsInfo() << Tr::tr("Trying to detect %1...").arg(compilerName); - const auto compilerFilePath = findClangCl(); + const QString compilerFilePath = findClangCl(); if (compilerFilePath.isEmpty()) { qbsInfo() << Tr::tr("%1 was not found.").arg(compilerName); return; } - + const QFileInfo compiler(compilerFilePath); const auto vcvarsallPath = findCompatibleVcsarsallBat(); if (vcvarsallPath.isEmpty()) { qbsWarning() @@ -202,7 +202,7 @@ void clangClProbe(Settings *settings, QList<Profile> &profiles) QStringLiteral("x86_64"), QStringLiteral("x86") }; - const auto toolchainInstallPath = getToolchainInstallPath(compilerFilePath); + const auto toolchainInstallPath = getToolchainInstallPath(compiler); for (const auto &arch: architectures) { const auto profileName = QStringLiteral("clang-cl-%1").arg(arch); auto profile = createProfileHelper( diff --git a/src/app/qbs-setup-toolchains/clangclprobe.h b/src/app/qbs-setup-toolchains/clangclprobe.h index 1e7724fbf..1afbbb1b8 100644 --- a/src/app/qbs-setup-toolchains/clangclprobe.h +++ b/src/app/qbs-setup-toolchains/clangclprobe.h @@ -37,19 +37,23 @@ ** ****************************************************************************/ -#ifndef CLANGCLPROBE_H -#define CLANGCLPROBE_H +#ifndef QBS_SETUPTOOLCHAINS_CLANGCLPROBE_H +#define QBS_SETUPTOOLCHAINS_CLANGCLPROBE_H #include <QtCore/qlist.h> +QT_BEGIN_NAMESPACE +class QFileInfo; +QT_END_NAMESPACE + namespace qbs { class Profile; class Settings; } -void createClangClProfile( - const QString &profileName, const QString &compilerFilePath, qbs::Settings *settings); +void createClangClProfile(const QFileInfo &compiler, qbs::Settings *settings, + const QString &profileName); void clangClProbe(qbs::Settings *settings, QList<qbs::Profile> &profiles); -#endif // CLANGCLPROBE_H +#endif // Header guard diff --git a/src/app/qbs-setup-toolchains/commandlineparser.h b/src/app/qbs-setup-toolchains/commandlineparser.h index 9d5b0c246..0616f068e 100644 --- a/src/app/qbs-setup-toolchains/commandlineparser.h +++ b/src/app/qbs-setup-toolchains/commandlineparser.h @@ -36,6 +36,7 @@ ** $QT_END_LICENSE$ ** ****************************************************************************/ + #ifndef QBS_SETUPTOOLCHAINS_COMMANDLINEPARSER_H #define QBS_SETUPTOOLCHAINS_COMMANDLINEPARSER_H @@ -75,4 +76,4 @@ private: QString m_command; }; -#endif // Include guard +#endif // Header guard diff --git a/src/app/qbs-setup-toolchains/gccprobe.cpp b/src/app/qbs-setup-toolchains/gccprobe.cpp new file mode 100644 index 000000000..a8482f8d0 --- /dev/null +++ b/src/app/qbs-setup-toolchains/gccprobe.cpp @@ -0,0 +1,515 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qbs. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "probe.h" +#include "gccprobe.h" + +#include "../shared/logging/consolelogger.h" + +#include <logging/translator.h> + +#include <tools/hostosinfo.h> +#include <tools/profile.h> +#include <tools/settings.h> +#include <tools/toolchains.h> + +#include <QtCore/qdir.h> +#include <QtCore/qprocess.h> + +#include <algorithm> + +using namespace qbs; +using Internal::HostOsInfo; +using Internal::Tr; + +static QString qsystem(const QString &exe, const QStringList &args = QStringList()) +{ + QProcess p; + p.setProcessChannelMode(QProcess::MergedChannels); + p.start(exe, args); + if (!p.waitForStarted()) { + throw qbs::ErrorInfo(Tr::tr("Failed to start compiler '%1': %2") + .arg(exe, p.errorString())); + } + if (!p.waitForFinished(-1) || p.exitCode() != 0) + throw qbs::ErrorInfo(Tr::tr("Failed to run compiler '%1': %2") + .arg(exe, p.errorString())); + return QString::fromLocal8Bit(p.readAll()); +} + +static QStringList validMinGWMachines() +{ + // List of MinGW machine names (gcc -dumpmachine) recognized by Qbs + return {QStringLiteral("mingw32"), + QStringLiteral("mingw64"), + QStringLiteral("i686-w64-mingw32"), + QStringLiteral("x86_64-w64-mingw32"), + QStringLiteral("i686-w64-mingw32.shared"), + QStringLiteral("x86_64-w64-mingw32.shared"), + QStringLiteral("i686-w64-mingw32.static"), + QStringLiteral("x86_64-w64-mingw32.static"), + QStringLiteral("i586-mingw32msvc"), + QStringLiteral("amd64-mingw32msvc")}; +} + +static QString gccMachineName(const QFileInfo &compiler) +{ + return qsystem(compiler.absoluteFilePath(), {QStringLiteral("-dumpmachine")}) + .trimmed(); +} + +static QStringList standardCompilerFileNames() +{ + return {HostOsInfo::appendExecutableSuffix(QStringLiteral("gcc")), + HostOsInfo::appendExecutableSuffix(QStringLiteral("g++")), + HostOsInfo::appendExecutableSuffix(QStringLiteral("clang")), + HostOsInfo::appendExecutableSuffix(QStringLiteral("clang++"))}; +} + +class ToolchainDetails +{ +public: + explicit ToolchainDetails(const QFileInfo &compiler) + { + auto baseName = compiler.completeBaseName(); + if (baseName.contains(QRegExp(QLatin1String("\\d$")))) { + const auto dashIndex = baseName.lastIndexOf(QLatin1Char('-')); + version = baseName.mid(dashIndex + 1); + baseName = baseName.left(dashIndex); + } + + const auto dashIndex = baseName.lastIndexOf(QLatin1Char('-')); + suffix = baseName.mid(dashIndex + 1); + prefix = baseName.left(dashIndex + 1); + } + + QString prefix; + QString suffix; + QString version; +}; + +static void setCommonProperties(Profile &profile, const QFileInfo &compiler, + const QStringList &toolchainTypes, const ToolchainDetails &details) +{ + if (toolchainTypes.contains(QStringLiteral("mingw"))) + profile.setValue(QStringLiteral("qbs.targetPlatform"), + QStringLiteral("windows")); + + if (!details.prefix.isEmpty()) + profile.setValue(QStringLiteral("cpp.toolchainPrefix"), details.prefix); + + profile.setValue(QStringLiteral("cpp.toolchainInstallPath"), + compiler.absolutePath()); + profile.setValue(QStringLiteral("qbs.toolchain"), toolchainTypes); + + if (!standardCompilerFileNames().contains( + HostOsInfo::appendExecutableSuffix(details.suffix))) { + qWarning("%s", qPrintable( + QStringLiteral("'%1' is not a standard compiler file name; " + "you must set the cpp.cCompilerName and " + "cpp.cxxCompilerName properties of this profile " + "manually").arg(compiler.fileName()))); + } +} + +class ToolPathSetup +{ +public: + explicit ToolPathSetup(Profile *profile, QString path, ToolchainDetails details) + : m_profile(profile), + m_compilerDirPath(std::move(path)), + m_details(std::move(details)) + { + } + + void apply(const QString &toolName, const QString &propertyName) const + { + // Check for full tool name at first (includes suffix and version). + QString filePath = toolFilePath(toolName, UseFullToolName); + if (filePath.isEmpty()) { + // Check for base tool name at second (without of suffix and version). + filePath = toolFilePath(toolName, UseBaseToolName); + if (filePath.isEmpty()) { + // Check for short tool name at third (only a tool name). + filePath = toolFilePath(toolName, UseOnlyShortToolName); + } + } + + if (filePath.isEmpty()) { + qWarning("%s", qPrintable( + QStringLiteral("'%1' not found in '%2'. " + "Qbs will try to find it in PATH at build time.") + .arg(toolName, m_compilerDirPath))); + } else { + m_profile->setValue(propertyName, filePath); + } + } + +private: + enum ToolNameParts : quint8 { + UseOnlyShortToolName = 0x0, + UseToolPrefix = 0x01, + UseToolSuffix = 0x02, + UseToolVersion = 0x04, + UseFullToolName = UseToolPrefix | UseToolSuffix | UseToolVersion, + UseBaseToolName = UseToolPrefix, + }; + + QString toolFilePath(const QString &toolName, int parts) const + { + QString fileName; + if ((parts & UseToolPrefix) && !m_details.prefix.isEmpty()) + fileName += m_details.prefix; + if ((parts & UseToolSuffix) && !m_details.suffix.isEmpty()) + fileName += m_details.suffix + QLatin1Char('-'); + fileName += toolName; + if ((parts & UseToolVersion) && !m_details.version.isEmpty()) + fileName += QLatin1Char('-') + m_details.version; + + fileName = HostOsInfo::appendExecutableSuffix(fileName); + QString filePath = QDir(m_compilerDirPath).absoluteFilePath(fileName); + if (QFile::exists(filePath)) + return filePath; + return {}; + } + + Profile * const m_profile; + QString m_compilerDirPath; + ToolchainDetails m_details; +}; + +static bool doesProfileTargetOS(const Profile &profile, const QString &os) +{ + const auto target = profile.value(QStringLiteral("qbs.targetPlatform")); + if (target.isValid()) { + return Internal::contains(HostOsInfo::canonicalOSIdentifiers( + target.toString().toStdString()), + os.toStdString()); + } + return Internal::contains(HostOsInfo::hostOSIdentifiers(), os.toStdString()); +} + +static QString buildProfileName(const QFileInfo &cfi) +{ + // We need to replace a dot-separated compiler version string + // with a underscore-separated string, because the profile + // name does not allow a dots. + auto result = cfi.completeBaseName(); + result.replace(QLatin1Char('.'), QLatin1Char('_')); + return result; +} + +static QStringList buildCompilerNameFilters(const QString &compilerName) +{ + QStringList filters = { + // "clang", "gcc" + compilerName, + // "clang-8", "gcc-5" + compilerName + QLatin1String("-[1-9]*"), + // "avr-gcc" + QLatin1String("*-") + compilerName, + // "avr-gcc-5.4.0" + QLatin1String("*-") + compilerName + QLatin1String("-[1-9]*"), + // "arm-none-eabi-gcc" + QLatin1String("*-*-*-") + compilerName, + // "arm-none-eabi-gcc-9.1.0" + QLatin1String("*-*-*-") + compilerName + QLatin1String("-[1-9]*"), + // "x86_64-pc-linux-gnu-gcc" + QLatin1String("*-*-*-*-") + compilerName, + // "x86_64-pc-linux-gnu-gcc-7.4.1" + QLatin1String("*-*-*-*-") + compilerName + QLatin1String("-[1-9]*") + }; + + std::transform(filters.begin(), filters.end(), filters.begin(), + [](const auto &filter) { + return HostOsInfo::appendExecutableSuffix(filter); + }); + + return filters; +} + +static QStringList gnuRegistrySearchPaths() +{ + if (!HostOsInfo::isWindowsHost()) + return {}; + + // Registry token for the "GNU Tools for ARM Embedded Processors". + static const char kRegistryToken[] = "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\" \ + "Windows\\CurrentVersion\\Uninstall\\"; + + QStringList searchPaths; + + QSettings registry(QLatin1String(kRegistryToken), QSettings::NativeFormat); + const auto productGroups = registry.childGroups(); + for (const QString &productKey : productGroups) { + if (!productKey.startsWith( + QLatin1String("GNU Tools for ARM Embedded Processors"))) { + continue; + } + registry.beginGroup(productKey); + QString uninstallFilePath = registry.value( + QLatin1String("UninstallString")).toString(); + if (uninstallFilePath.startsWith(QLatin1Char('"'))) + uninstallFilePath.remove(0, 1); + if (uninstallFilePath.endsWith(QLatin1Char('"'))) + uninstallFilePath.remove(uninstallFilePath.size() - 1, 1); + registry.endGroup(); + + const QString toolkitRootPath = QFileInfo(uninstallFilePath).path(); + const QString toolchainPath = toolkitRootPath + QLatin1String("/bin"); + searchPaths.push_back(toolchainPath); + } + + return searchPaths; +} + +static QStringList atmelRegistrySearchPaths() +{ + if (!HostOsInfo::isWindowsHost()) + return {}; + + // Registry token for the "Atmel" toolchains, e.g. provided by installed + // "Atmel Studio" IDE. + static const char kRegistryToken[] = "HKEY_LOCAL_MACHINE\\SOFTWARE\\Atmel\\"; + + QStringList searchPaths; + QSettings registry(QLatin1String(kRegistryToken), QSettings::NativeFormat); + + // This code enumerate the installed toolchains provided + // by the Atmel Studio v6.x. + const auto toolchainGroups = registry.childGroups(); + for (const QString &toolchainKey : toolchainGroups) { + if (!toolchainKey.endsWith(QLatin1String("GCC"))) + continue; + registry.beginGroup(toolchainKey); + const auto entries = registry.childGroups(); + for (const auto &entryKey : entries) { + registry.beginGroup(entryKey); + const QString installDir = registry.value( + QStringLiteral("Native/InstallDir")).toString(); + const QString version = registry.value( + QStringLiteral("Native/Version")).toString(); + registry.endGroup(); + + QString toolchainPath = installDir + + QLatin1String("/Atmel Toolchain/") + + toolchainKey + QLatin1String("/Native/") + + version; + if (toolchainKey.startsWith(QLatin1String("ARM"))) + toolchainPath += QLatin1String("/arm-gnu-toolchain"); + else if (toolchainKey.startsWith(QLatin1String("AVR32"))) + toolchainPath += QLatin1String("/avr32-gnu-toolchain"); + else if (toolchainKey.startsWith(QLatin1String("AVR8)"))) + toolchainPath += QLatin1String("/avr8-gnu-toolchain"); + else + break; + + toolchainPath += QLatin1String("/bin"); + + if (QFileInfo::exists(toolchainPath)) { + searchPaths.push_back(toolchainPath); + break; + } + } + registry.endGroup(); + } + + // This code enumerate the installed toolchains provided + // by the Atmel Studio v7. + registry.beginGroup(QStringLiteral("AtmelStudio")); + const auto productVersions = registry.childGroups(); + for (const auto &productVersionKey : productVersions) { + registry.beginGroup(productVersionKey); + const QString installDir = registry.value( + QStringLiteral("InstallDir")).toString(); + registry.endGroup(); + + const QStringList knownToolchainSubdirs = { + QStringLiteral("/toolchain/arm/arm-gnu-toolchain/bin/"), + QStringLiteral("/toolchain/avr8/avr8-gnu-toolchain/bin/"), + QStringLiteral("/toolchain/avr32/avr32-gnu-toolchain/bin/"), + }; + + for (const auto &subdir : knownToolchainSubdirs) { + const QString toolchainPath = installDir + subdir; + if (!QFileInfo::exists(toolchainPath)) + continue; + searchPaths.push_back(toolchainPath); + } + } + registry.endGroup(); + + return searchPaths; +} + +Profile createGccProfile(const QFileInfo &compiler, Settings *settings, + const QStringList &toolchainTypes, + const QString &profileName) +{ + const QString machineName = gccMachineName(compiler); + + if (toolchainTypes.contains(QLatin1String("mingw"))) { + if (!validMinGWMachines().contains(machineName)) { + throw ErrorInfo(Tr::tr("Detected gcc platform '%1' is not supported.") + .arg(machineName)); + } + } + + Profile profile(!profileName.isEmpty() ? profileName : machineName, settings); + profile.removeProfile(); + + const ToolchainDetails details(compiler); + + setCommonProperties(profile, compiler, toolchainTypes, details); + + if (HostOsInfo::isWindowsHost() && toolchainTypes.contains(QLatin1String("clang"))) { + const QStringList profileNames = settings->profiles(); + bool foundMingw = false; + for (const QString &profileName : profileNames) { + const Profile otherProfile(profileName, settings); + if (otherProfile.value(QLatin1String("qbs.toolchainType")).toString() + == QLatin1String("mingw") + || otherProfile.value(QLatin1String("qbs.toolchain")) + .toStringList().contains(QLatin1String("mingw"))) { + const QFileInfo tcDir(otherProfile.value(QLatin1String("cpp.toolchainInstallPath")) + .toString()); + if (!tcDir.fileName().isEmpty() && tcDir.exists()) { + profile.setValue(QLatin1String("qbs.sysroot"), tcDir.path()); + foundMingw = true; + break; + } + } + } + if (!foundMingw) { + qbsWarning() << Tr::tr("Using clang on Windows requires a mingw installation. " + "Please set qbs.sysroot accordingly for profile '%1'.") + .arg(profile.name()); + } + } + + if (!toolchainTypes.contains(QLatin1String("clang"))) { + // Check whether auxiliary tools reside within the toolchain's install path. + // This might not be the case when using icecc or another compiler wrapper. + const QString compilerDirPath = compiler.absolutePath(); + const ToolPathSetup toolPathSetup(&profile, compilerDirPath, details); + toolPathSetup.apply(QStringLiteral("ar"), QStringLiteral("cpp.archiverPath")); + toolPathSetup.apply(QStringLiteral("as"), QStringLiteral("cpp.assemblerPath")); + toolPathSetup.apply(QStringLiteral("nm"), QStringLiteral("cpp.nmPath")); + if (doesProfileTargetOS(profile, QStringLiteral("darwin"))) + toolPathSetup.apply(QStringLiteral("dsymutil"), + QStringLiteral("cpp.dsymutilPath")); + else + toolPathSetup.apply(QStringLiteral("objcopy"), + QStringLiteral("cpp.objcopyPath")); + toolPathSetup.apply(QStringLiteral("strip"), + QStringLiteral("cpp.stripPath")); + } + + qbsInfo() << Tr::tr("Profile '%1' created for '%2'.") + .arg(profile.name(), compiler.absoluteFilePath()); + return profile; +} + +void gccProbe(Settings *settings, QList<Profile> &profiles, const QString &compilerName) +{ + qbsInfo() << Tr::tr("Trying to detect %1...").arg(compilerName); + + QStringList searchPaths; + searchPaths << systemSearchPaths() << gnuRegistrySearchPaths() + << atmelRegistrySearchPaths(); + + std::vector<QFileInfo> candidates; + const auto filters = buildCompilerNameFilters(compilerName); + for (const auto &searchPath : searchPaths) { + const QDir dir(searchPath); + const QStringList fileNames = dir.entryList( + filters, QDir::Files | QDir::Executable); + for (const QString &fileName : fileNames) { + // Ignore unexpected compiler names. + if (fileName.startsWith(QLatin1String("c89-gcc")) + || fileName.startsWith(QLatin1String("c99-gcc"))) { + continue; + } + const QFileInfo candidate = dir.filePath(fileName); + // Filter duplicates. + const auto existingEnd = candidates.end(); + const auto existingIt = std::find_if( + candidates.begin(), existingEnd, + [candidate](const QFileInfo &existing) { + return isSameExecutable(candidate.absoluteFilePath(), + existing.absoluteFilePath()); + }); + if (existingIt == existingEnd) { + // No duplicates are found, just add a new candidate. + candidates.push_back(candidate); + } else { + // Replace the existing entry if a candidate name more than + // an existing name. + const auto candidateName = candidate.completeBaseName(); + const auto existingName = existingIt->completeBaseName(); + if (candidateName > existingName) + *existingIt = candidate; + } + } + } + + if (candidates.empty()) { + qbsInfo() << Tr::tr("No %1 toolchains found.").arg(compilerName); + return; + } + + // Sort candidates so that mingw comes first. Information from mingw profiles is potentially + // used for setting up clang profiles. + if (HostOsInfo::isWindowsHost()) { + std::sort(candidates.begin(), candidates.end(), + [](const QFileInfo &fi1, const QFileInfo &fi2) { + return fi1.absoluteFilePath().contains(QLatin1String("mingw")) + && !fi2.absoluteFilePath().contains(QLatin1String("mingw")); + }); + } + + for (const auto &candidate : qAsConst(candidates)) { + const QStringList toolchainTypes = toolchainTypeFromCompilerName( + candidate.baseName()); + const QString profileName = buildProfileName(candidate); + auto profile = createGccProfile(candidate, settings, + toolchainTypes, profileName); + profiles.push_back(std::move(profile)); + } +} diff --git a/src/app/qbs-setup-toolchains/gccprobe.h b/src/app/qbs-setup-toolchains/gccprobe.h new file mode 100644 index 000000000..4344c5836 --- /dev/null +++ b/src/app/qbs-setup-toolchains/gccprobe.h @@ -0,0 +1,62 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qbs. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QBS_SETUPTOOLCHAINS_GCCPROBE_H +#define QBS_SETUPTOOLCHAINS_GCCPROBE_H + +#include <QtCore/qlist.h> + +QT_BEGIN_NAMESPACE +class QFileInfo; +QT_END_NAMESPACE + +namespace qbs { +class Profile; +class Settings; +} + +qbs::Profile createGccProfile(const QFileInfo &compiler, + qbs::Settings *settings, + const QStringList &toolchainTypes, + const QString &profileName = QString()); + +void gccProbe(qbs::Settings *settings, QList<qbs::Profile> &profiles, + const QString &compilerName); + +#endif // Header guard diff --git a/src/app/qbs-setup-toolchains/iarewprobe.cpp b/src/app/qbs-setup-toolchains/iarewprobe.cpp index 5d3785759..47592b9c0 100644 --- a/src/app/qbs-setup-toolchains/iarewprobe.cpp +++ b/src/app/qbs-setup-toolchains/iarewprobe.cpp @@ -47,9 +47,9 @@ #include <tools/hostosinfo.h> #include <tools/profile.h> -#include <QtCore/qfileinfo.h> -#include <QtCore/qlist.h> +#include <QtCore/qprocess.h> #include <QtCore/qsettings.h> +#include <QtCore/qstandardpaths.h> using namespace qbs; using Internal::Tr; @@ -57,7 +57,9 @@ using Internal::HostOsInfo; static QStringList knownIarCompilerNames() { - return {QStringLiteral("icc8051"), QStringLiteral("iccarm"), QStringLiteral("iccavr")}; + return {QStringLiteral("icc8051"), QStringLiteral("iccarm"), + QStringLiteral("iccavr"), QStringLiteral("iccstm8"), + QStringLiteral("icc430")}; } static QString guessIarArchitecture(const QFileInfo &compiler) @@ -69,17 +71,31 @@ static QString guessIarArchitecture(const QFileInfo &compiler) return QStringLiteral("arm"); if (baseName == QLatin1String("iccavr")) return QStringLiteral("avr"); + if (baseName == QLatin1String("iccstm8")) + return QStringLiteral("stm8"); + if (baseName == QLatin1String("icc430")) + return QStringLiteral("msp430"); return {}; } -static Profile createIarProfileHelper(const QFileInfo &compiler, Settings *settings, +static Profile createIarProfileHelper(const ToolchainInstallInfo &info, + Settings *settings, QString profileName = QString()) { + const QFileInfo compiler = info.compilerPath; const QString architecture = guessIarArchitecture(compiler); // In case the profile is auto-detected. - if (profileName.isEmpty()) - profileName = QLatin1String("iar-") + architecture; + if (profileName.isEmpty()) { + if (!info.compilerVersion.isValid()) { + profileName = QStringLiteral("iar-unknown-%1").arg(architecture); + } else { + const QString version = info.compilerVersion.toString(QLatin1Char('_'), + QLatin1Char('_')); + profileName = QStringLiteral("iar-%1-%2").arg( + version, architecture); + } + } Profile profile(profileName, settings); profile.setValue(QLatin1String("cpp.toolchainInstallPath"), compiler.absolutePath()); @@ -92,9 +108,53 @@ static Profile createIarProfileHelper(const QFileInfo &compiler, Settings *setti return profile; } -static std::vector<IarInstallInfo> installedIarsFromPath() +static Version dumpIarCompilerVersion(const QFileInfo &compiler) +{ + const QString outFilePath = QStandardPaths::writableLocation(QStandardPaths::TempLocation) + + QLatin1String("/macros.dump"); + const QStringList args = {QStringLiteral("."), + QStringLiteral("--predef_macros"), + outFilePath}; + QProcess p; + p.start(compiler.absoluteFilePath(), args); + p.waitForFinished(3000); + const auto es = p.exitStatus(); + if (es != QProcess::NormalExit) { + const QByteArray out = p.readAll(); + qbsWarning() << Tr::tr("Compiler dumping failed:\n%1") + .arg(QString::fromUtf8(out)); + return Version{}; + } + + QByteArray dump; + QFile out(outFilePath); + if (out.open(QIODevice::ReadOnly)) + dump = out.readAll(); + out.remove(); + + const int verCode = extractVersion(dump, "__VER__ "); + if (verCode < 0) { + qbsWarning() << Tr::tr("No '__VER__' token was found in a compiler dump:\n%1") + .arg(QString::fromUtf8(dump)); + return Version{}; + } + + const QString arch = guessIarArchitecture(compiler); + if (arch == QLatin1String("arm")) { + return Version{verCode / 1000000, (verCode / 1000) % 1000, verCode % 1000}; + } else if (arch == QLatin1String("avr") + || arch == QLatin1String("mcs51") + || arch == QLatin1String("stm8") + || arch == QLatin1String("msp430")) { + return Version{verCode / 100, verCode % 100}; + } + + return Version{}; +} + +static std::vector<ToolchainInstallInfo> installedIarsFromPath() { - std::vector<IarInstallInfo> infos; + std::vector<ToolchainInstallInfo> infos; const auto compilerNames = knownIarCompilerNames(); for (const QString &compilerName : compilerNames) { const QFileInfo iarPath( @@ -102,14 +162,16 @@ static std::vector<IarInstallInfo> installedIarsFromPath() HostOsInfo::appendExecutableSuffix(compilerName))); if (!iarPath.exists()) continue; - infos.push_back({iarPath.absoluteFilePath(), {}}); + const Version version = dumpIarCompilerVersion(iarPath); + infos.push_back({iarPath, version}); } + std::sort(infos.begin(), infos.end()); return infos; } -static std::vector<IarInstallInfo> installedIarsFromRegistry() +static std::vector<ToolchainInstallInfo> installedIarsFromRegistry() { - std::vector<IarInstallInfo> infos; + std::vector<ToolchainInstallInfo> infos; if (HostOsInfo::isWindowsHost()) { @@ -127,6 +189,8 @@ static std::vector<IarInstallInfo> installedIarsFromRegistry() {QStringLiteral("EWARM"), QStringLiteral("\\arm\\bin\\iccarm.exe")}, {QStringLiteral("EWAVR"), QStringLiteral("\\avr\\bin\\iccavr.exe")}, {QStringLiteral("EW8051"), QStringLiteral("\\8051\\bin\\icc8051.exe")}, + {QStringLiteral("EWSTM8"), QStringLiteral("\\stm8\\bin\\iccstm8.exe")}, + {QStringLiteral("EW430"), QStringLiteral("\\430\\bin\\icc430.exe")}, }; QSettings registry(QLatin1String(kRegistryNode), QSettings::NativeFormat); @@ -148,7 +212,7 @@ static std::vector<IarInstallInfo> installedIarsFromRegistry() if (iarPath.exists()) { // Note: threeLevelKey is a guessed toolchain version. const QString version = threeLevelKey; - infos.push_back({iarPath.absoluteFilePath(), version}); + infos.push_back({iarPath, Version::fromString(version)}); } } registry.endGroup(); @@ -161,6 +225,7 @@ static std::vector<IarInstallInfo> installedIarsFromRegistry() } + std::sort(infos.begin(), infos.end()); return infos; } @@ -175,19 +240,25 @@ bool isIarCompiler(const QString &compilerName) void createIarProfile(const QFileInfo &compiler, Settings *settings, QString profileName) { - createIarProfileHelper(compiler, settings, profileName); + const ToolchainInstallInfo info = {compiler, Version{}}; + createIarProfileHelper(info, settings, profileName); } void iarProbe(Settings *settings, QList<Profile> &profiles) { qbsInfo() << Tr::tr("Trying to detect IAR toolchains..."); - std::vector<IarInstallInfo> allInfos = installedIarsFromRegistry(); - const std::vector<IarInstallInfo> pathInfos = installedIarsFromPath(); - allInfos.insert(std::end(allInfos), std::begin(pathInfos), std::end(pathInfos)); + // Make sure that a returned infos are sorted before using the std::set_union! + const std::vector<ToolchainInstallInfo> regInfos = installedIarsFromRegistry(); + const std::vector<ToolchainInstallInfo> pathInfos = installedIarsFromPath(); + std::vector<ToolchainInstallInfo> allInfos; + allInfos.reserve(regInfos.size() + pathInfos.size()); + std::set_union(regInfos.cbegin(), regInfos.cend(), + pathInfos.cbegin(), pathInfos.cend(), + std::back_inserter(allInfos)); - for (const IarInstallInfo &info : allInfos) { - const auto profile = createIarProfileHelper(info.compilerPath, settings); + for (const ToolchainInstallInfo &info : allInfos) { + const auto profile = createIarProfileHelper(info, settings); profiles.push_back(profile); } diff --git a/src/app/qbs-setup-toolchains/iarewprobe.h b/src/app/qbs-setup-toolchains/iarewprobe.h index f5caf61ed..b604d6c6b 100644 --- a/src/app/qbs-setup-toolchains/iarewprobe.h +++ b/src/app/qbs-setup-toolchains/iarewprobe.h @@ -37,8 +37,8 @@ ** ****************************************************************************/ -#ifndef IAREWPROBE_H -#define IAREWPROBE_H +#ifndef QBS_SETUPTOOLCHAINS_IAREWPROBE_H +#define QBS_SETUPTOOLCHAINS_IAREWPROBE_H #include <QtCore/qlist.h> @@ -51,12 +51,6 @@ class Profile; class Settings; } -struct IarInstallInfo -{ - QString compilerPath; - QString version; -}; - bool isIarCompiler(const QString &compilerName); void createIarProfile(const QFileInfo &compiler, qbs::Settings *settings, @@ -64,4 +58,4 @@ void createIarProfile(const QFileInfo &compiler, qbs::Settings *settings, void iarProbe(qbs::Settings *settings, QList<qbs::Profile> &profiles); -#endif // IAREWPROBE_H +#endif // Header guard diff --git a/src/app/qbs-setup-toolchains/keilprobe.cpp b/src/app/qbs-setup-toolchains/keilprobe.cpp index dc327d2ee..08f0f2167 100644 --- a/src/app/qbs-setup-toolchains/keilprobe.cpp +++ b/src/app/qbs-setup-toolchains/keilprobe.cpp @@ -47,9 +47,9 @@ #include <tools/hostosinfo.h> #include <tools/profile.h> -#include <QtCore/qfileinfo.h> -#include <QtCore/qlist.h> +#include <QtCore/qprocess.h> #include <QtCore/qsettings.h> +#include <QtCore/qtemporaryfile.h> using namespace qbs; using Internal::Tr; @@ -70,14 +70,24 @@ static QString guessKeilArchitecture(const QFileInfo &compiler) return {}; } -static Profile createKeilProfileHelper(const QFileInfo &compiler, Settings *settings, +static Profile createKeilProfileHelper(const ToolchainInstallInfo &info, + Settings *settings, QString profileName = QString()) { + const QFileInfo compiler = info.compilerPath; const QString architecture = guessKeilArchitecture(compiler); // In case the profile is auto-detected. - if (profileName.isEmpty()) - profileName = QLatin1String("keil-") + architecture; + if (profileName.isEmpty()) { + if (!info.compilerVersion.isValid()) { + profileName = QStringLiteral("keil-unknown-%1").arg(architecture); + } else { + const QString version = info.compilerVersion.toString(QLatin1Char('_'), + QLatin1Char('_')); + profileName = QStringLiteral("keil-%1-%2").arg( + version, architecture); + } + } Profile profile(profileName, settings); profile.setValue(QStringLiteral("cpp.toolchainInstallPath"), compiler.absolutePath()); @@ -90,9 +100,80 @@ static Profile createKeilProfileHelper(const QFileInfo &compiler, Settings *sett return profile; } -static std::vector<KeilInstallInfo> installedKeilsFromPath() +static Version dumpKeilCompilerVersion(const QFileInfo &compiler) +{ + const QString arch = guessKeilArchitecture(compiler); + if (arch == QLatin1String("mcs51")) { + QTemporaryFile fakeIn; + if (!fakeIn.open()) { + qbsWarning() << Tr::tr("Unable to open temporary file %1 for output: %2") + .arg(fakeIn.fileName(), fakeIn.errorString()); + return Version{}; + } + fakeIn.write("#define VALUE_TO_STRING(x) #x\n"); + fakeIn.write("#define VALUE(x) VALUE_TO_STRING(x)\n"); + fakeIn.write("#define VAR_NAME_VALUE(var) \"\"\"|\"#var\"|\"VALUE(var)\n"); + fakeIn.write("#ifdef __C51__\n"); + fakeIn.write("#pragma message(VAR_NAME_VALUE(__C51__))\n"); + fakeIn.write("#endif\n"); + fakeIn.write("#ifdef __CX51__\n"); + fakeIn.write("#pragma message(VAR_NAME_VALUE(__CX51__))\n"); + fakeIn.write("#endif\n"); + fakeIn.close(); + + const QStringList args = {fakeIn.fileName()}; + QProcess p; + p.start(compiler.absoluteFilePath(), args); + p.waitForFinished(3000); + const auto es = p.exitStatus(); + if (es != QProcess::NormalExit) { + const QByteArray out = p.readAll(); + qbsWarning() << Tr::tr("Compiler dumping failed:\n%1") + .arg(QString::fromUtf8(out)); + return Version{}; + } + + const QByteArray dump = p.readAllStandardOutput(); + const int verCode = extractVersion(dump, "\"__C51__\"|\""); + if (verCode < 0) { + qbsWarning() << Tr::tr("No '__C51__' token was found" + " in the compiler dump:\n%1") + .arg(QString::fromUtf8(dump)); + return Version{}; + } + return Version{verCode / 100, verCode % 100}; + } else if (arch == QLatin1String("arm")) { + const QStringList args = {QStringLiteral("-E"), + QStringLiteral("--list-macros"), + QStringLiteral("nul")}; + QProcess p; + p.start(compiler.absoluteFilePath(), args); + p.waitForFinished(3000); + const auto es = p.exitStatus(); + if (es != QProcess::NormalExit) { + const QByteArray out = p.readAll(); + qbsWarning() << Tr::tr("Compiler dumping failed:\n%1") + .arg(QString::fromUtf8(out)); + return Version{}; + } + + const QByteArray dump = p.readAll(); + const int verCode = extractVersion(dump, "__ARMCC_VERSION "); + if (verCode < 0) { + qbsWarning() << Tr::tr("No '__ARMCC_VERSION' token was found " + "in the compiler dump:\n%1") + .arg(QString::fromUtf8(dump)); + return Version{}; + } + return Version{verCode / 1000000, (verCode / 10000) % 100, verCode % 10000}; + } + + return Version{}; +} + +static std::vector<ToolchainInstallInfo> installedKeilsFromPath() { - std::vector<KeilInstallInfo> infos; + std::vector<ToolchainInstallInfo> infos; const auto compilerNames = knownKeilCompilerNames(); for (const QString &compilerName : compilerNames) { const QFileInfo keilPath( @@ -100,14 +181,16 @@ static std::vector<KeilInstallInfo> installedKeilsFromPath() HostOsInfo::appendExecutableSuffix(compilerName))); if (!keilPath.exists()) continue; - infos.push_back({keilPath.absoluteFilePath(), {}}); + const Version version = dumpKeilCompilerVersion(keilPath); + infos.push_back({keilPath, version}); } + std::sort(infos.begin(), infos.end()); return infos; } -static std::vector<KeilInstallInfo> installedKeilsFromRegistry() +static std::vector<ToolchainInstallInfo> installedKeilsFromRegistry() { - std::vector<KeilInstallInfo> infos; + std::vector<ToolchainInstallInfo> infos; if (HostOsInfo::isWindowsHost()) { @@ -148,7 +231,7 @@ static std::vector<KeilInstallInfo> installedKeilsFromRegistry() .toString(); if (version.startsWith(QLatin1Char('V'))) version.remove(0, 1); - infos.push_back({keilPath.absoluteFilePath(), version}); + infos.push_back({keilPath, Version::fromString(version)}); } } registry.endGroup(); @@ -156,6 +239,7 @@ static std::vector<KeilInstallInfo> installedKeilsFromRegistry() } + std::sort(infos.begin(), infos.end()); return infos; } @@ -170,19 +254,25 @@ bool isKeilCompiler(const QString &compilerName) void createKeilProfile(const QFileInfo &compiler, Settings *settings, QString profileName) { - createKeilProfileHelper(compiler, settings, profileName); + const ToolchainInstallInfo info = {compiler, Version{}}; + createKeilProfileHelper(info, settings, profileName); } void keilProbe(Settings *settings, QList<Profile> &profiles) { qbsInfo() << Tr::tr("Trying to detect KEIL toolchains..."); - std::vector<KeilInstallInfo> allInfos = installedKeilsFromRegistry(); - const std::vector<KeilInstallInfo> pathInfos = installedKeilsFromPath(); - allInfos.insert(std::end(allInfos), std::begin(pathInfos), std::end(pathInfos)); + // Make sure that a returned infos are sorted before using the std::set_union! + const std::vector<ToolchainInstallInfo> regInfos = installedKeilsFromRegistry(); + const std::vector<ToolchainInstallInfo> pathInfos = installedKeilsFromPath(); + std::vector<ToolchainInstallInfo> allInfos; + allInfos.reserve(regInfos.size() + pathInfos.size()); + std::set_union(regInfos.cbegin(), regInfos.cend(), + pathInfos.cbegin(), pathInfos.cend(), + std::back_inserter(allInfos)); - for (const KeilInstallInfo &info : allInfos) { - const auto profile = createKeilProfileHelper(info.compilerPath, settings); + for (const ToolchainInstallInfo &info : allInfos) { + const auto profile = createKeilProfileHelper(info, settings); profiles.push_back(profile); } diff --git a/src/app/qbs-setup-toolchains/keilprobe.h b/src/app/qbs-setup-toolchains/keilprobe.h index 6a897b84b..c7e66ee24 100644 --- a/src/app/qbs-setup-toolchains/keilprobe.h +++ b/src/app/qbs-setup-toolchains/keilprobe.h @@ -37,8 +37,8 @@ ** ****************************************************************************/ -#ifndef KEILPROBE_H -#define KEILPROBE_H +#ifndef QBS_SETUPTOOLCHAINS_KEILPROBE_H +#define QBS_SETUPTOOLCHAINS_KEILPROBE_H #include <QtCore/qlist.h> @@ -51,12 +51,6 @@ class Profile; class Settings; } -struct KeilInstallInfo -{ - QString compilerPath; - QString version; -}; - bool isKeilCompiler(const QString &compilerName); void createKeilProfile(const QFileInfo &compiler, qbs::Settings *settings, @@ -64,4 +58,4 @@ void createKeilProfile(const QFileInfo &compiler, qbs::Settings *settings, void keilProbe(qbs::Settings *settings, QList<qbs::Profile> &profiles); -#endif // KEILPROBE_H +#endif // Header guard diff --git a/src/app/qbs-setup-toolchains/msvcprobe.cpp b/src/app/qbs-setup-toolchains/msvcprobe.cpp index d0b60a7fe..c8108bfd2 100644 --- a/src/app/qbs-setup-toolchains/msvcprobe.cpp +++ b/src/app/qbs-setup-toolchains/msvcprobe.cpp @@ -464,9 +464,10 @@ void msvcProbe(Settings *settings, QList<Profile> &profiles) } } -void createMsvcProfile(const QString &profileName, const QString &compilerFilePath, - Settings *settings) +void createMsvcProfile(const QFileInfo &compiler, Settings *settings, + const QString &profileName) { + const auto compilerFilePath = compiler.absoluteFilePath(); MSVC msvc(compilerFilePath, MSVC::architectureFromClPath(compilerFilePath)); msvc.init(); QList<Profile> dummy; diff --git a/src/app/qbs-setup-toolchains/msvcprobe.h b/src/app/qbs-setup-toolchains/msvcprobe.h index 4fa2cde48..f63dd5dc8 100644 --- a/src/app/qbs-setup-toolchains/msvcprobe.h +++ b/src/app/qbs-setup-toolchains/msvcprobe.h @@ -37,13 +37,17 @@ ** ****************************************************************************/ -#ifndef MSVCPROBE_H -#define MSVCPROBE_H +#ifndef QBS_SETUPTOOLCHAINS_MSVCPROBE_H +#define QBS_SETUPTOOLCHAINS_MSVCPROBE_H #include <QtCore/qlist.h> #include <vector> +QT_BEGIN_NAMESPACE +class QFileInfo; +QT_END_NAMESPACE + namespace qbs { class Profile; class Settings; @@ -59,9 +63,9 @@ struct MSVCInstallInfo std::vector<MSVCInstallInfo> installedMSVCs(); -void createMsvcProfile(const QString &profileName, const QString &compilerFilePath, - qbs::Settings *settings); +void createMsvcProfile(const QFileInfo &compiler, qbs::Settings *settings, + const QString &profileName); void msvcProbe(qbs::Settings *settings, QList<qbs::Profile> &profiles); -#endif // MSVCPROBE_H +#endif // Header guard diff --git a/src/app/qbs-setup-toolchains/probe.cpp b/src/app/qbs-setup-toolchains/probe.cpp index 3fae20a6e..205306acd 100644 --- a/src/app/qbs-setup-toolchains/probe.cpp +++ b/src/app/qbs-setup-toolchains/probe.cpp @@ -39,6 +39,7 @@ #include "probe.h" #include "clangclprobe.h" +#include "gccprobe.h" #include "iarewprobe.h" #include "keilprobe.h" #include "msvcprobe.h" @@ -46,22 +47,26 @@ #include "xcodeprobe.h" #include <logging/translator.h> -#include <tools/architectures.h> #include <tools/error.h> #include <tools/hostosinfo.h> #include <tools/profile.h> -#include <tools/qttools.h> #include <tools/settings.h> #include <tools/toolchains.h> -#include <tools/stlutils.h> #include <QtCore/qdir.h> -#include <QtCore/qfileinfo.h> -#include <QtCore/qprocess.h> -#include <QtCore/qstringlist.h> +#include <QtCore/qoperatingsystemversion.h> #include <QtCore/qtextstream.h> -#include <cstdio> +#ifdef Q_OS_WIN +// We need defines for Windows 8. +#undef _WIN32_WINNT +#define _WIN32_WINNT _WIN32_WINNT_WIN8 + +#include <qt_windows.h> +#include <shlobj.h> +#else +#include <qplatformdefs.h> +#endif // Q_OS_WIN using namespace qbs; using Internal::HostOsInfo; @@ -70,6 +75,11 @@ using Internal::Tr; static QTextStream qStdout(stdout); static QTextStream qStderr(stderr); +QStringList systemSearchPaths() +{ + return QString::fromLocal8Bit(qgetenv("PATH")).split(HostOsInfo::pathListSeparator()); +} + QString findExecutable(const QString &fileName) { QString fullFileName = fileName; @@ -77,8 +87,7 @@ QString findExecutable(const QString &fileName) && !fileName.endsWith(QLatin1String(".exe"), Qt::CaseInsensitive)) { fullFileName += QLatin1String(".exe"); } - const QString path = QString::fromLocal8Bit(qgetenv("PATH")); - const auto ppaths = path.split(HostOsInfo::pathListSeparator()); + const auto ppaths = systemSearchPaths(); for (const QString &ppath : ppaths) { const QString fullPath = ppath + QLatin1Char('/') + fullFileName; if (QFileInfo::exists(fullPath)) @@ -87,31 +96,7 @@ QString findExecutable(const QString &fileName) return {}; } -static QString qsystem(const QString &exe, const QStringList &args = QStringList()) -{ - QProcess p; - p.setProcessChannelMode(QProcess::MergedChannels); - p.start(exe, args); - if (!p.waitForStarted()) { - throw qbs::ErrorInfo(Tr::tr("Failed to start compiler '%1': %2") - .arg(exe, p.errorString())); - } - if (!p.waitForFinished(-1) || p.exitCode() != 0) - throw qbs::ErrorInfo(Tr::tr("Failed to run compiler '%1': %2").arg(exe, p.errorString())); - return QString::fromLocal8Bit(p.readAll()); -} - -static QStringList validMinGWMachines() -{ - // List of MinGW machine names (gcc -dumpmachine) recognized by Qbs - return {QStringLiteral("mingw32"), QStringLiteral("mingw64"), - QStringLiteral("i686-w64-mingw32"), QStringLiteral("x86_64-w64-mingw32"), - QStringLiteral("i686-w64-mingw32.shared"), QStringLiteral("x86_64-w64-mingw32.shared"), - QStringLiteral("i686-w64-mingw32.static"), QStringLiteral("x86_64-w64-mingw32.static"), - QStringLiteral("i586-mingw32msvc"), QStringLiteral("amd64-mingw32msvc")}; -} - -static QStringList toolchainTypeFromCompilerName(const QString &compilerName) +QStringList toolchainTypeFromCompilerName(const QString &compilerName) { if (compilerName == QLatin1String("cl.exe")) return canonicalToolchain(QStringLiteral("msvc")); @@ -134,174 +119,19 @@ static QStringList toolchainTypeFromCompilerName(const QString &compilerName) return {}; } -static QString gccMachineName(const QString &compilerFilePath) -{ - return qsystem(compilerFilePath, QStringList() << QStringLiteral("-dumpmachine")).trimmed(); -} - -static QStringList standardCompilerFileNames() -{ - return {HostOsInfo::appendExecutableSuffix(QStringLiteral("gcc")), - HostOsInfo::appendExecutableSuffix(QStringLiteral("g++")), - HostOsInfo::appendExecutableSuffix(QStringLiteral("clang")), - HostOsInfo::appendExecutableSuffix(QStringLiteral("clang++"))}; -} - -static void setCommonProperties(Profile &profile, const QString &compilerFilePath, - const QStringList &toolchainTypes) -{ - const QFileInfo cfi(compilerFilePath); - const QString compilerName = cfi.fileName(); - - if (toolchainTypes.contains(QStringLiteral("mingw"))) - profile.setValue(QStringLiteral("qbs.targetPlatform"), QStringLiteral("windows")); - - const QString prefix = compilerName.left(compilerName.lastIndexOf(QLatin1Char('-')) + 1); - if (!prefix.isEmpty()) - profile.setValue(QStringLiteral("cpp.toolchainPrefix"), prefix); - - profile.setValue(QStringLiteral("cpp.toolchainInstallPath"), cfi.absolutePath()); - profile.setValue(QStringLiteral("qbs.toolchain"), toolchainTypes); - - const QString suffix = compilerName.right(compilerName.size() - prefix.size()); - if (!standardCompilerFileNames().contains(suffix)) - qWarning("%s", qPrintable( - QStringLiteral("'%1' is not a standard compiler file name; " - "you must set the cpp.cCompilerName and " - "cpp.cxxCompilerName properties of this profile " - "manually").arg(compilerName))); -} - -class ToolPathSetup -{ -public: - ToolPathSetup(Profile *profile, QString path, QString toolchainPrefix) - : m_profile(profile), - m_compilerDirPath(std::move(path)), - m_toolchainPrefix(std::move(toolchainPrefix)) - { - } - - void apply(const QString &toolName, const QString &propertyName) const - { - QString toolFileName = m_toolchainPrefix + HostOsInfo::appendExecutableSuffix(toolName); - if (QFile::exists(m_compilerDirPath + QLatin1Char('/') + toolFileName)) - return; - const QString toolFilePath = findExecutable(toolFileName); - if (toolFilePath.isEmpty()) { - qWarning("%s", qPrintable(QStringLiteral("'%1' exists neither in '%2' nor in PATH.") - .arg(toolFileName, m_compilerDirPath))); - } - m_profile->setValue(propertyName, toolFilePath); - } - -private: - Profile * const m_profile; - QString m_compilerDirPath; - QString m_toolchainPrefix; -}; - -static bool doesProfileTargetOS(const Profile &profile, const QString &os) -{ - const auto target = profile.value(QStringLiteral("qbs.targetPlatform")); - if (target.isValid()) { - return Internal::contains(HostOsInfo::canonicalOSIdentifiers( - target.toString().toStdString()), os.toStdString()); - } - return Internal::contains(HostOsInfo::hostOSIdentifiers(), os.toStdString()); -} - -static Profile createGccProfile(const QString &compilerFilePath, Settings *settings, - const QStringList &toolchainTypes, - const QString &profileName = QString()) -{ - const QString machineName = gccMachineName(compilerFilePath); - - if (toolchainTypes.contains(QLatin1String("mingw"))) { - if (!validMinGWMachines().contains(machineName)) { - throw ErrorInfo(Tr::tr("Detected gcc platform '%1' is not supported.") - .arg(machineName)); - } - } - - Profile profile(!profileName.isEmpty() ? profileName : machineName, settings); - profile.removeProfile(); - setCommonProperties(profile, compilerFilePath, toolchainTypes); - - // Check whether auxiliary tools reside within the toolchain's install path. - // This might not be the case when using icecc or another compiler wrapper. - const QString compilerDirPath = QFileInfo(compilerFilePath).absolutePath(); - const ToolPathSetup toolPathSetup(&profile, compilerDirPath, - profile.value(QStringLiteral("cpp.toolchainPrefix")) - .toString()); - toolPathSetup.apply(QStringLiteral("ar"), QStringLiteral("cpp.archiverPath")); - toolPathSetup.apply(QStringLiteral("as"), QStringLiteral("cpp.assemblerPath")); - toolPathSetup.apply(QStringLiteral("nm"), QStringLiteral("cpp.nmPath")); - if (doesProfileTargetOS(profile, QStringLiteral("darwin"))) - toolPathSetup.apply(QStringLiteral("dsymutil"), QStringLiteral("cpp.dsymutilPath")); - else - toolPathSetup.apply(QStringLiteral("objcopy"), QStringLiteral("cpp.objcopyPath")); - toolPathSetup.apply(QStringLiteral("strip"), QStringLiteral("cpp.stripPath")); - - qStdout << Tr::tr("Profile '%1' created for '%2'.").arg(profile.name(), compilerFilePath) - << endl; - return profile; -} - -static void gccProbe(Settings *settings, QList<Profile> &profiles, const QString &compilerName) -{ - qStdout << Tr::tr("Trying to detect %1...").arg(compilerName) << endl; - - const QString crossCompilePrefix = QString::fromLocal8Bit(qgetenv("CROSS_COMPILE")); - const QString compilerFilePath = findExecutable(crossCompilePrefix + compilerName); - QFileInfo cfi(compilerFilePath); - if (!cfi.exists()) { - qStderr << Tr::tr("%1 not found.").arg(compilerName) << endl; - return; - } - const QString profileName = cfi.completeBaseName(); - const QStringList toolchainTypes = toolchainTypeFromCompilerName(compilerName); - profiles.push_back(createGccProfile(compilerFilePath, settings, toolchainTypes, profileName)); -} - -static void mingwProbe(Settings *settings, QList<Profile> &profiles) -{ - // List of possible compiler binary names for this platform - QStringList compilerNames; - if (HostOsInfo::isWindowsHost()) { - compilerNames << QStringLiteral("gcc"); - } else { - const auto machineNames = validMinGWMachines(); - for (const QString &machineName : machineNames) { - compilerNames << machineName + QLatin1String("-gcc"); - } - } - - for (const QString &compilerName : qAsConst(compilerNames)) { - const QString gccPath - = findExecutable(HostOsInfo::appendExecutableSuffix(compilerName)); - if (!gccPath.isEmpty()) - profiles.push_back(createGccProfile(gccPath, settings, - canonicalToolchain(QStringLiteral("mingw")))); - } -} - void probe(Settings *settings) { QList<Profile> profiles; if (HostOsInfo::isWindowsHost()) { msvcProbe(settings, profiles); clangClProbe(settings, profiles); - } else { - gccProbe(settings, profiles, QStringLiteral("gcc")); - gccProbe(settings, profiles, QStringLiteral("clang")); - - if (HostOsInfo::isMacosHost()) { - xcodeProbe(settings, profiles); - } + } else if (HostOsInfo::isMacosHost()) { + xcodeProbe(settings, profiles); } - mingwProbe(settings, profiles); + gccProbe(settings, profiles, QStringLiteral("gcc")); + gccProbe(settings, profiles, QStringLiteral("clang")); + iarProbe(settings, profiles); keilProbe(settings, profiles); sdccProbe(settings, profiles); @@ -334,11 +164,11 @@ void createProfile(const QString &profileName, const QString &toolchainType, toolchainTypes = canonicalToolchain(toolchainType); if (toolchainTypes.contains(QLatin1String("msvc"))) - createMsvcProfile(profileName, compiler.absoluteFilePath(), settings); + createMsvcProfile(compiler, settings, profileName); else if (toolchainTypes.contains(QLatin1String("clang-cl"))) - createClangClProfile(profileName, compiler.absoluteFilePath(), settings); + createClangClProfile(compiler, settings, profileName); else if (toolchainTypes.contains(QLatin1String("gcc"))) - createGccProfile(compiler.absoluteFilePath(), settings, toolchainTypes, profileName); + createGccProfile(compiler, settings, toolchainTypes, profileName); else if (toolchainTypes.contains(QLatin1String("iar"))) createIarProfile(compiler, settings, profileName); else if (toolchainTypes.contains(QLatin1String("keil"))) @@ -348,3 +178,126 @@ void createProfile(const QString &profileName, const QString &toolchainType, else throw qbs::ErrorInfo(Tr::tr("Cannot create profile: Unknown toolchain type.")); } + +int extractVersion(const QByteArray ¯oDump, const QByteArray &keyToken) +{ + const int startIndex = macroDump.indexOf(keyToken); + if (startIndex == -1) + return -1; + const int endIndex = macroDump.indexOf('\n', startIndex); + if (endIndex == -1) + return -1; + const auto keyLength = keyToken.length(); + const int version = macroDump.mid(startIndex + keyLength, + endIndex - startIndex - keyLength) + .toInt(); + return version; +} + +static QString resolveSymlinks(const QString &filePath) +{ + QFileInfo fi(filePath); + int links = 16; + while (links-- && fi.isSymLink()) + fi.setFile(fi.dir(), fi.symLinkTarget()); + if (links <= 0) + return {}; + return fi.filePath(); +} + +// Copied from qfilesystemengine_win.cpp. +#ifdef Q_OS_WIN + +// File ID for Windows up to version 7. +static inline QByteArray fileIdWin7(HANDLE handle) +{ + BY_HANDLE_FILE_INFORMATION info; + if (GetFileInformationByHandle(handle, &info)) { + char buffer[sizeof "01234567:0123456701234567\0"]; + qsnprintf(buffer, sizeof(buffer), "%lx:%08lx%08lx", + info.dwVolumeSerialNumber, + info.nFileIndexHigh, + info.nFileIndexLow); + return QByteArray(buffer); + } + return {}; +} + +// File ID for Windows starting from version 8. +static QByteArray fileIdWin8(HANDLE handle) +{ + QByteArray result; + FILE_ID_INFO infoEx = {}; + if (::GetFileInformationByHandleEx( + handle, + static_cast<FILE_INFO_BY_HANDLE_CLASS>(18), // FileIdInfo in Windows 8 + &infoEx, sizeof(FILE_ID_INFO))) { + result = QByteArray::number(infoEx.VolumeSerialNumber, 16); + result += ':'; + // Note: MinGW-64's definition of FILE_ID_128 differs from the MSVC one. + result += QByteArray(reinterpret_cast<const char *>(&infoEx.FileId), + int(sizeof(infoEx.FileId))).toHex(); + } + return result; +} + +static QByteArray fileIdWin(HANDLE fHandle) +{ + return QOperatingSystemVersion::current() >= QOperatingSystemVersion::Windows8 + ? fileIdWin8(HANDLE(fHandle)) + : fileIdWin7(HANDLE(fHandle)); +} + +static QByteArray fileId(const QString &filePath) +{ + QByteArray result; + const HANDLE handle = ::CreateFile( + reinterpret_cast<const wchar_t*>(filePath.utf16()), 0, + FILE_SHARE_READ, nullptr, OPEN_EXISTING, + FILE_FLAG_BACKUP_SEMANTICS, nullptr); + if (handle != INVALID_HANDLE_VALUE) { + result = fileIdWin(handle); + ::CloseHandle(handle); + } + return result; +} + +static qint64 fileSize(const QString &filePath) +{ + return QFileInfo(filePath).size(); +} + +#else + +static QByteArray fileId(const QString &filePath) +{ + QByteArray result; + if (Q_UNLIKELY(filePath.isEmpty())) + return {}; + QT_STATBUF statResult = {}; + if (QT_STAT(filePath.toLocal8Bit().constData(), &statResult)) + return {}; + result = QByteArray::number(quint64(statResult.st_dev), 16); + result += ':'; + result += QByteArray::number(quint64(statResult.st_ino)); + return result; +} + +#endif // Q_OS_WIN + +bool isSameExecutable(const QString &filePath1, const QString &filePath2) +{ + if (filePath1 == filePath2) + return true; + if (resolveSymlinks(filePath1) == resolveSymlinks(filePath2)) + return true; + if (fileId(filePath1) == fileId(filePath2)) + return true; + +#ifdef Q_OS_WIN + if (fileSize(filePath1) == fileSize(filePath2)) + return true; +#endif + + return false; +} diff --git a/src/app/qbs-setup-toolchains/probe.h b/src/app/qbs-setup-toolchains/probe.h index 510747ef7..235d7a899 100644 --- a/src/app/qbs-setup-toolchains/probe.h +++ b/src/app/qbs-setup-toolchains/probe.h @@ -36,10 +36,15 @@ ** $QT_END_LICENSE$ ** ****************************************************************************/ -#ifndef QBS_PROBE_H -#define QBS_PROBE_H -#include <QtCore/qglobal.h> +#ifndef QBS_SETUPTOOLCHAINS_PROBE_H +#define QBS_SETUPTOOLCHAINS_PROBE_H + +#include <tools/version.h> + +#include <QtCore/qfileinfo.h> + +#include <tuple> // for std::tie QT_BEGIN_NAMESPACE class QString; @@ -48,11 +53,32 @@ QT_END_NAMESPACE namespace qbs { class Settings; } +QStringList systemSearchPaths(); + QString findExecutable(const QString &fileName); +QStringList toolchainTypeFromCompilerName(const QString &compilerName); + void createProfile(const QString &profileName, const QString &toolchainType, const QString &compilerFilePath, qbs::Settings *settings); void probe(qbs::Settings *settings); +struct ToolchainInstallInfo +{ + QFileInfo compilerPath; + qbs::Version compilerVersion; +}; + +inline bool operator<(const ToolchainInstallInfo &lhs, const ToolchainInstallInfo &rhs) +{ + const auto lp = lhs.compilerPath.absoluteFilePath(); + const auto rp = rhs.compilerPath.absoluteFilePath(); + return std::tie(lp, lhs.compilerVersion) < std::tie(rp, rhs.compilerVersion); +} + +int extractVersion(const QByteArray ¯oDump, const QByteArray &keyToken); + +bool isSameExecutable(const QString &exe1, const QString &exe2); + #endif // Header guard diff --git a/src/app/qbs-setup-toolchains/qbs-setup-toolchains.pro b/src/app/qbs-setup-toolchains/qbs-setup-toolchains.pro index e83a9c716..6581bec63 100644 --- a/src/app/qbs-setup-toolchains/qbs-setup-toolchains.pro +++ b/src/app/qbs-setup-toolchains/qbs-setup-toolchains.pro @@ -5,6 +5,7 @@ TARGET = qbs-setup-toolchains HEADERS += \ clangclprobe.h \ commandlineparser.h \ + gccprobe.h \ iarewprobe.h \ keilprobe.h \ msvcprobe.h \ @@ -15,6 +16,7 @@ HEADERS += \ SOURCES += \ clangclprobe.cpp \ commandlineparser.cpp \ + gccprobe.cpp \ iarewprobe.cpp \ keilprobe.cpp \ main.cpp \ diff --git a/src/app/qbs-setup-toolchains/qbs-setup-toolchains.qbs b/src/app/qbs-setup-toolchains/qbs-setup-toolchains.qbs index fd3043a28..554891fc4 100644 --- a/src/app/qbs-setup-toolchains/qbs-setup-toolchains.qbs +++ b/src/app/qbs-setup-toolchains/qbs-setup-toolchains.qbs @@ -8,6 +8,8 @@ QbsApp { "clangclprobe.h", "commandlineparser.cpp", "commandlineparser.h", + "gccprobe.cpp", + "gccprobe.h", "iarewprobe.cpp", "iarewprobe.h", "keilprobe.cpp", diff --git a/src/app/qbs-setup-toolchains/sdccprobe.cpp b/src/app/qbs-setup-toolchains/sdccprobe.cpp index 87c616ff0..eccd3ccae 100644 --- a/src/app/qbs-setup-toolchains/sdccprobe.cpp +++ b/src/app/qbs-setup-toolchains/sdccprobe.cpp @@ -47,9 +47,9 @@ #include <tools/hostosinfo.h> #include <tools/profile.h> -#include <QtCore/qfileinfo.h> -#include <QtCore/qlist.h> +#include <QtCore/qprocess.h> #include <QtCore/qsettings.h> +#include <QtCore/qtemporaryfile.h> using namespace qbs; using Internal::Tr; @@ -60,37 +60,119 @@ static QStringList knownSdccCompilerNames() return {QStringLiteral("sdcc")}; } -static QString guessSdccArchitecture(const QFileInfo &compiler) +static QByteArray dumpSdccMacros(const QFileInfo &compiler, + const QString &targetFlag = QString()) { - const auto baseName = compiler.baseName(); - if (baseName == QLatin1String("sdcc")) - return QStringLiteral("mcs51"); - return {}; + QTemporaryFile fakeIn(QStringLiteral("XXXXXX.c")); + if (!fakeIn.open()) { + qbsWarning() << Tr::tr("Unable to open temporary file %1 for output: %2") + .arg(fakeIn.fileName(), fakeIn.errorString()); + return {}; + } + fakeIn.close(); + + const QStringList args = {QStringLiteral("-dM"), + QStringLiteral("-E"), + targetFlag, + fakeIn.fileName()}; + QProcess p; + p.start(compiler.absoluteFilePath(), args); + p.waitForFinished(3000); + const auto es = p.exitStatus(); + if (es != QProcess::NormalExit) { + const QByteArray out = p.readAll(); + qbsWarning() << Tr::tr("Compiler dumping failed:\n%1") + .arg(QString::fromUtf8(out)); + return {}; + } + + return p.readAllStandardOutput(); +} + +static QString dumpSdccArchitecture(const QFileInfo &compiler, + const QString &arch) +{ + const auto targetFlag = QStringLiteral("-m%1").arg(arch); + const auto token = QStringLiteral("__SDCC_%1").arg(arch); + const auto macros = dumpSdccMacros(compiler, targetFlag); + return macros.contains(token.toLatin1()) ? arch : QString(); } -static Profile createSdccProfileHelper(const QFileInfo &compiler, Settings *settings, - QString profileName = QString()) +static std::vector<Profile> createSdccProfileHelper( + const ToolchainInstallInfo &info, + Settings *settings, + const QString &profileName = QString()) { - const QString architecture = guessSdccArchitecture(compiler); + const QFileInfo compiler = info.compilerPath; - // In case the profile is auto-detected. - if (profileName.isEmpty()) - profileName = QLatin1String("sdcc-") + architecture; + std::vector<Profile> profiles; - Profile profile(profileName, settings); - profile.setValue(QStringLiteral("cpp.toolchainInstallPath"), compiler.absolutePath()); - profile.setValue(QStringLiteral("qbs.toolchainType"), QStringLiteral("sdcc")); - if (!architecture.isEmpty()) - profile.setValue(QStringLiteral("qbs.architecture"), architecture); + const char *knownArchs[] = {"mcs51", "stm8"}; + for (const auto &knownArch : knownArchs) { + const auto actualArch = dumpSdccArchitecture( + compiler, QString::fromLatin1(knownArch)); + // Don't create a profile in case the compiler does + // not support the proposed architecture. + if (actualArch != QString::fromLatin1(knownArch)) + continue; + + QString fullProfileName = profileName; + if (fullProfileName.isEmpty()) { + // Create a full profile name in case we is + // in auto-detecting mode. + if (!info.compilerVersion.isValid()) { + fullProfileName = QStringLiteral("sdcc-unknown-%1") + .arg(actualArch); + } else { + const QString version = info.compilerVersion.toString( + QLatin1Char('_'), QLatin1Char('_')); + fullProfileName = QStringLiteral("sdcc-%1-%2").arg( + version, actualArch); + } + } else { + // Append the detected actual architecture name + // to the proposed profile name. + fullProfileName = QStringLiteral("%1-%2").arg( + fullProfileName, actualArch); + } + + Profile profile(fullProfileName, settings); + profile.setValue(QStringLiteral("cpp.toolchainInstallPath"), + compiler.absolutePath()); + profile.setValue(QStringLiteral("qbs.toolchainType"), + QStringLiteral("sdcc")); + if (!actualArch.isEmpty()) + profile.setValue(QStringLiteral("qbs.architecture"), actualArch); + + qbsInfo() << Tr::tr("Profile '%1' created for '%2'.").arg( + profile.name(), compiler.absoluteFilePath()); + } + + return profiles; +} + +static Version dumpSdccCompilerVersion(const QFileInfo &compiler) +{ + const QByteArray dump = dumpSdccMacros(compiler); + if (dump.isEmpty()) + return Version{}; + + const int major = extractVersion(dump, "__SDCC_VERSION_MAJOR "); + const int minor = extractVersion(dump, "__SDCC_VERSION_MINOR "); + const int patch = extractVersion(dump, "__SDCC_VERSION_PATCH "); + if (major < 0 || minor < 0 || patch < 0) { + qbsWarning() << Tr::tr("No '__SDCC_VERSION_xxx' token was found " + "in the compiler dump:\n%1") + .arg(QString::fromUtf8(dump)); + return Version{}; + } - qbsInfo() << Tr::tr("Profile '%1' created for '%2'.").arg( - profile.name(), compiler.absoluteFilePath()); - return profile; + return Version{major, minor, patch}; } -static std::vector<SdccInstallInfo> installedSdccsFromPath() +static std::vector<ToolchainInstallInfo> installedSdccsFromPath() { - std::vector<SdccInstallInfo> infos; + std::vector<ToolchainInstallInfo> infos; const auto compilerNames = knownSdccCompilerNames(); for (const QString &compilerName : compilerNames) { const QFileInfo sdccPath( @@ -98,14 +180,16 @@ static std::vector<SdccInstallInfo> installedSdccsFromPath() HostOsInfo::appendExecutableSuffix(compilerName))); if (!sdccPath.exists()) continue; - infos.push_back({sdccPath.absoluteFilePath(), {}}); + const Version version = dumpSdccCompilerVersion(sdccPath); + infos.push_back({sdccPath, version}); } + std::sort(infos.begin(), infos.end()); return infos; } -static std::vector<SdccInstallInfo> installedSdccsFromRegistry() +static std::vector<ToolchainInstallInfo> installedSdccsFromRegistry() { - std::vector<SdccInstallInfo> infos; + std::vector<ToolchainInstallInfo> infos; if (HostOsInfo::isWindowsHost()) { // Tries to detect the candidate from the 32-bit @@ -146,14 +230,16 @@ static std::vector<SdccInstallInfo> installedSdccsFromRegistry() continue; const auto infosEnd = infos.cend(); const auto infosIt = std::find_if(infos.cbegin(), infosEnd, - [candidate](const SdccInstallInfo &info) { - return candidate == info; + [candidate](const ToolchainInstallInfo &info) { + return candidate == SdccInstallInfo{ + info.compilerPath.filePath(), info.compilerVersion.toString()}; }); if (infosIt == infosEnd) - infos.push_back(candidate); + infos.push_back({candidate.compilerPath, Version::fromString(candidate.version)}); } } + std::sort(infos.begin(), infos.end()); return infos; } @@ -168,20 +254,28 @@ bool isSdccCompiler(const QString &compilerName) void createSdccProfile(const QFileInfo &compiler, Settings *settings, QString profileName) { - createSdccProfileHelper(compiler, settings, profileName); + const ToolchainInstallInfo info = {compiler, Version{}}; + createSdccProfileHelper(info, settings, profileName); } void sdccProbe(Settings *settings, QList<Profile> &profiles) { qbsInfo() << Tr::tr("Trying to detect SDCC toolchains..."); - std::vector<SdccInstallInfo> allInfos = installedSdccsFromRegistry(); - const std::vector<SdccInstallInfo> pathInfos = installedSdccsFromPath(); - allInfos.insert(std::end(allInfos), std::begin(pathInfos), std::end(pathInfos)); + // Make sure that a returned infos are sorted before using the std::set_union! + const std::vector<ToolchainInstallInfo> regInfos = installedSdccsFromRegistry(); + const std::vector<ToolchainInstallInfo> pathInfos = installedSdccsFromPath(); + std::vector<ToolchainInstallInfo> allInfos; + allInfos.reserve(regInfos.size() + pathInfos.size()); + std::set_union(regInfos.cbegin(), regInfos.cend(), + pathInfos.cbegin(), pathInfos.cend(), + std::back_inserter(allInfos)); - for (const SdccInstallInfo &info : allInfos) { - const auto profile = createSdccProfileHelper(info.compilerPath, settings); - profiles.push_back(profile); + for (const ToolchainInstallInfo &info : allInfos) { + const auto newProfiles = createSdccProfileHelper(info, settings); + profiles.reserve(profiles.size() + int(newProfiles.size())); + std::copy(newProfiles.cbegin(), newProfiles.cend(), + std::back_inserter(profiles)); } if (allInfos.empty()) diff --git a/src/app/qbs-setup-toolchains/sdccprobe.h b/src/app/qbs-setup-toolchains/sdccprobe.h index 55062ff19..aa2c613f3 100644 --- a/src/app/qbs-setup-toolchains/sdccprobe.h +++ b/src/app/qbs-setup-toolchains/sdccprobe.h @@ -37,8 +37,8 @@ ** ****************************************************************************/ -#ifndef SDCCPROBE_H -#define SDCCPROBE_H +#ifndef QBS_SETUPTOOLCHAINS_SDCCPROBE_H +#define QBS_SETUPTOOLCHAINS_SDCCPROBE_H #include <QtCore/qlist.h> @@ -72,4 +72,4 @@ void createSdccProfile(const QFileInfo &compiler, qbs::Settings *settings, void sdccProbe(qbs::Settings *settings, QList<qbs::Profile> &profiles); -#endif // SDCCPROBE_H +#endif // Header guard diff --git a/src/app/qbs-setup-toolchains/xcodeprobe.h b/src/app/qbs-setup-toolchains/xcodeprobe.h index 11fc2bffa..ab501036b 100644 --- a/src/app/qbs-setup-toolchains/xcodeprobe.h +++ b/src/app/qbs-setup-toolchains/xcodeprobe.h @@ -37,8 +37,8 @@ ** ****************************************************************************/ -#ifndef XCODEPROBE_H -#define XCODEPROBE_H +#ifndef QBS_SETUPTOOLCHAINS_XCODEPROBE_H +#define QBS_SETUPTOOLCHAINS_XCODEPROBE_H #include <QtCore/qlist.h> @@ -49,4 +49,4 @@ class Settings; void xcodeProbe(qbs::Settings *settings, QList<qbs::Profile> &profiles); -#endif // XCODEPROBE_H +#endif // Header guard diff --git a/src/app/qbs/commandlinefrontend.cpp b/src/app/qbs/commandlinefrontend.cpp index 95c3c10bc..8be06f3af 100644 --- a/src/app/qbs/commandlinefrontend.cpp +++ b/src/app/qbs/commandlinefrontend.cpp @@ -40,6 +40,7 @@ #include "application.h" #include "consoleprogressobserver.h" +#include "session.h" #include "status.h" #include "parser/commandlineoption.h" #include "../shared/logging/consolelogger.h" @@ -129,6 +130,10 @@ void CommandLineFrontend::start() throw ErrorInfo(error); } break; + case SessionCommandType: { + startSession(); + return; + } default: break; } @@ -418,6 +423,7 @@ void CommandLineFrontend::handleProjectsResolved() break; case HelpCommandType: case VersionCommandType: + case SessionCommandType: Q_ASSERT_X(false, Q_FUNC_INFO, "Impossible."); } } diff --git a/src/app/qbs/parser/commandlineparser.cpp b/src/app/qbs/parser/commandlineparser.cpp index 3c25c51e2..052f6b92f 100644 --- a/src/app/qbs/parser/commandlineparser.cpp +++ b/src/app/qbs/parser/commandlineparser.cpp @@ -386,6 +386,7 @@ QList<Command *> CommandLineParser::CommandLineParserPrivate::allCommands() cons commandPool.getCommand(DumpNodesTreeCommandType), commandPool.getCommand(ListProductsCommandType), commandPool.getCommand(VersionCommandType), + commandPool.getCommand(SessionCommandType), commandPool.getCommand(HelpCommandType)}; } diff --git a/src/app/qbs/parser/commandpool.cpp b/src/app/qbs/parser/commandpool.cpp index a49608c56..1362a563c 100644 --- a/src/app/qbs/parser/commandpool.cpp +++ b/src/app/qbs/parser/commandpool.cpp @@ -95,6 +95,9 @@ qbs::Command *CommandPool::getCommand(CommandType type) const case VersionCommandType: command = new VersionCommand(m_optionPool); break; + case SessionCommandType: + command = new SessionCommand(m_optionPool); + break; } } return command; diff --git a/src/app/qbs/parser/commandtype.h b/src/app/qbs/parser/commandtype.h index a8c618933..7d70356e7 100644 --- a/src/app/qbs/parser/commandtype.h +++ b/src/app/qbs/parser/commandtype.h @@ -45,7 +45,7 @@ enum CommandType { ResolveCommandType, BuildCommandType, CleanCommandType, RunCommandType, ShellCommandType, StatusCommandType, UpdateTimestampsCommandType, DumpNodesTreeCommandType, InstallCommandType, HelpCommandType, GenerateCommandType, ListProductsCommandType, - VersionCommandType, + VersionCommandType, SessionCommandType, }; } // namespace qbs diff --git a/src/app/qbs/parser/parsercommand.cpp b/src/app/qbs/parser/parsercommand.cpp index 9485b0878..c7185a725 100644 --- a/src/app/qbs/parser/parsercommand.cpp +++ b/src/app/qbs/parser/parsercommand.cpp @@ -593,4 +593,27 @@ void VersionCommand::parseNext(QStringList &input) throwError(Tr::tr("This command takes no arguments.")); } +QString SessionCommand::shortDescription() const +{ + return Tr::tr("Starts a session for an IDE."); +} + +QString SessionCommand::longDescription() const +{ + QString description = Tr::tr("qbs %1\n").arg(representation()); + return description += Tr::tr("Communicates on stdin and stdout via a JSON-based API.\n" + "Intended for use with other tools, such as IDEs.\n"); +} + +QString SessionCommand::representation() const +{ + return QLatin1String("session"); +} + +void SessionCommand::parseNext(QStringList &input) +{ + QBS_CHECK(!input.empty()); + throwError(Tr::tr("This command takes no arguments.")); +} + } // namespace qbs diff --git a/src/app/qbs/parser/parsercommand.h b/src/app/qbs/parser/parsercommand.h index 649563ba1..8998d38e6 100644 --- a/src/app/qbs/parser/parsercommand.h +++ b/src/app/qbs/parser/parsercommand.h @@ -261,6 +261,20 @@ private: void parseNext(QStringList &input) override; }; +class SessionCommand : public Command +{ +public: + SessionCommand(CommandLineOptionPool &optionPool) : Command(optionPool) {} + +private: + CommandType type() const override { return SessionCommandType; } + QString shortDescription() const override; + QString longDescription() const override; + QString representation() const override; + QList<CommandLineOption::Type> supportedOptions() const override { return {}; } + void parseNext(QStringList &input) override; +}; + } // namespace qbs #endif // QBS_PARSER_COMMAND_H diff --git a/src/app/qbs/qbs.pro b/src/app/qbs/qbs.pro index ac9d6f0ca..e9f0061c6 100644 --- a/src/app/qbs/qbs.pro +++ b/src/app/qbs/qbs.pro @@ -6,6 +6,10 @@ TARGET = qbs SOURCES += main.cpp \ ctrlchandler.cpp \ application.cpp \ + session.cpp \ + sessionpacket.cpp \ + sessionpacketreader.cpp \ + stdinreader.cpp \ status.cpp \ consoleprogressobserver.cpp \ commandlinefrontend.cpp \ @@ -14,6 +18,10 @@ SOURCES += main.cpp \ HEADERS += \ ctrlchandler.h \ application.h \ + session.h \ + sessionpacket.h \ + sessionpacketreader.h \ + stdinreader.h \ status.h \ consoleprogressobserver.h \ commandlinefrontend.h \ diff --git a/src/app/qbs/qbs.qbs b/src/app/qbs/qbs.qbs index f22fe5de5..91357445e 100644 --- a/src/app/qbs/qbs.qbs +++ b/src/app/qbs/qbs.qbs @@ -23,8 +23,16 @@ QbsApp { "main.cpp", "qbstool.cpp", "qbstool.h", + "session.cpp", + "session.h", + "sessionpacket.cpp", + "sessionpacket.h", + "sessionpacketreader.cpp", + "sessionpacketreader.h", "status.cpp", "status.h", + "stdinreader.cpp", + "stdinreader.h", ] Group { name: "parser" diff --git a/src/app/qbs/session.cpp b/src/app/qbs/session.cpp new file mode 100644 index 000000000..0b93aff49 --- /dev/null +++ b/src/app/qbs/session.cpp @@ -0,0 +1,751 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qbs. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "session.h" + +#include "sessionpacket.h" +#include "sessionpacketreader.h" + +#include <api/jobs.h> +#include <api/project.h> +#include <api/projectdata.h> +#include <api/runenvironment.h> +#include <logging/ilogsink.h> +#include <tools/buildoptions.h> +#include <tools/cleanoptions.h> +#include <tools/error.h> +#include <tools/installoptions.h> +#include <tools/jsonhelper.h> +#include <tools/preferences.h> +#include <tools/processresult.h> +#include <tools/qbsassert.h> +#include <tools/settings.h> +#include <tools/setupprojectparameters.h> +#include <tools/stringconstants.h> + +#include <QtCore/qcoreapplication.h> +#include <QtCore/qdir.h> +#include <QtCore/qjsonarray.h> +#include <QtCore/qjsonobject.h> +#include <QtCore/qobject.h> +#include <QtCore/qprocess.h> + +#include <algorithm> +#include <cstdlib> +#include <iostream> +#include <memory> + +namespace qbs { +namespace Internal { + +class SessionLogSink : public QObject, public ILogSink +{ + Q_OBJECT +signals: + void newMessage(const QJsonObject &msg); + +private: + void doPrintMessage(LoggerLevel, const QString &message, const QString &) override + { + QJsonObject msg; + msg.insert(StringConstants::type(), QLatin1String("log-data")); + msg.insert(StringConstants::messageKey(), message); + emit newMessage(msg); + } + + void doPrintWarning(const ErrorInfo &warning) override + { + QJsonObject msg; + static const QString warningString(QLatin1String("warning")); + msg.insert(StringConstants::type(), warningString); + msg.insert(warningString, warning.toJson()); + emit newMessage(msg); + } +}; + +class Session : public QObject +{ + Q_OBJECT +public: + Session(); + +private: + enum class ProjectDataMode { Never, Always, OnlyIfChanged }; + ProjectDataMode dataModeFromRequest(const QJsonObject &request); + QStringList modulePropertiesFromRequest(const QJsonObject &request); + void insertProjectDataIfNecessary( + QJsonObject &reply, + ProjectDataMode dataMode, + const ProjectData &oldProjectData, + bool includeTopLevelData + ); + void setLogLevelFromRequest(const QJsonObject &request); + bool checkNormalRequestPrerequisites(const char *replyType); + + void sendPacket(const QJsonObject &message); + void setupProject(const QJsonObject &request); + void buildProject(const QJsonObject &request); + void cleanProject(const QJsonObject &request); + void installProject(const QJsonObject &request); + void addFiles(const QJsonObject &request); + void removeFiles(const QJsonObject &request); + void getRunEnvironment(const QJsonObject &request); + void getGeneratedFilesForSources(const QJsonObject &request); + void releaseProject(); + void cancelCurrentJob(); + void quitSession(); + + void sendErrorReply(const char *replyType, const QString &message); + void sendErrorReply(const char *replyType, const ErrorInfo &error); + void insertErrorInfoIfNecessary(QJsonObject &reply, const ErrorInfo &error); + void connectProgressSignals(AbstractJob *job); + QList<ProductData> getProductsByName(const QStringList &productNames) const; + ProductData getProductByName(const QString &productName) const; + + struct ProductSelection { + ProductSelection(Project::ProductSelection s) : selection(s) {} + ProductSelection(const QList<ProductData> &p) : products(p) {} + + Project::ProductSelection selection = Project::ProductSelectionDefaultOnly; + QList<ProductData> products; + }; + ProductSelection getProductSelection(const QJsonObject &request); + + struct FileUpdateData { + QJsonObject createErrorReply(const char *type, const QString &mainMessage) const; + + ProductData product; + GroupData group; + QStringList filePaths; + ErrorInfo error; + }; + FileUpdateData prepareFileUpdate(const QJsonObject &request); + + SessionPacketReader m_packetReader; + Project m_project; + ProjectData m_projectData; + SessionLogSink m_logSink; + std::unique_ptr<Settings> m_settings; + QJsonObject m_resolveRequest; + QStringList m_moduleProperties; + AbstractJob *m_currentJob = nullptr; +}; + +void startSession() +{ + const auto session = new Session; + QObject::connect(qApp, &QCoreApplication::aboutToQuit, session, [session] { delete session; }); +} + +Session::Session() +{ + sendPacket(SessionPacket::helloMessage()); + connect(&m_logSink, &SessionLogSink::newMessage, this, &Session::sendPacket); + connect(&m_packetReader, &SessionPacketReader::errorOccurred, + this, [](const QString &msg) { + std::cerr << qPrintable(tr("Error: %1").arg(msg)); + qApp->exit(EXIT_FAILURE); + }); + connect(&m_packetReader, &SessionPacketReader::packetReceived, this, [this](const QJsonObject &packet) { + // qDebug() << "got packet:" << packet; // Uncomment for debugging. + const QString type = packet.value(StringConstants::type()).toString(); + if (type == QLatin1String("resolve-project")) + setupProject(packet); + else if (type == QLatin1String("build-project")) + buildProject(packet); + else if (type == QLatin1String("clean-project")) + cleanProject(packet); + else if (type == QLatin1String("install-project")) + installProject(packet); + else if (type == QLatin1String("add-files")) + addFiles(packet); + else if (type == QLatin1String("remove-files")) + removeFiles(packet); + else if (type == QLatin1String("get-run-environment")) + getRunEnvironment(packet); + else if (type == QLatin1String("get-generated-files-for-sources")) + getGeneratedFilesForSources(packet); + else if (type == QLatin1String("release-project")) + releaseProject(); + else if (type == QLatin1String("quit")) + quitSession(); + else if (type == QLatin1String("cancel-job")) + cancelCurrentJob(); + else + sendErrorReply("protocol-error", tr("Unknown request type '%1'.").arg(type)); + }); + m_packetReader.start(); +} + +Session::ProjectDataMode Session::dataModeFromRequest(const QJsonObject &request) +{ + const QString modeString = request.value(QLatin1String("data-mode")).toString(); + if (modeString == QLatin1String("only-if-changed")) + return ProjectDataMode::OnlyIfChanged; + if (modeString == QLatin1String("always")) + return ProjectDataMode::Always; + return ProjectDataMode::Never; +} + +void Session::sendPacket(const QJsonObject &message) +{ + std::cout << SessionPacket::createPacket(message).constData() << std::flush; +} + +void Session::setupProject(const QJsonObject &request) +{ + if (m_currentJob) { + if (qobject_cast<SetupProjectJob *>(m_currentJob) + && m_currentJob->state() == AbstractJob::StateCanceling) { + m_resolveRequest = std::move(request); + return; + } + sendErrorReply("project-resolved", + tr("Cannot start resolving while another job is still running.")); + return; + } + m_moduleProperties = modulePropertiesFromRequest(request); + auto params = SetupProjectParameters::fromJson(request); + const ProjectDataMode dataMode = dataModeFromRequest(request); + m_settings.reset(new Settings(params.settingsDirectory())); + const Preferences prefs(m_settings.get()); + const QString appDir = QDir::cleanPath(QCoreApplication::applicationDirPath()); + params.setSearchPaths(prefs.searchPaths(appDir + QLatin1String( + "/" QBS_RELATIVE_SEARCH_PATH))); + params.setPluginPaths(prefs.pluginPaths(appDir + QLatin1String( + "/" QBS_RELATIVE_PLUGINS_PATH))); + params.setLibexecPath(appDir + QLatin1String("/" QBS_RELATIVE_LIBEXEC_PATH)); + params.setOverrideBuildGraphData(true); + setLogLevelFromRequest(request); + SetupProjectJob * const setupJob = m_project.setupProject(params, &m_logSink, this); + m_currentJob = setupJob; + connectProgressSignals(setupJob); + connect(setupJob, &AbstractJob::finished, this, + [this, setupJob, dataMode](bool success) { + if (!m_resolveRequest.isEmpty()) { // Canceled job was superseded. + const QJsonObject newRequest = std::move(m_resolveRequest); + m_resolveRequest = QJsonObject(); + m_currentJob->deleteLater(); + m_currentJob = nullptr; + setupProject(newRequest); + return; + } + const ProjectData oldProjectData = m_projectData; + m_project = setupJob->project(); + m_projectData = m_project.projectData(); + QJsonObject reply; + reply.insert(StringConstants::type(), QLatin1String("project-resolved")); + if (success) + insertProjectDataIfNecessary(reply, dataMode, oldProjectData, true); + else + insertErrorInfoIfNecessary(reply, setupJob->error()); + sendPacket(reply); + m_currentJob->deleteLater(); + m_currentJob = nullptr; + }); +} + +void Session::buildProject(const QJsonObject &request) +{ + if (!checkNormalRequestPrerequisites("build-done")) + return; + const ProductSelection productSelection = getProductSelection(request); + setLogLevelFromRequest(request); + auto options = BuildOptions::fromJson(request); + options.setSettingsDirectory(m_settings->baseDirectory()); + BuildJob * const buildJob = productSelection.products.empty() + ? m_project.buildAllProducts(options, productSelection.selection, this) + : m_project.buildSomeProducts(productSelection.products, options, this); + m_currentJob = buildJob; + m_moduleProperties = modulePropertiesFromRequest(request); + const ProjectDataMode dataMode = dataModeFromRequest(request); + connectProgressSignals(buildJob); + connect(buildJob, &BuildJob::reportCommandDescription, this, + [this](const QString &highlight, const QString &message) { + QJsonObject descData; + descData.insert(StringConstants::type(), QLatin1String("command-description")); + descData.insert(QLatin1String("highlight"), highlight); + descData.insert(StringConstants::messageKey(), message); + sendPacket(descData); + }); + connect(buildJob, &BuildJob::reportProcessResult, this, [this](const ProcessResult &result) { + if (result.success() && result.stdOut().isEmpty() && result.stdErr().isEmpty()) + return; + QJsonObject resultData = result.toJson(); + resultData.insert(StringConstants::type(), QLatin1String("process-result")); + sendPacket(resultData); + }); + connect(buildJob, &BuildJob::finished, this, + [this, dataMode](bool success) { + QJsonObject reply; + reply.insert(StringConstants::type(), QLatin1String("project-built")); + const ProjectData oldProjectData = m_projectData; + m_projectData = m_project.projectData(); + if (success) + insertProjectDataIfNecessary(reply, dataMode, oldProjectData, false); + else + insertErrorInfoIfNecessary(reply, m_currentJob->error()); + sendPacket(reply); + m_currentJob->deleteLater(); + m_currentJob = nullptr; + }); +} + +void Session::cleanProject(const QJsonObject &request) +{ + if (!checkNormalRequestPrerequisites("project-cleaned")) + return; + setLogLevelFromRequest(request); + const ProductSelection productSelection = getProductSelection(request); + const auto options = CleanOptions::fromJson(request); + m_currentJob = productSelection.products.empty() + ? m_project.cleanAllProducts(options, this) + : m_project.cleanSomeProducts(productSelection.products, options, this); + connectProgressSignals(m_currentJob); + connect(m_currentJob, &AbstractJob::finished, this, [this](bool success) { + QJsonObject reply; + reply.insert(StringConstants::type(), QLatin1String("project-cleaned")); + if (!success) + insertErrorInfoIfNecessary(reply, m_currentJob->error()); + sendPacket(reply); + m_currentJob->deleteLater(); + m_currentJob = nullptr; + }); +} + +void Session::installProject(const QJsonObject &request) +{ + if (!checkNormalRequestPrerequisites("install-done")) + return; + setLogLevelFromRequest(request); + const ProductSelection productSelection = getProductSelection(request); + const auto options = InstallOptions::fromJson(request); + m_currentJob = productSelection.products.empty() + ? m_project.installAllProducts(options, productSelection.selection, this) + : m_project.installSomeProducts(productSelection.products, options, this); + connectProgressSignals(m_currentJob); + connect(m_currentJob, &AbstractJob::finished, this, [this](bool success) { + QJsonObject reply; + reply.insert(StringConstants::type(), QLatin1String("install-done")); + if (!success) + insertErrorInfoIfNecessary(reply, m_currentJob->error()); + sendPacket(reply); + m_currentJob->deleteLater(); + m_currentJob = nullptr; + }); +} + +void Session::addFiles(const QJsonObject &request) +{ + const FileUpdateData data = prepareFileUpdate(request); + if (data.error.hasError()) { + sendPacket(data.createErrorReply("files-added", tr("Failed to add files to project: %1") + .arg(data.error.toString()))); + return; + } + ErrorInfo error; + QStringList failedFiles; +#ifdef QBS_ENABLE_PROJECT_FILE_UPDATES + for (const QString &filePath : data.filePaths) { + const ErrorInfo e = m_project.addFiles(data.product, data.group, {filePath}); + if (e.hasError()) { + for (const ErrorItem &ei : e.items()) + error.append(ei); + failedFiles.push_back(filePath); + } + } +#endif + QJsonObject reply; + reply.insert(StringConstants::type(), QLatin1String("files-added")); + insertErrorInfoIfNecessary(reply, error); + + if (failedFiles.size() != data.filePaths.size()) { + // Note that Project::addFiles() directly changes the existing project data object, so + // there's no need to retrieve it from m_project. + insertProjectDataIfNecessary(reply, ProjectDataMode::Always, {}, false); + } + + if (!failedFiles.isEmpty()) + reply.insert(QLatin1String("failed-files"), QJsonArray::fromStringList(failedFiles)); + sendPacket(reply); +} + +void Session::removeFiles(const QJsonObject &request) +{ + const FileUpdateData data = prepareFileUpdate(request); + if (data.error.hasError()) { + sendPacket(data.createErrorReply("files-removed", + tr("Failed to remove files from project: %1") + .arg(data.error.toString()))); + return; + } + ErrorInfo error; + QStringList failedFiles; +#ifdef QBS_ENABLE_PROJECT_FILE_UPDATES + for (const QString &filePath : data.filePaths) { + const ErrorInfo e = m_project.removeFiles(data.product, data.group, {filePath}); + if (e.hasError()) { + for (const ErrorItem &ei : e.items()) + error.append(ei); + failedFiles.push_back(filePath); + } + } +#endif + QJsonObject reply; + reply.insert(StringConstants::type(), QLatin1String("files-removed")); + insertErrorInfoIfNecessary(reply, error); + if (failedFiles.size() != data.filePaths.size()) + insertProjectDataIfNecessary(reply, ProjectDataMode::Always, {}, false); + if (!failedFiles.isEmpty()) + reply.insert(QLatin1String("failed-files"), QJsonArray::fromStringList(failedFiles)); + sendPacket(reply); +} + +void Session::connectProgressSignals(AbstractJob *job) +{ + static QString maxProgressString(QLatin1String("max-progress")); + connect(job, &AbstractJob::taskStarted, this, + [this](const QString &description, int maxProgress) { + QJsonObject msg; + msg.insert(StringConstants::type(), QLatin1String("task-started")); + msg.insert(StringConstants::descriptionProperty(), description); + msg.insert(maxProgressString, maxProgress); + sendPacket(msg); + }); + connect(job, &AbstractJob::totalEffortChanged, this, [this](int maxProgress) { + QJsonObject msg; + msg.insert(StringConstants::type(), QLatin1String("new-max-progress")); + msg.insert(maxProgressString, maxProgress); + sendPacket(msg); + }); + connect(job, &AbstractJob::taskProgress, this, [this](int progress) { + QJsonObject msg; + msg.insert(StringConstants::type(), QLatin1String("task-progress")); + msg.insert(QLatin1String("progress"), progress); + sendPacket(msg); + }); +} + +static QList<ProductData> getProductsByNameForProject(const ProjectData &project, + QStringList &productNames) +{ + QList<ProductData> products; + if (productNames.empty()) + return products; + for (const ProductData &p : project.products()) { + for (auto it = productNames.begin(); it != productNames.end(); ++it) { + if (*it == p.fullDisplayName()) { + products << p; + productNames.erase(it); + if (productNames.empty()) + return products; + break; + } + } + } + for (const ProjectData &p : project.subProjects()) { + products << getProductsByNameForProject(p, productNames); + if (productNames.empty()) + break; + } + return products; +} + +QList<ProductData> Session::getProductsByName(const QStringList &productNames) const +{ + QStringList remainingNames = productNames; + return getProductsByNameForProject(m_projectData, remainingNames); +} + +ProductData Session::getProductByName(const QString &productName) const +{ + const QList<ProductData> products = getProductsByName({productName}); + return products.empty() ? ProductData() : products.first(); +} + +void Session::getRunEnvironment(const QJsonObject &request) +{ + const char * const replyType = "run-environment"; + if (!checkNormalRequestPrerequisites(replyType)) + return; + const QString productName = request.value(QLatin1String("product")).toString(); + const ProductData product = getProductByName(productName); + if (!product.isValid()) { + sendErrorReply(replyType, tr("No such product '%1'.").arg(productName)); + return; + } + const auto inEnv = fromJson<QProcessEnvironment>( + request.value(QLatin1String("base-environment"))); + const QStringList config = fromJson<QStringList>(request.value(QLatin1String("config"))); + const RunEnvironment runEnv = m_project.getRunEnvironment(product, InstallOptions(), inEnv, + config, m_settings.get()); + ErrorInfo error; + const QProcessEnvironment outEnv = runEnv.runEnvironment(&error); + if (error.hasError()) { + sendErrorReply(replyType, error); + return; + } + QJsonObject reply; + reply.insert(StringConstants::type(), QLatin1String(replyType)); + QJsonObject outEnvObj; + const QStringList keys = outEnv.keys(); + for (const QString &key : keys) + outEnvObj.insert(key, outEnv.value(key)); + reply.insert(QLatin1String("full-environment"), outEnvObj); + sendPacket(reply); +} + +void Session::getGeneratedFilesForSources(const QJsonObject &request) +{ + const char * const replyType = "generated-files-for-sources"; + if (!checkNormalRequestPrerequisites(replyType)) + return; + QJsonObject reply; + reply.insert(StringConstants::type(), QLatin1String(replyType)); + const QJsonArray specs = request.value(StringConstants::productsKey()).toArray(); + QJsonArray resultProducts; + for (const QJsonValue &p : specs) { + const QJsonObject productObject = p.toObject(); + const ProductData product = getProductByName( + productObject.value(StringConstants::fullDisplayNameKey()).toString()); + if (!product.isValid()) + continue; + QJsonObject resultProduct; + resultProduct.insert(StringConstants::fullDisplayNameKey(), product.fullDisplayName()); + QJsonArray results; + const QJsonArray requests = productObject.value(QLatin1String("requests")).toArray(); + for (const QJsonValue &r : requests) { + const QJsonObject request = r.toObject(); + const QString filePath = request.value(QLatin1String("source-file")).toString(); + const QStringList tags = fromJson<QStringList>(request.value(QLatin1String("tags"))); + const bool recursive = request.value(QLatin1String("recursive")).toBool(); + const QStringList generatedFiles = m_project.generatedFiles(product, filePath, + recursive, tags); + if (!generatedFiles.isEmpty()) { + QJsonObject result; + result.insert(QLatin1String("source-file"), filePath); + result.insert(QLatin1String("generated-files"), + QJsonArray::fromStringList(generatedFiles)); + results << result; + } + } + if (!results.isEmpty()) { + resultProduct.insert(QLatin1String("results"), results); + resultProducts << resultProduct; + } + } + reply.insert(StringConstants::productsKey(), resultProducts); + sendPacket(reply); +} + +void Session::releaseProject() +{ + const char * const replyType = "project-released"; + if (!m_project.isValid()) { + sendErrorReply(replyType, tr("No open project.")); + return; + } + if (m_currentJob) { + m_currentJob->disconnect(this); + m_currentJob->cancel(); + m_currentJob = nullptr; + } + m_project = Project(); + m_projectData = ProjectData(); + m_resolveRequest = QJsonObject(); + QJsonObject reply; + reply.insert(StringConstants::type(), QLatin1String(replyType)); + sendPacket(reply); +} + +void Session::cancelCurrentJob() +{ + if (m_currentJob) { + if (!m_resolveRequest.isEmpty()) + m_resolveRequest = QJsonObject(); + m_currentJob->cancel(); + } +} + +Session::ProductSelection Session::getProductSelection(const QJsonObject &request) +{ + const QJsonValue productSelection = request.value(StringConstants::productsKey()); + if (productSelection.isArray()) + return ProductSelection(getProductsByName(fromJson<QStringList>(productSelection))); + return ProductSelection(productSelection.toString() == QLatin1String("all") + ? Project::ProductSelectionWithNonDefault + : Project::ProductSelectionDefaultOnly); +} + +Session::FileUpdateData Session::prepareFileUpdate(const QJsonObject &request) +{ + FileUpdateData data; + const QString productName = request.value(QLatin1String("product")).toString(); + data.product = getProductByName(productName); + if (data.product.isValid()) { + const QString groupName = request.value(QLatin1String("group")).toString(); + for (const GroupData &g : data.product.groups()) { + if (g.name() == groupName) { + data.group = g; + break; + } + } + if (!data.group.isValid()) + data.error = tr("Group '%1' not found in product '%2'.").arg(groupName, productName); + } else { + data.error = tr("Product '%1' not found in project.").arg(productName); + } + const QJsonArray filesArray = request.value(QLatin1String("files")).toArray(); + for (const QJsonValue &v : filesArray) + data.filePaths << v.toString(); + if (m_currentJob) + data.error = tr("Cannot update the list of source files while a job is running."); + if (!m_project.isValid()) + data.error = tr("No valid project. You need to resolve first."); +#ifndef QBS_ENABLE_PROJECT_FILE_UPDATES + data.error = ErrorInfo(tr("Project file updates are not enabled in this build of qbs.")); +#endif + return data; +} + +void Session::insertProjectDataIfNecessary(QJsonObject &reply, ProjectDataMode dataMode, + const ProjectData &oldProjectData, bool includeTopLevelData) +{ + const bool sendProjectData = dataMode == ProjectDataMode::Always + || (dataMode == ProjectDataMode::OnlyIfChanged && m_projectData != oldProjectData); + if (!sendProjectData) + return; + QJsonObject projectData = m_projectData.toJson(m_moduleProperties); + if (includeTopLevelData) { + QJsonArray buildSystemFiles; + for (const QString &f : m_project.buildSystemFiles()) + buildSystemFiles.push_back(f); + projectData.insert(StringConstants::buildDirectoryKey(), m_projectData.buildDirectory()); + projectData.insert(QLatin1String("build-system-files"), buildSystemFiles); + const Project::BuildGraphInfo bgInfo = m_project.getBuildGraphInfo(); + projectData.insert(QLatin1String("build-graph-file-path"), bgInfo.bgFilePath); + projectData.insert(QLatin1String("profile-data"), + QJsonObject::fromVariantMap(bgInfo.profileData)); + projectData.insert(QLatin1String("overridden-properties"), + QJsonObject::fromVariantMap(bgInfo.overriddenProperties)); + } + reply.insert(QLatin1String("project-data"), projectData); +} + +void Session::setLogLevelFromRequest(const QJsonObject &request) +{ + const QString logLevelString = request.value(QLatin1String("log-level")).toString(); + if (logLevelString.isEmpty()) + return; + for (const LoggerLevel l : {LoggerError, LoggerWarning, LoggerInfo, LoggerDebug, LoggerTrace}) { + if (logLevelString == logLevelName(l)) { + m_logSink.setLogLevel(l); + return; + } + } +} + +bool Session::checkNormalRequestPrerequisites(const char *replyType) +{ + if (m_currentJob) { + sendErrorReply(replyType, tr("Another job is still running.")); + return false; + } + if (!m_project.isValid()) { + sendErrorReply(replyType, tr("No valid project. You need to resolve first.")); + return false; + } + return true; +} + +QStringList Session::modulePropertiesFromRequest(const QJsonObject &request) +{ + return fromJson<QStringList>(request.value(StringConstants::modulePropertiesKey())); +} + +void Session::sendErrorReply(const char *replyType, const ErrorInfo &error) +{ + QJsonObject reply; + reply.insert(StringConstants::type(), QLatin1String(replyType)); + insertErrorInfoIfNecessary(reply, error); + sendPacket(reply); +} + +void Session::sendErrorReply(const char *replyType, const QString &message) +{ + sendErrorReply(replyType, ErrorInfo(message)); +} + +void Session::insertErrorInfoIfNecessary(QJsonObject &reply, const ErrorInfo &error) +{ + if (error.hasError()) + reply.insert(QLatin1String("error"), error.toJson()); +} + +void Session::quitSession() +{ + m_logSink.disconnect(this); + m_packetReader.disconnect(this); + if (m_currentJob) { + m_currentJob->disconnect(this); + connect(m_currentJob, &AbstractJob::finished, qApp, QCoreApplication::quit); + m_currentJob->cancel(); + } else { + qApp->quit(); + } +} + +QJsonObject Session::FileUpdateData::createErrorReply(const char *type, + const QString &mainMessage) const +{ + QBS_ASSERT(error.hasError(), return QJsonObject()); + ErrorInfo error(mainMessage); + for (const ErrorItem &ei : error.items()) + error.append(ei); + QJsonObject reply; + reply.insert(StringConstants::type(), QLatin1String(type)); + reply.insert(QLatin1String("error"), error.toJson()); + reply.insert(QLatin1String("failed-files"), QJsonArray::fromStringList(filePaths)); + return reply; +} + +} // namespace Internal +} // namespace qbs + +#include <session.moc> diff --git a/src/app/qbs/session.h b/src/app/qbs/session.h new file mode 100644 index 000000000..ebbc93b1f --- /dev/null +++ b/src/app/qbs/session.h @@ -0,0 +1,51 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qbs. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QBS_SESSION_H +#define QBS_SESSION_H + +namespace qbs { +namespace Internal { + +void startSession(); + +} // namespace Internal +} // namespace qbs + +#endif // Include guard diff --git a/src/app/qbs/sessionpacket.cpp b/src/app/qbs/sessionpacket.cpp new file mode 100644 index 000000000..ce9fdaf76 --- /dev/null +++ b/src/app/qbs/sessionpacket.cpp @@ -0,0 +1,113 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qbs. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "sessionpacket.h" + +#include <tools/qbsassert.h> +#include <tools/stringconstants.h> +#include <tools/version.h> + +#include <QtCore/qdebug.h> +#include <QtCore/qjsondocument.h> +#include <QtCore/qjsonvalue.h> +#include <QtCore/qstring.h> + +namespace qbs { +namespace Internal { + +const QByteArray packetStart = "qbsmsg:"; + +SessionPacket::Status SessionPacket::parseInput(QByteArray &input) +{ + //qDebug() << m_expectedPayloadLength << m_payload << input; + if (m_expectedPayloadLength == -1) { + const int packetStartOffset = input.indexOf(packetStart); + if (packetStartOffset == -1) + return Status::Incomplete; + const int numberOffset = packetStartOffset + packetStart.length(); + const int newLineOffset = input.indexOf('\n', numberOffset); + if (newLineOffset == -1) + return Status::Incomplete; + const QByteArray sizeString = input.mid(numberOffset, newLineOffset - numberOffset); + bool isNumber; + const int payloadLen = sizeString.toInt(&isNumber); + if (!isNumber || payloadLen < 0) + return Status::Invalid; + m_expectedPayloadLength = payloadLen; + input.remove(0, newLineOffset + 1); + } + const int bytesToAdd = m_expectedPayloadLength - m_payload.length(); + QBS_ASSERT(bytesToAdd >= 0, return Status::Invalid); + m_payload += input.left(bytesToAdd); + input.remove(0, bytesToAdd); + return isComplete() ? Status::Complete : Status::Incomplete; +} + +QJsonObject SessionPacket::retrievePacket() +{ + QBS_ASSERT(isComplete(), return QJsonObject()); + const auto packet = QJsonDocument::fromJson(QByteArray::fromBase64(m_payload)).object(); + m_payload.clear(); + m_expectedPayloadLength = -1; + return packet; +} + +QByteArray SessionPacket::createPacket(const QJsonObject &packet) +{ + const QByteArray jsonData = QJsonDocument(packet).toJson(QJsonDocument::Compact).toBase64(); + return QByteArray(packetStart).append(QByteArray::number(jsonData.length())).append('\n') + .append(jsonData); +} + +QJsonObject SessionPacket::helloMessage() +{ + return QJsonObject{ + {StringConstants::type(), QLatin1String("hello")}, + {QLatin1String("api-level"), 1}, + {QLatin1String("api-compat-level"), 1} + }; +} + +bool SessionPacket::isComplete() const +{ + return m_payload.length() == m_expectedPayloadLength; +} + +} // namespace Internal +} // namespace qbs diff --git a/src/app/qbs/sessionpacket.h b/src/app/qbs/sessionpacket.h new file mode 100644 index 000000000..d919ff340 --- /dev/null +++ b/src/app/qbs/sessionpacket.h @@ -0,0 +1,70 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qbs. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QBS_SESSIONPACKET_H +#define QBS_SESSIONPACKET_H + +#include <QtCore/qbytearray.h> +#include <QtCore/qjsonobject.h> + +namespace qbs { +namespace Internal { + +class SessionPacket +{ +public: + enum class Status { Incomplete, Complete, Invalid }; + Status parseInput(QByteArray &input); + + QJsonObject retrievePacket(); + + static QByteArray createPacket(const QJsonObject &packet); + static QJsonObject helloMessage(); + +private: + bool isComplete() const; + + QByteArray m_payload; + int m_expectedPayloadLength = -1; +}; + +} // namespace Internal +} // namespace qbs + +#endif // Include guard diff --git a/src/app/qbs/sessionpacketreader.cpp b/src/app/qbs/sessionpacketreader.cpp new file mode 100644 index 000000000..fe4b73f69 --- /dev/null +++ b/src/app/qbs/sessionpacketreader.cpp @@ -0,0 +1,85 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qbs. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "sessionpacketreader.h" + +#include "sessionpacket.h" +#include "stdinreader.h" + +namespace qbs { +namespace Internal { + +class SessionPacketReader::Private +{ +public: + QByteArray incomingData; + SessionPacket currentPacket; +}; + +SessionPacketReader::SessionPacketReader(QObject *parent) : QObject(parent), d(new Private) { } + +SessionPacketReader::~SessionPacketReader() +{ + delete d; +} + +void SessionPacketReader::start() +{ + StdinReader * const stdinReader = StdinReader::create(this); + connect(stdinReader, &StdinReader::errorOccurred, this, &SessionPacketReader::errorOccurred); + connect(stdinReader, &StdinReader::dataAvailable, this, [this](const QByteArray &data) { + d->incomingData += data; + while (!d->incomingData.isEmpty()) { + switch (d->currentPacket.parseInput(d->incomingData)) { + case SessionPacket::Status::Invalid: + emit errorOccurred(tr("Received invalid input.")); + return; + case SessionPacket::Status::Complete: + emit packetReceived(d->currentPacket.retrievePacket()); + break; + case SessionPacket::Status::Incomplete: + return; + } + } + }); + stdinReader->start(); +} + +} // namespace Internal +} // namespace qbs diff --git a/src/app/qbs/sessionpacketreader.h b/src/app/qbs/sessionpacketreader.h new file mode 100644 index 000000000..87d70cf39 --- /dev/null +++ b/src/app/qbs/sessionpacketreader.h @@ -0,0 +1,70 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qbs. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QBS_SESSIONPACKETREADER_H +#define QBS_SESSIONPACKETREADER_H + +#include <QtCore/qjsonobject.h> +#include <QtCore/qobject.h> + +namespace qbs { +namespace Internal { + +class SessionPacketReader : public QObject +{ + Q_OBJECT +public: + explicit SessionPacketReader(QObject *parent = nullptr); + ~SessionPacketReader(); + + void start(); + +signals: + void packetReceived(const QJsonObject &packet); + void errorOccurred(const QString &msg); + +private: + class Private; + Private * const d; +}; + +} // namespace Internal +} // namespace qbs + +#endif // Include guard diff --git a/src/app/qbs/stdinreader.cpp b/src/app/qbs/stdinreader.cpp new file mode 100644 index 000000000..4f784505d --- /dev/null +++ b/src/app/qbs/stdinreader.cpp @@ -0,0 +1,146 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qbs. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "stdinreader.h" + +#include <tools/hostosinfo.h> + +#include <QtCore/qfile.h> +#include <QtCore/qsocketnotifier.h> + +#include <cerrno> +#include <cstring> + +#ifdef Q_OS_WIN32 +#include <qt_windows.h> +#include <QtCore/qtimer.h> +#else +#include <fcntl.h> +#endif + +namespace qbs { +namespace Internal { + +class UnixStdinReader : public StdinReader +{ +public: + UnixStdinReader(QObject *parent) : StdinReader(parent), m_notifier(0, QSocketNotifier::Read) {} + +private: + void start() override + { + if (!m_stdIn.open(stdin, QIODevice::ReadOnly)) { + emit errorOccurred(tr("Cannot read from standard input.")); + return; + } + const auto emitError = [this] { + emit errorOccurred(tr("Failed to make standard input non-blocking: %1") + .arg(QLatin1String(std::strerror(errno)))); + }; +#ifdef Q_OS_UNIX + const int flags = fcntl(0, F_GETFL, 0); + if (flags == -1) { + emitError(); + return; + } + if (fcntl(0, F_SETFL, flags | O_NONBLOCK)) { + emitError(); + return; + } +#endif + connect(&m_notifier, &QSocketNotifier::activated, this, [this] { + emit dataAvailable(m_stdIn.readAll()); + }); + } + + QFile m_stdIn; + QSocketNotifier m_notifier; +}; + +class WindowsStdinReader : public StdinReader +{ +public: + WindowsStdinReader(QObject *parent) : StdinReader(parent) {} + +private: + void start() override + { +#ifdef Q_OS_WIN32 + m_stdinHandle = GetStdHandle(STD_INPUT_HANDLE); + if (!m_stdinHandle) { + emit errorOccurred(tr("Failed to create handle for standard input.")); + return; + } + + // A timer seems slightly less awful than to block in a thread + // (how would we abort that one?), but ideally we'd like + // to have a signal-based approach like in the Unix variant. + const auto timer = new QTimer(this); + connect(timer, &QTimer::timeout, this, [this] { + char buf[1024]; + DWORD bytesAvail; + PeekNamedPipe(m_stdinHandle, nullptr, 0, nullptr, &bytesAvail, nullptr); + while (bytesAvail > 0) { + DWORD bytesRead; + ReadFile(m_stdinHandle, buf, std::min<DWORD>(bytesAvail, sizeof buf), &bytesRead, + nullptr); + emit dataAvailable(QByteArray(buf, bytesRead)); + bytesAvail -= bytesRead; + } + }); + timer->start(10); +#endif + } + +#ifdef Q_OS_WIN32 + HANDLE m_stdinHandle; +#endif +}; + +StdinReader *StdinReader::create(QObject *parent) +{ + if (HostOsInfo::isWindowsHost()) + return new WindowsStdinReader(parent); + return new UnixStdinReader(parent); +} + +StdinReader::StdinReader(QObject *parent) : QObject(parent) { } + +} // namespace Internal +} // namespace qbs diff --git a/src/app/qbs/stdinreader.h b/src/app/qbs/stdinreader.h new file mode 100644 index 000000000..b3737e5ae --- /dev/null +++ b/src/app/qbs/stdinreader.h @@ -0,0 +1,66 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qbs. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QBS_STDINREADER_H +#define QBS_STDINREADER_H + +#include <QtCore/qobject.h> + +namespace qbs { +namespace Internal { + +class StdinReader : public QObject +{ + Q_OBJECT +public: + static StdinReader *create(QObject *parent); + virtual void start() = 0; + +signals: + void errorOccurred(const QString &error); + void dataAvailable(const QByteArray &data); + +protected: + explicit StdinReader(QObject *parent); +}; + +} // namespace Internal +} // namespace qbs + +#endif // Include guard diff --git a/src/lib/corelib/api/project.cpp b/src/lib/corelib/api/project.cpp index 3ffd6b2e9..d0fe7296e 100644 --- a/src/lib/corelib/api/project.cpp +++ b/src/lib/corelib/api/project.cpp @@ -726,7 +726,7 @@ void ProjectPrivate::updateExternalCodeLocations(const ProjectData &project, void ProjectPrivate::prepareChangeToProject() { if (internalProject->locked) - throw ErrorInfo(Tr::tr("A job is currently in process.")); + throw ErrorInfo(Tr::tr("A job is currently in progress.")); if (!m_projectData.isValid()) retrieveProjectData(m_projectData, internalProject); } @@ -766,7 +766,7 @@ RuleCommandList ProjectPrivate::ruleCommands(const ProductData &product, const QString &inputFilePath, const QString &outputFileTag) { if (internalProject->locked) - throw ErrorInfo(Tr::tr("A job is currently in process.")); + throw ErrorInfo(Tr::tr("A job is currently in progress.")); const ResolvedProductConstPtr resolvedProduct = internalProduct(product); if (!resolvedProduct) throw ErrorInfo(Tr::tr("No such product '%1'.").arg(product.name())); @@ -896,7 +896,7 @@ void ProjectPrivate::retrieveProjectData(ProjectData &projectData, } for (const ResolvedProductPtr &resolvedDependentProduct : qAsConst(resolvedProduct->dependencies)) { - product.d->dependencies << resolvedDependentProduct->name; + product.d->dependencies << resolvedDependentProduct->name; // FIXME: Shouldn't this be a unique name? } std::sort(product.d->type.begin(), product.d->type.end()); std::sort(product.d->groups.begin(), product.d->groups.end()); @@ -1252,6 +1252,22 @@ Project::BuildGraphInfo Project::getBuildGraphInfo(const QString &bgFilePath, return info; } +Project::BuildGraphInfo Project::getBuildGraphInfo() const +{ + QBS_ASSERT(isValid(), return {}); + BuildGraphInfo info; + try { + if (d->internalProject->locked) + throw ErrorInfo(Tr::tr("A job is currently in progress.")); + info.bgFilePath = d->internalProject->buildGraphFilePath(); + info.overriddenProperties = d->internalProject->overriddenValues; + info.profileData = d->internalProject->profileConfigs; + } catch (const ErrorInfo &e) { + info.error = e; + } + return info; +} + #ifdef QBS_ENABLE_PROJECT_FILE_UPDATES /*! * \brief Adds a new empty group to the given product. diff --git a/src/lib/corelib/api/project.h b/src/lib/corelib/api/project.h index 05f08deee..9000d6548 100644 --- a/src/lib/corelib/api/project.h +++ b/src/lib/corelib/api/project.h @@ -155,6 +155,9 @@ public: static BuildGraphInfo getBuildGraphInfo(const QString &bgFilePath, const QStringList &requestedProperties); + // Use with loaded project. Does not set requestedProperties. + BuildGraphInfo getBuildGraphInfo() const; + #ifdef QBS_ENABLE_PROJECT_FILE_UPDATES ErrorInfo addGroup(const ProductData &product, const QString &groupName); diff --git a/src/lib/corelib/api/projectdata.cpp b/src/lib/corelib/api/projectdata.cpp index 56700b8be..7c64bf6ff 100644 --- a/src/lib/corelib/api/projectdata.cpp +++ b/src/lib/corelib/api/projectdata.cpp @@ -45,21 +45,57 @@ #include <tools/fileinfo.h> #include <tools/jsliterals.h> #include <tools/qbsassert.h> +#include <tools/stringconstants.h> #include <tools/qttools.h> #include <tools/stringconstants.h> #include <QtCore/qdir.h> +#include <QtCore/qjsonarray.h> +#include <QtCore/qjsonobject.h> #include <algorithm> namespace qbs { +using namespace Internal; + +template<typename T> static QJsonArray toJsonArray(const QList<T> &list, + const QStringList &moduleProperties) +{ + QJsonArray jsonArray; + std::transform(list.begin(), list.end(), std::back_inserter(jsonArray), + [&moduleProperties](const T &v) { return v.toJson(moduleProperties);}); + return jsonArray; +} + +static QVariant getModuleProperty(const PropertyMap &properties, const QString &fullPropertyName) +{ + const int lastDotIndex = fullPropertyName.lastIndexOf(QLatin1Char('.')); + if (lastDotIndex == -1) + return QVariant(); + return properties.getModuleProperty(fullPropertyName.left(lastDotIndex), + fullPropertyName.mid(lastDotIndex + 1)); +} + +static void addModuleProperties(QJsonObject &obj, const PropertyMap &properties, + const QStringList &propertyNames) +{ + QJsonObject propertyValues; + for (const QString &prop : propertyNames) { + const QVariant v = getModuleProperty(properties, prop); + if (v.isValid()) + propertyValues.insert(prop, QJsonValue::fromVariant(v)); + } + if (!propertyValues.isEmpty()) + obj.insert(StringConstants::modulePropertiesKey(), propertyValues); +} + /*! * \class GroupData * \brief The \c GroupData class corresponds to the Group item in a qbs source file. */ -GroupData::GroupData() : d(new Internal::GroupDataPrivate) +GroupData::GroupData() : d(new GroupDataPrivate) { } @@ -81,6 +117,22 @@ bool GroupData::isValid() const return d->isValid; } +QJsonObject GroupData::toJson(const QStringList &moduleProperties) const +{ + QJsonObject obj; + if (isValid()) { + obj.insert(StringConstants::locationKey(), location().toJson()); + obj.insert(StringConstants::nameProperty(), name()); + obj.insert(StringConstants::prefixProperty(), prefix()); + obj.insert(StringConstants::isEnabledKey(), isEnabled()); + obj.insert(QStringLiteral("source-artifacts"), toJsonArray(sourceArtifacts(), {})); + obj.insert(QStringLiteral("source-artifacts-from-wildcards"), + toJsonArray(sourceArtifactsFromWildcards(), {})); + addModuleProperties(obj, properties(), moduleProperties); + } + return obj; +} + /*! * \brief The location at which the group is defined in the respective source file. */ @@ -204,7 +256,7 @@ bool operator<(const GroupData &lhs, const GroupData &rhs) * or it gets generated during the build process. */ -ArtifactData::ArtifactData() : d(new Internal::ArtifactDataPrivate) +ArtifactData::ArtifactData() : d(new ArtifactDataPrivate) { } @@ -226,6 +278,21 @@ bool ArtifactData::isValid() const return d->isValid; } +QJsonObject ArtifactData::toJson(const QStringList &moduleProperties) const +{ + QJsonObject obj; + if (isValid()) { + obj.insert(StringConstants::filePathKey(), filePath()); + obj.insert(QStringLiteral("file-tags"), QJsonArray::fromStringList(fileTags())); + obj.insert(QStringLiteral("is-generated"), isGenerated()); + obj.insert(QStringLiteral("is-executable"), isExecutable()); + obj.insert(QStringLiteral("is-target"), isTargetArtifact()); + obj.insert(QStringLiteral("install-data"), installData().toJson()); + addModuleProperties(obj, properties(), moduleProperties); + } + return obj; +} + /*! * \brief The full path of this file. */ @@ -256,8 +323,8 @@ bool ArtifactData::isExecutable() const { const bool isBundle = d->properties.getModuleProperty( QStringLiteral("bundle"), QStringLiteral("isBundle")).toBool(); - return Internal::isRunnableArtifact( - Internal::FileTags::fromStringList(d->fileTags), isBundle); + return isRunnableArtifact( + FileTags::fromStringList(d->fileTags), isBundle); } /*! @@ -309,7 +376,7 @@ bool operator<(const ArtifactData &ta1, const ArtifactData &ta2) * \brief The \c InstallData class provides the installation-related data of an artifact. */ -InstallData::InstallData() : d(new Internal::InstallDataPrivate) +InstallData::InstallData() : d(new InstallDataPrivate) { } @@ -331,6 +398,19 @@ bool InstallData::isValid() const return d->isValid; } +QJsonObject InstallData::toJson() const +{ + QJsonObject obj; + if (isValid()) { + obj.insert(QStringLiteral("is-installable"), isInstallable()); + if (isInstallable()) { + obj.insert(QStringLiteral("install-file-path"), installFilePath()); + obj.insert(QStringLiteral("install-root"), installRoot()); + } + } + return obj; +} + /*! \brief Returns true if and only if \c{qbs.install} is \c true for the artifact. */ @@ -348,7 +428,7 @@ bool InstallData::isInstallable() const QString InstallData::installDir() const { QBS_ASSERT(isValid(), return {}); - return Internal::FileInfo::path(installFilePath()); + return FileInfo::path(installFilePath()); } /*! @@ -392,7 +472,7 @@ QString InstallData::localInstallFilePath() const * \brief The \c ProductData class corresponds to the Product item in a qbs source file. */ -ProductData::ProductData() : d(new Internal::ProductDataPrivate) +ProductData::ProductData() : d(new ProductDataPrivate) { } @@ -414,6 +494,39 @@ bool ProductData::isValid() const return d->isValid; } +QJsonObject ProductData::toJson(const QStringList &propertyNames) const +{ + QJsonObject obj; + if (!isValid()) + return obj; + obj.insert(StringConstants::typeProperty(), QJsonArray::fromStringList(type())); + obj.insert(StringConstants::dependenciesProperty(), + QJsonArray::fromStringList(dependencies())); + obj.insert(StringConstants::nameProperty(), name()); + obj.insert(StringConstants::fullDisplayNameKey(), fullDisplayName()); + obj.insert(QStringLiteral("target-name"), targetName()); + obj.insert(StringConstants::versionProperty(), version()); + obj.insert(QStringLiteral("multiplex-configuration-id"), multiplexConfigurationId()); + obj.insert(StringConstants::locationKey(), location().toJson()); + obj.insert(StringConstants::buildDirectoryKey(), buildDirectory()); + obj.insert(QStringLiteral("generated-artifacts"), toJsonArray(generatedArtifacts(), + propertyNames)); + obj.insert(QStringLiteral("target-executable"), targetExecutable()); + QJsonArray groupArray; + for (const GroupData &g : groups()) { + const QStringList groupPropNames = g.properties() == moduleProperties() + ? QStringList() : propertyNames; + groupArray << g.toJson(groupPropNames); + } + obj.insert(QStringLiteral("groups"), groupArray); + obj.insert(QStringLiteral("properties"), QJsonObject::fromVariantMap(properties())); + obj.insert(StringConstants::isEnabledKey(), isEnabled()); + obj.insert(QStringLiteral("is-runnable"), isRunnable()); + obj.insert(QStringLiteral("is-multiplexed"), isMultiplexed()); + addModuleProperties(obj, moduleProperties(), propertyNames); + return obj; +} + /*! * \brief The product type, which is the list of file tags matching the product's target artifacts. */ @@ -445,7 +558,7 @@ QString ProductData::name() const */ QString ProductData::fullDisplayName() const { - return Internal::ResolvedProduct::fullDisplayName(name(), multiplexConfigurationId()); + return ResolvedProduct::fullDisplayName(name(), multiplexConfigurationId()); } /*! @@ -470,8 +583,8 @@ QString ProductData::version() const QString ProductData::profile() const { return d->moduleProperties.getModuleProperty( - Internal::StringConstants::qbsModule(), - Internal::StringConstants::profileProperty()).toString(); + StringConstants::qbsModule(), + StringConstants::profileProperty()).toString(); } QString ProductData::multiplexConfigurationId() const @@ -661,7 +774,7 @@ bool operator<(const ProductData &lhs, const ProductData &rhs) * \brief The products in this project. */ -ProjectData::ProjectData() : d(new Internal::ProjectDataPrivate) +ProjectData::ProjectData() : d(new ProjectDataPrivate) { } @@ -683,6 +796,19 @@ bool ProjectData::isValid() const return d->isValid; } +QJsonObject ProjectData::toJson(const QStringList &moduleProperties) const +{ + QJsonObject obj; + if (!isValid()) + return obj; + obj.insert(StringConstants::nameProperty(), name()); + obj.insert(StringConstants::locationKey(), location().toJson()); + obj.insert(StringConstants::isEnabledKey(), isEnabled()); + obj.insert(StringConstants::productsKey(), toJsonArray(products(), moduleProperties)); + obj.insert(QStringLiteral("sub-projects"), toJsonArray(subProjects(), moduleProperties)); + return obj; +} + /*! * \brief The name of this project. */ @@ -788,14 +914,14 @@ bool operator<(const ProjectData &lhs, const ProjectData &rhs) */ PropertyMap::PropertyMap() - : d(std::make_unique<Internal::PropertyMapPrivate>()) + : d(std::make_unique<PropertyMapPrivate>()) { - static Internal::PropertyMapPtr defaultInternalMap = Internal::PropertyMapInternal::create(); + static PropertyMapPtr defaultInternalMap = PropertyMapInternal::create(); d->m_map = defaultInternalMap; } PropertyMap::PropertyMap(const PropertyMap &other) - : d(std::make_unique<Internal::PropertyMapPrivate>(*other.d)) + : d(std::make_unique<PropertyMapPrivate>(*other.d)) { } @@ -806,7 +932,7 @@ PropertyMap::~PropertyMap() = default; PropertyMap &PropertyMap::operator =(const PropertyMap &other) { if (this != &other) - d = std::make_unique<Internal::PropertyMapPrivate>(*other.d); + d = std::make_unique<PropertyMapPrivate>(*other.d); return *this; } diff --git a/src/lib/corelib/api/projectdata.h b/src/lib/corelib/api/projectdata.h index 3bd1c4540..a285f8570 100644 --- a/src/lib/corelib/api/projectdata.h +++ b/src/lib/corelib/api/projectdata.h @@ -110,6 +110,7 @@ public: ~ArtifactData(); bool isValid() const; + QJsonObject toJson(const QStringList &moduleProperties = {}) const; QString filePath() const; QStringList fileTags() const; @@ -135,6 +136,7 @@ public: ~InstallData(); bool isValid() const; + QJsonObject toJson() const; bool isInstallable() const; QString installDir() const; @@ -162,6 +164,7 @@ public: ~GroupData(); bool isValid() const; + QJsonObject toJson(const QStringList &moduleProperties = {}) const; CodeLocation location() const; QString name() const; @@ -193,6 +196,7 @@ public: ~ProductData(); bool isValid() const; + QJsonObject toJson(const QStringList &propertyNames = {}) const; QStringList type() const; QStringList dependencies() const; @@ -235,6 +239,7 @@ public: ~ProjectData(); bool isValid() const; + QJsonObject toJson(const QStringList &moduleProperties = {}) const; QString name() const; CodeLocation location() const; diff --git a/src/lib/corelib/buildgraph/abstractcommandexecutor.cpp b/src/lib/corelib/buildgraph/abstractcommandexecutor.cpp index 1a1d51f11..16c3621b6 100644 --- a/src/lib/corelib/buildgraph/abstractcommandexecutor.cpp +++ b/src/lib/corelib/buildgraph/abstractcommandexecutor.cpp @@ -1,6 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2019 Jochen Ulrich <jochenulrich@t-online.de> ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. @@ -58,6 +59,14 @@ AbstractCommandExecutor::AbstractCommandExecutor(Logger logger, QObject *parent) , m_dryRun(false) , m_logger(std::move(logger)) { + m_watchdog.setSingleShot(true); + connect(&m_watchdog, &QTimer::timeout, + this, [this]() { + cancel(ErrorInfo{Tr::tr("Command cancelled because it exceeded the timeout.")}); + }); + connect(this, &AbstractCommandExecutor::finished, + &m_watchdog, &QTimer::stop); + } void AbstractCommandExecutor::start(Transformer *transformer, AbstractCommand *cmd) @@ -66,7 +75,8 @@ void AbstractCommandExecutor::start(Transformer *transformer, AbstractCommand *c m_command = cmd; doSetup(); doReportCommandDescription(transformer->product()->fullDisplayName()); - doStart(); + if (doStart()) + startTimeout(); } void AbstractCommandExecutor::doReportCommandDescription(const QString &productName) @@ -84,5 +94,14 @@ void AbstractCommandExecutor::doReportCommandDescription(const QString &productN } } +void AbstractCommandExecutor::startTimeout() +{ + if (!m_dryRun || m_command->ignoreDryRun()) { + const auto timeout = m_command->timeout(); + if (timeout > 0) + m_watchdog.start(timeout * 1000); + } +} + } // namespace Internal } // namespace qbs diff --git a/src/lib/corelib/buildgraph/abstractcommandexecutor.h b/src/lib/corelib/buildgraph/abstractcommandexecutor.h index 60b2b40b2..c0f149622 100644 --- a/src/lib/corelib/buildgraph/abstractcommandexecutor.h +++ b/src/lib/corelib/buildgraph/abstractcommandexecutor.h @@ -1,6 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2019 Jochen Ulrich <jochenulrich@t-online.de> ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. @@ -45,6 +46,7 @@ #include <tools/error.h> #include <QtCore/qobject.h> +#include <QtCore/qtimer.h> namespace qbs { class ErrorInfo; @@ -64,7 +66,7 @@ public: void setDryRunEnabled(bool enabled) { m_dryRun = enabled; } void setEchoMode(CommandEchoMode echoMode) { m_echoMode = echoMode; } - virtual void cancel() = 0; + virtual void cancel(const qbs::ErrorInfo &reason = {}) = 0; void start(Transformer *transformer, AbstractCommand *cmd); @@ -83,7 +85,9 @@ protected: private: virtual void doSetup() { }; - virtual void doStart() = 0; + virtual bool doStart() = 0; + + void startTimeout(); private: AbstractCommand *m_command; @@ -91,6 +95,7 @@ private: ScriptEngine *m_mainThreadScriptEngine; bool m_dryRun; Internal::Logger m_logger; + QTimer m_watchdog; }; } // namespace Internal diff --git a/src/lib/corelib/buildgraph/jscommandexecutor.cpp b/src/lib/corelib/buildgraph/jscommandexecutor.cpp index 30970779c..5c83b2056 100644 --- a/src/lib/corelib/buildgraph/jscommandexecutor.cpp +++ b/src/lib/corelib/buildgraph/jscommandexecutor.cpp @@ -1,6 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2019 Jochen Ulrich <jochenulrich@t-online.de> ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. @@ -82,9 +83,11 @@ public: return m_result; } - void cancel() + void cancel(const qbs::ErrorInfo &reason) { QBS_ASSERT(m_scriptEngine, return); + m_result.success = !reason.hasError(); + m_result.errorMessage = reason.toString(); m_scriptEngine->abortEvaluation(); } @@ -226,24 +229,25 @@ void JsCommandExecutor::waitForFinished() loop.exec(); } -void JsCommandExecutor::doStart() +bool JsCommandExecutor::doStart() { - QBS_ASSERT(!m_running, return); + QBS_ASSERT(!m_running, return false); m_thread->start(); if (dryRun() && !command()->ignoreDryRun()) { QTimer::singleShot(0, this, [this] { emit finished(); }); // Don't call back on the caller. - return; + return false; } m_running = true; emit startRequested(jsCommand(), transformer()); + return true; } -void JsCommandExecutor::cancel() +void JsCommandExecutor::cancel(const qbs::ErrorInfo &reason) { if (m_running && !dryRun()) - QTimer::singleShot(0, m_objectInThread, [this] { m_objectInThread->cancel(); }); + QTimer::singleShot(0, m_objectInThread, [objectInThread = m_objectInThread, reason] { objectInThread->cancel(reason); }); } void JsCommandExecutor::onJavaScriptCommandFinished() diff --git a/src/lib/corelib/buildgraph/jscommandexecutor.h b/src/lib/corelib/buildgraph/jscommandexecutor.h index 0170c5231..0725f0d24 100644 --- a/src/lib/corelib/buildgraph/jscommandexecutor.h +++ b/src/lib/corelib/buildgraph/jscommandexecutor.h @@ -1,6 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2019 Jochen Ulrich <jochenulrich@t-online.de> ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. @@ -65,8 +66,8 @@ private: void onJavaScriptCommandFinished(); void doReportCommandDescription(const QString &productName) override; - void doStart() override; - void cancel() override; + bool doStart() override; + void cancel(const qbs::ErrorInfo &reason) override; void waitForFinished(); diff --git a/src/lib/corelib/buildgraph/processcommandexecutor.cpp b/src/lib/corelib/buildgraph/processcommandexecutor.cpp index c4e4a2be6..79edda320 100644 --- a/src/lib/corelib/buildgraph/processcommandexecutor.cpp +++ b/src/lib/corelib/buildgraph/processcommandexecutor.cpp @@ -1,6 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2019 Jochen Ulrich <jochenulrich@t-online.de> ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. @@ -119,9 +120,9 @@ void ProcessCommandExecutor::doSetup() m_shellInvocation = shellQuote(QDir::toNativeSeparators(m_program), m_arguments); } -void ProcessCommandExecutor::doStart() +bool ProcessCommandExecutor::doStart() { - QBS_ASSERT(m_process.state() == QProcess::NotRunning, return); + QBS_ASSERT(m_process.state() == QProcess::NotRunning, return false); const ProcessCommand * const cmd = processCommand(); @@ -131,7 +132,7 @@ void ProcessCommandExecutor::doStart() if (dryRun() && !cmd->ignoreDryRun()) { QTimer::singleShot(0, this, [this] { emit finished(); }); // Don't call back on the caller. - return; + return false; } const QString workingDir = QDir::fromNativeSeparators(cmd->workingDir()); @@ -142,7 +143,7 @@ void ProcessCommandExecutor::doStart() "is invalid.").arg(QDir::toNativeSeparators(workingDir), QDir::toNativeSeparators(m_program)), cmd->codeLocation())); - return; + return false; } } @@ -163,7 +164,7 @@ void ProcessCommandExecutor::doStart() if (!responseFile.open()) { emit finished(ErrorInfo(Tr::tr("Cannot create response file '%1'.") .arg(responseFile.fileName()))); - return; + return false; } for (int i = cmd->responseFileArgumentIndex(); i < cmd->arguments().size(); ++i) { const QString arg = cmd->arguments().at(i); @@ -172,7 +173,7 @@ void ProcessCommandExecutor::doStart() if (!f.open(QIODevice::ReadOnly)) { emit finished(ErrorInfo(Tr::tr("Cannot open command file '%1'.") .arg(QDir::toNativeSeparators(f.fileName())))); - return; + return false; } responseFile.write(f.readAll()); } else { @@ -194,13 +195,15 @@ void ProcessCommandExecutor::doStart() qCDebug(lcExec) << "Additional environment:" << additionalVariables.toStringList(); m_process.setWorkingDirectory(workingDir); m_process.start(m_program, arguments); + return true; } -void ProcessCommandExecutor::cancel() +void ProcessCommandExecutor::cancel(const qbs::ErrorInfo &reason) { // We don't want this command to be reported as failing, since we explicitly terminated it. disconnect(this, &ProcessCommandExecutor::reportProcessResult, nullptr, nullptr); + m_cancelReason = reason; m_process.cancel(); } @@ -304,10 +307,13 @@ void ProcessCommandExecutor::sendProcessOutput() const bool processError = result.error() != QProcess::UnknownError; const bool failureExit = quint32(m_process.exitCode()) > quint32(processCommand()->maxExitCode()); - result.d->success = !processError && !failureExit; + const bool cancelledWithError = m_cancelReason.hasError(); + result.d->success = !processError && !failureExit && !cancelledWithError; emit reportProcessResult(result); - if (Q_UNLIKELY(processError)) { + if (Q_UNLIKELY(cancelledWithError)) { + emit finished(m_cancelReason); + } else if (Q_UNLIKELY(processError)) { emit finished(ErrorInfo(errorString)); } else if (Q_UNLIKELY(failureExit)) { emit finished(ErrorInfo(Tr::tr("Process failed with exit code %1.") @@ -325,6 +331,8 @@ void ProcessCommandExecutor::onProcessError() QTimer::singleShot(0, this, &ProcessCommandExecutor::onProcessError); return; } + if (m_cancelReason.hasError()) + return; // Ignore. Cancel reasons will be handled by on ProcessFinished(). switch (m_process.error()) { case QProcess::FailedToStart: { removeResponseFile(); diff --git a/src/lib/corelib/buildgraph/processcommandexecutor.h b/src/lib/corelib/buildgraph/processcommandexecutor.h index 67eb9f746..b0f955882 100644 --- a/src/lib/corelib/buildgraph/processcommandexecutor.h +++ b/src/lib/corelib/buildgraph/processcommandexecutor.h @@ -1,6 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2019 Jochen Ulrich <jochenulrich@t-online.de> ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. @@ -71,8 +72,8 @@ private: void doSetup() override; void doReportCommandDescription(const QString &productName) override; - void doStart() override; - void cancel() override; + bool doStart() override; + void cancel(const qbs::ErrorInfo &reason) override; void startProcessCommand(); QString filterProcessOutput(const QByteArray &output, const QString &filterFunctionSource); @@ -91,6 +92,7 @@ private: QProcessEnvironment m_buildEnvironment; QProcessEnvironment m_commandEnvironment; QString m_responseFileName; + qbs::ErrorInfo m_cancelReason; }; } // namespace Internal diff --git a/src/lib/corelib/buildgraph/rulecommands.cpp b/src/lib/corelib/buildgraph/rulecommands.cpp index ecbc54292..31ff6be4b 100644 --- a/src/lib/corelib/buildgraph/rulecommands.cpp +++ b/src/lib/corelib/buildgraph/rulecommands.cpp @@ -1,6 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2019 Jochen Ulrich <jochenulrich@t-online.de> ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. @@ -74,6 +75,7 @@ static QString stderrFilePathProperty() { return QStringLiteral("stderrFilePath" static QString stderrFilterFunctionProperty() { return QStringLiteral("stderrFilterFunction"); } static QString stdoutFilePathProperty() { return QStringLiteral("stdoutFilePath"); } static QString stdoutFilterFunctionProperty() { return QStringLiteral("stdoutFilterFunction"); } +static QString timeoutProperty() { return QStringLiteral("timeout"); } static QString workingDirProperty() { return QStringLiteral("workingDirectory"); } static QString invokedSourceCode(const QScriptValue codeOrFunction) @@ -87,7 +89,8 @@ AbstractCommand::AbstractCommand() m_extendedDescription(defaultExtendedDescription()), m_highlight(defaultHighLight()), m_ignoreDryRun(defaultIgnoreDryRun()), - m_silent(defaultIsSilent()) + m_silent(defaultIsSilent()), + m_timeout(defaultTimeout()) { } @@ -104,6 +107,7 @@ bool AbstractCommand::equals(const AbstractCommand *other) const && m_ignoreDryRun == other->m_ignoreDryRun && m_silent == other->m_silent && m_jobPool == other->m_jobPool + && m_timeout == other->m_timeout && m_properties == other->m_properties; } @@ -115,6 +119,9 @@ void AbstractCommand::fillFromScriptValue(const QScriptValue *scriptValue, const m_ignoreDryRun = scriptValue->property(ignoreDryRunProperty()).toBool(); m_silent = scriptValue->property(silentProperty()).toBool(); m_jobPool = scriptValue->property(StringConstants::jobPoolProperty()).toString(); + const auto timeoutScriptValue = scriptValue->property(timeoutProperty()); + if (!timeoutScriptValue.isUndefined() && !timeoutScriptValue.isNull()) + m_timeout = timeoutScriptValue.toInt32(); m_codeLocation = codeLocation; m_predefinedProperties @@ -123,7 +130,8 @@ void AbstractCommand::fillFromScriptValue(const QScriptValue *scriptValue, const << highlightProperty() << ignoreDryRunProperty() << StringConstants::jobPoolProperty() - << silentProperty(); + << silentProperty() + << timeoutProperty(); } QString AbstractCommand::fullDescription(const QString &productName) const @@ -173,6 +181,8 @@ static QScriptValue js_CommandBase(QScriptContext *context, QScriptEngine *engin engine->toScriptValue(AbstractCommand::defaultIgnoreDryRun())); cmd.setProperty(silentProperty(), engine->toScriptValue(AbstractCommand::defaultIsSilent())); + cmd.setProperty(timeoutProperty(), + engine->toScriptValue(AbstractCommand::defaultTimeout())); return cmd; } diff --git a/src/lib/corelib/buildgraph/rulecommands.h b/src/lib/corelib/buildgraph/rulecommands.h index d9d561454..d4d70d591 100644 --- a/src/lib/corelib/buildgraph/rulecommands.h +++ b/src/lib/corelib/buildgraph/rulecommands.h @@ -1,6 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2019 Jochen Ulrich <jochenulrich@t-online.de> ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. @@ -70,6 +71,7 @@ public: static QString defaultHighLight() { return {}; } static bool defaultIgnoreDryRun() { return false; } static bool defaultIsSilent() { return false; } + static int defaultTimeout() { return -1; } virtual CommandType type() const = 0; virtual bool equals(const AbstractCommand *other) const; @@ -83,6 +85,7 @@ public: bool isSilent() const { return m_silent; } QString jobPool() const { return m_jobPool; } CodeLocation codeLocation() const { return m_codeLocation; } + int timeout() const { return m_timeout; } const QVariantMap &properties() const { return m_properties; } @@ -100,7 +103,7 @@ private: { pool.serializationOp<opType>(m_description, m_extendedDescription, m_highlight, m_ignoreDryRun, m_silent, m_codeLocation, m_jobPool, - m_properties); + m_timeout, m_properties); } QString m_description; @@ -110,6 +113,7 @@ private: bool m_silent; CodeLocation m_codeLocation; QString m_jobPool; + int m_timeout; QVariantMap m_properties; }; diff --git a/src/lib/corelib/corelib.qbs b/src/lib/corelib/corelib.qbs index a9ca5131a..2f0ced926 100644 --- a/src/lib/corelib/corelib.qbs +++ b/src/lib/corelib/corelib.qbs @@ -198,7 +198,24 @@ QbsLibrary { "generatableprojectiterator.h", "generator.cpp", "generatordata.cpp", + "generatorutils.cpp", + "generatorutils.h", + "generatorversioninfo.cpp", + "generatorversioninfo.h", "igeneratableprojectvisitor.h", + "ixmlnodevisitor.h", + "xmlproject.cpp", + "xmlproject.h", + "xmlprojectwriter.cpp", + "xmlprojectwriter.h", + "xmlproperty.cpp", + "xmlproperty.h", + "xmlpropertygroup.cpp", + "xmlpropertygroup.h", + "xmlworkspace.cpp", + "xmlworkspace.h", + "xmlworkspacewriter.cpp", + "xmlworkspacewriter.h", ] } Group { @@ -401,6 +418,7 @@ QbsLibrary { "joblimits.cpp", "jsliterals.cpp", "jsliterals.h", + "jsonhelper.h", "installoptions.cpp", "launcherinterface.cpp", "launcherinterface.h", diff --git a/src/lib/corelib/generators/generators.pri b/src/lib/corelib/generators/generators.pri index 093e45f40..e9730d895 100644 --- a/src/lib/corelib/generators/generators.pri +++ b/src/lib/corelib/generators/generators.pri @@ -3,13 +3,31 @@ include(../../../install_prefix.pri) SOURCES += \ $$PWD/generatableprojectiterator.cpp \ $$PWD/generator.cpp \ - $$PWD/generatordata.cpp + $$PWD/generatordata.cpp \ + $$PWD/generatorutils.cpp \ + $$PWD/generatorversioninfo.cpp \ + $$PWD/xmlproject.cpp \ + $$PWD/xmlprojectwriter.cpp\ + $$PWD/xmlproperty.cpp \ + $$PWD/xmlpropertygroup.cpp \ + $$PWD/xmlworkspace.cpp \ + $$PWD/xmlworkspacewriter.cpp HEADERS += \ $$PWD/generatableprojectiterator.h \ $$PWD/generator.h \ $$PWD/generatordata.h \ - $$PWD/igeneratableprojectvisitor.h + $$PWD/generatorutils.h \ + $$PWD/generatorversioninfo.h \ + $$PWD/igeneratableprojectvisitor.h \ + $$PWD/ixmlnodevisitor.h \ + $$PWD/ixmlnodevisitor.h \ + $$PWD/xmlproject.h \ + $$PWD/xmlprojectwriter.h \ + $$PWD/xmlproperty.h \ + $$PWD/xmlpropertygroup.h \ + $$PWD/xmlworkspace.h \ + $$PWD/xmlworkspacewriter.h !qbs_no_dev_install { generators_headers.files = \ diff --git a/src/lib/corelib/generators/generatorutils.cpp b/src/lib/corelib/generators/generatorutils.cpp new file mode 100644 index 000000000..9c00eef05 --- /dev/null +++ b/src/lib/corelib/generators/generatorutils.cpp @@ -0,0 +1,262 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt.io/licensing +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "generatorutils.h" + +namespace qbs { +namespace gen { +namespace utils { + +QString architectureName(Architecture arch) +{ + switch (arch) { + case Architecture::Arm: + return QStringLiteral("arm"); + case Architecture::Avr: + return QStringLiteral("avr"); + case Architecture::Mcs51: + return QStringLiteral("mcs51"); + default: + return QStringLiteral("unknown"); + } +} + +Architecture architecture(const Project &qbsProject) +{ + const auto qbsArch = qbsProject.projectConfiguration() + .value(Internal::StringConstants::qbsModule()).toMap() + .value(QStringLiteral("architecture")).toString(); + + if (qbsArch == QLatin1String("arm")) + return Architecture::Arm; + if (qbsArch == QLatin1String("avr")) + return Architecture::Avr; + if (qbsArch == QLatin1String("mcs51")) + return Architecture::Mcs51; + if (qbsArch == QLatin1String("stm8")) + return Architecture::Stm8; + if (qbsArch == QLatin1String("msp430")) + return Architecture::Msp430; + return Architecture::Unknown; +} + +QString buildConfigurationName(const Project &qbsProject) +{ + return qbsProject.projectConfiguration() + .value(Internal::StringConstants::qbsModule()).toMap() + .value(QStringLiteral("configurationName")).toString(); +} + +int debugInformation(const ProductData &qbsProduct) +{ + return qbsProduct.moduleProperties().getModuleProperty( + Internal::StringConstants::qbsModule(), + QStringLiteral("debugInformation")) + .toInt(); +} + +QString buildRootPath(const Project &qbsProject) +{ + QDir dir(qbsProject.projectData().buildDirectory()); + dir.cdUp(); + return dir.absolutePath(); +} + +QString relativeFilePath(const QString &baseDirectory, + const QString &fullFilePath) +{ + return QDir(baseDirectory).relativeFilePath(fullFilePath); +} + +QString binaryOutputDirectory(const QString &baseDirectory, + const ProductData &qbsProduct) +{ + return QDir(baseDirectory).relativeFilePath( + qbsProduct.buildDirectory()) + + QLatin1String("/bin"); +} + +QString objectsOutputDirectory(const QString &baseDirectory, + const ProductData &qbsProduct) +{ + return QDir(baseDirectory).relativeFilePath( + qbsProduct.buildDirectory()) + + QLatin1String("/obj"); +} + +QString listingOutputDirectory(const QString &baseDirectory, + const ProductData &qbsProduct) +{ + return QDir(baseDirectory).relativeFilePath( + qbsProduct.buildDirectory()) + + QLatin1String("/lst"); +} + +std::vector<ProductData> dependenciesOf(const ProductData &qbsProduct, + const GeneratableProject &genProject, + const QString &configurationName) +{ + std::vector<ProductData> result; + const auto depsNames = qbsProduct.dependencies(); + for (const auto &product : qAsConst(genProject.products)) { + const auto pt = product.type(); + if (!pt.contains(QLatin1String("staticlibrary"))) + continue; + const auto pn = product.name(); + if (!depsNames.contains(pn)) + continue; + result.push_back(product.data.value(configurationName)); + } + return result; +} + +QString targetBinary(const ProductData &qbsProduct) +{ + const auto type = qbsProduct.type(); + if (type.contains(QLatin1String("application"))) { + return QFileInfo(qbsProduct.targetExecutable()).fileName(); + } else if (type.contains(QLatin1String("staticlibrary"))) { + const auto artifacts = qbsProduct.targetArtifacts(); + for (const auto &artifact : artifacts) { + if (artifact.fileTags().contains(QLatin1String("staticlibrary"))) + return QFileInfo(artifact.filePath()).fileName(); + } + } + + return {}; +} + +QString targetBinaryPath(const QString &baseDirectory, + const ProductData &qbsProduct) +{ + return binaryOutputDirectory(baseDirectory, qbsProduct) + + QLatin1Char('/') + targetBinary(qbsProduct); +} + +QString cppStringModuleProperty(const PropertyMap &qbsProps, + const QString &propertyName) +{ + return qbsProps.getModuleProperty( + Internal::StringConstants::cppModule(), + propertyName).toString().trimmed(); +} + +bool cppBooleanModuleProperty(const PropertyMap &qbsProps, + const QString &propertyName) +{ + return qbsProps.getModuleProperty( + Internal::StringConstants::cppModule(), + propertyName).toBool(); +} + +int cppIntegerModuleProperty(const PropertyMap &qbsProps, + const QString &propertyName) +{ + return qbsProps.getModuleProperty( + Internal::StringConstants::cppModule(), + propertyName).toInt(); +} + +QStringList cppStringModuleProperties(const PropertyMap &qbsProps, + const QStringList &propertyNames) +{ + QStringList properties; + for (const auto &propertyName : propertyNames) { + const auto entries = qbsProps.getModuleProperty( + Internal::StringConstants::cppModule(), + propertyName).toStringList(); + for (const auto &entry : entries) + properties.push_back(entry.trimmed()); + } + return properties; +} + +QVariantList cppVariantModuleProperties(const PropertyMap &qbsProps, + const QStringList &propertyNames) +{ + QVariantList properties; + for (const auto &propertyName : propertyNames) { + properties << qbsProps.getModuleProperty( + Internal::StringConstants::cppModule(), + propertyName).toList(); + } + return properties; +} + +static QString parseFlagValue(const QString &flagKey, + QStringList::const_iterator &flagIt, + const QStringList::const_iterator &flagEnd) +{ + if (flagIt->contains(QLatin1Char('='))) { + // In this case an option is in form of 'flagKey=<flagValue>'. + const auto parts = flagIt->split(QLatin1Char('=')); + if (parts.count() == 2) + return parts.at(1).trimmed(); + } else if (flagKey < *flagIt) { + // In this case an option is in form of 'flagKey<flagValue>'. + return flagIt->mid(flagKey.count()).trimmed(); + } else { + // In this case an option is in form of 'flagKey <flagValue>'. + ++flagIt; + if (flagIt < flagEnd && !flagIt->startsWith(QLatin1Char('-'))) + return (*flagIt).trimmed(); + } + return {}; +} + +QString firstFlagValue(const QStringList &flags, const QString &flagKey) +{ + const auto flagBegin = flags.cbegin(); + const auto flagEnd = flags.cend(); + auto flagIt = std::find_if(flagBegin, flagEnd, [flagKey](const QString &flag) { + return flag == flagKey || flag.startsWith(flagKey); + }); + if (flagIt == flagEnd) + return {}; + return parseFlagValue(flagKey, flagIt, flagEnd); +} + +QStringList allFlagValues(const QStringList &flags, const QString &flagKey) +{ + QStringList values; + const auto flagEnd = flags.cend(); + for (auto flagIt = flags.cbegin(); flagIt < flagEnd; ++flagIt) { + if (*flagIt == flagKey || flagIt->startsWith(flagKey)) { + const QString value = parseFlagValue(flagKey, flagIt, flagEnd); + if (!value.isEmpty()) + values.push_back(value); + } + } + return values; +} + +} // namespace utils +} // namespace gen +} // namespace qbs diff --git a/src/lib/corelib/generators/generatorutils.h b/src/lib/corelib/generators/generatorutils.h new file mode 100644 index 000000000..9348ab18c --- /dev/null +++ b/src/lib/corelib/generators/generatorutils.h @@ -0,0 +1,96 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt.io/licensing +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef GENERATORS_UTILS_H +#define GENERATORS_UTILS_H + +#include <qbs.h> + +#include <tools/qbs_export.h> +#include <tools/stringconstants.h> + +namespace qbs { +namespace gen { +namespace utils { + +enum class Architecture { + Arm, + Avr, + Mcs51, + Stm8, + Msp430, + Unknown +}; + +QBS_EXPORT QString architectureName(Architecture arch); +QBS_EXPORT Architecture architecture(const Project &qbsProject); +QBS_EXPORT QString buildConfigurationName(const Project &qbsProject); +QBS_EXPORT int debugInformation(const ProductData &qbsProduct); +QBS_EXPORT QString buildRootPath(const Project &qbsProject); +QBS_EXPORT QString relativeFilePath(const QString &baseDirectory, + const QString &fullFilePath); +QBS_EXPORT QString binaryOutputDirectory(const QString &baseDirectory, + const ProductData &qbsProduct); +QBS_EXPORT QString objectsOutputDirectory(const QString &baseDirectory, + const ProductData &qbsProduct); +QBS_EXPORT QString listingOutputDirectory(const QString &baseDirectory, + const ProductData &qbsProduct); +QBS_EXPORT std::vector<ProductData> dependenciesOf(const ProductData &qbsProduct, + const GeneratableProject &genProject, + const QString &configurationName); +QBS_EXPORT QString targetBinary(const ProductData &qbsProduct); +QBS_EXPORT QString targetBinaryPath(const QString &baseDirectory, + const ProductData &qbsProduct); +QBS_EXPORT QString cppStringModuleProperty(const PropertyMap &qbsProps, + const QString &propertyName); +QBS_EXPORT bool cppBooleanModuleProperty(const PropertyMap &qbsProps, + const QString &propertyName); +QBS_EXPORT int cppIntegerModuleProperty(const PropertyMap &qbsProps, + const QString &propertyName); +QBS_EXPORT QStringList cppStringModuleProperties(const PropertyMap &qbsProps, + const QStringList &propertyNames); +QBS_EXPORT QVariantList cppVariantModuleProperties(const PropertyMap &qbsProps, + const QStringList &propertyNames); +QBS_EXPORT QString firstFlagValue(const QStringList &flags, + const QString &flagKey); +QBS_EXPORT QStringList allFlagValues(const QStringList &flags, + const QString &flagKey); + +template <typename T> +bool inBounds(const T &value, const T &low, const T &high) +{ + return !(value < low) && !(high < value); +} + +} // namespace utils +} // namespace gen +} // namespace qbs + +#endif // GENERATORS_UTILS_H diff --git a/src/lib/corelib/generators/generatorversioninfo.cpp b/src/lib/corelib/generators/generatorversioninfo.cpp new file mode 100644 index 000000000..3e2106b57 --- /dev/null +++ b/src/lib/corelib/generators/generatorversioninfo.cpp @@ -0,0 +1,83 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qbs. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "generatorversioninfo.h" + +namespace qbs { +namespace gen { + +VersionInfo::VersionInfo(const Version &version, + const std::set<utils::Architecture> &archs) + : m_version(version), m_archs(archs) +{ +} + +bool VersionInfo::operator<(const VersionInfo &other) const +{ + return m_version < other.m_version; +} + +bool VersionInfo::operator==(const VersionInfo &other) const +{ + return m_version == other.m_version + && m_archs == other.m_archs; +} + +Version VersionInfo::version() const +{ + return m_version; +} + +bool VersionInfo::containsArchitecture(utils::Architecture arch) const +{ + return m_archs.find(arch) != m_archs.cend(); +} + +int VersionInfo::marketingVersion() const +{ + return m_version.majorVersion(); +} + +quint32 qHash(const VersionInfo &info) +{ + return qHash(info.version().toString()); +} + +} // namespace gen +} // namespace qbs diff --git a/src/lib/corelib/generators/generatorversioninfo.h b/src/lib/corelib/generators/generatorversioninfo.h new file mode 100644 index 000000000..65bfcf685 --- /dev/null +++ b/src/lib/corelib/generators/generatorversioninfo.h @@ -0,0 +1,78 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qbs. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef GENERATORS_VERSION_INFO_H +#define GENERATORS_VERSION_INFO_H + +#include "generatorutils.h" + +#include <tools/qbs_export.h> +#include <tools/version.h> + +#include <set> + +namespace qbs { +namespace gen { + +class QBS_EXPORT VersionInfo +{ +public: + VersionInfo(const Version &version, + const std::set<utils::Architecture> &archs); + virtual ~VersionInfo() = default; + + bool operator<(const VersionInfo &other) const; + bool operator==(const VersionInfo &other) const; + + Version version() const; + bool containsArchitecture(utils::Architecture arch) const; + + virtual int marketingVersion() const; + +private: + Version m_version; + std::set<utils::Architecture> m_archs; +}; + +quint32 qHash(const VersionInfo &info); + +} // namespace gen +} // namespace qbs + +#endif // GENERATORS_VERSION_INFO_H diff --git a/src/lib/corelib/generators/ixmlnodevisitor.h b/src/lib/corelib/generators/ixmlnodevisitor.h new file mode 100644 index 000000000..d3d118975 --- /dev/null +++ b/src/lib/corelib/generators/ixmlnodevisitor.h @@ -0,0 +1,69 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt.io/licensing +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef GENERATORS_XML_INODE_VISITOR_H +#define GENERATORS_XML_INODE_VISITOR_H + +#include <tools/qbs_export.h> + +#include <QtCore/qxmlstream.h> + +namespace qbs { +namespace gen { +namespace xml { + +class Project; +class Property; +class PropertyGroup; +class Workspace; + +class QBS_EXPORT INodeVisitor +{ +public: + virtual ~INodeVisitor() {} + + virtual void visitWorkspaceStart(const Workspace *workspace) { Q_UNUSED(workspace) } + virtual void visitWorkspaceEnd(const Workspace *workspace) { Q_UNUSED(workspace) } + + virtual void visitProjectStart(const Project *project) { Q_UNUSED(project) } + virtual void visitProjectEnd(const Project *project) { Q_UNUSED(project) } + + virtual void visitPropertyStart(const Property *property) = 0; + virtual void visitPropertyEnd(const Property *property) = 0; + + virtual void visitPropertyGroupStart(const PropertyGroup *propertyGroup) = 0; + virtual void visitPropertyGroupEnd(const PropertyGroup *propertyGroup) = 0; +}; + +} // namespace xml +} // namespace gen +} // namespace qbs + +#endif // GENERATORS_XML_INODE_VISITOR_H diff --git a/src/lib/corelib/generators/xmlproject.cpp b/src/lib/corelib/generators/xmlproject.cpp new file mode 100644 index 000000000..e2ac951aa --- /dev/null +++ b/src/lib/corelib/generators/xmlproject.cpp @@ -0,0 +1,50 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt.io/licensing +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "xmlproject.h" +#include "ixmlnodevisitor.h" + +namespace qbs { +namespace gen { +namespace xml { + +void Project::accept(INodeVisitor *visitor) const +{ + visitor->visitProjectStart(this); + + for (const auto &child : children()) + child->accept(visitor); + + visitor->visitProjectEnd(this); +} + +} // namespace xml +} // namespace gen +} // namespace qbs diff --git a/src/lib/corelib/generators/xmlproject.h b/src/lib/corelib/generators/xmlproject.h new file mode 100644 index 000000000..a7f5b2b65 --- /dev/null +++ b/src/lib/corelib/generators/xmlproject.h @@ -0,0 +1,54 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt.io/licensing +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef GENERATORS_XML_PROJECT_H +#define GENERATORS_XML_PROJECT_H + +#include "xmlproperty.h" + +#include <tools/qbs_export.h> + +#include <memory> + +namespace qbs { +namespace gen { +namespace xml { + +class QBS_EXPORT Project : public Property +{ +public: + void accept(INodeVisitor *visitor) const final; +}; + +} // namespace xml +} // namespace gen +} // namespace qbs + +#endif // GENERATORS_XML_PROJECT_H diff --git a/src/lib/corelib/generators/xmlprojectwriter.cpp b/src/lib/corelib/generators/xmlprojectwriter.cpp new file mode 100644 index 000000000..5554e5935 --- /dev/null +++ b/src/lib/corelib/generators/xmlprojectwriter.cpp @@ -0,0 +1,92 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt.io/licensing +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "xmlproject.h" +#include "xmlprojectwriter.h" +#include "xmlproperty.h" +#include "xmlpropertygroup.h" + +#include <ostream> + +namespace qbs { +namespace gen { +namespace xml { + +ProjectWriter::ProjectWriter(std::ostream *device) + : m_device(device) +{ + m_writer.reset(new QXmlStreamWriter(&m_buffer)); + m_writer->setAutoFormatting(true); +} + +bool ProjectWriter::write(const Project *project) +{ + m_buffer.clear(); + m_writer->writeStartDocument(); + project->accept(this); + m_writer->writeEndDocument(); + if (m_writer->hasError()) + return false; + m_device->write(&*std::begin(m_buffer), m_buffer.size()); + return m_device->good(); +} + +void ProjectWriter::visitPropertyStart(const Property *property) +{ + const auto value = property->value().toString(); + const auto name = QString::fromUtf8(property->name()); + m_writer->writeTextElement(name, value); +} + +void ProjectWriter::visitPropertyEnd(const Property *property) +{ + Q_UNUSED(property) +} + +void ProjectWriter::visitPropertyGroupStart(const PropertyGroup *propertyGroup) +{ + const auto name = QString::fromUtf8(propertyGroup->name()); + m_writer->writeStartElement(name); +} + +void ProjectWriter::visitPropertyGroupEnd(const PropertyGroup *propertyGroup) +{ + Q_UNUSED(propertyGroup) + m_writer->writeEndElement(); +} + +QXmlStreamWriter *ProjectWriter::writer() const +{ + return m_writer.get(); +} + +} // namespace xml +} // namespace gen +} // namespace qbs diff --git a/src/lib/corelib/generators/xmlprojectwriter.h b/src/lib/corelib/generators/xmlprojectwriter.h new file mode 100644 index 000000000..8198de61c --- /dev/null +++ b/src/lib/corelib/generators/xmlprojectwriter.h @@ -0,0 +1,70 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt.io/licensing +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef GENERATORS_XML_PROJECT_WRITER_H +#define GENERATORS_XML_PROJECT_WRITER_H + +#include "ixmlnodevisitor.h" + +#include <tools/qbs_export.h> + +#include <memory> + +namespace qbs { +namespace gen { +namespace xml { + +class QBS_EXPORT ProjectWriter : public INodeVisitor +{ + Q_DISABLE_COPY(ProjectWriter) +public: + explicit ProjectWriter(std::ostream *device); + bool write(const Project *project); + +protected: + QXmlStreamWriter *writer() const; + +private: + void visitPropertyStart(const Property *property) final; + void visitPropertyEnd(const Property *property) final; + + void visitPropertyGroupStart(const PropertyGroup *propertyGroup) final; + void visitPropertyGroupEnd(const PropertyGroup *propertyGroup) final; + + std::ostream *m_device = nullptr; + QByteArray m_buffer; + std::unique_ptr<QXmlStreamWriter> m_writer; +}; + +} // namespace xml +} // namespace gen +} // namespace qbs + +#endif // GENERATORS_XML_PROJECT_WRITER_H diff --git a/src/lib/corelib/generators/xmlproperty.cpp b/src/lib/corelib/generators/xmlproperty.cpp new file mode 100644 index 000000000..2fe5a0147 --- /dev/null +++ b/src/lib/corelib/generators/xmlproperty.cpp @@ -0,0 +1,56 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt.io/licensing +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "ixmlnodevisitor.h" +#include "xmlproperty.h" + +namespace qbs { +namespace gen { +namespace xml { + +Property::Property(QByteArray name, QVariant value) +{ + setName(std::move(name)); + setValue(std::move(value)); +} + +void Property::accept(INodeVisitor *visitor) const +{ + visitor->visitPropertyStart(this); + + for (const auto &child : children()) + child->accept(visitor); + + visitor->visitPropertyEnd(this); +} + +} // namespace xml +} // namespace gen +} // namespace qbs diff --git a/src/lib/corelib/generators/xmlproperty.h b/src/lib/corelib/generators/xmlproperty.h new file mode 100644 index 000000000..795735881 --- /dev/null +++ b/src/lib/corelib/generators/xmlproperty.h @@ -0,0 +1,88 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt.io/licensing +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef GENERATORS_XML_PROPERTY_H +#define GENERATORS_XML_PROPERTY_H + +#include <tools/qbs_export.h> + +#include <QtCore/qvariant.h> + +#include <memory> + +namespace qbs { +namespace gen { +namespace xml { + +class INodeVisitor; + +class QBS_EXPORT Property +{ + Q_DISABLE_COPY(Property) +public: + Property() = default; + explicit Property(QByteArray name, QVariant value); + virtual ~Property() = default; + + QByteArray name() const { return m_name; } + void setName(QByteArray name) { m_name = std::move(name); } + + QVariant value() const { return m_value; } + void setValue(QVariant value) { m_value = std::move(value); } + + template<class T> + T *appendChild(std::unique_ptr<T> child) { + const auto p = child.get(); + m_children.push_back(std::move(child)); + return p; + } + + template<class T, class... Args> + T *appendChild(Args&&... args) { + return appendChild(std::make_unique<T>(std::forward<Args>(args)...)); + } + + virtual void accept(INodeVisitor *visitor) const; + +protected: + const std::vector<std::unique_ptr<Property>> &children() const + { return m_children; } + +private: + QByteArray m_name; + QVariant m_value; + std::vector<std::unique_ptr<Property>> m_children; +}; + +} // namespace xml +} // namespace gen +} // namespace qbs + +#endif // GENERATORS_XML_PROPERTY_H diff --git a/src/lib/corelib/generators/xmlpropertygroup.cpp b/src/lib/corelib/generators/xmlpropertygroup.cpp new file mode 100644 index 000000000..398d68e77 --- /dev/null +++ b/src/lib/corelib/generators/xmlpropertygroup.cpp @@ -0,0 +1,67 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt.io/licensing +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "ixmlnodevisitor.h" +#include "xmlpropertygroup.h" + +namespace qbs { +namespace gen { +namespace xml { + +PropertyGroup::PropertyGroup(QByteArray name) +{ + setName(std::move(name)); +} + +void PropertyGroup::appendProperty(QByteArray name, QVariant value) +{ + appendChild<Property>(std::move(name), std::move(value)); +} + +void PropertyGroup::appendMultiLineProperty( + QByteArray key, QStringList values, QChar sep) +{ + const auto line = values.join(std::move(sep)); + appendProperty(std::move(key), QVariant::fromValue(line)); +} + +void PropertyGroup::accept(INodeVisitor *visitor) const +{ + visitor->visitPropertyGroupStart(this); + + for (const auto &child : children()) + child->accept(visitor); + + visitor->visitPropertyGroupEnd(this); +} + +} // namespace xml +} // namespace gen +} // namespace qbs diff --git a/src/lib/corelib/generators/xmlpropertygroup.h b/src/lib/corelib/generators/xmlpropertygroup.h new file mode 100644 index 000000000..e63b515fc --- /dev/null +++ b/src/lib/corelib/generators/xmlpropertygroup.h @@ -0,0 +1,78 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt.io/licensing +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef GENERATORS_XML_PROPERTY_GROUP_H +#define GENERATORS_XML_PROPERTY_GROUP_H + +#include "generatorversioninfo.h" +#include "xmlproperty.h" + +#include <tools/qbs_export.h> + +#include <memory> + +namespace qbs { + +class ProductData; +class Project; + +namespace gen { +namespace xml { + +class QBS_EXPORT PropertyGroup : public Property +{ +public: + explicit PropertyGroup(QByteArray name); + + void appendProperty(QByteArray name, QVariant value); + void appendMultiLineProperty(QByteArray key, QStringList values, + QChar sep = QLatin1Char(',')); + + void accept(INodeVisitor *visitor) const final; +}; + +class PropertyGroupFactory +{ +public: + virtual ~PropertyGroupFactory() = default; + virtual bool canCreate(utils::Architecture arch, + const Version &version) const = 0; + + virtual std::unique_ptr<PropertyGroup> create( + const qbs::Project &qbsProject, + const qbs::ProductData &qbsProduct, + const std::vector<ProductData> &qbsProductDeps) const = 0; +}; + +} // namespace xml +} // namespace gen +} // namespace qbs + +#endif // GENERATORS_XML_PROPERTY_GROUP_H diff --git a/src/lib/corelib/generators/xmlworkspace.cpp b/src/lib/corelib/generators/xmlworkspace.cpp new file mode 100644 index 000000000..7ce3f5164 --- /dev/null +++ b/src/lib/corelib/generators/xmlworkspace.cpp @@ -0,0 +1,66 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qbs. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "ixmlnodevisitor.h" +#include "xmlproperty.h" +#include "xmlpropertygroup.h" +#include "xmlworkspace.h" + +namespace qbs { +namespace gen { +namespace xml { + +Workspace::Workspace(const QString &workspacePath) + : m_baseDirectory(QFileInfo(workspacePath).absoluteDir()) +{ +} + +void Workspace::accept(INodeVisitor *visitor) const +{ + visitor->visitWorkspaceStart(this); + + for (const auto &child : children()) + child->accept(visitor); + + visitor->visitWorkspaceEnd(this); +} + +} // namespace xml +} // namespace gen +} // namespace qbs diff --git a/src/lib/corelib/generators/xmlworkspace.h b/src/lib/corelib/generators/xmlworkspace.h new file mode 100644 index 000000000..beab22c4a --- /dev/null +++ b/src/lib/corelib/generators/xmlworkspace.h @@ -0,0 +1,69 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qbs. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef GENERATORS_XML_WWORKSPACE_H +#define GENERATORS_XML_WWORKSPACE_H + +#include "xmlproperty.h" + +#include <tools/qbs_export.h> + +#include <QtCore/qdir.h> + +namespace qbs { +namespace gen { +namespace xml { + +class QBS_EXPORT Workspace : public Property +{ +public: + explicit Workspace(const QString &workspacePath); + void accept(INodeVisitor *visitor) const final; + + virtual void addProject(const QString &projectPath) = 0; + +protected: + const QDir m_baseDirectory; +}; + +} // namespace xml +} // namespace gen +} // namespace qbs + +#endif // GENERATORS_XML_WWORKSPACE_H diff --git a/src/lib/corelib/generators/xmlworkspacewriter.cpp b/src/lib/corelib/generators/xmlworkspacewriter.cpp new file mode 100644 index 000000000..c88cb06d0 --- /dev/null +++ b/src/lib/corelib/generators/xmlworkspacewriter.cpp @@ -0,0 +1,92 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt.io/licensing +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "xmlproperty.h" +#include "xmlpropertygroup.h" +#include "xmlworkspace.h" +#include "xmlworkspacewriter.h" + +#include <ostream> + +namespace qbs { +namespace gen { +namespace xml { + +WorkspaceWriter::WorkspaceWriter(std::ostream *device) + : m_device(device) +{ + m_writer.reset(new QXmlStreamWriter(&m_buffer)); + m_writer->setAutoFormatting(true); +} + +bool WorkspaceWriter::write(const Workspace *workspace) +{ + m_buffer.clear(); + m_writer->writeStartDocument(); + workspace->accept(this); + m_writer->writeEndDocument(); + if (m_writer->hasError()) + return false; + m_device->write(&*std::begin(m_buffer), m_buffer.size()); + return m_device->good(); +} + +void WorkspaceWriter::visitPropertyStart(const Property *property) +{ + const auto value = property->value().toString(); + const auto name = QString::fromUtf8(property->name()); + m_writer->writeTextElement(name, value); +} + +void WorkspaceWriter::visitPropertyEnd(const Property *property) +{ + Q_UNUSED(property) +} + +void WorkspaceWriter::visitPropertyGroupStart(const PropertyGroup *propertyGroup) +{ + const auto name = QString::fromUtf8(propertyGroup->name()); + m_writer->writeStartElement(name); +} + +void WorkspaceWriter::visitPropertyGroupEnd(const PropertyGroup *propertyGroup) +{ + Q_UNUSED(propertyGroup) + m_writer->writeEndElement(); +} + +QXmlStreamWriter *WorkspaceWriter::writer() const +{ + return m_writer.get(); +} + +} // namespace xml +} // namespace gen +} // namespace qbs diff --git a/src/lib/corelib/generators/xmlworkspacewriter.h b/src/lib/corelib/generators/xmlworkspacewriter.h new file mode 100644 index 000000000..343face5d --- /dev/null +++ b/src/lib/corelib/generators/xmlworkspacewriter.h @@ -0,0 +1,70 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt.io/licensing +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef GENERATORS_XML_WORKSPACE_WRITER_H +#define GENERATORS_XML_WORKSPACE_WRITER_H + +#include "ixmlnodevisitor.h" + +#include <tools/qbs_export.h> + +#include <memory> + +namespace qbs { +namespace gen { +namespace xml { + +class QBS_EXPORT WorkspaceWriter : public INodeVisitor +{ + Q_DISABLE_COPY(WorkspaceWriter) +public: + explicit WorkspaceWriter(std::ostream *device); + bool write(const Workspace *workspace); + +protected: + QXmlStreamWriter *writer() const; + +private: + void visitPropertyStart(const Property *property) final; + void visitPropertyEnd(const Property *property) final; + + void visitPropertyGroupStart(const PropertyGroup *propertyGroup) final; + void visitPropertyGroupEnd(const PropertyGroup *propertyGroup) final; + + std::ostream *m_device = nullptr; + QByteArray m_buffer; + std::unique_ptr<QXmlStreamWriter> m_writer; +}; + +} // namespace xml +} // namespace gen +} // namespace qbs + +#endif // GENERATORS_XML_WORKSPACE_WRITER_H diff --git a/src/lib/corelib/language/evaluatorscriptclass.cpp b/src/lib/corelib/language/evaluatorscriptclass.cpp index 55a9e1aac..375954133 100644 --- a/src/lib/corelib/language/evaluatorscriptclass.cpp +++ b/src/lib/corelib/language/evaluatorscriptclass.cpp @@ -205,7 +205,18 @@ private: result.second = false; return result; } - SVConverter converter(scriptClass, object, item->property(*propertyName), item, + const ValuePtr v = item->property(*propertyName); + + // This can happen when resolving shadow products. The error will be ignored + // in that case. + if (!v) { + const QString errorMessage = Tr::tr("Error setting up 'original'."); + extraScope = engine->currentContext()->throwError(errorMessage); + result.second = false; + return result; + } + + SVConverter converter(scriptClass, object, v, item, propertyName, data, &originalValue); converter.start(); } else { diff --git a/src/lib/corelib/language/moduleloader.cpp b/src/lib/corelib/language/moduleloader.cpp index 67d60e05d..9c8f9da1d 100644 --- a/src/lib/corelib/language/moduleloader.cpp +++ b/src/lib/corelib/language/moduleloader.cpp @@ -688,6 +688,9 @@ void ModuleLoader::handleProject(ModuleLoaderResult *loadResult, m_qbsVersion.toString())); } + resolveProbes(&dummyProductContext, projectItem); + projectContext.topLevelProject->probes << dummyProductContext.info.probes; + handleProfileItems(projectItem, &projectContext); QList<Item *> multiplexedProducts; @@ -699,9 +702,6 @@ void ModuleLoader::handleProject(ModuleLoaderResult *loadResult, for (Item * const additionalProductItem : qAsConst(multiplexedProducts)) Item::addChild(projectItem, additionalProductItem); - resolveProbes(&dummyProductContext, projectItem); - projectContext.topLevelProject->probes << dummyProductContext.info.probes; - const QList<Item *> originalChildren = projectItem->children(); for (Item * const child : originalChildren) { switch (child->type()) { diff --git a/src/lib/corelib/tools/buildoptions.cpp b/src/lib/corelib/tools/buildoptions.cpp index 5507e0842..75417ab0b 100644 --- a/src/lib/corelib/tools/buildoptions.cpp +++ b/src/lib/corelib/tools/buildoptions.cpp @@ -38,6 +38,9 @@ ****************************************************************************/ #include "buildoptions.h" +#include "jsonhelper.h" + +#include <QtCore/qjsonobject.h> #include <QtCore/qshareddata.h> #include <QtCore/qthread.h> @@ -413,4 +416,56 @@ bool operator==(const BuildOptions &bo1, const BuildOptions &bo2) && bo1.removeExistingInstallation() == bo2.removeExistingInstallation(); } +namespace Internal { +template<> JobLimits fromJson(const QJsonValue &limitsData) +{ + JobLimits limits; + const QJsonArray &limitsArray = limitsData.toArray(); + for (const QJsonValue &v : limitsArray) { + const QJsonObject limitData = v.toObject(); + QString pool; + int limit = 0; + setValueFromJson(pool, limitData, "pool"); + setValueFromJson(limit, limitData, "limit"); + if (!pool.isEmpty() && limit > 0) + limits.setJobLimit(pool, limit); + } + return limits; +} + +template<> CommandEchoMode fromJson(const QJsonValue &modeData) +{ + const QString modeString = modeData.toString(); + if (modeString == QLatin1String("silent")) + return CommandEchoModeSilent; + if (modeString == QLatin1String("command-line")) + return CommandEchoModeCommandLine; + if (modeString == QLatin1String("command-line-with-environment")) + return CommandEchoModeCommandLineWithEnvironment; + return CommandEchoModeSummary; +} +} // namespace Internal + +qbs::BuildOptions qbs::BuildOptions::fromJson(const QJsonObject &data) +{ + using namespace Internal; + BuildOptions opt; + setValueFromJson(opt.d->changedFiles, data, "changed-files"); + setValueFromJson(opt.d->filesToConsider, data, "files-to-consider"); + setValueFromJson(opt.d->activeFileTags, data, "active-file-tags"); + setValueFromJson(opt.d->jobLimits, data, "job-limits"); + setValueFromJson(opt.d->maxJobCount, data, "max-job-count"); + setValueFromJson(opt.d->dryRun, data, "dry-run"); + setValueFromJson(opt.d->keepGoing, data, "keep-going"); + setValueFromJson(opt.d->forceTimestampCheck, data, "check-timestamps"); + setValueFromJson(opt.d->forceOutputCheck, data, "check-outputs"); + setValueFromJson(opt.d->logElapsedTime, data, "log-time"); + setValueFromJson(opt.d->echoMode, data, "command-echo-mode"); + setValueFromJson(opt.d->install, data, "install"); + setValueFromJson(opt.d->removeExistingInstallation, data, "clean-install-root"); + setValueFromJson(opt.d->onlyExecuteRules, data, "only-execute-rules"); + setValueFromJson(opt.d->jobLimitsFromProjectTakePrecedence, data, "enforce-project-job-limits"); + return opt; +} + } // namespace qbs diff --git a/src/lib/corelib/tools/buildoptions.h b/src/lib/corelib/tools/buildoptions.h index cea89d0ea..bd0fb22cb 100644 --- a/src/lib/corelib/tools/buildoptions.h +++ b/src/lib/corelib/tools/buildoptions.h @@ -47,6 +47,7 @@ #include <QtCore/qshareddata.h> QT_BEGIN_NAMESPACE +class QJsonObject; class QStringList; QT_END_NAMESPACE @@ -61,6 +62,8 @@ public: BuildOptions &operator=(const BuildOptions &other); ~BuildOptions(); + static BuildOptions fromJson(const QJsonObject &data); + QStringList filesToConsider() const; void setFilesToConsider(const QStringList &files); diff --git a/src/lib/corelib/tools/cleanoptions.cpp b/src/lib/corelib/tools/cleanoptions.cpp index 4fbe77b5d..b888fb1e8 100644 --- a/src/lib/corelib/tools/cleanoptions.cpp +++ b/src/lib/corelib/tools/cleanoptions.cpp @@ -38,6 +38,8 @@ ****************************************************************************/ #include "cleanoptions.h" +#include "jsonhelper.h" + #include <QtCore/qshareddata.h> namespace qbs { @@ -151,4 +153,14 @@ void CleanOptions::setLogElapsedTime(bool log) d->logElapsedTime = log; } +qbs::CleanOptions qbs::CleanOptions::fromJson(const QJsonObject &data) +{ + CleanOptions opt; + using namespace Internal; + setValueFromJson(opt.d->dryRun, data, "dry-run"); + setValueFromJson(opt.d->keepGoing, data, "keep-going"); + setValueFromJson(opt.d->logElapsedTime, data, "log-time"); + return opt; +} + } // namespace qbs diff --git a/src/lib/corelib/tools/cleanoptions.h b/src/lib/corelib/tools/cleanoptions.h index 3f67cf5a5..7827697bb 100644 --- a/src/lib/corelib/tools/cleanoptions.h +++ b/src/lib/corelib/tools/cleanoptions.h @@ -43,6 +43,10 @@ #include <QtCore/qshareddata.h> +QT_BEGIN_NAMESPACE +class QJsonObject; +QT_END_NAMESPACE + namespace qbs { namespace Internal { class CleanOptionsPrivate; } @@ -56,6 +60,8 @@ public: CleanOptions &operator=(CleanOptions &&other) Q_DECL_NOEXCEPT; ~CleanOptions(); + static CleanOptions fromJson(const QJsonObject &data); + bool dryRun() const; void setDryRun(bool dryRun); diff --git a/src/lib/corelib/tools/codelocation.cpp b/src/lib/corelib/tools/codelocation.cpp index 2c6ade3b0..5eff378e1 100644 --- a/src/lib/corelib/tools/codelocation.cpp +++ b/src/lib/corelib/tools/codelocation.cpp @@ -41,9 +41,12 @@ #include <tools/fileinfo.h> #include <tools/persistence.h> #include <tools/qbsassert.h> +#include <tools/stringconstants.h> #include <QtCore/qdatastream.h> #include <QtCore/qdir.h> +#include <QtCore/qjsonobject.h> +#include <QtCore/qjsonvalue.h> #include <QtCore/qregexp.h> #include <QtCore/qshareddata.h> #include <QtCore/qstring.h> @@ -134,6 +137,18 @@ QString CodeLocation::toString() const return str; } +QJsonObject CodeLocation::toJson() const +{ + QJsonObject obj; + if (!filePath().isEmpty()) + obj.insert(Internal::StringConstants::filePathKey(), filePath()); + if (line() != -1) + obj.insert(QStringLiteral("line"), line()); + if (column() != -1) + obj.insert(QStringLiteral("column"), column()); + return obj; +} + void CodeLocation::load(Internal::PersistentPool &pool) { const bool isValid = pool.load<bool>(); diff --git a/src/lib/corelib/tools/codelocation.h b/src/lib/corelib/tools/codelocation.h index 3dc8f26b1..3e84ce2d1 100644 --- a/src/lib/corelib/tools/codelocation.h +++ b/src/lib/corelib/tools/codelocation.h @@ -47,6 +47,7 @@ QT_BEGIN_NAMESPACE class QDataStream; +class QJsonObject; class QString; QT_END_NAMESPACE @@ -70,6 +71,7 @@ public: bool isValid() const; QString toString() const; + QJsonObject toJson() const; void load(Internal::PersistentPool &pool); void store(Internal::PersistentPool &pool) const; diff --git a/src/lib/corelib/tools/error.cpp b/src/lib/corelib/tools/error.cpp index 185dc0531..fc0b9377e 100644 --- a/src/lib/corelib/tools/error.cpp +++ b/src/lib/corelib/tools/error.cpp @@ -41,7 +41,10 @@ #include "persistence.h" #include "qttools.h" +#include "stringconstants.h" +#include <QtCore/qjsonarray.h> +#include <QtCore/qjsonobject.h> #include <QtCore/qshareddata.h> #include <QtCore/qstringlist.h> @@ -156,6 +159,14 @@ QString ErrorItem::toString() const return str += description(); } +QJsonObject ErrorItem::toJson() const +{ + QJsonObject data; + data.insert(Internal::StringConstants::descriptionProperty(), description()); + data.insert(Internal::StringConstants::locationKey(), codeLocation().toJson()); + return data; +} + class ErrorInfo::ErrorInfoPrivate : public QSharedData { @@ -248,7 +259,7 @@ void ErrorInfo::prepend(const QString &description, const CodeLocation &location * Most often, there will be one element in this list, but there can be more e.g. to illustrate * how an error condition propagates through several source files. */ -QList<ErrorItem> ErrorInfo::items() const +const QList<ErrorItem> ErrorInfo::items() const { return d->items; } @@ -282,6 +293,17 @@ QString ErrorInfo::toString() const return lines.join(QLatin1Char('\n')); } +QJsonObject ErrorInfo::toJson() const +{ + QJsonObject data; + data.insert(QLatin1String("is-internal"), isInternalError()); + QJsonArray itemsArray; + for (const ErrorItem &item : items()) + itemsArray.append(item.toJson()); + data.insert(QLatin1String("items"), itemsArray); + return data; +} + /*! * \brief Returns true if this error represents a bug in qbs, false otherwise. */ diff --git a/src/lib/corelib/tools/error.h b/src/lib/corelib/tools/error.h index 4832499af..abad85bad 100644 --- a/src/lib/corelib/tools/error.h +++ b/src/lib/corelib/tools/error.h @@ -47,6 +47,7 @@ #include <QtCore/qshareddata.h> QT_BEGIN_NAMESPACE +class QJsonObject; template <class T> class QList; class QString; class QStringList; @@ -68,6 +69,7 @@ public: QString description() const; CodeLocation codeLocation() const; QString toString() const; + QJsonObject toJson() const; bool isBacktraceItem() const; @@ -97,10 +99,11 @@ public: void append(const ErrorItem &item); void append(const QString &description, const CodeLocation &location = CodeLocation()); void prepend(const QString &description, const CodeLocation &location = CodeLocation()); - QList<ErrorItem> items() const; + const QList<ErrorItem> items() const; bool hasError() const { return !items().empty(); } void clear(); QString toString() const; + QJsonObject toJson() const; bool isInternalError() const; bool hasLocation() const; diff --git a/src/lib/corelib/tools/installoptions.cpp b/src/lib/corelib/tools/installoptions.cpp index 5cddae4ad..93fd54efe 100644 --- a/src/lib/corelib/tools/installoptions.cpp +++ b/src/lib/corelib/tools/installoptions.cpp @@ -36,9 +36,13 @@ ** $QT_END_LICENSE$ ** ****************************************************************************/ + #include "installoptions.h" -#include "language/language.h" -#include <tools/stringconstants.h> + +#include "jsonhelper.h" +#include "stringconstants.h" + +#include <language/language.h> #include <QtCore/qdir.h> #include <QtCore/qshareddata.h> @@ -230,4 +234,17 @@ void InstallOptions::setLogElapsedTime(bool logElapsedTime) d->logElapsedTime = logElapsedTime; } +qbs::InstallOptions qbs::InstallOptions::fromJson(const QJsonObject &data) +{ + using namespace Internal; + InstallOptions opt; + setValueFromJson(opt.d->installRoot, data, "install-root"); + setValueFromJson(opt.d->useSysroot, data, "use-sysroot"); + setValueFromJson(opt.d->removeExisting, data, "clean-install-root"); + setValueFromJson(opt.d->dryRun, data, "dry-run"); + setValueFromJson(opt.d->keepGoing, data, "keep-going"); + setValueFromJson(opt.d->logElapsedTime, data, "log-time"); + return opt; +} + } // namespace qbs diff --git a/src/lib/corelib/tools/installoptions.h b/src/lib/corelib/tools/installoptions.h index 69e00aae5..16511aa3d 100644 --- a/src/lib/corelib/tools/installoptions.h +++ b/src/lib/corelib/tools/installoptions.h @@ -44,6 +44,7 @@ #include <QtCore/qshareddata.h> QT_BEGIN_NAMESPACE +class QJsonObject; class QString; QT_END_NAMESPACE @@ -65,6 +66,8 @@ public: InstallOptions &operator=(InstallOptions &&other) Q_DECL_NOEXCEPT; ~InstallOptions(); + static InstallOptions fromJson(const QJsonObject &data); + static QString defaultInstallRoot(); QString installRoot() const; void setInstallRoot(const QString &installRoot); diff --git a/src/lib/corelib/tools/jsonhelper.h b/src/lib/corelib/tools/jsonhelper.h new file mode 100644 index 000000000..d87802c0a --- /dev/null +++ b/src/lib/corelib/tools/jsonhelper.h @@ -0,0 +1,89 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qbs. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QBS_JSON_HELPER_H +#define QBS_JSON_HELPER_H + +#include <QtCore/qjsonarray.h> +#include <QtCore/qjsonobject.h> +#include <QtCore/qjsonvalue.h> +#include <QtCore/qprocess.h> +#include <QtCore/qstringlist.h> +#include <QtCore/qvariant.h> + +#include <algorithm> +#include <iterator> + +namespace qbs { +namespace Internal { + +template<typename T> inline T fromJson(const QJsonValue &v); +template<> inline bool fromJson(const QJsonValue &v) { return v.toBool(); } +template<> inline int fromJson(const QJsonValue &v) { return v.toInt(); } +template<> inline QString fromJson(const QJsonValue &v) { return v.toString(); } +template<> inline QStringList fromJson(const QJsonValue &v) +{ + const QJsonArray &jsonList = v.toArray(); + QStringList stringList; + std::transform(jsonList.begin(), jsonList.end(), std::back_inserter(stringList), + [](const QVariant &v) { return v.toString(); }); + return stringList; +} +template<> inline QVariantMap fromJson(const QJsonValue &v) { return v.toObject().toVariantMap(); } +template<> inline QProcessEnvironment fromJson(const QJsonValue &v) +{ + const QJsonObject obj = v.toObject(); + QProcessEnvironment env; + for (auto it = obj.begin(); it != obj.end(); ++it) + env.insert(it.key(), it.value().toString()); + return env; +} + +template<typename T> inline void setValueFromJson(T &targetValue, const QJsonObject &data, + const char *jsonProperty) +{ + const QJsonValue v = data.value(QLatin1String(jsonProperty)); + if (!v.isNull()) + targetValue = fromJson<T>(v); +} + +} // namespace Internal +} // namespace qbs + +#endif // Include guard diff --git a/src/lib/corelib/tools/processresult.cpp b/src/lib/corelib/tools/processresult.cpp index 12e45b251..3fb2f8dbc 100644 --- a/src/lib/corelib/tools/processresult.cpp +++ b/src/lib/corelib/tools/processresult.cpp @@ -39,6 +39,9 @@ #include "processresult.h" #include "processresult_p.h" +#include <QtCore/qjsonarray.h> +#include <QtCore/qjsonobject.h> + /*! * \class SetupProjectParameters * \brief The \c ProcessResult class describes a finished qbs process command. @@ -129,4 +132,31 @@ QStringList ProcessResult::stdErr() const return d->stdErr; } +static QJsonValue processErrorToJson(QProcess::ProcessError error) +{ + switch (error) { + case QProcess::FailedToStart: return QLatin1String("failed-to-start"); + case QProcess::Crashed: return QLatin1String("crashed"); + case QProcess::Timedout: return QLatin1String("timed-out"); + case QProcess::WriteError: return QLatin1String("write-error"); + case QProcess::ReadError: return QLatin1String("read-error"); + case QProcess::UnknownError: return QStringLiteral("unknown-error"); + } + return {}; // For dumb compilers. +} + +QJsonObject qbs::ProcessResult::toJson() const +{ + return QJsonObject{ + {QStringLiteral("success"), success()}, + {QStringLiteral("executable-file-path"), executableFilePath()}, + {QStringLiteral("arguments"), QJsonArray::fromStringList(arguments())}, + {QStringLiteral("working-directory"), workingDirectory()}, + {QStringLiteral("error"), processErrorToJson(error())}, + {QStringLiteral("exit-code"), exitCode()}, + {QStringLiteral("stdout"), QJsonArray::fromStringList(stdOut())}, + {QStringLiteral("stderr"), QJsonArray::fromStringList(stdErr())} + }; +} + } // namespace qbs diff --git a/src/lib/corelib/tools/processresult.h b/src/lib/corelib/tools/processresult.h index 2d2ebbfb4..92408aa31 100644 --- a/src/lib/corelib/tools/processresult.h +++ b/src/lib/corelib/tools/processresult.h @@ -46,6 +46,7 @@ #include <QtCore/qprocess.h> QT_BEGIN_NAMESPACE +class QJsonObject; class QString; class QStringList; QT_END_NAMESPACE @@ -65,6 +66,8 @@ public: ProcessResult &operator=(const ProcessResult &other); ~ProcessResult(); + QJsonObject toJson() const; + bool success() const; QString executableFilePath() const; QStringList arguments() const; diff --git a/src/lib/corelib/tools/setupprojectparameters.cpp b/src/lib/corelib/tools/setupprojectparameters.cpp index 6d817c8f3..41af7b926 100644 --- a/src/lib/corelib/tools/setupprojectparameters.cpp +++ b/src/lib/corelib/tools/setupprojectparameters.cpp @@ -42,6 +42,7 @@ #include <logging/translator.h> #include <tools/buildgraphlocker.h> #include <tools/installoptions.h> +#include <tools/jsonhelper.h> #include <tools/profile.h> #include <tools/qbsassert.h> #include <tools/scripttools.h> @@ -50,6 +51,7 @@ #include <QtCore/qdir.h> #include <QtCore/qfileinfo.h> #include <QtCore/qprocess.h> +#include <QtCore/qjsonobject.h> namespace qbs { namespace Internal { @@ -69,14 +71,14 @@ public: , forceProbeExecution(false) , waitLockBuildGraph(false) , restoreBehavior(SetupProjectParameters::RestoreAndTrackChanges) - , propertyCheckingMode(ErrorHandlingMode::Relaxed) + , propertyCheckingMode(ErrorHandlingMode::Strict) , productErrorMode(ErrorHandlingMode::Strict) { } QString projectFilePath; QString topLevelProfile; - QString configurationName; + QString configurationName = QLatin1String("default"); QString buildRoot; QStringList searchPaths; QStringList pluginPaths; @@ -121,6 +123,47 @@ SetupProjectParameters &SetupProjectParameters::operator=(const SetupProjectPara return *this; } +namespace Internal { +template<> ErrorHandlingMode fromJson(const QJsonValue &v) +{ + if (v.toString() == QLatin1String("relaxed")) + return ErrorHandlingMode::Relaxed; + return ErrorHandlingMode::Strict; +} + +template<> SetupProjectParameters::RestoreBehavior fromJson(const QJsonValue &v) +{ + const QString value = v.toString(); + if (value == QLatin1String("restore-only")) + return SetupProjectParameters::RestoreOnly; + if (value == QLatin1String("resolve-only")) + return SetupProjectParameters::ResolveOnly; + return SetupProjectParameters::RestoreAndTrackChanges; +} +} // namespace Internal + +SetupProjectParameters SetupProjectParameters::fromJson(const QJsonObject &data) +{ + using namespace Internal; + SetupProjectParameters params; + setValueFromJson(params.d->topLevelProfile, data, "top-level-profile"); + setValueFromJson(params.d->configurationName, data, "configuration-name"); + setValueFromJson(params.d->projectFilePath, data, "project-file-path"); + setValueFromJson(params.d->buildRoot, data, "build-root"); + setValueFromJson(params.d->settingsBaseDir, data, "settings-directory"); + setValueFromJson(params.d->overriddenValues, data, "overridden-properties"); + setValueFromJson(params.d->dryRun, data, "dry-run"); + setValueFromJson(params.d->logElapsedTime, data, "log-time"); + setValueFromJson(params.d->forceProbeExecution, data, "force-probe-execution"); + setValueFromJson(params.d->waitLockBuildGraph, data, "wait-lock-build-graph"); + setValueFromJson(params.d->fallbackProviderEnabled, data, "fallback-provider-enabled"); + setValueFromJson(params.d->environment, data, "environment"); + setValueFromJson(params.d->restoreBehavior, data, "restore-behavior"); + setValueFromJson(params.d->propertyCheckingMode, data, "error-handling-mode"); + params.d->productErrorMode = params.d->propertyCheckingMode; + return params; +} + SetupProjectParameters &SetupProjectParameters::operator=(SetupProjectParameters &&other) Q_DECL_NOEXCEPT = default; /*! diff --git a/src/lib/corelib/tools/setupprojectparameters.h b/src/lib/corelib/tools/setupprojectparameters.h index cf3b200cb..a4d090ec5 100644 --- a/src/lib/corelib/tools/setupprojectparameters.h +++ b/src/lib/corelib/tools/setupprojectparameters.h @@ -71,6 +71,8 @@ public: SetupProjectParameters &operator=(const SetupProjectParameters &other); SetupProjectParameters &operator=(SetupProjectParameters &&other) Q_DECL_NOEXCEPT; + static SetupProjectParameters fromJson(const QJsonObject &data); + QString topLevelProfile() const; void setTopLevelProfile(const QString &profile); diff --git a/src/lib/corelib/tools/stringconstants.h b/src/lib/corelib/tools/stringconstants.h index cd41f3768..79cbcd125 100644 --- a/src/lib/corelib/tools/stringconstants.h +++ b/src/lib/corelib/tools/stringconstants.h @@ -69,6 +69,7 @@ public: QBS_STRING_CONSTANT(baseNameProperty, "baseName") QBS_STRING_CONSTANT(baseProfileProperty, "baseProfile") QBS_STRING_CONSTANT(buildDirectoryProperty, "buildDirectory") + QBS_STRING_CONSTANT(buildDirectoryKey, "build-directory") QBS_STRING_CONSTANT(builtByDefaultProperty, "builtByDefault") QBS_STRING_CONSTANT(classNameProperty, "className") QBS_STRING_CONSTANT(completeBaseNameProperty, "completeBaseName") @@ -90,11 +91,13 @@ public: static const QString &fileNameProperty() { return fileName(); } static const QString &filePathProperty() { return filePath(); } static const QString &filePathVar() { return filePath(); } + QBS_STRING_CONSTANT(filePathKey, "file-path") QBS_STRING_CONSTANT(fileTagsFilterProperty, "fileTagsFilter") QBS_STRING_CONSTANT(fileTagsProperty, "fileTags") QBS_STRING_CONSTANT(filesProperty, "files") QBS_STRING_CONSTANT(filesAreTargetsProperty, "filesAreTargets") QBS_STRING_CONSTANT(foundProperty, "found") + QBS_STRING_CONSTANT(fullDisplayNameKey, "full-display-name") QBS_STRING_CONSTANT(imports, "imports") static const QString &importsDir() { return imports(); } static const QString &importsProperty() { return imports(); } @@ -106,12 +109,16 @@ public: QBS_STRING_CONSTANT(installPrefixProperty, "installPrefix") QBS_STRING_CONSTANT(installDirProperty, "installDir") QBS_STRING_CONSTANT(installSourceBaseProperty, "installSourceBase") + QBS_STRING_CONSTANT(isEnabledKey, "is-enabled") QBS_STRING_CONSTANT(jobCountProperty, "jobCount") QBS_STRING_CONSTANT(jobPoolProperty, "jobPool") QBS_STRING_CONSTANT(lengthProperty, "length") QBS_STRING_CONSTANT(limitToSubProjectProperty, "limitToSubProject") + QBS_STRING_CONSTANT(locationKey, "location") + QBS_STRING_CONSTANT(messageKey, "message") QBS_STRING_CONSTANT(minimumQbsVersionProperty, "minimumQbsVersion") QBS_STRING_CONSTANT(moduleNameProperty, "moduleName") + QBS_STRING_CONSTANT(modulePropertiesKey, "module-properties") QBS_STRING_CONSTANT(moduleProviders, "moduleProviders") QBS_STRING_CONSTANT(multiplexByQbsPropertiesProperty, "multiplexByQbsProperties") QBS_STRING_CONSTANT(multiplexConfigurationIdProperty, "multiplexConfigurationId") @@ -135,6 +142,7 @@ public: QBS_STRING_CONSTANT(profileProperty, "profile") static const QString &profilesProperty() { return profiles(); } QBS_STRING_CONSTANT(productTypesProperty, "productTypes") + QBS_STRING_CONSTANT(productsKey, "products") QBS_STRING_CONSTANT(qbsSearchPathsProperty, "qbsSearchPaths") QBS_STRING_CONSTANT(referencesProperty, "references") QBS_STRING_CONSTANT(recursiveProperty, "recursive") @@ -149,7 +157,8 @@ public: QBS_STRING_CONSTANT(sourceDirectoryProperty, "sourceDirectory") QBS_STRING_CONSTANT(submodulesProperty, "submodules") QBS_STRING_CONSTANT(targetNameProperty, "targetName") - QBS_STRING_CONSTANT(typeProperty, "type") + static const QString &typeProperty() { return type(); } + QBS_STRING_CONSTANT(type, "type") QBS_STRING_CONSTANT(validateProperty, "validate") QBS_STRING_CONSTANT(versionProperty, "version") QBS_STRING_CONSTANT(versionAtLeastProperty, "versionAtLeast") diff --git a/src/lib/corelib/tools/tools.pri b/src/lib/corelib/tools/tools.pri index f9c6be9a5..89d752671 100644 --- a/src/lib/corelib/tools/tools.pri +++ b/src/lib/corelib/tools/tools.pri @@ -23,6 +23,7 @@ HEADERS += \ $$PWD/iosutils.h \ $$PWD/joblimits.h \ $$PWD/jsliterals.h \ + $$PWD/jsonhelper.h \ $$PWD/launcherinterface.h \ $$PWD/launcherpackets.h \ $$PWD/launchersocket.h \ diff --git a/src/lib/corelib/tools/version.cpp b/src/lib/corelib/tools/version.cpp index d2b337d3a..dfb7f49b7 100644 --- a/src/lib/corelib/tools/version.cpp +++ b/src/lib/corelib/tools/version.cpp @@ -105,13 +105,17 @@ Version Version::fromString(const QString &versionString, bool buildNumberAllowe return Version{majorNr, minorNr, patchNr, buildNr}; } -QString Version::toString() const +QString Version::toString(const QChar &separator, const QChar &buildSeparator) const { if (m_build) { - return QString(QStringLiteral("%1.%2.%3-%4")) - .arg(m_major).arg(m_minor).arg(m_patch).arg(m_build); + return QStringLiteral("%1%5%2%5%3%6%4") + .arg(QString::number(m_major), QString::number(m_minor), + QString::number(m_patch), QString::number(m_build), + separator, buildSeparator); } - return QString(QStringLiteral("%1.%2.%3")).arg(m_major).arg(m_minor).arg(m_patch); + return QStringLiteral("%1%4%2%4%3") + .arg(QString::number(m_major), QString::number(m_minor), + QString::number(m_patch), separator); } int compare(const Version &lhs, const Version &rhs) diff --git a/src/lib/corelib/tools/version.h b/src/lib/corelib/tools/version.h index 4f5e46500..a0239a6e4 100644 --- a/src/lib/corelib/tools/version.h +++ b/src/lib/corelib/tools/version.h @@ -42,6 +42,7 @@ #include "qbs_export.h" +#include <QtCore/qchar.h> #include <QtCore/qglobal.h> QT_BEGIN_NAMESPACE @@ -71,7 +72,8 @@ public: void setBuildNumber(int nr); static Version fromString(const QString &versionString, bool buildNumberAllowed = false); - QString toString() const; + QString toString(const QChar &separator = QLatin1Char('.'), + const QChar &buildSeparator = QLatin1Char('-')) const; private: int m_major; diff --git a/src/plugins/generator/generator.pro b/src/plugins/generator/generator.pro index 1607aa14d..4a3861321 100644 --- a/src/plugins/generator/generator.pro +++ b/src/plugins/generator/generator.pro @@ -1,2 +1,6 @@ TEMPLATE = subdirs -SUBDIRS = clangcompilationdb makefilegenerator visualstudio +SUBDIRS += clangcompilationdb +SUBDIRS += makefilegenerator +SUBDIRS += visualstudio +SUBDIRS += iarew +SUBDIRS += keiluv diff --git a/src/plugins/generator/iarew/archs/arm/armarchiversettingsgroup_v8.cpp b/src/plugins/generator/iarew/archs/arm/armarchiversettingsgroup_v8.cpp new file mode 100644 index 000000000..cc0750627 --- /dev/null +++ b/src/plugins/generator/iarew/archs/arm/armarchiversettingsgroup_v8.cpp @@ -0,0 +1,95 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt.io/licensing +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "armarchiversettingsgroup_v8.h" + +#include "../../iarewutils.h" + +namespace qbs { +namespace iarew { +namespace arm { +namespace v8 { + +constexpr int kArchiverArchiveVersion = 0; +constexpr int kArchiverDataVersion = 0; + +namespace { + +// Output page options. + +struct OutputPageOptions final +{ + explicit OutputPageOptions(const QString &baseDirectory, + const ProductData &qbsProduct) + { + outputFile = QLatin1String("$PROJ_DIR$/") + + gen::utils::targetBinaryPath(baseDirectory, qbsProduct); + } + + QString outputFile; +}; + +} // namespace + +// ArmArchiverSettingsGroup + +ArmArchiverSettingsGroup::ArmArchiverSettingsGroup( + const Project &qbsProject, + const ProductData &qbsProduct, + const std::vector<ProductData> &qbsProductDeps) +{ + Q_UNUSED(qbsProductDeps) + + setName(QByteArrayLiteral("IARCHIVE")); + setArchiveVersion(kArchiverArchiveVersion); + setDataVersion(kArchiverDataVersion); + setDataDebugInfo(gen::utils::debugInformation(qbsProduct)); + + const QString buildRootDirectory = gen::utils::buildRootPath(qbsProject); + buildOutputPage(buildRootDirectory, qbsProduct); +} + +void ArmArchiverSettingsGroup::buildOutputPage( + const QString &baseDirectory, + const ProductData &qbsProduct) +{ + const OutputPageOptions opts(baseDirectory, qbsProduct); + // Add 'IarchiveOverride' item (Override default). + addOptionsGroup(QByteArrayLiteral("IarchiveOverride"), + {1}); + // Add 'IarchiveOutput' item (Output filename). + addOptionsGroup(QByteArrayLiteral("IarchiveOutput"), + {opts.outputFile}); +} + +} // namespace v8 +} // namespace arm +} // namespace iarew +} // namespace qbs diff --git a/src/plugins/generator/iarew/archs/arm/armarchiversettingsgroup_v8.h b/src/plugins/generator/iarew/archs/arm/armarchiversettingsgroup_v8.h new file mode 100644 index 000000000..c99c2eeba --- /dev/null +++ b/src/plugins/generator/iarew/archs/arm/armarchiversettingsgroup_v8.h @@ -0,0 +1,58 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt.io/licensing +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef QBS_IAREWARMAARCHIVERSETTINGSGROUP_V8_H +#define QBS_IAREWARMAARCHIVERSETTINGSGROUP_V8_H + +#include "../../iarewsettingspropertygroup.h" + +namespace qbs { +namespace iarew { +namespace arm { +namespace v8 { + +class ArmArchiverSettingsGroup final : public IarewSettingsPropertyGroup +{ +public: + explicit ArmArchiverSettingsGroup(const Project &qbsProject, + const ProductData &qbsProduct, + const std::vector<ProductData> &qbsProductDeps); + +private: + void buildOutputPage(const QString &baseDirectory, + const ProductData &qbsProduct); +}; + +} // namespace v8 +} // namespace arm +} // namespace iarew +} // namespace qbs + +#endif // QBS_IAREWARMAARCHIVERSETTINGSGROUP_V8_H diff --git a/src/plugins/generator/iarew/archs/arm/armassemblersettingsgroup_v8.cpp b/src/plugins/generator/iarew/archs/arm/armassemblersettingsgroup_v8.cpp new file mode 100644 index 000000000..66c4c9ee6 --- /dev/null +++ b/src/plugins/generator/iarew/archs/arm/armassemblersettingsgroup_v8.cpp @@ -0,0 +1,230 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt.io/licensing +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "armassemblersettingsgroup_v8.h" + +#include "../../iarewutils.h" + +namespace qbs { +namespace iarew { +namespace arm { +namespace v8 { + +constexpr int kAssemblerArchiveVersion = 2; +constexpr int kAssemblerDataVersion = 10; + +namespace { + +// Language page options. + +struct LanguagePageOptions final +{ + enum MacroQuoteCharacter { + AngleBracketsQuote, + RoundBracketsQuote, + SquareBracketsQuote, + FigureBracketsQuote + }; + + explicit LanguagePageOptions(const ProductData &qbsProduct) + { + const auto &qbsProps = qbsProduct.moduleProperties(); + const QStringList flags = IarewUtils::cppModuleAssemblerFlags(qbsProps); + enableSymbolsCaseSensitive = flags.contains(QLatin1String("-s+")); + allowAlternativeRegister = flags.contains(QLatin1String("-j")); + disableCodeMemoryDataReads = flags.contains( + QLatin1String("--no_literal_pool")); + if (flags.contains(QLatin1String("-M<>"))) + macroQuoteCharacter = LanguagePageOptions::AngleBracketsQuote; + else if (flags.contains(QLatin1String("-M()"))) + macroQuoteCharacter = LanguagePageOptions::RoundBracketsQuote; + else if (flags.contains(QLatin1String("-M[]"))) + macroQuoteCharacter = LanguagePageOptions::SquareBracketsQuote; + else if (flags.contains(QLatin1String("-M{}"))) + macroQuoteCharacter = LanguagePageOptions::FigureBracketsQuote; + } + + MacroQuoteCharacter macroQuoteCharacter = AngleBracketsQuote; + int enableSymbolsCaseSensitive = 0; + int allowAlternativeRegister = 0; + int disableCodeMemoryDataReads = 0; +}; + +// Output page options. + +struct OutputPageOptions final +{ + explicit OutputPageOptions(const ProductData &qbsProduct) + { + debugInfo = gen::utils::debugInformation(qbsProduct); + } + + int debugInfo = 0; +}; + +// Preprocessor page options. + +struct PreprocessorPageOptions final +{ + explicit PreprocessorPageOptions(const QString &baseDirectory, + const ProductData &qbsProduct) + { + const auto &qbsProps = qbsProduct.moduleProperties(); + defineSymbols = gen::utils::cppVariantModuleProperties( + qbsProps, {QStringLiteral("defines")}); + + const QString toolkitPath = IarewUtils::toolkitRootPath(qbsProduct); + const QStringList fullIncludePaths = gen::utils::cppStringModuleProperties( + qbsProps, {QStringLiteral("includePaths"), + QStringLiteral("systemIncludePaths")}); + for (const QString &fullIncludePath : fullIncludePaths) { + const QFileInfo includeFileInfo(fullIncludePath); + const QString includeFilePath = includeFileInfo.absoluteFilePath(); + if (includeFilePath.startsWith(toolkitPath, Qt::CaseInsensitive)) { + const QString path = IarewUtils::toolkitRelativeFilePath( + toolkitPath, includeFilePath); + includePaths.push_back(path); + } else { + const QString path = IarewUtils::projectRelativeFilePath( + baseDirectory, includeFilePath); + includePaths.push_back(path); + } + } + } + + QVariantList defineSymbols; + QVariantList includePaths; +}; + +// Diagnostics page options. + +struct DiagnosticsPageOptions final +{ + explicit DiagnosticsPageOptions(const ProductData &qbsProduct) + { + const auto &qbsProps = qbsProduct.moduleProperties(); + const QString warningLevel = gen::utils::cppStringModuleProperty( + qbsProps, QStringLiteral("warningLevel")); + if (warningLevel == QLatin1String("all")) { + enableWarnings = 0; + enableAllWarnings = 0; + } else if (warningLevel == QLatin1String("none")) { + enableWarnings = 1; + enableAllWarnings = 0; + } else { + enableWarnings = 0; + enableAllWarnings = 1; + } + } + + int enableWarnings = 0; + int enableAllWarnings = 0; +}; + +} // namespace + +// ArmAssemblerSettingsGroup + +ArmAssemblerSettingsGroup::ArmAssemblerSettingsGroup( + const Project &qbsProject, + const ProductData &qbsProduct, + const std::vector<ProductData> &qbsProductDeps) +{ + Q_UNUSED(qbsProductDeps) + + setName(QByteArrayLiteral("AARM")); + setArchiveVersion(kAssemblerArchiveVersion); + setDataVersion(kAssemblerDataVersion); + setDataDebugInfo(gen::utils::debugInformation(qbsProduct)); + + const QString buildRootDirectory = gen::utils::buildRootPath(qbsProject); + + buildLanguagePage(qbsProduct); + buildOutputPage(qbsProduct); + buildPreprocessorPage(buildRootDirectory, qbsProduct); + buildDiagnosticsPage(qbsProduct); +} + +void ArmAssemblerSettingsGroup::buildLanguagePage( + const ProductData &qbsProduct) +{ + const LanguagePageOptions opts(qbsProduct); + // Add 'ACaseSensitivity' item (User symbols are case sensitive). + addOptionsGroup(QByteArrayLiteral("ACaseSensitivity"), + {opts.enableSymbolsCaseSensitive}); + // Add 'AltRegisterNames' item (Allow alternative register names, + // mnemonics and operands). + addOptionsGroup(QByteArrayLiteral("AltRegisterNames"), + {opts.allowAlternativeRegister}); + // Add 'AsmNoLiteralPool' item (No data reads in code memory). + addOptionsGroup(QByteArrayLiteral("AsmNoLiteralPool"), + {opts.disableCodeMemoryDataReads}); + // Add 'MacroChars' item (Macro quote characters: ()/[]/{}/<>). + addOptionsGroup(QByteArrayLiteral("MacroChars"), + {opts.macroQuoteCharacter}, 0); +} +void ArmAssemblerSettingsGroup::buildOutputPage( + const ProductData &qbsProduct) +{ + const OutputPageOptions opts(qbsProduct); + // Add 'ADebug' item (Generate debug information). + addOptionsGroup(QByteArrayLiteral("ADebug"), + {opts.debugInfo}); +} + +void ArmAssemblerSettingsGroup::buildPreprocessorPage( + const QString &baseDirectory, + const ProductData &qbsProduct) +{ + const PreprocessorPageOptions opts(baseDirectory, qbsProduct); + // Add 'ADefines' item (Defined symbols). + addOptionsGroup(QByteArrayLiteral("ADefines"), + opts.defineSymbols); + // Add 'AUserIncludes' item (Additional include directories). + addOptionsGroup(QByteArrayLiteral("AUserIncludes"), + opts.includePaths); +} + +void ArmAssemblerSettingsGroup::buildDiagnosticsPage( + const ProductData &qbsProduct) +{ + const DiagnosticsPageOptions opts(qbsProduct); + // Add 'AWarnEnable' item (Enable/disable warnings). + addOptionsGroup(QByteArrayLiteral("AWarnEnable"), + {opts.enableWarnings}); + // Add 'AWarnWhat' item (Enable/disable all warnings). + addOptionsGroup(QByteArrayLiteral("AWarnWhat"), + {opts.enableAllWarnings}); +} + +} // namespace v8 +} // namespace arm +} // namespace iarew +} // namespace qbs diff --git a/src/plugins/generator/iarew/archs/arm/armassemblersettingsgroup_v8.h b/src/plugins/generator/iarew/archs/arm/armassemblersettingsgroup_v8.h new file mode 100644 index 000000000..620dcf1f5 --- /dev/null +++ b/src/plugins/generator/iarew/archs/arm/armassemblersettingsgroup_v8.h @@ -0,0 +1,63 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt.io/licensing +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef QBS_IAREWARMASSEMBLERSETTINGSGROUP_V8_H +#define QBS_IAREWARMASSEMBLERSETTINGSGROUP_V8_H + +#include "../../iarewsettingspropertygroup.h" + +namespace qbs { +namespace iarew { +namespace arm { +namespace v8 { + +class ArmAssemblerSettingsGroup final + : public IarewSettingsPropertyGroup +{ +public: + explicit ArmAssemblerSettingsGroup( + const Project &qbsProject, + const ProductData &qbsProduct, + const std::vector<ProductData> &qbsProductDeps); + +private: + void buildLanguagePage(const ProductData &qbsProduct); + void buildOutputPage(const ProductData &qbsProduct); + void buildPreprocessorPage(const QString &baseDirectory, + const ProductData &qbsProduct); + void buildDiagnosticsPage(const ProductData &qbsProduct); +}; + +} // namespace v8 +} // namespace arm +} // namespace iarew +} // namespace qbs + +#endif // QBS_IAREWARMASSEMBLERSETTINGSGROUP_V8_H diff --git a/src/plugins/generator/iarew/archs/arm/armbuildconfigurationgroup_v8.cpp b/src/plugins/generator/iarew/archs/arm/armbuildconfigurationgroup_v8.cpp new file mode 100644 index 000000000..a16e57a42 --- /dev/null +++ b/src/plugins/generator/iarew/archs/arm/armbuildconfigurationgroup_v8.cpp @@ -0,0 +1,98 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt.io/licensing +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "armarchiversettingsgroup_v8.h" +#include "armassemblersettingsgroup_v8.h" +#include "armbuildconfigurationgroup_v8.h" +#include "armcompilersettingsgroup_v8.h" +#include "armgeneralsettingsgroup_v8.h" +#include "armlinkersettingsgroup_v8.h" + +#include "../../iarewtoolchainpropertygroup.h" +#include "../../iarewutils.h" + +namespace qbs { +namespace iarew { +namespace arm { +namespace v8 { + +ArmBuildConfigurationGroup::ArmBuildConfigurationGroup( + const qbs::Project &qbsProject, + const qbs::ProductData &qbsProduct, + const std::vector<ProductData> &qbsProductDeps) + : gen::xml::PropertyGroup("configuration") +{ + // Append configuration name item. + const QString cfgName = gen::utils::buildConfigurationName(qbsProject); + appendProperty("name", cfgName); + + // Apend toolchain name group item. + appendChild<IarewToolchainPropertyGroup>("ARM"); + + // Append debug info item. + const int debugBuild = gen::utils::debugInformation(qbsProduct); + appendProperty("debug", debugBuild); + + // Append settings group items. + appendChild<ArmArchiverSettingsGroup>( + qbsProject, qbsProduct, qbsProductDeps); + appendChild<ArmAssemblerSettingsGroup>( + qbsProject, qbsProduct, qbsProductDeps); + appendChild<ArmCompilerSettingsGroup>( + qbsProject, qbsProduct, qbsProductDeps); + appendChild<ArmGeneralSettingsGroup>( + qbsProject, qbsProduct, qbsProductDeps); + appendChild<ArmLinkerSettingsGroup>( + qbsProject, qbsProduct, qbsProductDeps); +} + +bool ArmBuildConfigurationGroupFactory::canCreate( + gen::utils::Architecture arch, + const Version &version) const +{ + return arch == gen::utils::Architecture::Arm + && version.majorVersion() == 8; +} + +std::unique_ptr<gen::xml::PropertyGroup> +ArmBuildConfigurationGroupFactory::create( + const qbs::Project &qbsProject, + const qbs::ProductData &qbsProduct, + const std::vector<ProductData> &qbsProductDeps) const +{ + const auto group = new ArmBuildConfigurationGroup( + qbsProject, qbsProduct, qbsProductDeps); + return std::unique_ptr<ArmBuildConfigurationGroup>(group); +} + +} // namespace v8 +} // namespace arm +} // namespace iarew +} // namespace qbs diff --git a/src/plugins/generator/iarew/archs/arm/armbuildconfigurationgroup_v8.h b/src/plugins/generator/iarew/archs/arm/armbuildconfigurationgroup_v8.h new file mode 100644 index 000000000..26370c9b8 --- /dev/null +++ b/src/plugins/generator/iarew/archs/arm/armbuildconfigurationgroup_v8.h @@ -0,0 +1,71 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt.io/licensing +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef QBS_IAREWARMBUILDCONFIGURATIONGROUP_V8_H +#define QBS_IAREWARMBUILDCONFIGURATIONGROUP_V8_H + +#include <generators/xmlpropertygroup.h> + +namespace qbs { +namespace iarew { +namespace arm { +namespace v8 { + +class ArmBuildConfigurationGroup final + : public gen::xml::PropertyGroup +{ +private: + explicit ArmBuildConfigurationGroup( + const qbs::Project &qbsProject, + const qbs::ProductData &qbsProduct, + const std::vector<ProductData> &qbsProductDeps); + + friend class ArmBuildConfigurationGroupFactory; +}; + +class ArmBuildConfigurationGroupFactory final + : public gen::xml::PropertyGroupFactory +{ +public: + bool canCreate(gen::utils::Architecture arch, + const Version &version) const final; + + std::unique_ptr<gen::xml::PropertyGroup> create( + const qbs::Project &qbsProject, + const qbs::ProductData &qbsProduct, + const std::vector<ProductData> &qbsProductDeps) const final; +}; + +} // namespace v8 +} // namespace arm +} // namespace iarew +} // namespace qbs + +#endif // QBS_IAREWARMBUILDCONFIGURATIONGROUP_V8_H diff --git a/src/plugins/generator/iarew/archs/arm/armcompilersettingsgroup_v8.cpp b/src/plugins/generator/iarew/archs/arm/armcompilersettingsgroup_v8.cpp new file mode 100644 index 000000000..0981fade4 --- /dev/null +++ b/src/plugins/generator/iarew/archs/arm/armcompilersettingsgroup_v8.cpp @@ -0,0 +1,478 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt.io/licensing +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "armcompilersettingsgroup_v8.h" + +#include "../../iarewutils.h" + +namespace qbs { +namespace iarew { +namespace arm { +namespace v8 { + +constexpr int kCompilerArchiveVersion = 2; +constexpr int kCompilerDataVersion = 34; + +namespace { + +// Output page options. + +struct OutputPageOptions final +{ + explicit OutputPageOptions(const ProductData &qbsProduct) + { + debugInfo = gen::utils::debugInformation(qbsProduct); + } + + int debugInfo = 0; +}; + +// Language 1 page options. + +struct LanguageOnePageOptions final +{ + enum LanguageExtension { + CLanguageExtension, + CxxLanguageExtension, + AutoLanguageExtension + }; + + enum CLanguageDialect { + C89LanguageDialect, + C11LanguageDialect + }; + + enum LanguageConformance { + AllowIarExtension, + RelaxedStandard, + StrictStandard + }; + + explicit LanguageOnePageOptions(const ProductData &qbsProduct) + { + const auto &qbsProps = qbsProduct.moduleProperties(); + // File extension based by default. + languageExtension = LanguageOnePageOptions::AutoLanguageExtension; + // Language dialect. + const QStringList cLanguageVersion = gen::utils::cppStringModuleProperties( + qbsProps, {QStringLiteral("cLanguageVersion")}); + cLanguageDialect = cLanguageVersion.contains(QLatin1String("c89")) + ? LanguageOnePageOptions::C89LanguageDialect + : LanguageOnePageOptions::C11LanguageDialect; + + const QStringList flags = IarewUtils::cppModuleCompilerFlags(qbsProps); + // Language conformance. + if (flags.contains(QLatin1String("-e"))) + languageConformance = LanguageOnePageOptions::AllowIarExtension; + else if (flags.contains(QLatin1String("--strict"))) + languageConformance = LanguageOnePageOptions::StrictStandard; + else + languageConformance = LanguageOnePageOptions::RelaxedStandard; + // Exceptions, rtti, static desrtuction. + enableExceptions = !flags.contains(QLatin1String("--no_exceptions")); + enableRtti = !flags.contains(QLatin1String("--no_rtti")); + destroyStaticObjects = !flags.contains( + QLatin1String("--no_static_destruction")); + allowVla = flags.contains(QLatin1String("--vla")); + enableInlineSemantics = flags.contains(QLatin1String("--use_c++_inline")); + requirePrototypes = flags.contains(QLatin1String("--require_prototypes")); + } + + LanguageExtension languageExtension = AutoLanguageExtension; + CLanguageDialect cLanguageDialect = C89LanguageDialect; + LanguageConformance languageConformance = AllowIarExtension; + // C++ options. + int enableExceptions = 0; + int enableRtti = 0; + int destroyStaticObjects = 0; + int allowVla = 0; + int enableInlineSemantics = 0; + int requirePrototypes = 0; +}; + +// Language 2 page options. + +struct LanguageTwoPageOptions final +{ + enum PlainCharacter { + SignedCharacter, + UnsignedCharacter + }; + + enum FloatingPointSemantic { + StrictSemantic, + RelaxedSemantic + }; + + explicit LanguageTwoPageOptions(const ProductData &qbsProduct) + { + const auto &qbsProps = qbsProduct.moduleProperties(); + const QStringList flags = IarewUtils::cppModuleCompilerFlags(qbsProps); + plainCharacter = flags.contains(QLatin1String("--char_is_signed")) + ? LanguageTwoPageOptions::SignedCharacter + : LanguageTwoPageOptions::UnsignedCharacter; + floatingPointSemantic = flags.contains(QLatin1String("--relaxed_fp")) + ? LanguageTwoPageOptions::RelaxedSemantic + : LanguageTwoPageOptions::StrictSemantic; + } + + PlainCharacter plainCharacter = SignedCharacter; + FloatingPointSemantic floatingPointSemantic = StrictSemantic; +}; + +// Optimizations page options. + +struct OptimizationsPageOptions final +{ + // Optimizations level radio-buttons with + // combo-box on "level" widget. + + enum Strategy { + StrategyBalanced, + StrategySize, + StrategySpeed + }; + + enum Level { + LevelNone, + LevelLow, + LevelMedium, + LevelHigh + }; + + enum LevelSlave { + LevelSlave0, + LevelSlave1, + LevelSlave2, + LevelSlave3 + }; + + explicit OptimizationsPageOptions(const ProductData &qbsProduct) + { + const auto &qbsProps = qbsProduct.moduleProperties(); + const QString optimization = gen::utils::cppStringModuleProperty( + qbsProps, QStringLiteral("optimization")); + if (optimization == QLatin1String("none")) { + optimizationStrategy = OptimizationsPageOptions::StrategyBalanced; + optimizationLevel = OptimizationsPageOptions::LevelNone; + optimizationLevelSlave = OptimizationsPageOptions::LevelSlave0; + } else if (optimization == QLatin1String("fast")) { + optimizationStrategy = OptimizationsPageOptions::StrategySpeed; + optimizationLevel = OptimizationsPageOptions::LevelHigh; + optimizationLevelSlave = OptimizationsPageOptions::LevelSlave3; + } else if (optimization == QLatin1String("small")) { + optimizationStrategy = OptimizationsPageOptions::StrategySize; + optimizationLevel = OptimizationsPageOptions::LevelHigh; + optimizationLevelSlave = OptimizationsPageOptions::LevelSlave3; + } + + const QStringList flags = IarewUtils::cppModuleCompilerFlags(qbsProps); + enableCommonSubexpressionElimination = !flags.contains( + QLatin1String("--no_cse")); + enableLoopUnroll = !flags.contains( + QLatin1String("--no_unroll")); + enableFunctionInlining = !flags.contains( + QLatin1String("--no_inline")); + enableCodeMotion = !flags.contains( + QLatin1String("--no_code_motion")); + enableTypeBasedAliasAnalysis = !flags.contains( + QLatin1String("--no_tbaa")); + enableStaticClustering = !flags.contains( + QLatin1String("--no_clustering")); + enableInstructionScheduling = !flags.contains( + QLatin1String("--no_scheduling")); + enableVectorization = flags.contains( + QLatin1String("--vectorize")); + disableSizeConstraints = flags.contains( + QLatin1String("--no_size_constraints")); + } + + Strategy optimizationStrategy = StrategyBalanced; + Level optimizationLevel = LevelNone; + LevelSlave optimizationLevelSlave = LevelSlave0; + // Eight bit-field flags on "enabled optimizations" widget. + int enableCommonSubexpressionElimination = 0; // Common sub-expression elimination. + int enableLoopUnroll = 0; // Loop unrolling. + int enableFunctionInlining = 0; // Function inlining. + int enableCodeMotion = 0; // Code motion. + int enableTypeBasedAliasAnalysis = 0; // Type-based alias analysis. + int enableStaticClustering = 0; // Static clustering. + int enableInstructionScheduling = 0; // Instruction scheduling. + int enableVectorization = 0; // Vectorization. + + // Separate "no size constraints" checkbox. + int disableSizeConstraints = 0; +}; + +// Preprocessor page options. + +struct PreprocessorPageOptions final +{ + explicit PreprocessorPageOptions(const QString &baseDirectory, + const ProductData &qbsProduct) + { + const auto &qbsProps = qbsProduct.moduleProperties(); + defineSymbols = gen::utils::cppVariantModuleProperties( + qbsProps, {QStringLiteral("defines")}); + + const QString toolkitPath = IarewUtils::toolkitRootPath(qbsProduct); + const QStringList fullIncludePaths = gen::utils::cppStringModuleProperties( + qbsProps, {QStringLiteral("includePaths"), + QStringLiteral("systemIncludePaths")}); + for (const QString &fullIncludePath : fullIncludePaths) { + const QFileInfo includeFileInfo(fullIncludePath); + const QString includeFilePath = includeFileInfo.absoluteFilePath(); + if (includeFilePath.startsWith(toolkitPath, Qt::CaseInsensitive)) { + const QString path = IarewUtils::toolkitRelativeFilePath( + toolkitPath, includeFilePath); + includePaths.push_back(path); + } else { + const QString path = IarewUtils::projectRelativeFilePath( + baseDirectory, includeFilePath); + includePaths.push_back(path); + } + } + } + + QVariantList defineSymbols; + QVariantList includePaths; +}; + +// Diagnostics page options. + +struct DiagnosticsPageOptions final +{ + explicit DiagnosticsPageOptions(const ProductData &qbsProduct) + { + const auto &qbsProps = qbsProduct.moduleProperties(); + treatWarningsAsErrors = gen::utils::cppIntegerModuleProperty( + qbsProps, QStringLiteral("treatWarningsAsErrors")); + } + + int treatWarningsAsErrors = 0; +}; + +// Code page options. + +struct CodePageOptions final +{ + enum ProcessorMode { + CpuArmMode, + CpuThumbMode + }; + + explicit CodePageOptions(const ProductData &qbsProduct) + { + const auto &qbsProps = qbsProduct.moduleProperties(); + const QStringList flags = IarewUtils::cppModuleCompilerFlags(qbsProps); + const QString cpuModeValue = IarewUtils::flagValue( + flags, QStringLiteral("--cpu_mode")); + if (cpuModeValue == QLatin1String("thumb")) + cpuMode = CodePageOptions::CpuThumbMode; + else if (cpuModeValue == QLatin1String("arm")) + cpuMode = CodePageOptions::CpuArmMode; + + generateReadOnlyPosIndependentCode = flags.contains( + QLatin1String("--ropi")); + generateReadWritePosIndependentCode = flags.contains( + QLatin1String("--rwpi")); + disableDynamicReadWriteInitialization = flags.contains( + QLatin1String("--no_rw_dynamic_init")); + disableCodeMemoryDataReads = flags.contains( + QLatin1String("--no_literal_pool")); + } + + ProcessorMode cpuMode = CpuThumbMode; + int generateReadOnlyPosIndependentCode = 0; + int generateReadWritePosIndependentCode = 0; + int disableDynamicReadWriteInitialization = 0; + int disableCodeMemoryDataReads = 0; +}; + +} // namespace + +// ArmCompilerSettingsGroup + +ArmCompilerSettingsGroup::ArmCompilerSettingsGroup( + const Project &qbsProject, + const ProductData &qbsProduct, + const std::vector<ProductData> &qbsProductDeps) +{ + Q_UNUSED(qbsProject) + Q_UNUSED(qbsProductDeps) + + setName(QByteArrayLiteral("ICCARM")); + setArchiveVersion(kCompilerArchiveVersion); + setDataVersion(kCompilerDataVersion); + setDataDebugInfo(gen::utils::debugInformation(qbsProduct)); + + const QString buildRootDirectory = gen::utils::buildRootPath(qbsProject); + + buildOutputPage(qbsProduct); + buildLanguageOnePage(qbsProduct); + buildLanguageTwoPage(qbsProduct); + buildOptimizationsPage(qbsProduct); + buildPreprocessorPage(buildRootDirectory, qbsProduct); + buildDiagnosticsPage(qbsProduct); + buildCodePage(qbsProduct); +} + +void ArmCompilerSettingsGroup::buildOutputPage( + const ProductData &qbsProduct) +{ + const OutputPageOptions opts(qbsProduct); + // Add 'CCDebugInfo' item (Generate debug info). + addOptionsGroup(QByteArrayLiteral("CCDebugInfo"), + {opts.debugInfo}); +} + +void ArmCompilerSettingsGroup::buildLanguageOnePage( + const ProductData &qbsProduct) +{ + const LanguageOnePageOptions opts(qbsProduct); + // Add 'IccLang' item with 'auto-extension based' + // value (Language: C/C++/Auto). + addOptionsGroup(QByteArrayLiteral("IccLang"), + {opts.languageExtension}); + // Add 'IccCDialect' item (C dialect: c89/99/11). + addOptionsGroup(QByteArrayLiteral("IccCDialect"), + {opts.cLanguageDialect}); + // Add 'CCExt' item (Language conformance: IAR/relaxed/strict). + addOptionsGroup(QByteArrayLiteral("CCLangConformance"), + {opts.languageConformance}); + // Add 'IccExceptions2' item (Enable exceptions). + addOptionsGroup(QByteArrayLiteral("IccExceptions2"), + {opts.enableExceptions}); + // Add 'IccRTTI2' item (Enable RTTI). + addOptionsGroup(QByteArrayLiteral("IccRTTI2"), + {opts.enableRtti}); + // Add 'IccStaticDestr' item (Destroy static objects). + addOptionsGroup(QByteArrayLiteral("IccStaticDestr"), + {opts.destroyStaticObjects}); + // Add 'IccAllowVLA' item (Allow VLA). + addOptionsGroup(QByteArrayLiteral("IccAllowVLA"), + {opts.allowVla}); + // Add 'IccCppInlineSemantics' item (C++ inline semantics). + addOptionsGroup(QByteArrayLiteral("IccCppInlineSemantics"), + {opts.enableInlineSemantics}); + // Add 'CCRequirePrototypes' item (Require prototypes). + addOptionsGroup(QByteArrayLiteral("CCRequirePrototypes"), + {opts.requirePrototypes}); +} + +void ArmCompilerSettingsGroup::buildLanguageTwoPage( + const ProductData &qbsProduct) +{ + const LanguageTwoPageOptions opts(qbsProduct); + // Add 'CCSignedPlainChar' item (Plain char is: signed/unsigned). + addOptionsGroup(QByteArrayLiteral("CCSignedPlainChar"), + {opts.plainCharacter}); + // Add 'IccFloatSemantics' item + // (Floating-point semantic: strict/relaxed). + addOptionsGroup(QByteArrayLiteral("IccFloatSemantics"), + {opts.floatingPointSemantic}); +} + +void ArmCompilerSettingsGroup::buildOptimizationsPage( + const ProductData &qbsProduct) +{ + const OptimizationsPageOptions opts(qbsProduct); + // Add 'CCOptStrategy', 'CCOptLevel' + // and 'CCOptLevelSlave' items (Level). + addOptionsGroup(QByteArrayLiteral("CCOptStrategy"), + {opts.optimizationStrategy}); + addOptionsGroup(QByteArrayLiteral("CCOptLevel"), + {opts.optimizationLevel}); + addOptionsGroup(QByteArrayLiteral("CCOptLevelSlave"), + {opts.optimizationLevelSlave}); + // Add 'CCAllowList' item (Enabled optimizations: 6 check boxes). + const QString transformations = QStringLiteral("%1%2%3%4%5%6%7%8") + .arg(opts.enableCommonSubexpressionElimination) + .arg(opts.enableLoopUnroll) + .arg(opts.enableFunctionInlining) + .arg(opts.enableCodeMotion) + .arg(opts.enableTypeBasedAliasAnalysis) + .arg(opts.enableStaticClustering) + .arg(opts.enableInstructionScheduling) + .arg(opts.enableVectorization); + addOptionsGroup(QByteArrayLiteral("CCAllowList"), + {transformations}); + // Add 'CCOptimizationNoSizeConstraints' item (No size constraints). + addOptionsGroup(QByteArrayLiteral("CCOptimizationNoSizeConstraints"), + {opts.disableSizeConstraints}); +} + +void ArmCompilerSettingsGroup::buildPreprocessorPage( + const QString &baseDirectory, + const ProductData &qbsProduct) +{ + const PreprocessorPageOptions opts(baseDirectory, qbsProduct); + // Add 'CCDefines' item (Defined symbols). + addOptionsGroup(QByteArrayLiteral("CCDefines"), + opts.defineSymbols); + // Add 'CCIncludePath2' item (Additional include directories). + addOptionsGroup(QByteArrayLiteral("CCIncludePath2"), + opts.includePaths); +} + +void ArmCompilerSettingsGroup::buildDiagnosticsPage( + const ProductData &qbsProduct) +{ + const DiagnosticsPageOptions opts(qbsProduct); + // Add 'CCDiagWarnAreErr' item (Treat all warnings as errors). + addOptionsGroup(QByteArrayLiteral("CCDiagWarnAreErr"), + {opts.treatWarningsAsErrors}); +} + +void ArmCompilerSettingsGroup::buildCodePage( + const ProductData &qbsProduct) +{ + const CodePageOptions opts(qbsProduct); + // Add 'IProcessorMode2' item (Processor mode: arm/thumb). + addOptionsGroup(QByteArrayLiteral("IProcessorMode2"), + {opts.cpuMode}); + // Add 'CCPosIndRopi' item (Code and read-only data "ropi"). + addOptionsGroup(QByteArrayLiteral("CCPosIndRopi"), + {opts.generateReadOnlyPosIndependentCode}); + // Add 'CCPosIndRwpi' item (Read/write data "rwpi"). + addOptionsGroup(QByteArrayLiteral("CCPosIndRwpi"), + {opts.generateReadWritePosIndependentCode}); + // Add 'CCPosIndNoDynInit' item (No dynamic read/write initialization). + addOptionsGroup(QByteArrayLiteral("CCPosIndNoDynInit"), + {opts.disableDynamicReadWriteInitialization}); + // Add 'CCNoLiteralPool' item (No data reads in code memory). + addOptionsGroup(QByteArrayLiteral("CCNoLiteralPool"), + {opts.disableCodeMemoryDataReads}); +} + +} // namespace v8 +} // namespace arm +} // namespace iarew +} // namespace qbs diff --git a/src/plugins/generator/iarew/archs/arm/armcompilersettingsgroup_v8.h b/src/plugins/generator/iarew/archs/arm/armcompilersettingsgroup_v8.h new file mode 100644 index 000000000..6137bc976 --- /dev/null +++ b/src/plugins/generator/iarew/archs/arm/armcompilersettingsgroup_v8.h @@ -0,0 +1,63 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt.io/licensing +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef QBS_IAREWARMCOMPILERSETTINGSGROUP_V8_H +#define QBS_IAREWARMCOMPILERSETTINGSGROUP_V8_H + +#include "../../iarewsettingspropertygroup.h" + +namespace qbs { +namespace iarew { +namespace arm { +namespace v8 { + +class ArmCompilerSettingsGroup final : public IarewSettingsPropertyGroup +{ +public: + explicit ArmCompilerSettingsGroup(const Project &qbsProject, + const ProductData &qbsProduct, + const std::vector<ProductData> &qbsProductDeps); + +private: + void buildOutputPage(const ProductData &qbsProduct); + void buildLanguageOnePage(const ProductData &qbsProduct); + void buildLanguageTwoPage(const ProductData &qbsProduct); + void buildOptimizationsPage(const ProductData &qbsProduct); + void buildPreprocessorPage(const QString &baseDirectory, const ProductData &qbsProduct); + void buildDiagnosticsPage(const ProductData &qbsProduct); + void buildCodePage(const ProductData &qbsProduct); +}; + +} // namespace v8 +} // namespace arm +} // namespace iarew +} // namespace qbs + +#endif // QBS_IAREWARMCOMPILERSETTINGSGROUP_V8_H diff --git a/src/plugins/generator/iarew/archs/arm/armgeneralsettingsgroup_v8.cpp b/src/plugins/generator/iarew/archs/arm/armgeneralsettingsgroup_v8.cpp new file mode 100644 index 000000000..911873cf4 --- /dev/null +++ b/src/plugins/generator/iarew/archs/arm/armgeneralsettingsgroup_v8.cpp @@ -0,0 +1,551 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt.io/licensing +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "armgeneralsettingsgroup_v8.h" + +#include "../../iarewutils.h" + +#include <QtCore/qdir.h> + +namespace qbs { +namespace iarew { +namespace arm { +namespace v8 { + +constexpr int kGeneralArchiveVersion = 3; +constexpr int kGeneralDataVersion = 30; + +namespace { + +struct CpuCoreEntry final +{ + enum CpuCoreCode { + Arm7tdmi = 0, + Arm7tdmis = 1, + Arm710t = 2, + Arm720t = 3, + Arm740t = 4, + Arm7ejs = 5, + Arm9tdmi = 6, + Arm920t = 7, + Arm922t = 8, + Arm940t = 9, + Arm9e = 10, + Arm9es = 11, + Arm926ejs = 12, + Arm946es = 13, + Arm966es = 14, + Arm968es = 15, + Arm10e = 16, + Arm1020e = 17, + Arm1022e = 18, + Arm1026ejs = 19, + Arm1136j = 20, + Arm1136js = 21, + Arm1176j = 24, + Arm1176js = 25, + Xscale = 32, + XscaleIr7 = 33, + CortexM0 = 34, + CortexM0Plus = 35, + CortexM1 = 36, + CortexMs1 = 37, + CortexM3 = 38, + CortexM4 = 39, + CortexM7 = 41, + CortexR4 = 42, + CortexR5 = 44, + CortexR7 = 46, + CortexR8 = 48, + CortexR52 = 49, + CortexA5 = 50, + CortexA7 = 52, + CortexA8 = 53, + CortexA9 = 54, + CortexA15 = 55, + CortexA17 = 56, + CortexM23 = 58, + CortexM33 = 59 + }; + + // Required to compile in MSVC2015. + CpuCoreEntry(CpuCoreCode cc, QByteArray tf) + : coreCode(cc), targetFlag(std::move(tf)) + {} + + CpuCoreCode coreCode = Arm7tdmi; + QByteArray targetFlag; +}; + +// Dictionary of known ARM CPU cores and its compiler options. +static const CpuCoreEntry cpusDict[] = { + {CpuCoreEntry::Arm7tdmi, "arm7tdmi"}, // same as 'sc100' + {CpuCoreEntry::Arm7tdmis, "arm7tdmi-s"}, + {CpuCoreEntry::Arm710t, "arm710t"}, + {CpuCoreEntry::Arm720t, "arm720t"}, + {CpuCoreEntry::Arm740t, "arm740t"}, + {CpuCoreEntry::Arm7ejs, "arm7ej-s"}, + {CpuCoreEntry::Arm9tdmi, "arm9tdmi"}, + {CpuCoreEntry::Arm920t, "arm920t"}, + {CpuCoreEntry::Arm922t, "arm922t"}, + {CpuCoreEntry::Arm940t, "arm940t"}, + {CpuCoreEntry::Arm9e, "arm9e"}, + {CpuCoreEntry::Arm9es, "arm9e-s"}, + {CpuCoreEntry::Arm926ejs, "arm926ej-s"}, + {CpuCoreEntry::Arm946es, "arm946e-s"}, + {CpuCoreEntry::Arm966es, "arm966e-s"}, + {CpuCoreEntry::Arm968es, "arm968e-s"}, + {CpuCoreEntry::Arm10e, "arm10e"}, + {CpuCoreEntry::Arm1020e, "arm1020e"}, + {CpuCoreEntry::Arm1022e, "arm1022e"}, + {CpuCoreEntry::Arm1026ejs, "arm1026ej-s"}, + {CpuCoreEntry::Arm1136j, "arm1136j"}, + {CpuCoreEntry::Arm1136js, "arm1136j-s"}, + {CpuCoreEntry::Arm1176j, "arm1176j"}, + {CpuCoreEntry::Arm1176js, "arm1176j-s"}, + {CpuCoreEntry::Xscale, "xscale"}, + {CpuCoreEntry::XscaleIr7, "xscale-ir7"}, + {CpuCoreEntry::CortexM0, "cortex-m0"}, + {CpuCoreEntry::CortexM0Plus, "cortex-m0+"}, // same as 'sc000' + {CpuCoreEntry::CortexM1, "cortex-m1"}, + {CpuCoreEntry::CortexMs1, "cortex-ms1"}, + {CpuCoreEntry::CortexM3, "cortex-m3"}, // same as 'sc300' + {CpuCoreEntry::CortexM4, "cortex-m4"}, + {CpuCoreEntry::CortexM7, "cortex-m7"}, + {CpuCoreEntry::CortexR4, "cortex-r4"}, + {CpuCoreEntry::CortexR5, "cortex-r5"}, + {CpuCoreEntry::CortexR7, "cortex-r7"}, + {CpuCoreEntry::CortexR8, "cortex-r8"}, + {CpuCoreEntry::CortexR52, "cortex-r52"}, + {CpuCoreEntry::CortexA5, "cortex-a5"}, + {CpuCoreEntry::CortexA7, "cortex-a7"}, + {CpuCoreEntry::CortexA8, "cortex-a8"}, + {CpuCoreEntry::CortexA9, "cortex-a9"}, + {CpuCoreEntry::CortexA15, "cortex-a15"}, + {CpuCoreEntry::CortexA17, "cortex-a17"}, + {CpuCoreEntry::CortexM23, "cortex-m23"}, + {CpuCoreEntry::CortexM33, "cortex-m33"}, +}; + +struct FpuCoreEntry final +{ + enum FpuRegistersCount { + NoFpuRegisters, + Fpu16Registers, + Fpu32Registers + }; + + enum FpuCoreCode { + NoVfp = 0, + Vfp2 = 2, + Vfp3d16 = 3, + Vfp3 = 3, + Vfp4sp = 4, + Vfp4d16 = 5, + Vfp4 = 5, + Vfp5sp = 6, + Vfp5d16 = 7, + Vfp9s = 8 + }; + + // Required to compile in MSVC2015. + FpuCoreEntry(FpuCoreCode cc, FpuRegistersCount rc, + QByteArray tf) + : coreCode(cc), regsCount(rc), targetFlag(std::move(tf)) + {} + + FpuCoreCode coreCode = NoVfp; + FpuRegistersCount regsCount = NoFpuRegisters; + QByteArray targetFlag; +}; + +// Dictionary of known ARM FPU cores and its compiler options. +static const FpuCoreEntry fpusDict[] = { + {FpuCoreEntry::Vfp2, FpuCoreEntry::NoFpuRegisters, "vfpv2"}, + {FpuCoreEntry::Vfp3d16, FpuCoreEntry::Fpu16Registers, "vfpv3_d16"}, + {FpuCoreEntry::Vfp3, FpuCoreEntry::Fpu32Registers, "vfpv3"}, + {FpuCoreEntry::Vfp4sp, FpuCoreEntry::Fpu16Registers, "vfpv4_sp"}, + {FpuCoreEntry::Vfp4d16, FpuCoreEntry::Fpu16Registers, "vfpv4_d16"}, + {FpuCoreEntry::Vfp4, FpuCoreEntry::Fpu32Registers, "vfpv4"}, + {FpuCoreEntry::Vfp5sp, FpuCoreEntry::Fpu16Registers, "vfpv5_sp"}, + {FpuCoreEntry::Vfp5d16, FpuCoreEntry::Fpu16Registers, "vfpv5_d16"}, + {FpuCoreEntry::Vfp9s, FpuCoreEntry::NoFpuRegisters, "vfp9-s"}, +}; + +// Target page options. + +struct TargetPageOptions final +{ + enum Endianness { + LittleEndian, + BigEndian + }; + + explicit TargetPageOptions(const ProductData &qbsProduct) + { + const auto &qbsProps = qbsProduct.moduleProperties(); + const QStringList flags = gen::utils::cppStringModuleProperties( + qbsProps, {QStringLiteral("driverFlags")}); + // Detect target CPU code. + const QString cpuValue = IarewUtils::flagValue( + flags, QStringLiteral("--cpu")) + .toLower(); + const auto cpuEnd = std::cend(cpusDict); + const auto cpuIt = std::find_if(std::cbegin(cpusDict), cpuEnd, + [cpuValue]( + const CpuCoreEntry &entry) { + return entry.targetFlag == cpuValue.toLatin1(); + }); + if (cpuIt != cpuEnd) + targetCpu = cpuIt->coreCode; + // Detect target FPU code. + const QString fpuValue = IarewUtils::flagValue( + flags, QStringLiteral("--fpu")) + .toLower(); + const auto fpuEnd = std::cend(fpusDict); + const auto fpuIt = std::find_if(std::cbegin(fpusDict), fpuEnd, + [fpuValue]( + const FpuCoreEntry &entry) { + return entry.targetFlag == fpuValue.toLatin1(); + }); + if (fpuIt != fpuEnd) { + targetFpu = fpuIt->coreCode; + targetFpuRegs = fpuIt->regsCount; + } + // Detect endian. + const QString prop = gen::utils::cppStringModuleProperty( + qbsProps, QStringLiteral("endianness")); + if (prop == QLatin1String("big")) + endianness = TargetPageOptions::BigEndian; + else if (prop == QLatin1String("little")) + endianness = TargetPageOptions::LittleEndian; + } + + CpuCoreEntry::CpuCoreCode targetCpu = CpuCoreEntry::Arm7tdmi; + FpuCoreEntry::FpuCoreCode targetFpu = FpuCoreEntry::NoVfp; + FpuCoreEntry::FpuRegistersCount targetFpuRegs = FpuCoreEntry::NoFpuRegisters; + Endianness endianness = LittleEndian; +}; + +// Library 1 page options. + +struct LibraryOnePageOptions final +{ + enum PrintfFormatter { + PrintfAutoFormatter, + PrintfFullFormatter, + PrintfLargeFormatter, + PrintfSmallFormatter, + PrintfTinyFormatter + }; + + enum ScanfFormatter { + ScanfAutoFormatter, + ScanfFullFormatter, + ScanfLargeFormatter, + ScanfSmallFormatter + }; + + explicit LibraryOnePageOptions(const ProductData &qbsProduct) + { + const auto &qbsProps = qbsProduct.moduleProperties(); + const QStringList flags = IarewUtils::cppModuleLinkerFlags(qbsProps); + for (auto flagIt = flags.cbegin(); flagIt < flags.cend(); ++flagIt) { + if (*flagIt != QLatin1String("--redirect")) + continue; + ++flagIt; + if (flagIt->startsWith(QLatin1String("_printf="), + Qt::CaseInsensitive)) { + const QString prop = flagIt->split( + QLatin1Char('=')).at(1).toLower(); + if (prop == QLatin1String("_printffullnomb")) + printfFormatter = LibraryOnePageOptions::PrintfFullFormatter; + else if (prop == QLatin1String("_printflargenomb")) + printfFormatter = LibraryOnePageOptions::PrintfLargeFormatter; + else if (prop == QLatin1String("_printfsmallnomb")) + printfFormatter = LibraryOnePageOptions::PrintfSmallFormatter; + else if (prop == QLatin1String("_printftiny")) + printfFormatter = LibraryOnePageOptions::PrintfTinyFormatter; + } else if (flagIt->startsWith(QLatin1String("_scanf="), + Qt::CaseInsensitive)) { + const QString prop = flagIt->split( + QLatin1Char('=')).at(1).toLower();; + if (prop == QLatin1String("_scanffullnomb")) + scanfFormatter = LibraryOnePageOptions::ScanfFullFormatter; + else if (prop == QLatin1String("_scanflargenomb")) + scanfFormatter = LibraryOnePageOptions::ScanfLargeFormatter; + else if (prop == QLatin1String("_scanfsmallnomb")) + scanfFormatter = LibraryOnePageOptions::ScanfSmallFormatter; + } + } + } + + PrintfFormatter printfFormatter = PrintfAutoFormatter; + ScanfFormatter scanfFormatter = ScanfAutoFormatter; +}; + +// Library 2 page options. + +struct LibraryTwoPageOptions final +{ + enum HeapType { + AutomaticHeap, + AdvancedHeap, + BasicHeap, + NoFreeHeap + }; + + explicit LibraryTwoPageOptions(const ProductData &qbsProduct) + { + const auto &qbsProps = qbsProduct.moduleProperties(); + const QStringList flags = IarewUtils::cppModuleLinkerFlags(qbsProps); + if (flags.contains(QLatin1String("--advanced_heap"))) + heapType = LibraryTwoPageOptions::AdvancedHeap; + else if (flags.contains(QLatin1String("--basic_heap"))) + heapType = LibraryTwoPageOptions::BasicHeap; + else if (flags.contains(QLatin1String("--no_free_heap"))) + heapType = LibraryTwoPageOptions::NoFreeHeap; + else + heapType = LibraryTwoPageOptions::AutomaticHeap; + } + + HeapType heapType = AutomaticHeap; +}; + +// Library configuration page options. + +struct LibraryConfigPageOptions final +{ + enum RuntimeLibrary { + NoLibrary, + NormalLibrary, + FullLibrary, + CustomLibrary + }; + + enum ThreadSupport { + NoThread, + EnableThread + }; + + enum LowLevelInterface { + NoInterface, + SemihostedInterface + }; + + explicit LibraryConfigPageOptions(const QString &baseDirectory, + const ProductData &qbsProduct) + { + const auto &qbsProps = qbsProduct.moduleProperties(); + const QStringList flags = IarewUtils::cppModuleCompilerFlags(qbsProps); + const QFileInfo dlibFileInfo(IarewUtils::flagValue( + flags, QStringLiteral("--dlib_config"))); + if (!dlibFileInfo.exists()) { + dlibType = LibraryConfigPageOptions::NoLibrary; + } else { + const QString toolkitPath = IarewUtils::toolkitRootPath(qbsProduct); + const QString dlibFilePath = dlibFileInfo.absoluteFilePath(); + if (dlibFilePath.startsWith(toolkitPath, Qt::CaseInsensitive)) { + if (dlibFilePath.endsWith(QLatin1String("dlib_config_normal.h"), + Qt::CaseInsensitive)) { + dlibType = LibraryConfigPageOptions::NormalLibrary; + } else if (dlibFilePath.endsWith( + QLatin1String("dlib_config_full.h"), + Qt::CaseInsensitive)) { + dlibType = LibraryConfigPageOptions::FullLibrary; + } else { + dlibType = LibraryConfigPageOptions::CustomLibrary; + } + + dlibConfigPath = IarewUtils::toolkitRelativeFilePath( + toolkitPath, dlibFilePath); + } else { + dlibType = LibraryConfigPageOptions::CustomLibrary; + dlibConfigPath = IarewUtils::projectRelativeFilePath( + baseDirectory, dlibFilePath); + } + } + + threadSupport = flags.contains(QLatin1String("--threaded_lib")) + ? LibraryConfigPageOptions::EnableThread + : LibraryConfigPageOptions::NoThread; + lowLevelInterface = flags.contains(QLatin1String("--semihosting")) + ? LibraryConfigPageOptions::SemihostedInterface + : LibraryConfigPageOptions::NoInterface; + } + + RuntimeLibrary dlibType = NoLibrary; + QString dlibConfigPath; + ThreadSupport threadSupport = NoThread; + LowLevelInterface lowLevelInterface = NoInterface; +}; + +// Output page options. + +struct OutputPageOptions final +{ + explicit OutputPageOptions(const QString &baseDirectory, + const ProductData &qbsProduct) + { + binaryType = IarewUtils::outputBinaryType(qbsProduct); + binaryDirectory = gen::utils::binaryOutputDirectory( + baseDirectory, qbsProduct); + objectDirectory = gen::utils::objectsOutputDirectory( + baseDirectory, qbsProduct); + listingDirectory = gen::utils::listingOutputDirectory( + baseDirectory, qbsProduct); + } + + IarewUtils::OutputBinaryType binaryType = IarewUtils::ApplicationOutputType; + QString binaryDirectory; + QString objectDirectory; + QString listingDirectory; +}; + +} // namespace + +// ArmGeneralSettingsGroup + +ArmGeneralSettingsGroup::ArmGeneralSettingsGroup( + const Project &qbsProject, + const ProductData &qbsProduct, + const std::vector<ProductData> &qbsProductDeps) +{ + Q_UNUSED(qbsProductDeps) + + setName(QByteArrayLiteral("General")); + setArchiveVersion(kGeneralArchiveVersion); + setDataVersion(kGeneralDataVersion); + setDataDebugInfo(gen::utils::debugInformation(qbsProduct)); + + const QString buildRootDirectory = gen::utils::buildRootPath(qbsProject); + + buildTargetPage(qbsProduct); + buildLibraryOptionsOnePage(qbsProduct); + buildLibraryOptionsTwoPage(qbsProduct); + buildLibraryConfigPage(buildRootDirectory, qbsProduct); + buildOutputPage(buildRootDirectory, qbsProduct); +} + +void ArmGeneralSettingsGroup::buildTargetPage( + const ProductData &qbsProduct) +{ + const TargetPageOptions opts(qbsProduct); + // Add 'GBECoreSlave', 'CoreVariant', 'GFPUCoreSlave2' items + // (Processor variant chooser). + addOptionsGroup(QByteArrayLiteral("GBECoreSlave"), + {opts.targetCpu}, 26); + addOptionsGroup(QByteArrayLiteral("CoreVariant"), + {opts.targetCpu}, 26); + addOptionsGroup(QByteArrayLiteral("GFPUCoreSlave2"), + {opts.targetCpu}, 26); + // Add 'FPU2', 'NrRegs' item (Floating point settings chooser). + addOptionsGroup(QByteArrayLiteral("FPU2"), + {opts.targetFpu}, 0); + addOptionsGroup(QByteArrayLiteral("NrRegs"), + {opts.targetFpuRegs}, 0); + // Add 'GEndianMode' item (Endian mode chooser). + addOptionsGroup(QByteArrayLiteral("GEndianMode"), + {opts.endianness}); +} + +void ArmGeneralSettingsGroup::buildLibraryOptionsOnePage( + const ProductData &qbsProduct) +{ + const LibraryOnePageOptions opts(qbsProduct); + // Add 'OGPrintfVariant' item (Printf formatter). + addOptionsGroup(QByteArrayLiteral("OGPrintfVariant"), + {opts.printfFormatter}); + // Add 'OGScanfVariant' item (Printf formatter). + addOptionsGroup(QByteArrayLiteral("OGScanfVariant"), + {opts.scanfFormatter}); +} + +void ArmGeneralSettingsGroup::buildLibraryOptionsTwoPage( + const ProductData &qbsProduct) +{ + const LibraryTwoPageOptions opts(qbsProduct); + // Add 'OgLibHeap' item (Heap selection: + // auto/advanced/basic/nofree). + addOptionsGroup(QByteArrayLiteral("OgLibHeap"), + {opts.heapType}); +} + +void ArmGeneralSettingsGroup::buildLibraryConfigPage( + const QString baseDirectory, + const ProductData &qbsProduct) +{ + const LibraryConfigPageOptions opts(baseDirectory, qbsProduct); + // Add 'GRuntimeLibSelect', 'GRuntimeLibSelectSlave' + // and 'RTConfigPath2' items + // (Link with runtime: none/normal/full/custom). + addOptionsGroup(QByteArrayLiteral("GRuntimeLibSelect"), + {opts.dlibType}); + addOptionsGroup(QByteArrayLiteral("GRuntimeLibSelectSlave"), + {opts.dlibType}); + addOptionsGroup(QByteArrayLiteral("RTConfigPath2"), + {opts.dlibConfigPath}); + // Add 'GRuntimeLibThreads'item + // (Enable thread support in library). + addOptionsGroup(QByteArrayLiteral("GRuntimeLibThreads"), + {opts.threadSupport}); + // Add 'GenLowLevelInterface' item (Library low-level + // interface: none/semihosted/breakpoint). + addOptionsGroup(QByteArrayLiteral("GenLowLevelInterface"), + {opts.lowLevelInterface}); +} + +void ArmGeneralSettingsGroup::buildOutputPage( + const QString baseDirectory, + const ProductData &qbsProduct) +{ + const OutputPageOptions opts(baseDirectory, qbsProduct); + // Add 'GOutputBinary' item + // (Output file: executable/library). + addOptionsGroup(QByteArrayLiteral("GOutputBinary"), + {opts.binaryType}); + // Add 'ExePath' item + // (Executable/binaries output directory). + addOptionsGroup(QByteArrayLiteral("ExePath"), + {opts.binaryDirectory}); + // Add 'ObjPath' item + // (Object files output directory). + addOptionsGroup(QByteArrayLiteral("ObjPath"), + {opts.objectDirectory}); + // Add 'ListPath' item + // (List files output directory). + addOptionsGroup(QByteArrayLiteral("ListPath"), + {opts.listingDirectory}); +} + +} // namespace v8 +} // namespace arm +} // namespace iarew +} // namespace qbs diff --git a/src/plugins/generator/iarew/archs/arm/armgeneralsettingsgroup_v8.h b/src/plugins/generator/iarew/archs/arm/armgeneralsettingsgroup_v8.h new file mode 100644 index 000000000..420e98008 --- /dev/null +++ b/src/plugins/generator/iarew/archs/arm/armgeneralsettingsgroup_v8.h @@ -0,0 +1,63 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt.io/licensing +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef QBS_IAREWARMGENERALSETTINGSGROUP_V8_H +#define QBS_IAREWARMGENERALSETTINGSGROUP_V8_H + +#include "../../iarewsettingspropertygroup.h" + +namespace qbs { +namespace iarew { +namespace arm { +namespace v8 { + +class ArmGeneralSettingsGroup final : public IarewSettingsPropertyGroup +{ +public: + explicit ArmGeneralSettingsGroup(const Project &qbsProject, + const ProductData &qbsProduct, + const std::vector<ProductData> &qbsProductDeps); + +private: + void buildTargetPage(const ProductData &qbsProduct); + void buildLibraryOptionsOnePage(const ProductData &qbsProduct); + void buildLibraryOptionsTwoPage(const ProductData &qbsProduct); + void buildLibraryConfigPage(const QString baseDirectory, + const ProductData &qbsProduct); + void buildOutputPage(const QString baseDirectory, + const ProductData &qbsProduct); +}; + +} // namespace v8 +} // namespace arm +} // namespace iarew +} // namespace qbs + +#endif // QBS_IAREWARMGENERALSETTINGSGROUP_V8_H diff --git a/src/plugins/generator/iarew/archs/arm/armlinkersettingsgroup_v8.cpp b/src/plugins/generator/iarew/archs/arm/armlinkersettingsgroup_v8.cpp new file mode 100644 index 000000000..b6b755b70 --- /dev/null +++ b/src/plugins/generator/iarew/archs/arm/armlinkersettingsgroup_v8.cpp @@ -0,0 +1,489 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt.io/licensing +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "armlinkersettingsgroup_v8.h" + +#include "../../iarewutils.h" + +#include <QtCore/qdir.h> + +namespace qbs { +namespace iarew { +namespace arm { +namespace v8 { + +constexpr int kLinkerArchiveVersion = 0; +constexpr int kLinkerDataVersion = 20; + +namespace { + +// Config page options. + +struct ConfigPageOptions final +{ + explicit ConfigPageOptions(const QString &baseDirectory, + const ProductData &qbsProduct) + { + const auto &qbsProps = qbsProduct.moduleProperties(); + // Accumulate config definitions (if exists). + const QStringList flags = IarewUtils::cppModuleLinkerFlags(qbsProps); + configDefines = IarewUtils::flagValues( + flags, QStringLiteral("--config_def")); + const QString toolkitPath = IarewUtils::toolkitRootPath(qbsProduct); + + // Enumerate all product linker config files + // (which are set trough 'linkerscript' tag). + const auto qbsGroups = qbsProduct.groups(); + for (const auto &qbsGroup : qbsGroups) { + if (!qbsGroup.isEnabled()) + continue; + const auto qbsArtifacts = qbsGroup.sourceArtifacts(); + for (const auto &qbsArtifact : qbsArtifacts) { + const auto qbsTags = qbsArtifact.fileTags(); + if (!qbsTags.contains(QLatin1String("linkerscript"))) + continue; + const QString fullConfigPath = qbsArtifact.filePath(); + if (fullConfigPath.startsWith(toolkitPath, Qt::CaseInsensitive)) { + const QString path = IarewUtils::toolkitRelativeFilePath( + toolkitPath, fullConfigPath); + configFilePaths.push_back(path); + } else { + const QString path = IarewUtils::projectRelativeFilePath( + baseDirectory, fullConfigPath); + configFilePaths.push_back(path); + } + } + } + + // Enumerate all product linker config files + // (which are set trough '--config' option). + const QVariantList configPathValues = IarewUtils::flagValues( + flags, QStringLiteral("--config")); + for (const auto &configPathValue : configPathValues) { + const QString fullConfigPath = configPathValue.toString(); + if (fullConfigPath.startsWith(toolkitPath, Qt::CaseInsensitive)) { + const QString path = IarewUtils::toolkitRelativeFilePath( + toolkitPath, fullConfigPath); + if (!configFilePaths.contains(path)) + configFilePaths.push_back(path); + } else { + const QString path = IarewUtils::projectRelativeFilePath( + baseDirectory, fullConfigPath); + if (!configFilePaths.contains(path)) + configFilePaths.push_back(path); + } + } + } + + QVariantList configFilePaths; + QVariantList configDefines; +}; + +// Library page options. + +struct LibraryPageOptions final +{ + explicit LibraryPageOptions(const QString &baseDirectory, + const ProductData &qbsProduct, + const std::vector<ProductData> &qbsProductDeps) + { + const auto &qbsProps = qbsProduct.moduleProperties(); + + entryPoint = gen::utils::cppStringModuleProperty( + qbsProps, QStringLiteral("entryPoint")); + + // Add libraries search paths. + const QString toolkitPath = IarewUtils::toolkitRootPath(qbsProduct); + const QStringList libraryPaths = gen::utils::cppStringModuleProperties( + qbsProps, {QStringLiteral("libraryPaths")}); + for (const QString &libraryPath : libraryPaths) { + const QFileInfo libraryPathInfo(libraryPath); + const QString fullLibrarySearchPath = + libraryPathInfo.absoluteFilePath(); + if (fullLibrarySearchPath.startsWith( + toolkitPath, Qt::CaseInsensitive)) { + const QString path = IarewUtils::toolkitRelativeFilePath( + toolkitPath, fullLibrarySearchPath); + librarySearchPaths.push_back(path); + } else { + const QString path = IarewUtils::projectRelativeFilePath( + baseDirectory,fullLibrarySearchPath); + librarySearchPaths.push_back(path); + } + } + + // Add static libraries paths. + const QStringList staticLibrariesProps = + gen::utils::cppStringModuleProperties( + qbsProps, {QStringLiteral("staticLibraries")}); + for (const QString &staticLibrary : staticLibrariesProps) { + const QFileInfo staticLibraryInfo(staticLibrary); + if (staticLibraryInfo.isAbsolute()) { + const QString fullStaticLibraryPath = + staticLibraryInfo.absoluteFilePath(); + if (fullStaticLibraryPath.startsWith( + toolkitPath, Qt::CaseInsensitive)) { + const QString path = IarewUtils::toolkitRelativeFilePath( + toolkitPath, fullStaticLibraryPath); + staticLibraries.push_back(path); + } else { + const QString path = IarewUtils::projectRelativeFilePath( + baseDirectory, fullStaticLibraryPath); + staticLibraries.push_back(path); + } + } else { + staticLibraries.push_back(staticLibrary); + } + } + + // Add static libraries from product dependencies. + for (const ProductData &qbsProductDep : qbsProductDeps) { + const QString depBinaryPath = QLatin1String("$PROJ_DIR$/") + + gen::utils::targetBinaryPath(baseDirectory, + qbsProductDep); + staticLibraries.push_back(depBinaryPath); + } + + const QStringList flags = IarewUtils::cppModuleLinkerFlags(qbsProps); + enableRuntimeLibsSearch = !flags.contains( + QLatin1String("--no_library_search")); + } + + QString entryPoint; + QVariantList staticLibraries; + QVariantList librarySearchPaths; + int enableRuntimeLibsSearch = 0; +}; + +// Output page options. + +struct OutputPageOptions final +{ + explicit OutputPageOptions(const ProductData &qbsProduct) + { + const auto &qbsProps = qbsProduct.moduleProperties(); + const QStringList flags = IarewUtils::cppModuleLinkerFlags(qbsProps); + debugInfo = !flags.contains(QLatin1String("--strip")); + outputFile = gen::utils::targetBinary(qbsProduct); + } + + int debugInfo = 0; + QString outputFile; +}; + +// Input page options. + +struct InputPageOptions final +{ + explicit InputPageOptions(const ProductData &qbsProduct) + { + const auto &qbsProps = qbsProduct.moduleProperties(); + const QStringList flags = IarewUtils::cppModuleLinkerFlags(qbsProps); + keepSymbols = IarewUtils::flagValues(flags, QStringLiteral("--keep")); + } + + QVariantList keepSymbols; +}; + +// List page options. + +struct ListPageOptions final +{ + enum ListingAction { + NoListing, + GenerateListing + }; + + explicit ListPageOptions(const ProductData &qbsProduct) + { + const auto &qbsProps = qbsProduct.moduleProperties(); + generateMap = gen::utils::cppBooleanModuleProperty( + qbsProps, QStringLiteral("generateMapFile")) + ? ListPageOptions::GenerateListing + : ListPageOptions::NoListing; + } + + ListingAction generateMap = GenerateListing; +}; + +// Optimizations page options. + +struct OptimizationsPageOptions final +{ + explicit OptimizationsPageOptions(const ProductData &qbsProduct) + { + const auto &qbsProps = qbsProduct.moduleProperties(); + const QStringList flags = IarewUtils::cppModuleLinkerFlags(qbsProps); + inlineSmallRoutines = flags.contains(QLatin1String("--inline")); + mergeDuplicateSections = flags.contains( + QLatin1String("--merge_duplicate_sections")); + virtualFuncElimination = flags.contains(QLatin1String("--vfe")); + } + + int inlineSmallRoutines = 0; + int mergeDuplicateSections = 0; + int virtualFuncElimination = 0; +}; + +// Advanced page options. + +struct AdvancedPageOptions final +{ + explicit AdvancedPageOptions(const ProductData &qbsProduct) + { + const auto &qbsProps = qbsProduct.moduleProperties(); + const QStringList flags = IarewUtils::cppModuleLinkerFlags(qbsProps); + allowExceptions = !flags.contains(QLatin1String("--no_exceptions")); + } + + int allowExceptions = 0; +}; + +// Defines page options. + +struct DefinesPageOptions final +{ + explicit DefinesPageOptions(const ProductData &qbsProduct) + { + const auto &qbsProps = qbsProduct.moduleProperties(); + const QStringList flags = IarewUtils::cppModuleLinkerFlags(qbsProps); + defineSymbols = IarewUtils::flagValues( + flags, QStringLiteral("--define_symbol")); + } + + QVariantList defineSymbols; +}; + +// Diagnostics page options. + +struct DiagnosticsPageOptions final +{ + explicit DiagnosticsPageOptions(const ProductData &qbsProduct) + { + const auto &qbsProps = qbsProduct.moduleProperties(); + treatWarningsAsErrors = gen::utils::cppIntegerModuleProperty( + qbsProps, QStringLiteral("treatWarningsAsErrors")); + } + + int treatWarningsAsErrors = 0; +}; + +} // namespace + +// ArmLinkerSettingsGroup + +ArmLinkerSettingsGroup::ArmLinkerSettingsGroup( + const Project &qbsProject, + const ProductData &qbsProduct, + const std::vector<ProductData> &qbsProductDeps) +{ + setName(QByteArrayLiteral("ILINK")); + setArchiveVersion(kLinkerArchiveVersion); + setDataVersion(kLinkerDataVersion); + setDataDebugInfo(gen::utils::debugInformation(qbsProduct)); + + const QString buildRootDirectory = gen::utils::buildRootPath(qbsProject); + + buildConfigPage(buildRootDirectory, qbsProduct); + buildLibraryPage(buildRootDirectory, qbsProduct, qbsProductDeps); + buildOutputPage(qbsProduct); + buildInputPage(qbsProduct); + buildListPage(qbsProduct); + buildOptimizationsPage(qbsProduct); + buildAdvancedPage(qbsProduct); + buildDefinesPage(qbsProduct); + + // Should be called as latest stage! + buildExtraOptionsPage(qbsProduct); +} + +void ArmLinkerSettingsGroup::buildConfigPage( + const QString &baseDirectory, + const ProductData &qbsProduct) +{ + ConfigPageOptions opts(baseDirectory, qbsProduct); + // Add 'IlinkConfigDefines' item + // (Configuration file symbol definitions). + addOptionsGroup(QByteArrayLiteral("IlinkConfigDefines"), + opts.configDefines); + + if (opts.configFilePaths.count() > 0) { + // Note: IAR IDE does not allow to specify a multiple config files, + // although the IAR linker support it. So, we use followig 'trick': + // we take a first config file and to add it as usual to required items; + // and then an other remainders we forward to the "Extra options page". + const QVariant configPath = opts.configFilePaths.takeFirst(); + // Add 'IlinkIcfOverride' item (Override default). + addOptionsGroup(QByteArrayLiteral("IlinkIcfOverride"), + {1}); + // Add 'IlinkIcfFile' item (Linker configuration file). + addOptionsGroup(QByteArrayLiteral("IlinkIcfFile"), + {configPath}); + + // Add remainder configuration files to the "Extra options page". + if (!opts.configFilePaths.isEmpty()) { + for (QVariant &configPath : opts.configFilePaths) + configPath = QLatin1String("--config ") + + configPath.toString(); + + m_extraOptions << opts.configFilePaths; + } + } +} + +void ArmLinkerSettingsGroup::buildLibraryPage( + const QString &baseDirectory, + const ProductData &qbsProduct, + const std::vector<ProductData> &qbsProductDeps) +{ + LibraryPageOptions opts(baseDirectory, qbsProduct, qbsProductDeps); + // Add 'IlinkOverrideProgramEntryLabel' item + // (Override default program entry). + addOptionsGroup(QByteArrayLiteral("IlinkOverrideProgramEntryLabel"), + {1}); + const int select = opts.entryPoint.isEmpty() ? 1 : 0; + addOptionsGroup(QByteArrayLiteral("IlinkProgramEntryLabelSelect"), + {select}); + // Add 'IlinkProgramEntryLabel' item (Entry point name). + addOptionsGroup(QByteArrayLiteral("IlinkProgramEntryLabel"), + {opts.entryPoint}); + + if (!opts.staticLibraries.isEmpty()) { + // Add 'IlinkAdditionalLibs' item (Additional libraries). + addOptionsGroup(QByteArrayLiteral("IlinkAdditionalLibs"), + opts.staticLibraries); + } + + // Add 'IlinkAutoLibEnable' item + // (Automatic runtime library selection). + addOptionsGroup(QByteArrayLiteral("IlinkAutoLibEnable"), + {opts.enableRuntimeLibsSearch}); + + // Add library searh directories to the + // "Extra options page", because IAR IDE + // has not other options to add this paths. + for (QVariant &libraryPath : opts.librarySearchPaths) + libraryPath = QLatin1String("-L ") + libraryPath.toString(); + + m_extraOptions << opts.librarySearchPaths; +} + +void ArmLinkerSettingsGroup::buildOutputPage( + const ProductData &qbsProduct) +{ + const OutputPageOptions opts(qbsProduct); + // Add 'IlinkDebugInfoEnable' item + // (Include debug information in output). + addOptionsGroup(QByteArrayLiteral("IlinkDebugInfoEnable"), + {opts.debugInfo}); + // Add 'IlinkOutputFile' item (Output filename). + addOptionsGroup(QByteArrayLiteral("IlinkOutputFile"), + {opts.outputFile}); +} + +void ArmLinkerSettingsGroup::buildInputPage( + const ProductData &qbsProduct) +{ + const InputPageOptions opts(qbsProduct); + // Add 'IlinkKeepSymbols' item (). + addOptionsGroup(QByteArrayLiteral("IlinkKeepSymbols"), + opts.keepSymbols); +} + +void ArmLinkerSettingsGroup::buildListPage( + const ProductData &qbsProduct) +{ + const ListPageOptions opts(qbsProduct); + // Add 'IlinkMapFile' item (Generate linker map file). + addOptionsGroup(QByteArrayLiteral("IlinkMapFile"), + {opts.generateMap}); +} + +void ArmLinkerSettingsGroup::buildOptimizationsPage( + const ProductData &qbsProduct) +{ + const OptimizationsPageOptions opts(qbsProduct); + // Add 'IlinkOptInline' item (Inline small routines). + addOptionsGroup(QByteArrayLiteral("IlinkOptInline"), + {opts.inlineSmallRoutines}); + // Add 'IlinkOptMergeDuplSections'item + // (Merge duplicate sections). + addOptionsGroup(QByteArrayLiteral("IlinkOptMergeDuplSections"), + {opts.mergeDuplicateSections}); + // Add 'IlinkOptUseVfe' item + // (Perform C++ virtual functions elimination). + addOptionsGroup(QByteArrayLiteral("IlinkOptUseVfe"), + {opts.virtualFuncElimination}); +} + +void ArmLinkerSettingsGroup::buildAdvancedPage( + const ProductData &qbsProduct) +{ + const AdvancedPageOptions opts(qbsProduct); + // Add 'IlinkOptExceptionsAllow' item (Allow C++ exceptions). + addOptionsGroup(QByteArrayLiteral("IlinkOptExceptionsAllow"), + {opts.allowExceptions}); +} + +void ArmLinkerSettingsGroup::buildDefinesPage( + const ProductData &qbsProduct) +{ + const DefinesPageOptions opts(qbsProduct); + // Add 'IlinkDefines' item (Defined symbols). + addOptionsGroup(QByteArrayLiteral("IlinkDefines"), + {opts.defineSymbols}); +} + +void ArmLinkerSettingsGroup::buildDiagnosticsPage( + const ProductData &qbsProduct) +{ + const DiagnosticsPageOptions opts(qbsProduct); + // Add 'IlinkWarningsAreErrors' item + // (Treat all warnings as errors). + addOptionsGroup(QByteArrayLiteral("IlinkWarningsAreErrors"), + {opts.treatWarningsAsErrors}); +} + +void ArmLinkerSettingsGroup::buildExtraOptionsPage( + const ProductData &qbsProduct) +{ + Q_UNUSED(qbsProduct) + + // Add 'IlinkUseExtraOptions' and 'IlinkExtraOptions' items. + addOptionsGroup(QByteArrayLiteral("IlinkUseExtraOptions"), + {1}); + addOptionsGroup(QByteArrayLiteral("IlinkExtraOptions"), + m_extraOptions); +} + +} // namespace v8 +} // namespace arm +} // namespace iarew +} // namespace qbs diff --git a/src/plugins/generator/iarew/archs/arm/armlinkersettingsgroup_v8.h b/src/plugins/generator/iarew/archs/arm/armlinkersettingsgroup_v8.h new file mode 100644 index 000000000..e86297e6e --- /dev/null +++ b/src/plugins/generator/iarew/archs/arm/armlinkersettingsgroup_v8.h @@ -0,0 +1,71 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt.io/licensing +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef QBS_IAREWARMLINKERSETTINGSGROUP_V8_H +#define QBS_IAREWARMLINKERSETTINGSGROUP_V8_H + +#include "../../iarewsettingspropertygroup.h" + +namespace qbs { +namespace iarew { +namespace arm { +namespace v8 { + +class ArmLinkerSettingsGroup final : public IarewSettingsPropertyGroup +{ +public: + explicit ArmLinkerSettingsGroup(const Project &qbsProject, + const ProductData &qbsProduct, + const std::vector<ProductData> &qbsProductDeps); + +private: + void buildConfigPage(const QString &baseDirectory, + const ProductData &qbsProduct); + void buildLibraryPage(const QString &baseDirectory, + const ProductData &qbsProduct, + const std::vector<ProductData> &qbsProductDeps); + void buildOutputPage(const ProductData &qbsProduct); + void buildInputPage(const ProductData &qbsProduct); + void buildListPage(const ProductData &qbsProduct); + void buildOptimizationsPage(const ProductData &qbsProduct); + void buildAdvancedPage(const ProductData &qbsProduct); + void buildDefinesPage(const ProductData &qbsProduct); + void buildDiagnosticsPage(const ProductData &qbsProduct); + void buildExtraOptionsPage(const ProductData &qbsProduct); + + QVariantList m_extraOptions; +}; + +} // namespace v8 +} // namespace arm +} // namespace iarew +} // namespace qbs + +#endif // QBS_IAREWARMLINKERSETTINGSGROUP_V8_H diff --git a/src/plugins/generator/iarew/archs/avr/avrarchiversettingsgroup_v7.cpp b/src/plugins/generator/iarew/archs/avr/avrarchiversettingsgroup_v7.cpp new file mode 100644 index 000000000..4e002d13f --- /dev/null +++ b/src/plugins/generator/iarew/archs/avr/avrarchiversettingsgroup_v7.cpp @@ -0,0 +1,94 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt.io/licensing +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "avrarchiversettingsgroup_v7.h" + +#include "../../iarewutils.h" + +namespace qbs { +namespace iarew { +namespace avr { +namespace v7 { + +constexpr int kArchiverArchiveVersion = 2; +constexpr int kArchiverDataVersion = 0; + +namespace { + +// Output page options. + +struct OutputPageOptions final +{ + explicit OutputPageOptions(const QString &baseDirectory, + const ProductData &qbsProduct) + { + outputFile = QLatin1String("$PROJ_DIR$/") + + gen::utils::targetBinaryPath(baseDirectory, qbsProduct); + } + + QString outputFile; +}; + +} // namespace + +// AvrArchiverSettingsGroup + +AvrArchiverSettingsGroup::AvrArchiverSettingsGroup( + const Project &qbsProject, + const ProductData &qbsProduct, + const std::vector<ProductData> &qbsProductDeps) +{ + Q_UNUSED(qbsProductDeps) + + setName(QByteArrayLiteral("XAR")); + setArchiveVersion(kArchiverArchiveVersion); + setDataVersion(kArchiverDataVersion); + setDataDebugInfo(gen::utils::debugInformation(qbsProduct)); + + const QString buildRootDirectory = gen::utils::buildRootPath(qbsProject); + buildOutputPage(buildRootDirectory, qbsProduct); +} + +void AvrArchiverSettingsGroup::buildOutputPage(const QString &baseDirectory, + const ProductData &qbsProduct) +{ + const OutputPageOptions opts(baseDirectory, qbsProduct); + // Add 'XAROutOverride' item (Override default). + addOptionsGroup(QByteArrayLiteral("XAROutOverride"), + {1}); + // Add 'OutputFile' item (Output filename). + addOptionsGroup(QByteArrayLiteral("OutputFile"), + {opts.outputFile}); +} + +} // namespace v7 +} // namespace avr +} // namespace iarew +} // namespace qbs diff --git a/src/plugins/generator/iarew/archs/avr/avrarchiversettingsgroup_v7.h b/src/plugins/generator/iarew/archs/avr/avrarchiversettingsgroup_v7.h new file mode 100644 index 000000000..2ff667e1d --- /dev/null +++ b/src/plugins/generator/iarew/archs/avr/avrarchiversettingsgroup_v7.h @@ -0,0 +1,58 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt.io/licensing +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef QBS_IAREWAVRARCHIVERSETTINGSGROUP_V7_H +#define QBS_IAREWAVRARCHIVERSETTINGSGROUP_V7_H + +#include "../../iarewsettingspropertygroup.h" + +namespace qbs { +namespace iarew { +namespace avr { +namespace v7 { + +class AvrArchiverSettingsGroup final : public IarewSettingsPropertyGroup +{ +public: + explicit AvrArchiverSettingsGroup(const Project &qbsProject, + const ProductData &qbsProduct, + const std::vector<ProductData> &qbsProductDeps); + +private: + void buildOutputPage(const QString &baseDirectory, + const ProductData &qbsProduct); +}; + +} // namespace v7 +} // namespace avr +} // namespace iarew +} // namespace qbs + +#endif // QBS_IAREWAVRARCHIVERSETTINGSGROUP_V7_H diff --git a/src/plugins/generator/iarew/archs/avr/avrassemblersettingsgroup_v7.cpp b/src/plugins/generator/iarew/archs/avr/avrassemblersettingsgroup_v7.cpp new file mode 100644 index 000000000..08e86be53 --- /dev/null +++ b/src/plugins/generator/iarew/archs/avr/avrassemblersettingsgroup_v7.cpp @@ -0,0 +1,226 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt.io/licensing +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "avrassemblersettingsgroup_v7.h" + +#include "../../iarewutils.h" + +namespace qbs { +namespace iarew { +namespace avr { +namespace v7 { + +constexpr int kAssemblerArchiveVersion = 5; +constexpr int kAssemblerDataVersion = 11; + +namespace { + +// Language page options. + +struct LanguagePageOptions final +{ + enum MacroQuoteCharacter { + AngleBracketsQuote, + RoundBracketsQuote, + SquareBracketsQuote, + FigureBracketsQuote + }; + + explicit LanguagePageOptions(const ProductData &qbsProduct) + { + const auto &qbsProps = qbsProduct.moduleProperties(); + const QStringList flags = gen::utils::cppStringModuleProperties( + qbsProps, {QStringLiteral("assemblerFlags")}); + enableSymbolsCaseSensitive = flags.contains(QLatin1String("-s+")); + enableMultibyteSupport = flags.contains(QLatin1String("-n")); + + if (flags.contains(QLatin1String("-M<>"))) + macroQuoteCharacter = LanguagePageOptions::AngleBracketsQuote; + else if (flags.contains(QLatin1String("-M()"))) + macroQuoteCharacter = LanguagePageOptions::RoundBracketsQuote; + else if (flags.contains(QLatin1String("-M[]"))) + macroQuoteCharacter = LanguagePageOptions::SquareBracketsQuote; + else if (flags.contains(QLatin1String("-M{}"))) + macroQuoteCharacter = LanguagePageOptions::FigureBracketsQuote; + } + + MacroQuoteCharacter macroQuoteCharacter = AngleBracketsQuote; + int enableSymbolsCaseSensitive = 0; + int enableMultibyteSupport = 0; +}; + +// Output page options. + +struct OutputPageOptions final +{ + explicit OutputPageOptions(const ProductData &qbsProduct) + { + debugInfo = gen::utils::debugInformation(qbsProduct); + } + + int debugInfo = 0; +}; + +// Preprocessor page options. + +struct PreprocessorPageOptions final +{ + explicit PreprocessorPageOptions(const QString &baseDirectory, + const ProductData &qbsProduct) + { + const auto &qbsProps = qbsProduct.moduleProperties(); + defineSymbols = gen::utils::cppVariantModuleProperties( + qbsProps, {QStringLiteral("defines")}); + + const QString toolkitPath = IarewUtils::toolkitRootPath(qbsProduct); + const QStringList fullIncludePaths = gen::utils::cppStringModuleProperties( + qbsProps, {QStringLiteral("includePaths"), + QStringLiteral("systemIncludePaths")}); + for (const auto &fullIncludePath : fullIncludePaths) { + const QFileInfo includeFileInfo(fullIncludePath); + const QString includeFilePath = includeFileInfo.absoluteFilePath(); + if (includeFilePath.startsWith(toolkitPath, Qt::CaseInsensitive)) { + const QString path = IarewUtils::toolkitRelativeFilePath( + toolkitPath, includeFilePath); + includePaths.push_back(path); + } else { + const QString path = IarewUtils::projectRelativeFilePath( + baseDirectory, includeFilePath); + includePaths.push_back(path); + } + } + } + + QVariantList defineSymbols; + QVariantList includePaths; +}; + +// Diagnostics page options. + +struct DiagnosticsPageOptions final +{ + explicit DiagnosticsPageOptions(const ProductData &qbsProduct) + { + const auto &qbsProps = qbsProduct.moduleProperties(); + const QString warningLevel = gen::utils::cppStringModuleProperty( + qbsProps, QStringLiteral("warningLevel")); + if (warningLevel == QLatin1String("all")) { + enableWarnings = 0; + enableAllWarnings = 0; + } else if (warningLevel == QLatin1String("none")) { + enableWarnings = 1; + enableAllWarnings = 0; + } else { + enableWarnings = 0; + enableAllWarnings = 1; + } + } + + int enableWarnings = 0; + int enableAllWarnings = 0; +}; + +} // namespace + +// AvrAssemblerSettingsGroup + +AvrAssemblerSettingsGroup::AvrAssemblerSettingsGroup( + const Project &qbsProject, + const ProductData &qbsProduct, + const std::vector<ProductData> &qbsProductDeps) +{ + Q_UNUSED(qbsProductDeps) + + setName(QByteArrayLiteral("AAVR")); + setArchiveVersion(kAssemblerArchiveVersion); + setDataVersion(kAssemblerDataVersion); + setDataDebugInfo(gen::utils::debugInformation(qbsProduct)); + + const QString buildRootDirectory = gen::utils::buildRootPath(qbsProject); + + buildLanguagePage(qbsProduct); + buildOutputPage(qbsProduct); + buildPreprocessorPage(buildRootDirectory, qbsProduct); + buildDiagnosticsPage(qbsProduct); +} + +void AvrAssemblerSettingsGroup::buildLanguagePage( + const ProductData &qbsProduct) +{ + const LanguagePageOptions opts(qbsProduct); + // Add 'ACaseSensitivity' item (User symbols are case sensitive). + addOptionsGroup(QByteArrayLiteral("ACaseSensitivity"), + {opts.enableSymbolsCaseSensitive}); + // Add 'AsmMultiByteSupport' item (Enable multibyte support). + addOptionsGroup(QByteArrayLiteral("AsmMultiByteSupport"), + {opts.enableMultibyteSupport}); + // Add 'MacroChars' item (Macro quote characters: ()/[]/{}/<>). + addOptionsGroup(QByteArrayLiteral("MacroChars"), + {opts.macroQuoteCharacter}, 0); +} + +void AvrAssemblerSettingsGroup::buildOutputPage( + const ProductData &qbsProduct) +{ + const OutputPageOptions opts(qbsProduct); + // Add 'CDebug' item (Generate debug information). + addOptionsGroup(QByteArrayLiteral("CDebug"), + {opts.debugInfo}); +} + +void AvrAssemblerSettingsGroup::buildPreprocessorPage( + const QString &baseDirectory, + const ProductData &qbsProduct) +{ + const PreprocessorPageOptions opts(baseDirectory, qbsProduct); + // Add 'ADefines' item (Defined symbols). + addOptionsGroup(QByteArrayLiteral("ADefines"), + opts.defineSymbols); + // Add 'AUserIncludes' item (Additional include directories). + addOptionsGroup(QByteArrayLiteral("ANewIncludes"), + opts.includePaths); +} + +void AvrAssemblerSettingsGroup::buildDiagnosticsPage( + const ProductData &qbsProduct) +{ + const DiagnosticsPageOptions opts(qbsProduct); + // Add 'AWarnEnable' item (Enable/disable warnings). + addOptionsGroup(QByteArrayLiteral("AWarnEnable"), + {opts.enableWarnings}); + // Add 'AWarnWhat' item (Enable/disable all warnings). + addOptionsGroup(QByteArrayLiteral("AWarnWhat"), + {opts.enableAllWarnings}); +} + +} // namespace v7 +} // namespace avr +} // namespace iarew +} // namespace qbs diff --git a/src/plugins/generator/iarew/archs/avr/avrassemblersettingsgroup_v7.h b/src/plugins/generator/iarew/archs/avr/avrassemblersettingsgroup_v7.h new file mode 100644 index 000000000..608a42652 --- /dev/null +++ b/src/plugins/generator/iarew/archs/avr/avrassemblersettingsgroup_v7.h @@ -0,0 +1,61 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt.io/licensing +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef QBS_IAREWAVRASSEMBLERSETTINGSGROUP_V7_H +#define QBS_IAREWAVRASSEMBLERSETTINGSGROUP_V7_H + +#include "../../iarewsettingspropertygroup.h" + +namespace qbs { +namespace iarew { +namespace avr { +namespace v7 { + +class AvrAssemblerSettingsGroup final : public IarewSettingsPropertyGroup +{ +public: + explicit AvrAssemblerSettingsGroup(const Project &qbsProject, + const ProductData &qbsProduct, + const std::vector<ProductData> &qbsProductDeps); + +private: + void buildLanguagePage(const ProductData &qbsProduct); + void buildOutputPage(const ProductData &qbsProduct); + void buildPreprocessorPage(const QString &baseDirectory, + const ProductData &qbsProduct); + void buildDiagnosticsPage(const ProductData &qbsProduct); +}; + +} // namespace v7 +} // namespace avr +} // namespace iarew +} // namespace qbs + +#endif // QBS_IAREWAVRASSEMBLERSETTINGSGROUP_V7_H diff --git a/src/plugins/generator/iarew/archs/avr/avrbuildconfigurationgroup_v7.cpp b/src/plugins/generator/iarew/archs/avr/avrbuildconfigurationgroup_v7.cpp new file mode 100644 index 000000000..dbb5c6620 --- /dev/null +++ b/src/plugins/generator/iarew/archs/avr/avrbuildconfigurationgroup_v7.cpp @@ -0,0 +1,98 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt.io/licensing +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "avrarchiversettingsgroup_v7.h" +#include "avrassemblersettingsgroup_v7.h" +#include "avrbuildconfigurationgroup_v7.h" +#include "avrcompilersettingsgroup_v7.h" +#include "avrgeneralsettingsgroup_v7.h" +#include "avrlinkersettingsgroup_v7.h" + +#include "../../iarewtoolchainpropertygroup.h" +#include "../../iarewutils.h" + +namespace qbs { +namespace iarew { +namespace avr { +namespace v7 { + +AvrBuildConfigurationGroup::AvrBuildConfigurationGroup( + const Project &qbsProject, + const ProductData &qbsProduct, + const std::vector<ProductData> &qbsProductDeps) + : gen::xml::PropertyGroup("configuration") +{ + // Append configuration name item. + const QString cfgName = gen::utils::buildConfigurationName(qbsProject); + appendProperty("name", cfgName); + + // Apend toolchain name group item. + appendChild<IarewToolchainPropertyGroup>("AVR"); + + // Append debug info item. + const int debugBuild = gen::utils::debugInformation(qbsProduct); + appendProperty("debug", debugBuild); + + // Append settings group items. + appendChild<AvrArchiverSettingsGroup>( + qbsProject, qbsProduct, qbsProductDeps); + appendChild<AvrAssemblerSettingsGroup>( + qbsProject, qbsProduct, qbsProductDeps); + appendChild<AvrCompilerSettingsGroup>( + qbsProject, qbsProduct, qbsProductDeps); + appendChild<AvrGeneralSettingsGroup>( + qbsProject, qbsProduct, qbsProductDeps); + appendChild<AvrLinkerSettingsGroup>( + qbsProject, qbsProduct, qbsProductDeps); +} + +bool AvrBuildConfigurationGroupFactory::canCreate( + gen::utils::Architecture arch, + const Version &version) const +{ + return arch == gen::utils::Architecture::Avr + && version.majorVersion() == 7; +} + +std::unique_ptr<gen::xml::PropertyGroup> +AvrBuildConfigurationGroupFactory::create( + const Project &qbsProject, + const ProductData &qbsProduct, + const std::vector<ProductData> &qbsProductDeps) const +{ + const auto group = new AvrBuildConfigurationGroup( + qbsProject, qbsProduct, qbsProductDeps); + return std::unique_ptr<AvrBuildConfigurationGroup>(group); +} + +} // namespace v7 +} // namespace avr +} // namespace iarew +} // namespace qbs diff --git a/src/plugins/generator/iarew/archs/avr/avrbuildconfigurationgroup_v7.h b/src/plugins/generator/iarew/archs/avr/avrbuildconfigurationgroup_v7.h new file mode 100644 index 000000000..618cef4c6 --- /dev/null +++ b/src/plugins/generator/iarew/archs/avr/avrbuildconfigurationgroup_v7.h @@ -0,0 +1,72 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt.io/licensing +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef QBS_IAREWAVRBUILDCONFIGURATIONGROUP_V7_H +#define QBS_IAREWAVRBUILDCONFIGURATIONGROUP_V7_H + +#include <generators/generatorutils.h> +#include <generators/xmlpropertygroup.h> + +namespace qbs { +namespace iarew { +namespace avr { +namespace v7 { + +class AvrBuildConfigurationGroup final + : public gen::xml::PropertyGroup +{ +private: + explicit AvrBuildConfigurationGroup( + const Project &qbsProject, + const ProductData &qbsProduct, + const std::vector<ProductData> &qbsProductDeps); + + friend class AvrBuildConfigurationGroupFactory; +}; + +class AvrBuildConfigurationGroupFactory final + : public gen::xml::PropertyGroupFactory +{ +public: + bool canCreate(gen::utils::Architecture arch, + const Version &version) const final; + + std::unique_ptr<gen::xml::PropertyGroup> create( + const Project &qbsProject, + const ProductData &qbsProduct, + const std::vector<ProductData> &qbsProductDeps) const final; +}; + +} // namespace v7 +} // namespace avr +} // namespace iarew +} // namespace qbs + +#endif // QBS_IAREWAVRBUILDCONFIGURATIONGROUP_V7_H diff --git a/src/plugins/generator/iarew/archs/avr/avrcompilersettingsgroup_v7.cpp b/src/plugins/generator/iarew/archs/avr/avrcompilersettingsgroup_v7.cpp new file mode 100644 index 000000000..26b6858f1 --- /dev/null +++ b/src/plugins/generator/iarew/archs/avr/avrcompilersettingsgroup_v7.cpp @@ -0,0 +1,492 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt.io/licensing +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "avrcompilersettingsgroup_v7.h" + +#include "../../iarewutils.h" + +namespace qbs { +namespace iarew { +namespace avr { +namespace v7 { + +constexpr int kCompilerArchiveVersion = 6; +constexpr int kCompilerDataVersion = 17; + +namespace { + +// Output page options. + +struct OutputPageOptions final +{ + explicit OutputPageOptions(const ProductData &qbsProduct) + { + const auto &qbsProps = qbsProduct.moduleProperties(); + const QStringList flags = IarewUtils::cppModuleCompilerFlags(qbsProps); + moduleType = flags.contains(QLatin1String("--library_module")) + ? OutputPageOptions::LibraryModule + : OutputPageOptions::ProgramModule; + debugInfo = gen::utils::debugInformation(qbsProduct); + disableErrorMessages = flags.contains( + QLatin1String("--no_ubrof_messages")); + } + + int debugInfo = 0; + int disableErrorMessages = 0; + enum ModuleType { ProgramModule, LibraryModule}; + ModuleType moduleType = ProgramModule; +}; + +// Language one page options. + +struct LanguageOnePageOptions final +{ + enum LanguageExtension { + CLanguageExtension, + CxxLanguageExtension, + AutoLanguageExtension + }; + + enum CLanguageDialect { + C89LanguageDialect, + C99LanguageDialect + }; + + enum CxxLanguageDialect { + EmbeddedCPlusPlus, + ExtendedEmbeddedCPlusPlus + }; + + enum LanguageConformance { + AllowIarExtension, + RelaxedStandard, + StrictStandard + }; + + explicit LanguageOnePageOptions(const ProductData &qbsProduct) + { + const auto &qbsProps = qbsProduct.moduleProperties(); + const QStringList flags = IarewUtils::cppModuleCompilerFlags(qbsProps); + // File extension based by default. + languageExtension = LanguageOnePageOptions::AutoLanguageExtension; + // C language dialect. + const QStringList cLanguageVersion = gen::utils::cppStringModuleProperties( + qbsProps, {QStringLiteral("cLanguageVersion")}); + if (cLanguageVersion.contains(QLatin1String("c89"))) + cLanguageDialect = LanguageOnePageOptions::C89LanguageDialect; + else if (cLanguageVersion.contains(QLatin1String("c99"))) + cLanguageDialect = LanguageOnePageOptions::C99LanguageDialect; + // C++ language dialect. + if (flags.contains(QLatin1String("--ec++"))) + cxxLanguageDialect = LanguageOnePageOptions::EmbeddedCPlusPlus; + else if (flags.contains(QLatin1String("--eec++"))) + cxxLanguageDialect = LanguageOnePageOptions::ExtendedEmbeddedCPlusPlus; + // Language conformance. + if (flags.contains(QLatin1String("-e"))) + languageConformance = LanguageOnePageOptions::AllowIarExtension; + else if (flags.contains(QLatin1String("--strict"))) + languageConformance = LanguageOnePageOptions::StrictStandard; + else + languageConformance = LanguageOnePageOptions::RelaxedStandard; + + allowVla = flags.contains(QLatin1String("--vla")); + useCppInlineSemantics = flags.contains( + QLatin1String("--use_c++_inline")); + requirePrototypes = flags.contains( + QLatin1String("--require_prototypes")); + destroyStaticObjects = !flags.contains( + QLatin1String("--no_static_destruction")); + } + + LanguageExtension languageExtension = AutoLanguageExtension; + CLanguageDialect cLanguageDialect = C89LanguageDialect; + CxxLanguageDialect cxxLanguageDialect = EmbeddedCPlusPlus; + LanguageConformance languageConformance = AllowIarExtension; + int allowVla = 0; + int useCppInlineSemantics = 0; + int requirePrototypes = 0; + int destroyStaticObjects = 0; +}; + +// Language two page options. + +struct LanguageTwoPageOptions final +{ + enum PlainCharacter { + SignedCharacter, + UnsignedCharacter + }; + + enum FloatingPointSemantic { + StrictSemantic, + RelaxedSemantic + }; + + explicit LanguageTwoPageOptions(const ProductData &qbsProduct) + { + const auto &qbsProps = qbsProduct.moduleProperties(); + const QStringList flags = IarewUtils::cppModuleCompilerFlags(qbsProps); + plainCharacter = flags.contains(QLatin1String("--char_is_signed")) + ? LanguageTwoPageOptions::SignedCharacter + : LanguageTwoPageOptions::UnsignedCharacter; + floatingPointSemantic = flags.contains(QLatin1String("--relaxed_fp")) + ? LanguageTwoPageOptions::RelaxedSemantic + : LanguageTwoPageOptions::StrictSemantic; + enableMultibyteSupport = flags.contains( + QLatin1String("--enable_multibytes")); + } + + PlainCharacter plainCharacter = SignedCharacter; + FloatingPointSemantic floatingPointSemantic = StrictSemantic; + int enableMultibyteSupport = 0; +}; + +// Optimizations page options. + +struct OptimizationsPageOptions final +{ + // Optimizations level radio-buttons with + // combo-box on "level" widget. + enum Strategy { + StrategyBalanced, + StrategySize, + StrategySpeed + }; + + enum Level { + LevelNone, + LevelLow, + LevelMedium, + LevelHigh + }; + + enum LevelSlave { + LevelSlave0, + LevelSlave1, + LevelSlave2, + LevelSlave3 + }; + + explicit OptimizationsPageOptions(const ProductData &qbsProduct) + { + const auto &qbsProps = qbsProduct.moduleProperties(); + const QString optimization = gen::utils::cppStringModuleProperty( + qbsProps, QStringLiteral("optimization")); + if (optimization == QLatin1String("none")) { + optimizationStrategy = OptimizationsPageOptions::StrategyBalanced; + optimizationLevel = OptimizationsPageOptions::LevelNone; + optimizationLevelSlave = OptimizationsPageOptions::LevelSlave0; + } else if (optimization == QLatin1String("fast")) { + optimizationStrategy = OptimizationsPageOptions::StrategySpeed; + optimizationLevel = OptimizationsPageOptions::LevelHigh; + optimizationLevelSlave = OptimizationsPageOptions::LevelSlave3; + } else if (optimization == QLatin1String("small")) { + optimizationStrategy = OptimizationsPageOptions::StrategySize; + optimizationLevel = OptimizationsPageOptions::LevelHigh; + optimizationLevelSlave = OptimizationsPageOptions::LevelSlave3; + } + + const QStringList flags = IarewUtils::cppModuleCompilerFlags(qbsProps); + enableCommonSubexpressionElimination = !flags.contains( + QLatin1String("--no_cse")); + enableFunctionInlining = !flags.contains(QLatin1String("--no_inline")); + enableCodeMotion = !flags.contains(QLatin1String("--no_code_motion")); + enableCrossCall = !flags.contains(QLatin1String("--no_cross_call")); + enableVariableClustering = !flags.contains( + QLatin1String("--no_clustering")); + enableTypeBasedAliasAnalysis = !flags.contains( + QLatin1String("--no_tbaa")); + enableForceCrossCall = flags.contains( + QLatin1String("--do_cross_call")); + } + + Strategy optimizationStrategy = StrategyBalanced; + Level optimizationLevel = LevelNone; + LevelSlave optimizationLevelSlave = LevelSlave0; + // Six bit-field flags on "enabled optimizations" widget. + int enableCommonSubexpressionElimination = 0; // Common sub-expression elimination. + int enableFunctionInlining = 0; // Function inlining. + int enableCodeMotion = 0; // Code motion. + int enableCrossCall = 0; // Cross call optimization. + int enableVariableClustering = 0; // Variable clustering. + int enableTypeBasedAliasAnalysis = 0; // Type based alias analysis. + // Force cross-call optimization. + int enableForceCrossCall = 0; +}; + +// Preprocessor page options. + +struct PreprocessorPageOptions final +{ + explicit PreprocessorPageOptions(const QString &baseDirectory, + const ProductData &qbsProduct) + { + const auto &qbsProps = qbsProduct.moduleProperties(); + defineSymbols = gen::utils::cppVariantModuleProperties( + qbsProps, {QStringLiteral("defines")}); + + const QString toolkitPath = IarewUtils::toolkitRootPath(qbsProduct); + const QStringList fullIncludePaths = gen::utils::cppStringModuleProperties( + qbsProps, {QStringLiteral("includePaths"), + QStringLiteral("systemIncludePaths")}); + for (const QString &fullIncludePath : fullIncludePaths) { + const QFileInfo includeFileInfo(fullIncludePath); + const QString includeFilePath = includeFileInfo.absoluteFilePath(); + if (includeFilePath.startsWith(toolkitPath, Qt::CaseInsensitive)) { + const QString path = IarewUtils::toolkitRelativeFilePath( + toolkitPath, includeFilePath); + includePaths.push_back(path); + } else { + const QString path = IarewUtils::projectRelativeFilePath( + baseDirectory, includeFilePath); + includePaths.push_back(path); + } + } + } + + QVariantList defineSymbols; + QVariantList includePaths; +}; + +// Diagnostics page options. + +struct DiagnosticsPageOptions final +{ + explicit DiagnosticsPageOptions(const ProductData &qbsProduct) + { + const auto &qbsProps = qbsProduct.moduleProperties(); + warningsAsErrors = gen::utils::cppIntegerModuleProperty( + qbsProps, QStringLiteral("treatWarningsAsErrors")); + } + + int warningsAsErrors = 0; +}; + +// Code page options. + +struct CodePageOptions final +{ + explicit CodePageOptions(const ProductData &qbsProduct) + { + const auto &qbsProps = qbsProduct.moduleProperties(); + const QStringList flags = IarewUtils::cppModuleCompilerFlags(qbsProps); + placeConstantsInRam = flags.contains(QLatin1String("-y")); + placeInitializiersInFlash = flags.contains( + QLatin1String("--initializiers_in_flash")); + forceVariablesGeneration = flags.contains( + QLatin1String("--root_variables")); + useIccA90CallingConvention = flags.contains( + QLatin1String("--version1_calls")); + lockRegistersCount = IarewUtils::flagValue( + flags, QStringLiteral("--lock_regs")).toInt(); + } + + int placeConstantsInRam = 0; + int placeInitializiersInFlash = 0; + int forceVariablesGeneration = 0; + int useIccA90CallingConvention = 0; + int lockRegistersCount = 0; +}; + +} // namespace + +// AvrCompilerSettingsGroup + +AvrCompilerSettingsGroup::AvrCompilerSettingsGroup( + const Project &qbsProject, + const ProductData &qbsProduct, + const std::vector<ProductData> &qbsProductDeps) +{ + Q_UNUSED(qbsProductDeps) + + setName(QByteArrayLiteral("ICCAVR")); + setArchiveVersion(kCompilerArchiveVersion); + setDataVersion(kCompilerDataVersion); + setDataDebugInfo(gen::utils::debugInformation(qbsProduct)); + + const QString buildRootDirectory = gen::utils::buildRootPath(qbsProject); + + buildOutputPage(qbsProduct); + buildLanguageOnePage(qbsProduct); + buildLanguageTwoPage(qbsProduct); + buildOptimizationsPage(qbsProduct); + buildPreprocessorPage(buildRootDirectory, qbsProduct); + buildDiagnosticsPage(qbsProduct); + buildCodePage(qbsProduct); +} + +void AvrCompilerSettingsGroup::buildOutputPage( + const ProductData &qbsProduct) +{ + const OutputPageOptions opts(qbsProduct); + // Add 'CCDebugInfo' item (Generate debug info). + addOptionsGroup(QByteArrayLiteral("CCDebugInfo"), + {opts.debugInfo}); + // Add 'CCNoErrorMsg' item (No error messages in output files). + addOptionsGroup(QByteArrayLiteral("CCNoErrorMsg"), + {opts.disableErrorMessages}); + // Add 'CCOverrideModuleTypeDefault' item + // (Override default module type). + addOptionsGroup(QByteArrayLiteral("CCOverrideModuleTypeDefault"), + {1}); + // Add 'CCRadioModuleType' item (Module type: program/library). + addOptionsGroup(QByteArrayLiteral("CCRadioModuleType"), + {opts.moduleType}); +} + +void AvrCompilerSettingsGroup::buildLanguageOnePage( + const ProductData &qbsProduct) +{ + const LanguageOnePageOptions opts(qbsProduct); + // Add 'IccLang' item with 'auto-extension based' + // value (Language: C/C++/Auto). + addOptionsGroup(QByteArrayLiteral("IccLang"), + {opts.languageExtension}); + // Add 'IccCDialect' item (C dialect: c89/99/11). + addOptionsGroup(QByteArrayLiteral("IccCDialect"), + {opts.cLanguageDialect}); + // Add 'IccCppDialect' item (C++ dialect: embedded/extended). + addOptionsGroup(QByteArrayLiteral("IccCppDialect"), + {opts.cxxLanguageDialect}); + // Add 'CCExt' item (Language conformance: IAR/relaxed/strict). + addOptionsGroup(QByteArrayLiteral("CCExt"), + {opts.languageConformance}); + // Add 'IccAllowVLA' item (Allow VLA). + addOptionsGroup(QByteArrayLiteral("IccAllowVLA"), + {opts.allowVla}); + // Add 'IccCppInlineSemantics' item (C++ inline semantics). + addOptionsGroup(QByteArrayLiteral("IccCppInlineSemantics"), + {opts.useCppInlineSemantics}); + // Add 'CCRequirePrototypes' item (Require prototypes). + addOptionsGroup(QByteArrayLiteral("CCRequirePrototypes"), + {opts.requirePrototypes}); + // Add 'IccStaticDestr' item (Destroy static objects). + addOptionsGroup(QByteArrayLiteral("IccStaticDestr"), + {opts.destroyStaticObjects}); +} + +void AvrCompilerSettingsGroup::buildLanguageTwoPage( + const ProductData &qbsProduct) +{ + const LanguageTwoPageOptions opts(qbsProduct); + // Add 'CCCharIs' item (Plain char is: signed/unsigned). + addOptionsGroup(QByteArrayLiteral("CCCharIs"), + {opts.plainCharacter}); + // Add 'IccFloatSemantics' item (Floatic-point + // semantics: strict/relaxed conformance). + addOptionsGroup(QByteArrayLiteral("IccFloatSemantics"), + {opts.floatingPointSemantic}); + // Add 'CCMultibyteSupport' item (Enable multibyte support). + addOptionsGroup(QByteArrayLiteral("CCMultibyteSupport"), + {opts.enableMultibyteSupport}); +} + +void AvrCompilerSettingsGroup::buildOptimizationsPage( + const ProductData &qbsProduct) +{ + const OptimizationsPageOptions opts(qbsProduct); + // Add 'CCOptStrategy', 'CCOptLevel' and + // 'CCOptLevelSlave' items (Level). + addOptionsGroup(QByteArrayLiteral("CCOptStrategy"), + {opts.optimizationStrategy}); + addOptionsGroup(QByteArrayLiteral("CCOptLevel"), + {opts.optimizationLevel}); + addOptionsGroup(QByteArrayLiteral("CCOptLevelSlave"), + {opts.optimizationLevelSlave}); + // Add 'CCAllowList' item + // (Enabled optimizations: 6 check boxes). + const QString bitflags = QStringLiteral("%1%2%3%4%5%6") + .arg(opts.enableCommonSubexpressionElimination) + .arg(opts.enableFunctionInlining) + .arg(opts.enableCodeMotion) + .arg(opts.enableCrossCall) + .arg(opts.enableVariableClustering) + .arg(opts.enableTypeBasedAliasAnalysis); + addOptionsGroup(QByteArrayLiteral("CCAllowList"), + {bitflags}); + // Add 'CCOptForceCrossCall' item + // (Always do cross call optimization). + addOptionsGroup(QByteArrayLiteral("CCOptForceCrossCall"), + {opts.enableForceCrossCall}); +} + +void AvrCompilerSettingsGroup::buildPreprocessorPage( + const QString &baseDirectory, + const ProductData &qbsProduct) +{ + const PreprocessorPageOptions opts(baseDirectory, qbsProduct); + // Add 'CCDefines' item (Defines symbols). + addOptionsGroup(QByteArrayLiteral("CCDefines"), + opts.defineSymbols); + // Add 'newCCIncludePaths' item + // (Additional include directories). + addOptionsGroup(QByteArrayLiteral("newCCIncludePaths"), + opts.includePaths); +} + +void AvrCompilerSettingsGroup::buildDiagnosticsPage( + const ProductData &qbsProduct) +{ + const DiagnosticsPageOptions opts(qbsProduct); + // Add 'CCWarnAsError' item (Treat all warnings as errors). + addOptionsGroup(QByteArrayLiteral("CCWarnAsError"), + {opts.warningsAsErrors}); +} + +void AvrCompilerSettingsGroup::buildCodePage( + const ProductData &qbsProduct) +{ + const CodePageOptions opts(qbsProduct); + // Add 'CCConstInRAM' item (Place string literals + // and constants in initialized RAM). + addOptionsGroup(QByteArrayLiteral("CCConstInRAM"), + {opts.placeConstantsInRam}); + // Add 'CCInitInFlash' item (Place aggregate + // initializiers in flash memory). + addOptionsGroup(QByteArrayLiteral("CCInitInFlash"), + {opts.placeInitializiersInFlash}); + // Add 'CCForceVariables' item (Force generation of + // all global and static variables). + addOptionsGroup(QByteArrayLiteral("CCForceVariables"), + {opts.forceVariablesGeneration}); + // Add 'CCOldCallConv' item (Use ICCA90 1.x + // calling convention). + addOptionsGroup(QByteArrayLiteral("CCOldCallConv"), + {opts.useIccA90CallingConvention}); + // Add 'CCLockRegs' item (Number of registers to + // lock for global variables). + addOptionsGroup(QByteArrayLiteral("CCLockRegs"), + {opts.lockRegistersCount}); +} + +} // namespace v7 +} // namespace avr +} // namespace iarew +} // namespace qbs diff --git a/src/plugins/generator/iarew/archs/avr/avrcompilersettingsgroup_v7.h b/src/plugins/generator/iarew/archs/avr/avrcompilersettingsgroup_v7.h new file mode 100644 index 000000000..2d8c53b84 --- /dev/null +++ b/src/plugins/generator/iarew/archs/avr/avrcompilersettingsgroup_v7.h @@ -0,0 +1,64 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt.io/licensing +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef QBS_IAREWAVRCOMPILERSETTINGSGROUP_V7_H +#define QBS_IAREWAVRCOMPILERSETTINGSGROUP_V7_H + +#include "../../iarewsettingspropertygroup.h" + +namespace qbs { +namespace iarew { +namespace avr { +namespace v7 { + +class AvrCompilerSettingsGroup final : public IarewSettingsPropertyGroup +{ +public: + explicit AvrCompilerSettingsGroup(const Project &qbsProject, + const ProductData &qbsProduct, + const std::vector<ProductData> &qbsProductDeps); + +private: + void buildOutputPage(const ProductData &qbsProduct); + void buildLanguageOnePage(const ProductData &qbsProduct); + void buildLanguageTwoPage(const ProductData &qbsProduct); + void buildOptimizationsPage(const ProductData &qbsProduct); + void buildPreprocessorPage(const QString &baseDirectory, + const ProductData &qbsProduct); + void buildDiagnosticsPage(const ProductData &qbsProduct); + void buildCodePage(const ProductData &qbsProduct); +}; + +} // namespace v7 +} // namespace avr +} // namespace iarew +} // namespace qbs + +#endif // QBS_IAREWAVRCOMPILERSETTINGSGROUP_V7_H diff --git a/src/plugins/generator/iarew/archs/avr/avrgeneralsettingsgroup_v7.cpp b/src/plugins/generator/iarew/archs/avr/avrgeneralsettingsgroup_v7.cpp new file mode 100644 index 000000000..a4819a90d --- /dev/null +++ b/src/plugins/generator/iarew/archs/avr/avrgeneralsettingsgroup_v7.cpp @@ -0,0 +1,774 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt.io/licensing +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "avrgeneralsettingsgroup_v7.h" + +#include "../../iarewutils.h" + +namespace qbs { +namespace iarew { +namespace avr { +namespace v7 { + +constexpr int kGeneralArchiveVersion = 12; +constexpr int kGeneralDataVersion = 10; + +namespace { + +struct TargetMcuEntry final +{ + QByteArray targetName; + QByteArray targetFlag; +}; + +// Dictionary of known AVR MCU's and its compiler options. +static const TargetMcuEntry mcusDict[] = { + {"AT43USB320A", "at43usb320a"}, + {"AT43USB325", "at43usb325"}, + {"AT43USB326", "at43usb326"}, + {"AT43USB351M", "at43usb351m"}, + {"AT43USB353M", "at43usb353m"}, + {"AT43USB355", "at43usb355"}, + {"AT76C712", "at76c712"}, + {"AT76C713", "at76c713"}, + {"AT86RF401", "at86rf401"}, + {"AT90CAN128", "can128"}, + {"AT90CAN32", "can32"}, + {"AT90CAN64", "can64"}, + {"AT90PWM1", "pwm1"}, + {"AT90PWM161", "pwm161"}, + {"AT90PWM2", "pwm2"}, + {"AT90PWM216", "pwm216"}, + {"AT90PWM2B", "pwm2b"}, + {"AT90PWM3", "pwm3"}, + {"AT90PWM316", "pwm316"}, + {"AT90PWM3B", "pwm3b"}, + {"AT90PWM81", "pwm81"}, + {"AT90S1200", "1200"}, + {"AT90S2313", "2313"}, + {"AT90S2323", "2323"}, + {"AT90S2333", "2333"}, + {"AT90S2343", "2343"}, + {"AT90S4414", "4414"}, + {"AT90S4433", "4433"}, + {"AT90S4434", "4434"}, + {"AT90S8515", "8515"}, + {"AT90S8534", "8534"}, + {"AT90S8535", "8535"}, + {"AT90SCR050", "scr050"}, + {"AT90SCR075", "scr075"}, + {"AT90SCR100", "scr100"}, + {"AT90SCR200", "scr200"}, + {"AT90SCR400", "scr400"}, + {"AT90USB128", "usb128"}, + {"AT90USB1286", "usb1286"}, + {"AT90USB1287", "usb1287"}, + {"AT90USB162", "usb162"}, + {"AT90USB64", "usb64"}, + {"AT90USB646", "usb646"}, + {"AT90USB647", "usb647"}, + {"AT90USB82", "usb82"}, + {"AT94Kxx", "at94k"}, + {"ATA5272", "ata5272"}, + {"ATA5505", "ata5505"}, + {"ATA5700M322", "ata5700m322"}, + {"ATA5702M322", "ata5702m322"}, + {"ATA5781", "ata5781"}, + {"ATA5782", "ata5782"}, + {"ATA5783", "ata5783"}, + {"ATA5785", "ata5785"}, + {"ATA5787", "ata5787"}, + {"ATA5790", "ata5790"}, + {"ATA5790N", "ata5790n"}, + {"ATA5795", "ata5795"}, + {"ATA5830", "ata5830"}, + {"ATA5831", "ata5831"}, + {"ATA5832", "ata5832"}, + {"ATA5833", "ata5833"}, + {"ATA5835", "ata5835"}, + {"ATA6285", "ata6285"}, + {"ATA6286", "ata6286"}, + {"ATA6289", "ata6289"}, + {"ATA8210", "ata8210"}, + {"ATA8215", "ata8215"}, + {"ATA8510", "ata8510"}, + {"ATA8515", "ata8515"}, + {"ATmX224E", "mx224e"}, + {"ATmXT112SL", "mxt112sl"}, + {"ATmXT224", "mxt224"}, + {"ATmXT224E", "mxt224e"}, + {"ATmXT336S", "mxt336s"}, + {"ATmXT540S", "mxt540s"}, + {"ATmXT540S_RevA", "mxt540s_reva"}, + {"ATmXTS200", "mxts200"}, + {"ATmXTS220", "mxts220"}, + {"ATmXTS220E", "mxts220e"}, + {"ATmega007", "m007"}, + {"ATmega103", "m103"}, + {"ATmega128", "m128"}, + {"ATmega1280", "m1280"}, + {"ATmega1281", "m1281"}, + {"ATmega1284", "m1284"}, + {"ATmega1284P", "m1284p"}, + {"ATmega1284RFR2", "m1284rfr2"}, + {"ATmega128A", "m128a"}, + {"ATmega128RFA1", "m128rfa1"}, + {"ATmega128RFA2", "m128rfa2"}, + {"ATmega128RFR2", "m128rfr2"}, + {"ATmega16", "m16"}, + {"ATmega1608", "m1608"}, + {"ATmega1609", "m1609"}, + {"ATmega161", "m161"}, + {"ATmega162", "m162"}, + {"ATmega163", "m163"}, + {"ATmega164", "m164"}, + {"ATmega164A", "m164a"}, + {"ATmega164P", "m164p"}, + {"ATmega164PA", "m164pa"}, + {"ATmega165", "m165"}, + {"ATmega165A", "m165a"}, + {"ATmega165P", "m165p"}, + {"ATmega165PA", "m165pa"}, + {"ATmega168", "m168"}, + {"ATmega168A", "m168a"}, + {"ATmega168P", "m168p"}, + {"ATmega168PA", "m168pa"}, + {"ATmega168PB", "m168pb"}, + {"ATmega169", "m169"}, + {"ATmega169A", "m169a"}, + {"ATmega169P", "m169p"}, + {"ATmega169PA", "m169pa"}, + {"ATmega16A", "m16a"}, + {"ATmega16HVA", "m16hva"}, + {"ATmega16HVA2", "m16hva2"}, + {"ATmega16HVB", "m16hvb"}, + {"ATmega16M1", "m16m1"}, + {"ATmega16U2", "m16u2"}, + {"ATmega16U4", "m16u4"}, + {"ATmega2560", "m2560"}, + {"ATmega2561", "m2561"}, + {"ATmega2564RFR2", "m2564rfr2"}, + {"ATmega256RFA2", "m256rfa2"}, + {"ATmega256RFR2", "m256rfr2"}, + {"ATmega26HVG", "m26hvg"}, + {"ATmega32", "m32"}, + {"ATmega3208", "m3208"}, + {"ATmega3209", "m3209"}, + {"ATmega323", "m323"}, + {"ATmega324", "m324"}, + {"ATmega324A", "m324a"}, + {"ATmega324P", "m324p"}, + {"ATmega324PA", "m324pa"}, + {"ATmega324PB", "m324pb"}, + {"ATmega325", "m325"}, + {"ATmega3250", "m3250"}, + {"ATmega3250A", "m3250a"}, + {"ATmega3250P", "m3250p"}, + {"ATmega3250PA", "m3250pa"}, + {"ATmega325A", "m325a"}, + {"ATmega325P", "m325p"}, + {"ATmega325PA", "m325pa"}, + {"ATmega328", "m328"}, + {"ATmega328P", "m328p"}, + {"ATmega328PB", "m328pb"}, + {"ATmega329", "m329"}, + {"ATmega3290", "m3290"}, + {"ATmega3290A", "m3290a"}, + {"ATmega3290P", "m3290p"}, + {"ATmega3290PA", "m3290pa"}, + {"ATmega329A", "m329a"}, + {"ATmega329P", "m329p"}, + {"ATmega329PA", "m329pa"}, + {"ATmega32A", "m32a"}, + {"ATmega32C1", "m32c1"}, + {"ATmega32HVB", "m32hvb"}, + {"ATmega32M1", "m32m1"}, + {"ATmega32U2", "m32u2"}, + {"ATmega32U4", "m32u4"}, + {"ATmega32U6", "m32u6"}, + {"ATmega406", "m406"}, + {"ATmega48", "m48"}, + {"ATmega4808", "m4808"}, + {"ATmega4809", "m4809"}, + {"ATmega48A", "m48a"}, + {"ATmega48HVF", "m48hvf"}, + {"ATmega48P", "m48p"}, + {"ATmega48PA", "m48pa"}, + {"ATmega48PB", "m48pb"}, + {"ATmega4HVD", "m4hvd"}, + {"ATmega603", "m603"}, + {"ATmega64", "m64"}, + {"ATmega640", "m640"}, + {"ATmega644", "m644"}, + {"ATmega644A", "m644a"}, + {"ATmega644P", "m644p"}, + {"ATmega644PA", "m644pa"}, + {"ATmega644RFR2", "m644rfr2"}, + {"ATmega645", "m645"}, + {"ATmega6450", "m6450"}, + {"ATmega6450A", "m6450a"}, + {"ATmega6450P", "m6450p"}, + {"ATmega645A", "m645a"}, + {"ATmega645P", "m645p"}, + {"ATmega649", "m649"}, + {"ATmega6490", "m6490"}, + {"ATmega6490A", "m6490a"}, + {"ATmega6490P", "m6490p"}, + {"ATmega649A", "m649a"}, + {"ATmega649P", "m649p"}, + {"ATmega64A", "m64a"}, + {"ATmega64C1", "m64c1"}, + {"ATmega64HVE", "m256rfa2"}, + {"ATmega64HVE", "m64hve"}, + {"ATmega64HVE2", "m64hve2"}, + {"ATmega64M1", "m64m1"}, + {"ATmega64RFA2", "m64rfa2"}, + {"ATmega64RFR2", "m64rfr2"}, + {"ATmega8", "m8"}, + {"ATmega808", "m808"}, + {"ATmega809", "m809"}, + {"ATmega83", "m83"}, + {"ATmega8515", "m8515"}, + {"ATmega8535", "m8535"}, + {"ATmega88", "m88"}, + {"ATmega88A", "m88a"}, + {"ATmega88P", "m88p"}, + {"ATmega88PA", "m88pa"}, + {"ATmega88PB", "m88pb"}, + {"ATmega8A", "m8a"}, + {"ATmega8HVA", "m8hva"}, + {"ATmega8HVD", "m8hvd"}, + {"ATmega8U2", "m8u2"}, + {"ATtiny10", "tiny10"}, + {"ATtiny102", "tiny102"}, + {"ATtiny104", "tiny104"}, + {"ATtiny11", "tiny11"}, + {"ATtiny12", "tiny12"}, + {"ATtiny13", "tiny13"}, + {"ATtiny13A", "tiny13a"}, + {"ATtiny15", "tiny15"}, + {"ATtiny1604", "tiny1604"}, + {"ATtiny1606", "tiny1606"}, + {"ATtiny1607", "tiny1607"}, + {"ATtiny1614", "tiny1614"}, + {"ATtiny1616", "tiny1616"}, + {"ATtiny1617", "tiny1617"}, + {"ATtiny1634", "tiny1634"}, + {"ATtiny167", "tiny167"}, + {"ATtiny20", "tiny20"}, + {"ATtiny202", "tiny202"}, + {"ATtiny204", "tiny204"}, + {"ATtiny212", "tiny212"}, + {"ATtiny214", "tiny214"}, + {"ATtiny22", "tiny22"}, + {"ATtiny2313", "tiny2313"}, + {"ATtiny2313A", "tiny2313a"}, + {"ATtiny23U", "tiny23u"}, + {"ATtiny24", "tiny24"}, + {"ATtiny24A", "tiny24a"}, + {"ATtiny25", "tiny25"}, + {"ATtiny26", "tiny26"}, + {"ATtiny261", "tiny261"}, + {"ATtiny261A", "tiny261a"}, + {"ATtiny28", "tiny28"}, + {"ATtiny3214", "tiny3214"}, + {"ATtiny3216", "tiny3216"}, + {"ATtiny3217", "tiny3217"}, + {"ATtiny4", "tiny4"}, + {"ATtiny40", "tiny40"}, + {"ATtiny402", "tiny402"}, + {"ATtiny404", "tiny404"}, + {"ATtiny406", "tiny406"}, + {"ATtiny412", "tiny412"}, + {"ATtiny414", "tiny414"}, + {"ATtiny416", "tiny416"}, + {"ATtiny417", "tiny417"}, + {"ATtiny4313", "tiny4313"}, + {"ATtiny43U", "tiny43u"}, + {"ATtiny44", "tiny44"}, + {"ATtiny441", "tiny441"}, + {"ATtiny44A", "tiny44a"}, + {"ATtiny45", "tiny45"}, + {"ATtiny461", "tiny461"}, + {"ATtiny461A", "tiny461a"}, + {"ATtiny474", "tiny474"}, + {"ATtiny48", "tiny48"}, + {"ATtiny5", "tiny5"}, + {"ATtiny80", "tiny80"}, + {"ATtiny804", "tiny804"}, + {"ATtiny806", "tiny806"}, + {"ATtiny807", "tiny807"}, + {"ATtiny80_pre_2015", "tiny80_pre_2015"}, + {"ATtiny814", "tiny814"}, + {"ATtiny816", "tiny816"}, + {"ATtiny817", "tiny817"}, + {"ATtiny828", "tiny828"}, + {"ATtiny84", "tiny84"}, + {"ATtiny840", "tiny840"}, + {"ATtiny841", "tiny841"}, + {"ATtiny84A", "tiny84a"}, + {"ATtiny85", "tiny85"}, + {"ATtiny861", "tiny861"}, + {"ATtiny861A", "tiny861a"}, + {"ATtiny87", "tiny87"}, + {"ATtiny88", "tiny88"}, + {"ATtiny9", "tiny9"}, + {"ATxmega128A1", "xm128a1"}, + {"ATxmega128A1U", "xm128a1u"}, + {"ATxmega128A3", "xm128a3"}, + {"ATxmega128A3U", "xm128a3u"}, + {"ATxmega128A4", "xm128a4"}, + {"ATxmega128A4U", "xm128a4u"}, + {"ATxmega128B1", "xm128b1"}, + {"ATxmega128B3", "xm128b3"}, + {"ATxmega128C3", "xm128c3"}, + {"ATxmega128D3", "xm128d3"}, + {"ATxmega128D4", "xm128d4"}, + {"ATxmega16A4", "xm16a4"}, + {"ATxmega16A4U", "xm16a4u"}, + {"ATxmega16C4", "xm16c4"}, + {"ATxmega16D4", "xm16d4"}, + {"ATxmega16E5", "xm16e5"}, + {"ATxmega192A1", "xm192a1"}, + {"ATxmega192A3", "xm192a3"}, + {"ATxmega192A3U", "xm192a3u"}, + {"ATxmega192C3", "xm192c3"}, + {"ATxmega192D3", "xm192d3"}, + {"ATxmega256A1", "xm256a1"}, + {"ATxmega256A3", "xm256a3"}, + {"ATxmega256A3B", "xm256a3b"}, + {"ATxmega256A3BU", "xm256a3bu"}, + {"ATxmega256A3U", "xm256a3u"}, + {"ATxmega256B1", "xm256b1"}, + {"ATxmega256C3", "xm256c3"}, + {"ATxmega256D3", "xm256d3"}, + {"ATxmega32A4", "xm32a4"}, + {"ATxmega32A4U", "xm32a4u"}, + {"ATxmega32C3", "xm32c3"}, + {"ATxmega32C4", "xm32c4"}, + {"ATxmega32D3", "xm32d3"}, + {"ATxmega32D4", "xm32d4"}, + {"ATxmega32D4P", "xm32d4p"}, + {"ATxmega32E5", "xm32e5"}, + {"ATxmega32X1", "xm32x1"}, + {"ATxmega384A1", "xm384a1"}, + {"ATxmega384C3", "xm384c3"}, + {"ATxmega384D3", "xm384d3"}, + {"ATxmega64A1", "xm64a1"}, + {"ATxmega64A1U", "xm64a1u"}, + {"ATxmega64A3", "xm64a3"}, + {"ATxmega64A3U", "xm64a3u"}, + {"ATxmega64A4", "xm64a4"}, + {"ATxmega64A4U", "xm64a4u"}, + {"ATxmega64B1", "xm64b1"}, + {"ATxmega64B3", "xm64b3"}, + {"ATxmega64C3", "xm64c3"}, + {"ATxmega64D3", "xm64d3"}, + {"ATxmega64D4", "xm64d4"}, + {"ATxmega8E5", "xm8e5"}, + {"M3000", "m3000"}, + {"MaxBSE", "maxbse"}, +}; + +// Target page options. + +struct TargetPageOptions final +{ + enum MemoryModel { + TinyModel, + SmallModel, + LargeModel, + HugeModel + }; + + explicit TargetPageOptions(const ProductData &qbsProduct) + { + const auto &qbsProps = qbsProduct.moduleProperties(); + const QStringList flags = gen::utils::cppStringModuleProperties( + qbsProps, {QStringLiteral("driverFlags")}); + // Detect target MCU record. + const QString mcuValue = IarewUtils::flagValue( + flags, QStringLiteral("--cpu")).toLower(); + targetMcu = mcuStringFromFlagValue(mcuValue); + // Detect target memory model. + const QString modelValue = IarewUtils::flagValue( + flags, QStringLiteral("-m")); + if (modelValue == QLatin1Char('t')) + memoryModel = TargetPageOptions::TinyModel; + else if (modelValue == QLatin1Char('s')) + memoryModel = TargetPageOptions::SmallModel; + else if (modelValue == QLatin1Char('l')) + memoryModel = TargetPageOptions::LargeModel; + else if (modelValue == QLatin1Char('h')) + memoryModel = TargetPageOptions::HugeModel; + // Detect target EEPROM util size. + eepromUtilSize = IarewUtils::flagValue( + flags, QStringLiteral("--eeprom_size")).toInt(); + } + + static QString mcuStringFromFlagValue(const QString &mcuValue) + { + const auto targetBegin = std::cbegin(mcusDict); + const auto targetEnd = std::cend(mcusDict); + const auto targetIt = std::find_if(targetBegin, targetEnd, + [mcuValue]( + const TargetMcuEntry &entry) { + return entry.targetFlag == mcuValue.toLatin1(); + }); + if (targetIt != targetEnd) { + return QStringLiteral("%1\t%2") + .arg(QString::fromLatin1(targetIt->targetFlag), + QString::fromLatin1(targetIt->targetName)); + } + return {}; + } + + QString targetMcu; + MemoryModel memoryModel = TinyModel; + int eepromUtilSize = 0; +}; + +// System page options. + +struct SystemPageOptions final +{ + explicit SystemPageOptions(const ProductData &qbsProduct) + { + const auto &qbsProps = qbsProduct.moduleProperties(); + const QStringList flags = gen::utils::cppStringModuleProperties( + qbsProps, {QStringLiteral("driverLinkerFlags"), + QStringLiteral("defines")}); + cstackSize = IarewUtils::flagValue( + flags, QStringLiteral("_..X_CSTACK_SIZE")).toInt(); + rstackSize = IarewUtils::flagValue( + flags, QStringLiteral("_..X_RSTACK_SIZE")).toInt(); + } + + int cstackSize = 0; + int rstackSize = 0; +}; + +// Library options page options. + +struct LibraryOptionsPageOptions final +{ + enum PrintfFormatter { + PrintfAutoFormatter = 0, + PrintfFullFormatter = 1, + PrintfFullNoMultibytesFormatter = 2, + PrintfLargeFormatter = 3, + PrintfLargeNoMultibytesFormatter = 4, + PrintfSmallFormatter = 6, + PrintfSmallNoMultibytesFormatter = 7, + PrintfTinyFormatter = 8 + }; + + enum ScanfFormatter { + ScanfAutoFormatter = 0, + ScanfFullFormatter = 1, + ScanfFullNoMultibytesFormatter = 2, + ScanfLargeFormatter = 3, + ScanfLargeNoMultibytesFormatter = 4, + ScanfSmallFormatter = 6, + ScanfSmallNoMultibytesFormatter = 7 + }; + + explicit LibraryOptionsPageOptions(const ProductData &qbsProduct) + { + const auto &qbsProps = qbsProduct.moduleProperties(); + const QStringList flags = IarewUtils::cppModuleLinkerFlags(qbsProps); + for (const QString &flag : flags) { + if (flag.endsWith(QLatin1String("_printf"), Qt::CaseInsensitive)) { + const QString prop = flag.split(QLatin1Char('=')).at(0).toLower(); + if (prop == QLatin1String("-e_printffull")) + printfFormatter = LibraryOptionsPageOptions::PrintfFullFormatter; + else if (prop == QLatin1String("-e_printffullnomb")) + printfFormatter = LibraryOptionsPageOptions::PrintfFullNoMultibytesFormatter; + else if (prop == QLatin1String("-e_printflarge")) + printfFormatter = LibraryOptionsPageOptions::PrintfLargeFormatter; + else if (prop == QLatin1String("-e_printflargenomb")) + printfFormatter = LibraryOptionsPageOptions::PrintfLargeNoMultibytesFormatter; + else if (prop == QLatin1String("-e_printfsmall")) + printfFormatter = LibraryOptionsPageOptions::PrintfSmallFormatter; + else if (prop == QLatin1String("-e_printfsmallnomb")) + printfFormatter = LibraryOptionsPageOptions::PrintfSmallNoMultibytesFormatter; + else if (prop == QLatin1String("-printftiny")) + printfFormatter = LibraryOptionsPageOptions::PrintfTinyFormatter; + } else if (flag.endsWith(QLatin1String("_scanf"), Qt::CaseInsensitive)) { + const QString prop = flag.split(QLatin1Char('=')).at(0).toLower(); + if (prop == QLatin1String("-e_scanffull")) + scanfFormatter = LibraryOptionsPageOptions::ScanfFullFormatter; + else if (prop == QLatin1String("-e_scanffullnomb")) + scanfFormatter = LibraryOptionsPageOptions::ScanfFullNoMultibytesFormatter; + else if (prop == QLatin1String("-e_scanflarge")) + scanfFormatter = LibraryOptionsPageOptions::ScanfLargeFormatter; + else if (prop == QLatin1String("-e_scanflargenomb")) + scanfFormatter = LibraryOptionsPageOptions::ScanfLargeNoMultibytesFormatter; + else if (prop == QLatin1String("-e_scanfsmall")) + scanfFormatter = LibraryOptionsPageOptions::ScanfSmallFormatter; + else if (prop == QLatin1String("-e_scanfsmallnomb")) + scanfFormatter = LibraryOptionsPageOptions::ScanfSmallNoMultibytesFormatter; + } + } + } + + PrintfFormatter printfFormatter = PrintfAutoFormatter; + ScanfFormatter scanfFormatter = ScanfAutoFormatter; +}; + +// Library configuration page options. + +struct LibraryConfigPageOptions final +{ + enum RuntimeLibrary { + NoLibrary, + NormalDlibLibrary, + FullDlibLibrary, + CustomDlibLibrary, + ClibLibrary, + CustomClibLibrary, + ThirdPartyLibrary + }; + + explicit LibraryConfigPageOptions(const QString &baseDirectory, + const ProductData &qbsProduct) + { + const auto &qbsProps = qbsProduct.moduleProperties(); + const QStringList flags = IarewUtils::cppModuleCompilerFlags(qbsProps); + + const QStringList libraryPaths = gen::utils::cppStringModuleProperties( + qbsProps, {QStringLiteral("staticLibraries")}); + const auto libraryBegin = libraryPaths.cbegin(); + const auto libraryEnd = libraryPaths.cend(); + + if (flags.contains(QLatin1String("--dlib"))) { + const QString dlibToolkitPath = + IarewUtils::dlibToolkitRootPath(qbsProduct); + const QFileInfo configInfo(IarewUtils::flagValue( + flags, + QStringLiteral("--dlib_config"))); + const QString configFilePath = configInfo.absoluteFilePath(); + if (configFilePath.startsWith(dlibToolkitPath, + Qt::CaseInsensitive)) { + if (configFilePath.endsWith(QLatin1String("-n.h"), + Qt::CaseInsensitive)) { + libraryType = LibraryConfigPageOptions::NormalDlibLibrary; + } else if (configFilePath.endsWith(QLatin1String("-f.h"), + Qt::CaseInsensitive)) { + libraryType = LibraryConfigPageOptions::FullDlibLibrary; + } else { + libraryType = LibraryConfigPageOptions::CustomDlibLibrary; + } + + configPath = IarewUtils::toolkitRelativeFilePath( + baseDirectory, configFilePath); + + // Find dlib library inside of IAR toolkit directory. + const auto libraryIt = std::find_if(libraryBegin, libraryEnd, + [dlibToolkitPath]( + const QString &libraryPath) { + return libraryPath.startsWith(dlibToolkitPath); + }); + if (libraryIt != libraryEnd) { + // This means that dlib library is 'standard' (placed inside + // of IAR toolkit directory). + libraryPath = IarewUtils::toolkitRelativeFilePath( + baseDirectory, *libraryIt); + } + } else { + // This means that dlib library is 'custom' + // (but we don't know its path). + libraryType = LibraryConfigPageOptions::CustomDlibLibrary; + configPath = IarewUtils::projectRelativeFilePath( + baseDirectory, configFilePath); + } + } else if (flags.contains(QLatin1String("--clib"))) { + const QString clibToolkitPath = + IarewUtils::clibToolkitRootPath(qbsProduct); + // Find clib library inside of IAR toolkit directory. + const auto libraryIt = std::find_if(libraryBegin, libraryEnd, + [clibToolkitPath]( + const QString &libraryPath) { + return libraryPath.startsWith(clibToolkitPath); + }); + if (libraryIt != libraryEnd) { + // This means that clib library is 'standard' (placed inside + // of IAR toolkit directory). + libraryType = LibraryConfigPageOptions::ClibLibrary; + libraryPath = IarewUtils::toolkitRelativeFilePath( + baseDirectory, *libraryIt); + } else { + // This means that clib library is 'custom' + // (but we don't know its path). + libraryType = LibraryConfigPageOptions::CustomClibLibrary; + } + } else { + libraryType = LibraryConfigPageOptions::NoLibrary; + } + } + + RuntimeLibrary libraryType = NoLibrary; + QString configPath; + QString libraryPath; +}; + +// Output page options. + +struct OutputPageOptions final +{ + explicit OutputPageOptions(const QString &baseDirectory, + const ProductData &qbsProduct) + { + binaryType = IarewUtils::outputBinaryType(qbsProduct); + binaryDirectory = gen::utils::binaryOutputDirectory( + baseDirectory, qbsProduct); + objectDirectory = gen::utils::objectsOutputDirectory( + baseDirectory, qbsProduct); + listingDirectory = gen::utils::listingOutputDirectory( + baseDirectory, qbsProduct); + } + + IarewUtils::OutputBinaryType binaryType = IarewUtils::ApplicationOutputType; + QString binaryDirectory; + QString objectDirectory; + QString listingDirectory; +}; + +} // namespace + +// AvrGeneralSettingsGroup + +AvrGeneralSettingsGroup::AvrGeneralSettingsGroup( + const Project &qbsProject, + const ProductData &qbsProduct, + const std::vector<ProductData> &qbsProductDeps) +{ + Q_UNUSED(qbsProductDeps) + + setName(QByteArrayLiteral("General")); + setArchiveVersion(kGeneralArchiveVersion); + setDataVersion(kGeneralDataVersion); + setDataDebugInfo(gen::utils::debugInformation(qbsProduct)); + + const QString buildRootDirectory = gen::utils::buildRootPath(qbsProject); + + buildTargetPage(qbsProduct); + buildSystemPage(qbsProduct); + buildLibraryOptionsPage(qbsProduct); + buildLibraryConfigPage(buildRootDirectory, qbsProduct); + buildOutputPage(buildRootDirectory, qbsProduct); +} + +void AvrGeneralSettingsGroup::buildTargetPage( + const ProductData &qbsProduct) +{ + const TargetPageOptions opts(qbsProduct); + // Add 'GenDeviceSelectMenu' item + // (Processor configuration chooser). + addOptionsGroup(QByteArrayLiteral("GenDeviceSelectMenu"), + {opts.targetMcu}); + // Add 'Variant Memory' item + // (Memory model: tiny/small/large/huge). + addOptionsGroup(QByteArrayLiteral("Variant Memory"), + {opts.memoryModel}); + // Add 'GGEepromUtilSize' item + // (Utilize inbuilt EEPROM size, in bytes). + addOptionsGroup(QByteArrayLiteral("GGEepromUtilSize"), + {opts.eepromUtilSize}); +} + +void AvrGeneralSettingsGroup::buildSystemPage( + const ProductData &qbsProduct) +{ + const SystemPageOptions opts (qbsProduct); + // Add 'SCCStackSize' item (Data stack + // - CSTACK size in bytes). + addOptionsGroup(QByteArrayLiteral("SCCStackSize"), + {opts.cstackSize}); + // Add 'SCRStackSize' item (Return address stack + // - RSTACK depth in bytes). + addOptionsGroup(QByteArrayLiteral("SCRStackSize"), + {opts.rstackSize}); +} + +void AvrGeneralSettingsGroup::buildLibraryOptionsPage( + const ProductData &qbsProduct) +{ + const LibraryOptionsPageOptions opts(qbsProduct); + // Add 'Output variant' item (Printf formatter). + addOptionsGroup(QByteArrayLiteral("Output variant"), + {opts.printfFormatter}); + // Add 'Input variant' item (Printf formatter). + addOptionsGroup(QByteArrayLiteral("Input variant"), + {opts.scanfFormatter}); +} + +void AvrGeneralSettingsGroup::buildLibraryConfigPage( + const QString &baseDirectory, + const ProductData &qbsProduct) +{ + const LibraryConfigPageOptions opts(baseDirectory, qbsProduct); + // Add 'GRuntimeLibSelect' and 'GRuntimeLibSelectSlave' items + // (Link with runtime: none/dlib/clib/etc). + addOptionsGroup(QByteArrayLiteral("GRuntimeLibSelect"), + {opts.libraryType}); + addOptionsGroup(QByteArrayLiteral("GRuntimeLibSelectSlave"), + {opts.libraryType}); + // Add 'RTConfigPath' item (Runtime configuration file). + addOptionsGroup(QByteArrayLiteral("RTConfigPath"), + {opts.configPath}); + // Add 'RTLibraryPath' item (Runtime library file). + addOptionsGroup(QByteArrayLiteral("RTLibraryPath"), + {opts.libraryPath}); +} + +void AvrGeneralSettingsGroup::buildOutputPage( + const QString &baseDirectory, + const ProductData &qbsProduct) +{ + const OutputPageOptions opts(baseDirectory, qbsProduct); + // Add 'GOutputBinary' item (Output file: executable/library). + addOptionsGroup(QByteArrayLiteral("GOutputBinary"), + {opts.binaryType}); + // Add 'ExePath' item (Executable/binaries output directory). + addOptionsGroup(QByteArrayLiteral("ExePath"), + {opts.binaryDirectory}); + // Add 'ObjPath' item (Object files output directory). + addOptionsGroup(QByteArrayLiteral("ObjPath"), + {opts.objectDirectory}); + // Add 'ListPath' item (List files output directory). + addOptionsGroup(QByteArrayLiteral("ListPath"), + {opts.listingDirectory}); +} + +} // namespace v7 +} // namespace avr +} // namespace iarew +} // namespace qbs diff --git a/src/plugins/generator/iarew/archs/avr/avrgeneralsettingsgroup_v7.h b/src/plugins/generator/iarew/archs/avr/avrgeneralsettingsgroup_v7.h new file mode 100644 index 000000000..5411eeae8 --- /dev/null +++ b/src/plugins/generator/iarew/archs/avr/avrgeneralsettingsgroup_v7.h @@ -0,0 +1,63 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt.io/licensing +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef QBS_IAREWAVRGENERALSETTINGSGROUP_V7_H +#define QBS_IAREWAVRGENERALSETTINGSGROUP_V7_H + +#include "../../iarewsettingspropertygroup.h" + +namespace qbs { +namespace iarew { +namespace avr { +namespace v7 { + +class AvrGeneralSettingsGroup final : public IarewSettingsPropertyGroup +{ +public: + explicit AvrGeneralSettingsGroup(const Project &qbsProject, + const ProductData &qbsProduct, + const std::vector<ProductData> &qbsProductDeps); + +private: + void buildTargetPage(const ProductData &qbsProduct); + void buildSystemPage(const ProductData &qbsProduct); + void buildLibraryOptionsPage(const ProductData &qbsProduct); + void buildLibraryConfigPage(const QString &baseDirectory, + const ProductData &qbsProduct); + void buildOutputPage(const QString &baseDirectory, + const ProductData &qbsProduct); +}; + +} // namespace v7 +} // namespace avr +} // namespace iarew +} // namespace qbs + +#endif // QBS_IAREWAVRGENERALSETTINGSGROUP_V7_H diff --git a/src/plugins/generator/iarew/archs/avr/avrlinkersettingsgroup_v7.cpp b/src/plugins/generator/iarew/archs/avr/avrlinkersettingsgroup_v7.cpp new file mode 100644 index 000000000..9fdb57a5a --- /dev/null +++ b/src/plugins/generator/iarew/archs/avr/avrlinkersettingsgroup_v7.cpp @@ -0,0 +1,388 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt.io/licensing +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "avrlinkersettingsgroup_v7.h" + +#include "../../iarewutils.h" + +#include <QtCore/qdir.h> + +namespace qbs { +namespace iarew { +namespace avr { +namespace v7 { + +constexpr int kLinkerArchiveVersion = 3; +constexpr int kLinkerDataVersion = 16; + +namespace { + +// Config page options. + +struct ConfigPageOptions final +{ + explicit ConfigPageOptions(const QString &baseDirectory, + const ProductData &qbsProduct, + const std::vector<ProductData> &qbsProductDeps) + { + const auto &qbsProps = qbsProduct.moduleProperties(); + const QString toolkitPath = IarewUtils::toolkitRootPath(qbsProduct); + + entryPoint = gen::utils::cppStringModuleProperty( + qbsProps, QStringLiteral("entryPoint")); + + // Enumerate all product linker config files + // (which are set trough 'linkerscript' tag). + const auto qbsGroups = qbsProduct.groups(); + for (const auto &qbsGroup : qbsGroups) { + const auto qbsArtifacts = qbsGroup.sourceArtifacts(); + for (const auto &qbsArtifact : qbsArtifacts) { + const auto qbsTags = qbsArtifact.fileTags(); + if (!qbsTags.contains(QLatin1String("linkerscript"))) + continue; + const QString fullConfigPath = qbsArtifact.filePath(); + if (fullConfigPath.startsWith(toolkitPath, Qt::CaseInsensitive)) { + const QString path = IarewUtils::toolkitRelativeFilePath( + toolkitPath, fullConfigPath); + configFilePaths.push_back(path); + } else { + const QString path = IarewUtils::projectRelativeFilePath( + baseDirectory, fullConfigPath); + configFilePaths.push_back(path); + } + } + } + + // Enumerate all product linker config files + // (which are set trough '-f' option). + const QStringList flags = IarewUtils::cppModuleLinkerFlags(qbsProps); + const QVariantList configPathValues = IarewUtils::flagValues( + flags, QStringLiteral("-f")); + for (const QVariant &configPathValue : configPathValues) { + const QString fullConfigPath = configPathValue.toString(); + if (fullConfigPath.startsWith(toolkitPath, Qt::CaseInsensitive)) { + const QString path = IarewUtils::toolkitRelativeFilePath( + toolkitPath, fullConfigPath); + if (!configFilePaths.contains(path)) + configFilePaths.push_back(path); + } else { + const QString path = IarewUtils::projectRelativeFilePath( + baseDirectory, fullConfigPath); + if (!configFilePaths.contains(path)) + configFilePaths.push_back(path); + } + } + + // Add libraries search paths. + const QStringList libraryPaths = gen::utils::cppStringModuleProperties( + qbsProps, {QStringLiteral("libraryPaths")}); + for (const QString &libraryPath : libraryPaths) { + const QFileInfo libraryPathInfo(libraryPath); + const QString fullLibrarySearchPath = + libraryPathInfo.absoluteFilePath(); + if (fullLibrarySearchPath.startsWith(toolkitPath, + Qt::CaseInsensitive)) { + const QString path = IarewUtils::toolkitRelativeFilePath( + toolkitPath, fullLibrarySearchPath); + librarySearchPaths.push_back(path); + } else { + const QString path = IarewUtils::projectRelativeFilePath( + baseDirectory, fullLibrarySearchPath); + librarySearchPaths.push_back(path); + } + } + + // Add static libraries paths. + const QStringList staticLibrariesProps = + gen::utils::cppStringModuleProperties( + qbsProps, {QStringLiteral("staticLibraries")}); + for (const QString &staticLibrary : staticLibrariesProps) { + const QFileInfo staticLibraryInfo(staticLibrary); + if (staticLibraryInfo.isAbsolute()) { + const QString fullStaticLibraryPath = + staticLibraryInfo.absoluteFilePath(); + if (fullStaticLibraryPath.startsWith(toolkitPath, + Qt::CaseInsensitive)) { + const QString path = IarewUtils::toolkitRelativeFilePath( + toolkitPath, fullStaticLibraryPath); + staticLibraries.push_back(path); + } else { + const QString path = IarewUtils::projectRelativeFilePath( + baseDirectory, fullStaticLibraryPath); + staticLibraries.push_back(path); + } + } else { + staticLibraries.push_back(staticLibrary); + } + } + + // Add static libraries from product dependencies. + for (const ProductData &qbsProductDep : qbsProductDeps) { + const QString depBinaryPath = QLatin1String("$PROJ_DIR$/") + + gen::utils::targetBinaryPath(baseDirectory, + qbsProductDep); + staticLibraries.push_back(depBinaryPath); + } + } + + QVariantList configFilePaths; + QVariantList librarySearchPaths; + QVariantList staticLibraries; + QString entryPoint; +}; + +// Output page options. + +struct OutputPageOptions final +{ + explicit OutputPageOptions(const ProductData &qbsProduct) + { + outputFile = gen::utils::targetBinary(qbsProduct); + } + + QString outputFile; +}; + +// List page options. + +struct ListPageOptions final +{ + enum ListingAction { + NoListing, + GenerateListing + }; + + explicit ListPageOptions(const ProductData &qbsProduct) + { + const auto &qbsProps = qbsProduct.moduleProperties(); + generateMap = gen::utils::cppBooleanModuleProperty( + qbsProps, QStringLiteral("generateMapFile")) + ? ListPageOptions::GenerateListing + : ListPageOptions::NoListing; + } + + ListingAction generateMap = NoListing; +}; + +// Define page options. + +struct DefinePageOptions final +{ + explicit DefinePageOptions(const ProductData &qbsProduct) + { + const auto &qbsProps = qbsProduct.moduleProperties(); + const QStringList flags = IarewUtils::cppModuleLinkerFlags(qbsProps); + // Enumerate all linker defines. + for (const QString &flag : flags) { + if (!flag.startsWith(QLatin1String("-D"))) + continue; + const auto symbol = flag.mid(2); + // Ignore system-defined macroses. + if (symbol.startsWith(QLatin1String("_..X_HEAP_SIZE")) + || symbol.startsWith(QLatin1String("_..X_TINY_HEAP_SIZE")) + || symbol.startsWith(QLatin1String("_..X_NEAR_HEAP_SIZE")) + || symbol.startsWith(QLatin1String("_..X_FAR_HEAP_SIZE")) + || symbol.startsWith(QLatin1String("_..X_HUGE_HEAP_SIZE")) + || symbol.startsWith(QLatin1String("_..X_CSTACK_SIZE")) + || symbol.startsWith(QLatin1String("_..X_RSTACK_SIZE")) + || symbol.startsWith(QLatin1String("_..X_FLASH_CODE_END")) + || symbol.startsWith(QLatin1String("_..X_FLASH_BASE")) + || symbol.startsWith(QLatin1String("_..X_CSTACK_BASE")) + || symbol.startsWith(QLatin1String("_..X_CSTACK_END")) + || symbol.startsWith(QLatin1String("_..X_RSTACK_BASE")) + || symbol.startsWith(QLatin1String("_..X_RSTACK_END")) + || symbol.startsWith(QLatin1String("_..X_EXT_SRAM_BASE")) + || symbol.startsWith(QLatin1String("_..X_EXT_SRAM_SIZE")) + || symbol.startsWith(QLatin1String("_..X_EXT_ROM_BASE")) + || symbol.startsWith(QLatin1String("_..X_EXT_ROM_SIZE")) + || symbol.startsWith(QLatin1String("_..X_EXT_NV_BASE")) + || symbol.startsWith(QLatin1String("_..X_EXT_NV_SIZE")) + || symbol.startsWith(QLatin1String("_..X_SRAM_BASE")) + || symbol.startsWith(QLatin1String("_..X_SRAM_SIZE")) + || symbol.startsWith(QLatin1String("_..X_RSTACK_BASE")) + || symbol.startsWith(QLatin1String("_..X_RSTACK_SIZE")) + ) { + continue; + } + defineSymbols.push_back(symbol); + } + } + + QVariantList defineSymbols; +}; + +// Diagnostics page options. + +struct DiagnosticsPageOptions final +{ + explicit DiagnosticsPageOptions(const ProductData &qbsProduct) + { + const auto &qbsProps = qbsProduct.moduleProperties(); + const QString warningLevel = gen::utils::cppStringModuleProperty( + qbsProps, QStringLiteral("warningLevel")); + suppressAllWarnings = (warningLevel == QLatin1String("none")); + } + + int suppressAllWarnings = 0; +}; + +} // namespace + +// AvrLinkerSettingsGroup + +AvrLinkerSettingsGroup::AvrLinkerSettingsGroup( + const Project &qbsProject, + const ProductData &qbsProduct, + const std::vector<ProductData> &qbsProductDeps) +{ + setName(QByteArrayLiteral("XLINK")); + setArchiveVersion(kLinkerArchiveVersion); + setDataVersion(kLinkerDataVersion); + setDataDebugInfo(gen::utils::debugInformation(qbsProduct)); + + const QString buildRootDirectory = gen::utils::buildRootPath(qbsProject); + + buildConfigPage(buildRootDirectory, qbsProduct, qbsProductDeps); + buildOutputPage(qbsProduct); + buildListPage(qbsProduct); + buildDefinePage(qbsProduct); + buildDiagnosticsPage(qbsProduct); + + // Should be called as latest stage! + buildExtraOptionsPage(qbsProduct); +} + +void AvrLinkerSettingsGroup::buildConfigPage( + const QString &baseDirectory, + const ProductData &qbsProduct, + const std::vector<ProductData> &qbsProductDeps) +{ + ConfigPageOptions opts(baseDirectory, qbsProduct, qbsProductDeps); + + if (opts.configFilePaths.count() > 0) { + // Note: IAR IDE does not allow to specify a multiple config files, + // although the IAR linker support it. So, we use followig 'trick': + // we take a first config file and to add it as usual to required items; + // and then an other remainders we forward to the "Extra options page". + const QVariant configPath = opts.configFilePaths.takeFirst(); + // Add 'XclOverride' item (Override default). + addOptionsGroup(QByteArrayLiteral("XclOverride"), + {1}); + // Add 'XclFile' item (Linke configuration file). + addOptionsGroup(QByteArrayLiteral("XclFile"), + {configPath}); + + // Add remainder configuration files to the "Extra options page". + if (!opts.configFilePaths.isEmpty()) { + for (QVariant &configPath : opts.configFilePaths) + configPath = QLatin1String("-f ") + configPath.toString(); + + m_extraOptions << opts.configFilePaths; + } + } + + if (opts.staticLibraries.count() > 0) + m_extraOptions << opts.staticLibraries; + + if (!opts.entryPoint.isEmpty()) { + // Add 'xcProgramEntryLabel' item (Entry symbol). + addOptionsGroup(QByteArrayLiteral("xcProgramEntryLabel"), + {opts.entryPoint}); + // Add 'xcOverrideProgramEntryLabel' item + // (Override default program entry). + addOptionsGroup(QByteArrayLiteral("xcOverrideProgramEntryLabel"), + {1}); + // Add 'xcProgramEntryLabelSelect' item. + addOptionsGroup(QByteArrayLiteral("xcProgramEntryLabelSelect"), + {0}); + } + + // Add 'XIncludes' item (Libraries search paths). + addOptionsGroup(QByteArrayLiteral("XIncludes"), + opts.librarySearchPaths); +} + +void AvrLinkerSettingsGroup::buildOutputPage( + const ProductData &qbsProduct) +{ + const OutputPageOptions opts(qbsProduct); + // Add 'XOutOverride' item (Override default output file). + addOptionsGroup(QByteArrayLiteral("XOutOverride"), + {1}); + // Add 'OutputFile' item (Output file name). + addOptionsGroup(QByteArrayLiteral("OutputFile"), + {opts.outputFile}); +} + +void AvrLinkerSettingsGroup::buildListPage( + const ProductData &qbsProduct) +{ + const ListPageOptions opts(qbsProduct); + // Add 'XList' item (Generate linker listing). + addOptionsGroup(QByteArrayLiteral("XList"), + {opts.generateMap}); +} + +void AvrLinkerSettingsGroup::buildDefinePage( + const ProductData &qbsProduct) +{ + const DefinePageOptions opts(qbsProduct); + // Add 'XDefines' item (Defined symbols). + addOptionsGroup(QByteArrayLiteral("XDefines"), + opts.defineSymbols); +} + +void AvrLinkerSettingsGroup::buildDiagnosticsPage( + const ProductData &qbsProduct) +{ + const DiagnosticsPageOptions opts(qbsProduct); + // Add 'SuppressAllWarn' item (Suppress all warnings). + addOptionsGroup(QByteArrayLiteral("SuppressAllWarn"), + {opts.suppressAllWarnings}); +} + +void AvrLinkerSettingsGroup::buildExtraOptionsPage(const ProductData &qbsProduct) +{ + Q_UNUSED(qbsProduct) + + if (!m_extraOptions.isEmpty()) { + // Add 'XExtraOptionsCheck' (Use command line options). + addOptionsGroup(QByteArrayLiteral("XExtraOptionsCheck"), + {1}); + // Add 'XExtraOptions' item (Command line options). + addOptionsGroup(QByteArrayLiteral("XExtraOptions"), + m_extraOptions); + } +} + +} // namespace v7 +} // namespace avr +} // namespace iarew +} // namespace qbs diff --git a/src/plugins/generator/iarew/archs/avr/avrlinkersettingsgroup_v7.h b/src/plugins/generator/iarew/archs/avr/avrlinkersettingsgroup_v7.h new file mode 100644 index 000000000..5427937b7 --- /dev/null +++ b/src/plugins/generator/iarew/archs/avr/avrlinkersettingsgroup_v7.h @@ -0,0 +1,66 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt.io/licensing +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef QBS_IAREWAVRLINKERSETTINGSGROUP_V7_H +#define QBS_IAREWAVRLINKERSETTINGSGROUP_V7_H + +#include "../../iarewsettingspropertygroup.h" + +namespace qbs { +namespace iarew { +namespace avr { +namespace v7 { + +class AvrLinkerSettingsGroup final : public IarewSettingsPropertyGroup +{ +public: + explicit AvrLinkerSettingsGroup(const Project &qbsProject, + const ProductData &qbsProduct, + const std::vector<ProductData> &qbsProductDeps); + +private: + void buildConfigPage(const QString &baseDirectory, + const ProductData &qbsProduct, + const std::vector<ProductData> &qbsProductDeps); + void buildOutputPage(const ProductData &qbsProduct); + void buildListPage(const ProductData &qbsProduct); + void buildDefinePage(const ProductData &qbsProduct); + void buildDiagnosticsPage(const ProductData &qbsProduct); + void buildExtraOptionsPage(const ProductData &qbsProduct); + + QVariantList m_extraOptions; +}; + +} // namespace v7 +} // namespace avr +} // namespace iarew +} // namespace qbs + +#endif // QBS_IAREWAVRLINKERSETTINGSGROUP_V7_H diff --git a/src/plugins/generator/iarew/archs/mcs51/mcs51archiversettingsgroup_v10.cpp b/src/plugins/generator/iarew/archs/mcs51/mcs51archiversettingsgroup_v10.cpp new file mode 100644 index 000000000..38264c653 --- /dev/null +++ b/src/plugins/generator/iarew/archs/mcs51/mcs51archiversettingsgroup_v10.cpp @@ -0,0 +1,95 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt.io/licensing +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "mcs51archiversettingsgroup_v10.h" + +#include "../../iarewutils.h" + +namespace qbs { +namespace iarew { +namespace mcs51 { +namespace v10 { + +constexpr int kArchiverArchiveVersion = 2; +constexpr int kArchiverDataVersion = 1; + +namespace { + +// Output page options. + +struct OutputPageOptions final +{ + explicit OutputPageOptions(const QString &baseDirectory, + const ProductData &qbsProduct) + { + outputFile = QLatin1String("$PROJ_DIR$/") + + gen::utils::targetBinaryPath(baseDirectory, qbsProduct); + } + + QString outputFile; +}; + +} // namespace + +// Mcs51ArchiverSettingsGroup + +Mcs51ArchiverSettingsGroup::Mcs51ArchiverSettingsGroup( + const Project &qbsProject, + const ProductData &qbsProduct, + const std::vector<ProductData> &qbsProductDeps) +{ + Q_UNUSED(qbsProductDeps) + + setName(QByteArrayLiteral("XAR")); + setArchiveVersion(kArchiverArchiveVersion); + setDataVersion(kArchiverDataVersion); + setDataDebugInfo(gen::utils::debugInformation(qbsProduct)); + + const QString buildRootDirectory = gen::utils::buildRootPath(qbsProject); + buildOutputPage(buildRootDirectory, qbsProduct); +} + +void Mcs51ArchiverSettingsGroup::buildOutputPage( + const QString &baseDirectory, + const ProductData &qbsProduct) +{ + const OutputPageOptions opts(baseDirectory, qbsProduct); + // Add 'XAROverride' item (Override default). + addOptionsGroup(QByteArrayLiteral("XAROverride"), + {1}); + // Add 'XAROutput2' item (Output filename). + addOptionsGroup(QByteArrayLiteral("XAROutput2"), + {opts.outputFile}); +} + +} // namespace v10 +} // namespace mcs51 +} // namespace iarew +} // namespace qbs diff --git a/src/plugins/generator/iarew/archs/mcs51/mcs51archiversettingsgroup_v10.h b/src/plugins/generator/iarew/archs/mcs51/mcs51archiversettingsgroup_v10.h new file mode 100644 index 000000000..21c66433d --- /dev/null +++ b/src/plugins/generator/iarew/archs/mcs51/mcs51archiversettingsgroup_v10.h @@ -0,0 +1,59 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt.io/licensing +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef QBS_IAREWMCS51ARCHIVERSETTINGSGROUP_V10_H +#define QBS_IAREWMCS51ARCHIVERSETTINGSGROUP_V10_H + +#include "../../iarewsettingspropertygroup.h" + +namespace qbs { +namespace iarew { +namespace mcs51 { +namespace v10 { + +class Mcs51ArchiverSettingsGroup final : public IarewSettingsPropertyGroup +{ +public: + explicit Mcs51ArchiverSettingsGroup( + const Project &qbsProject, + const ProductData &qbsProduct, + const std::vector<ProductData> &qbsProductDeps); + +private: + void buildOutputPage(const QString &baseDirectory, + const ProductData &qbsProduct); +}; + +} // namespace v10 +} // namespace mcs51 +} // namespace iarew +} // namespace qbs + +#endif // QBS_IAREWMCS51ARCHIVERSETTINGSGROUP_V10_H diff --git a/src/plugins/generator/iarew/archs/mcs51/mcs51assemblersettingsgroup_v10.cpp b/src/plugins/generator/iarew/archs/mcs51/mcs51assemblersettingsgroup_v10.cpp new file mode 100644 index 000000000..a840b29c6 --- /dev/null +++ b/src/plugins/generator/iarew/archs/mcs51/mcs51assemblersettingsgroup_v10.cpp @@ -0,0 +1,228 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt.io/licensing +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "mcs51assemblersettingsgroup_v10.h" + +//#include "../../iarewproperty.h" +#include "../../iarewutils.h" + +namespace qbs { +namespace iarew { +namespace mcs51 { +namespace v10 { + +constexpr int kAssemblerArchiveVersion = 2; +constexpr int kAssemblerDataVersion = 6; + +namespace { + +// Language page options. + +struct LanguagePageOptions final +{ + enum MacroQuoteCharacter { + AngleBracketsQuote, + RoundBracketsQuote, + SquareBracketsQuote, + FigureBracketsQuote + }; + + explicit LanguagePageOptions(const ProductData &qbsProduct) + { + const auto &qbsProps = qbsProduct.moduleProperties(); + const QStringList flags = gen::utils::cppStringModuleProperties( + qbsProps, {QStringLiteral("assemblerFlags")}); + enableSymbolsCaseSensitive = flags.contains(QLatin1String("-s+")); + enableMultibyteSupport = flags.contains(QLatin1String("-n")); + + if (flags.contains(QLatin1String("-M<>"))) + macroQuoteCharacter = LanguagePageOptions::AngleBracketsQuote; + else if (flags.contains(QLatin1String("-M()"))) + macroQuoteCharacter = LanguagePageOptions::RoundBracketsQuote; + else if (flags.contains(QLatin1String("-M[]"))) + macroQuoteCharacter = LanguagePageOptions::SquareBracketsQuote; + else if (flags.contains(QLatin1String("-M{}"))) + macroQuoteCharacter = LanguagePageOptions::FigureBracketsQuote; + } + + MacroQuoteCharacter macroQuoteCharacter = AngleBracketsQuote; + int enableSymbolsCaseSensitive = 0; + int enableMultibyteSupport = 0; +}; + +// Output page options. + +struct OutputPageOptions final +{ + explicit OutputPageOptions(const ProductData &qbsProduct) + { + debugInfo = gen::utils::debugInformation(qbsProduct); + } + + int debugInfo = 0; +}; + +// Preprocessor page options. + +struct PreprocessorPageOptions final +{ + explicit PreprocessorPageOptions(const QString &baseDirectory, + const ProductData &qbsProduct) + { + const auto &qbsProps = qbsProduct.moduleProperties(); + defineSymbols = gen::utils::cppVariantModuleProperties( + qbsProps, {QStringLiteral("defines")}); + + const QString toolkitPath = IarewUtils::toolkitRootPath(qbsProduct); + const QStringList fullIncludePaths = gen::utils::cppStringModuleProperties( + qbsProps, {QStringLiteral("includePaths"), + QStringLiteral("systemIncludePaths")}); + for (const auto &fullIncludePath : fullIncludePaths) { + const QFileInfo includeFileInfo(fullIncludePath); + const QString includeFilePath = includeFileInfo.absoluteFilePath(); + if (includeFilePath.startsWith(toolkitPath, Qt::CaseInsensitive)) { + const QString path = IarewUtils::toolkitRelativeFilePath( + toolkitPath, includeFilePath); + includePaths.push_back(path); + } else { + const QString path = IarewUtils::projectRelativeFilePath( + baseDirectory, includeFilePath); + includePaths.push_back(path); + } + } + } + + QVariantList defineSymbols; + QVariantList includePaths; +}; + +// Diagnostics page options. + +struct DiagnosticsPageOptions final +{ + explicit DiagnosticsPageOptions(const ProductData &qbsProduct) + { + const auto &qbsProps = qbsProduct.moduleProperties(); + const QString warningLevel = gen::utils::cppStringModuleProperty( + qbsProps, QStringLiteral("warningLevel")); + if (warningLevel == QLatin1String("all")) { + enableWarnings = 0; + enableAllWarnings = 0; + } else if (warningLevel == QLatin1String("none")) { + enableWarnings = 1; + enableAllWarnings = 0; + } else { + enableWarnings = 0; + enableAllWarnings = 1; + } + } + + int enableWarnings = 0; + int enableAllWarnings = 0; +}; + +} // namespace + +// Mcs51AssemblerSettingsGroup + +Mcs51AssemblerSettingsGroup::Mcs51AssemblerSettingsGroup( + const Project &qbsProject, + const ProductData &qbsProduct, + const std::vector<ProductData> &qbsProductDeps) +{ + Q_UNUSED(qbsProject) + Q_UNUSED(qbsProductDeps) + + setName(QByteArrayLiteral("A8051")); + setArchiveVersion(kAssemblerArchiveVersion); + setDataVersion(kAssemblerDataVersion); + setDataDebugInfo(gen::utils::debugInformation(qbsProduct)); + + const QString buildRootDirectory = gen::utils::buildRootPath(qbsProject); + + buildLanguagePage(qbsProduct); + buildOutputPage(qbsProduct); + buildPreprocessorPage(buildRootDirectory, qbsProduct); + buildDiagnosticsPage(qbsProduct); +} + +void Mcs51AssemblerSettingsGroup::buildLanguagePage( + const ProductData &qbsProduct) +{ + const LanguagePageOptions opts(qbsProduct); + // Add 'ACaseSensitivity' item (User symbols are case sensitive). + addOptionsGroup(QByteArrayLiteral("ACaseSensitivity"), + {opts.enableSymbolsCaseSensitive}); + // Add 'Asm multibyte support' item (Enable multibyte support). + addOptionsGroup(QByteArrayLiteral("Asm multibyte support"), + {opts.enableMultibyteSupport}); + // Add 'MacroChars' item (Macro quote characters: ()/[]/{}/<>). + addOptionsGroup(QByteArrayLiteral("MacroChars"), + {!opts.macroQuoteCharacter}, 0); +} + +void Mcs51AssemblerSettingsGroup::buildOutputPage( + const ProductData &qbsProduct) +{ + const OutputPageOptions opts(qbsProduct); + // Add 'Debug' item (Generate debug information). + addOptionsGroup(QByteArrayLiteral("Debug"), + {opts.debugInfo}); +} + +void Mcs51AssemblerSettingsGroup::buildPreprocessorPage( + const QString &baseDirectory, + const ProductData &qbsProduct) +{ + const PreprocessorPageOptions opts(baseDirectory, qbsProduct); + // Add 'ADefines' item (Defined symbols). + addOptionsGroup(QByteArrayLiteral("ADefines"), + opts.defineSymbols); + // Add 'Include directories' item (Additional include directories). + addOptionsGroup(QByteArrayLiteral("Include directories"), + opts.includePaths); +} + +void Mcs51AssemblerSettingsGroup::buildDiagnosticsPage( + const ProductData &qbsProduct) +{ + const DiagnosticsPageOptions opts(qbsProduct); + // Add 'AWarnEnable' item (Enable/disable warnings). + addOptionsGroup(QByteArrayLiteral("AWarnEnable"), + {opts.enableWarnings}); + // Add 'AWarnWhat' item (Enable/disable all warnings). + addOptionsGroup(QByteArrayLiteral("AWarnWhat"), + {opts.enableAllWarnings}); +} + +} // namespace v10 +} // namespace mcs51 +} // namespace iarew +} // namespace qbs diff --git a/src/plugins/generator/iarew/archs/mcs51/mcs51assemblersettingsgroup_v10.h b/src/plugins/generator/iarew/archs/mcs51/mcs51assemblersettingsgroup_v10.h new file mode 100644 index 000000000..bb9f4b613 --- /dev/null +++ b/src/plugins/generator/iarew/archs/mcs51/mcs51assemblersettingsgroup_v10.h @@ -0,0 +1,62 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt.io/licensing +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef QBS_IAREWMCS51ASSEMBLERSETTINGSGROUP_V10_H +#define QBS_IAREWMCS51ASSEMBLERSETTINGSGROUP_V10_H + +#include "../../iarewsettingspropertygroup.h" + +namespace qbs { +namespace iarew { +namespace mcs51 { +namespace v10 { + +class Mcs51AssemblerSettingsGroup final : public IarewSettingsPropertyGroup +{ +public: + explicit Mcs51AssemblerSettingsGroup( + const Project &qbsProject, + const ProductData &qbsProduct, + const std::vector<ProductData> &qbsProductDeps); + +private: + void buildLanguagePage(const ProductData &qbsProduct); + void buildOutputPage(const ProductData &qbsProduct); + void buildPreprocessorPage(const QString &baseDirectory, + const ProductData &qbsProduct); + void buildDiagnosticsPage(const ProductData &qbsProduct); +}; + +} // namespace v10 +} // namespace mcs51 +} // namespace iarew +} // namespace qbs + +#endif // QBS_IAREWMCS51ASSEMBLERSETTINGSGROUP_V10_H diff --git a/src/plugins/generator/iarew/archs/mcs51/mcs51buildconfigurationgroup_v10.cpp b/src/plugins/generator/iarew/archs/mcs51/mcs51buildconfigurationgroup_v10.cpp new file mode 100644 index 000000000..ba86bc54d --- /dev/null +++ b/src/plugins/generator/iarew/archs/mcs51/mcs51buildconfigurationgroup_v10.cpp @@ -0,0 +1,98 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt.io/licensing +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "mcs51archiversettingsgroup_v10.h" +#include "mcs51assemblersettingsgroup_v10.h" +#include "mcs51buildconfigurationgroup_v10.h" +#include "mcs51compilersettingsgroup_v10.h" +#include "mcs51generalsettingsgroup_v10.h" +#include "mcs51linkersettingsgroup_v10.h" + +#include "../../iarewtoolchainpropertygroup.h" +#include "../../iarewutils.h" + +namespace qbs { +namespace iarew { +namespace mcs51 { +namespace v10 { + +Mcs51BuildConfigurationGroup::Mcs51BuildConfigurationGroup( + const Project &qbsProject, + const ProductData &qbsProduct, + const std::vector<ProductData> &qbsProductDeps) + : gen::xml::PropertyGroup("configuration") +{ + // Append configuration name item. + const QString cfgName = gen::utils::buildConfigurationName(qbsProject); + appendProperty("name", cfgName); + + // Apend toolchain name group item. + appendChild<IarewToolchainPropertyGroup>("8051"); + + // Append debug info item. + const int debugBuild = gen::utils::debugInformation(qbsProduct); + appendProperty("debug", debugBuild); + + // Append settings group items. + appendChild<Mcs51ArchiverSettingsGroup>( + qbsProject, qbsProduct, qbsProductDeps); + appendChild<Mcs51AssemblerSettingsGroup>( + qbsProject, qbsProduct, qbsProductDeps); + appendChild<Mcs51CompilerSettingsGroup>( + qbsProject, qbsProduct, qbsProductDeps); + appendChild<Mcs51GeneralSettingsGroup>( + qbsProject, qbsProduct, qbsProductDeps); + appendChild<Mcs51LinkerSettingsGroup>( + qbsProject, qbsProduct, qbsProductDeps); +} + +bool Mcs51BuildConfigurationGroupFactory::canCreate( + gen::utils::Architecture arch, + const Version &version) const +{ + return arch == gen::utils::Architecture::Mcs51 + && version.majorVersion() == 10; +} + +std::unique_ptr<gen::xml::PropertyGroup> +Mcs51BuildConfigurationGroupFactory::create( + const Project &qbsProject, + const ProductData &qbsProduct, + const std::vector<ProductData> &qbsProductDeps) const +{ + const auto group = new Mcs51BuildConfigurationGroup( + qbsProject, qbsProduct, qbsProductDeps); + return std::unique_ptr<Mcs51BuildConfigurationGroup>(group); +} + +} // namespace v10 +} // namespace mcs51 +} // namespace iarew +} // namespace qbs diff --git a/src/plugins/generator/iarew/archs/mcs51/mcs51buildconfigurationgroup_v10.h b/src/plugins/generator/iarew/archs/mcs51/mcs51buildconfigurationgroup_v10.h new file mode 100644 index 000000000..edd16d5d7 --- /dev/null +++ b/src/plugins/generator/iarew/archs/mcs51/mcs51buildconfigurationgroup_v10.h @@ -0,0 +1,71 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt.io/licensing +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef QBS_IAREWMCS51BUILDCONFIGURATIONGROUP_V10_H +#define QBS_IAREWMCS51BUILDCONFIGURATIONGROUP_V10_H + +#include <generators/xmlpropertygroup.h> + +namespace qbs { +namespace iarew { +namespace mcs51 { +namespace v10 { + +class Mcs51BuildConfigurationGroup final + : public gen::xml::PropertyGroup +{ +private: + explicit Mcs51BuildConfigurationGroup( + const Project &qbsProject, + const ProductData &qbsProduct, + const std::vector<ProductData> &qbsProductDeps); + + friend class Mcs51BuildConfigurationGroupFactory; +}; + +class Mcs51BuildConfigurationGroupFactory final + : public gen::xml::PropertyGroupFactory +{ +public: + bool canCreate(gen::utils::Architecture arch, + const Version &version) const final; + + std::unique_ptr<gen::xml::PropertyGroup> create( + const Project &qbsProject, + const ProductData &qbsProduct, + const std::vector<ProductData> &qbsProductDeps) const final; +}; + +} // namespace v10 +} // namespace mcs51 +} // namespace iarew +} // namespace qbs + +#endif // QBS_IAREWMCS51BUILDCONFIGURATIONGROUP_V10_H diff --git a/src/plugins/generator/iarew/archs/mcs51/mcs51compilersettingsgroup_v10.cpp b/src/plugins/generator/iarew/archs/mcs51/mcs51compilersettingsgroup_v10.cpp new file mode 100644 index 000000000..649350a98 --- /dev/null +++ b/src/plugins/generator/iarew/archs/mcs51/mcs51compilersettingsgroup_v10.cpp @@ -0,0 +1,476 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt.io/licensing +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "mcs51compilersettingsgroup_v10.h" + +#include "../../iarewutils.h" + +namespace qbs { +namespace iarew { +namespace mcs51 { +namespace v10 { + +constexpr int kCompilerArchiveVersion = 7; +constexpr int kCompilerDataVersion = 12; + +namespace { + +// Output page options. + +struct OutputPageOptions final +{ + enum ModuleType { + ProgramModule, + LibraryModule + }; + + explicit OutputPageOptions(const ProductData &qbsProduct) + { + const auto &qbsProps = qbsProduct.moduleProperties(); + const QStringList flags = IarewUtils::cppModuleCompilerFlags(qbsProps); + moduleType = flags.contains(QLatin1String("--library_module")) + ? OutputPageOptions::LibraryModule + : OutputPageOptions::ProgramModule; + debugInfo = gen::utils::debugInformation(qbsProduct); + } + + int debugInfo = 0; + ModuleType moduleType = ProgramModule; +}; + +// Language one page options. + +struct LanguageOnePageOptions final +{ + enum LanguageExtension { + CLanguageExtension, + CxxLanguageExtension, + AutoLanguageExtension + }; + + enum CLanguageDialect { + C89LanguageDialect, + C99LanguageDialect + }; + + enum CxxLanguageDialect { + EmbeddedCPlusPlus, + ExtendedEmbeddedCPlusPlus + }; + + enum LanguageConformance { + AllowIarExtension, + RelaxedStandard, + StrictStandard + }; + + explicit LanguageOnePageOptions(const ProductData &qbsProduct) + { + const auto &qbsProps = qbsProduct.moduleProperties(); + const QStringList flags = IarewUtils::cppModuleCompilerFlags(qbsProps); + // File extension based by default. + languageExtension = LanguageOnePageOptions::AutoLanguageExtension; + // C language dialect. + const QStringList cLanguageVersion = gen::utils::cppStringModuleProperties( + qbsProps, {QStringLiteral("cLanguageVersion")}); + cLanguageDialect = cLanguageVersion.contains(QLatin1String("c89")) + ? LanguageOnePageOptions::C89LanguageDialect + : LanguageOnePageOptions::C99LanguageDialect; + // C++ language dialect. + if (flags.contains(QLatin1String("--ec++"))) + cxxLanguageDialect = LanguageOnePageOptions::EmbeddedCPlusPlus; + else if (flags.contains(QLatin1String("--eec++"))) + cxxLanguageDialect = LanguageOnePageOptions::ExtendedEmbeddedCPlusPlus; + // Language conformance. + if (flags.contains(QLatin1String("-e"))) + languageConformance = LanguageOnePageOptions::AllowIarExtension; + else if (flags.contains(QLatin1String("--strict"))) + languageConformance = LanguageOnePageOptions::StrictStandard; + else + languageConformance = LanguageOnePageOptions::RelaxedStandard; + + allowVla = flags.contains(QLatin1String("--vla")); + useCppInlineSemantics = flags.contains( + QLatin1String("--use_c++_inline")); + requirePrototypes = flags.contains( + QLatin1String("--require_prototypes")); + destroyStaticObjects = !flags.contains( + QLatin1String("--no_static_destruction")); + } + + LanguageExtension languageExtension = AutoLanguageExtension; + CLanguageDialect cLanguageDialect = C89LanguageDialect; + CxxLanguageDialect cxxLanguageDialect = EmbeddedCPlusPlus; + LanguageConformance languageConformance = AllowIarExtension; + int allowVla = 0; + int useCppInlineSemantics = 0; + int requirePrototypes = 0; + int destroyStaticObjects = 0; +}; + +// Language two page options. + +struct LanguageTwoPageOptions final +{ + enum PlainCharacter { + SignedCharacter, + UnsignedCharacter + }; + + enum FloatingPointSemantic { + StrictSemantic, + RelaxedSemantic + }; + + explicit LanguageTwoPageOptions(const ProductData &qbsProduct) + { + const auto &qbsProps = qbsProduct.moduleProperties(); + const QStringList flags = IarewUtils::cppModuleCompilerFlags(qbsProps); + plainCharacter = flags.contains( + QLatin1String("--char_is_signed")) + ? LanguageTwoPageOptions::SignedCharacter + : LanguageTwoPageOptions::UnsignedCharacter; + floatingPointSemantic = flags.contains( + QLatin1String("--relaxed_fp")) + ? LanguageTwoPageOptions::RelaxedSemantic + : LanguageTwoPageOptions::StrictSemantic; + enableMultibyteSupport = flags.contains( + QLatin1String("--enable_multibytes")); + } + + PlainCharacter plainCharacter = SignedCharacter; + FloatingPointSemantic floatingPointSemantic = StrictSemantic; + int enableMultibyteSupport = 0; +}; + +// Optimizations page options. + +struct OptimizationsPageOptions final +{ + // Optimizations level radio-buttons with combo-box + // on "level" widget. + enum Strategy { + StrategyBalanced, + StrategySize, + StrategySpeed + }; + + enum Level { + LevelNone, + LevelLow, + LevelMedium, + LevelHigh + }; + + enum LevelSlave { + LevelSlave0, + LevelSlave1, + LevelSlave2, + LevelSlave3 + }; + + explicit OptimizationsPageOptions(const ProductData &qbsProduct) + { + const auto &qbsProps = qbsProduct.moduleProperties(); + const QString optimization = gen::utils::cppStringModuleProperty( + qbsProps, QStringLiteral("optimization")); + if (optimization == QLatin1String("none")) { + optimizationStrategy = OptimizationsPageOptions::StrategyBalanced; + optimizationLevel = OptimizationsPageOptions::LevelNone; + optimizationLevelSlave = OptimizationsPageOptions::LevelSlave0; + } else if (optimization == QLatin1String("fast")) { + optimizationStrategy = OptimizationsPageOptions::StrategySpeed; + optimizationLevel = OptimizationsPageOptions::LevelHigh; + optimizationLevelSlave = OptimizationsPageOptions::LevelSlave3; + } else if (optimization == QLatin1String("small")) { + optimizationStrategy = OptimizationsPageOptions::StrategySize; + optimizationLevel = OptimizationsPageOptions::LevelHigh; + optimizationLevelSlave = OptimizationsPageOptions::LevelSlave3; + } + + const QStringList flags = IarewUtils::cppModuleCompilerFlags(qbsProps); + enableCommonSubexpressionElimination = !flags.contains( + QLatin1String("--no_cse")); + enableLoopUnroll = !flags.contains(QLatin1String("--no_unroll")); + enableFunctionInlining = !flags.contains(QLatin1String("--no_inline")); + enableCodeMotion = !flags.contains(QLatin1String("--no_code_motion")); + enableTypeBasedAliasAnalysis = !flags.contains( + QLatin1String("--no_tbaa")); + enableCrossCall = !flags.contains(QLatin1String("--no_cross_call")); + disableRegisterBanks = flags.contains( + QLatin1String("--disable_register_banks")); + + disableSizeConstrains = flags.contains( + QLatin1String("--no_size_constraints")); + } + + Strategy optimizationStrategy = StrategyBalanced; + Level optimizationLevel = LevelNone; + LevelSlave optimizationLevelSlave = LevelSlave0; + // Seven bit-field flags on "enabled transformations" widget. + int enableCommonSubexpressionElimination = 0; // Common sub-expression elimination. + int enableLoopUnroll = 0; // Loop unrolling. + int enableFunctionInlining = 0; // Function inlining. + int enableCodeMotion = 0; // Code motion. + int enableTypeBasedAliasAnalysis = 0; // Type based alias analysis. + int enableCrossCall = 0; // Cross call optimization. + int disableRegisterBanks = 0; // Disabled register banks. + int disableSizeConstrains = 0; // No size constraints. +}; + +// Preprocessor page options. + +struct PreprocessorPageOptions final +{ + explicit PreprocessorPageOptions(const QString &baseDirectory, + const ProductData &qbsProduct) + { + const auto &qbsProps = qbsProduct.moduleProperties(); + // TODO: Need to exclude the pre-defined maroses which are handled + // in 'General Options'. + defineSymbols = gen::utils::cppVariantModuleProperties( + qbsProps, {QStringLiteral("defines")}); + + const QString toolkitPath = IarewUtils::toolkitRootPath(qbsProduct); + const QStringList fullIncludePaths = gen::utils::cppStringModuleProperties( + qbsProps, {QStringLiteral("includePaths"), + QStringLiteral("systemIncludePaths")}); + const QString dlibToolkitPath = IarewUtils::dlibToolkitRootPath(qbsProduct); + for (const QString &fullIncludePath : fullIncludePaths) { + const QFileInfo includeFileInfo(fullIncludePath); + const QString includeFilePath = includeFileInfo.absoluteFilePath(); + // Exclude dlib config includes because it already handled in + // 'General Options->Library configuration page'. + if (includeFilePath.startsWith(dlibToolkitPath)) + continue; + if (includeFilePath.startsWith(toolkitPath, Qt::CaseInsensitive)) { + const QString path = IarewUtils::toolkitRelativeFilePath( + toolkitPath, includeFilePath); + includePaths.push_back(path); + } else { + const QString path = IarewUtils::projectRelativeFilePath( + baseDirectory, includeFilePath); + includePaths.push_back(path); + } + } + } + + QVariantList defineSymbols; + QVariantList includePaths; +}; + +// Diagnostics page options. + +struct DiagnosticsPageOptions final +{ + explicit DiagnosticsPageOptions(const ProductData &qbsProduct) + { + const auto &qbsProps = qbsProduct.moduleProperties(); + warningsAsErrors = gen::utils::cppIntegerModuleProperty( + qbsProps, QStringLiteral("treatWarningsAsErrors")); + } + + int warningsAsErrors = 0; +}; + +// Code page options. + +struct CodePageOptions final +{ + explicit CodePageOptions(const ProductData &qbsProduct) + { + const auto &qbsProps = qbsProduct.moduleProperties(); + const QStringList flags = IarewUtils::cppModuleCompilerFlags(qbsProps); + paddingForRomMonitorBreakpoints = flags.contains( + QLatin1String("--rom_mon_bp_padding")); + excludeUbrofMessagesInOutput = flags.contains( + QLatin1String("--no_ubrof_messages")); + } + + int paddingForRomMonitorBreakpoints = 0; + int excludeUbrofMessagesInOutput = 0; +}; + +} // namespace + +// Mcs51CompilerSettingsGroup + +Mcs51CompilerSettingsGroup::Mcs51CompilerSettingsGroup( + const Project &qbsProject, + const ProductData &qbsProduct, + const std::vector<ProductData> &qbsProductDeps) +{ + Q_UNUSED(qbsProject) + Q_UNUSED(qbsProductDeps) + + setName(QByteArrayLiteral("ICC8051")); + setArchiveVersion(kCompilerArchiveVersion); + setDataVersion(kCompilerDataVersion); + setDataDebugInfo(gen::utils::debugInformation(qbsProduct)); + + const QString buildRootDirectory = gen::utils::buildRootPath(qbsProject); + + buildOutputPage(qbsProduct); + buildLanguageOnePage(qbsProduct); + buildLanguageTwoPage(qbsProduct); + buildOptimizationsPage(qbsProduct); + buildPreprocessorPage(buildRootDirectory, qbsProduct); + buildDiagnosticsPage(qbsProduct); +} + +void Mcs51CompilerSettingsGroup::buildOutputPage( + const ProductData &qbsProduct) +{ + const OutputPageOptions opts(qbsProduct); + // Add 'CCDebugInfo' item (Generate debug info). + addOptionsGroup(QByteArrayLiteral("CCDebugInfo"), + {opts.debugInfo}); + // Add 'CCOverrideModuleTypeDefault' item + // (Override default module type). + addOptionsGroup(QByteArrayLiteral("CCOverrideModuleTypeDefault"), + {1}); + // Add 'CCRadioModuleType' item (Module type: program/library). + addOptionsGroup(QByteArrayLiteral("CCRadioModuleType"), + {opts.moduleType}); +} + +void Mcs51CompilerSettingsGroup::buildLanguageOnePage( + const ProductData &qbsProduct) +{ + const LanguageOnePageOptions opts(qbsProduct); + // Add 'IccLang' item with 'auto-extension based' + // value (Language: C/C++/Auto). + addOptionsGroup(QByteArrayLiteral("IccLang"), + {opts.languageExtension}); + // Add 'IccCDialect' item (C dialect: c89/99/11). + addOptionsGroup(QByteArrayLiteral("IccCDialect"), + {opts.cLanguageDialect}); + // Add 'IccCppDialect' item (C++ dialect: embedded/extended). + addOptionsGroup(QByteArrayLiteral("IccCppDialect"), + {opts.cxxLanguageDialect}); + // Add 'CCExt' item (Language conformance: IAR/relaxed/strict). + addOptionsGroup(QByteArrayLiteral("LangConform"), + {opts.languageConformance}); + // Add 'IccAllowVLA' item (Allow VLA). + addOptionsGroup(QByteArrayLiteral("IccAllowVLA"), + {opts.allowVla}); + // Add 'IccCppInlineSemantics' item (C++ inline semantics). + addOptionsGroup(QByteArrayLiteral("IccCppInlineSemantics"), + {opts.useCppInlineSemantics}); + // Add 'CCRequirePrototypes' item (Require prototypes). + addOptionsGroup(QByteArrayLiteral("CCRequirePrototypes"), + {opts.requirePrototypes}); + // Add 'IccStaticDestr' item (Destroy static objects). + addOptionsGroup(QByteArrayLiteral("IccStaticDestr"), + {opts.destroyStaticObjects}); +} + +void Mcs51CompilerSettingsGroup::buildLanguageTwoPage( + const ProductData &qbsProduct) +{ + const LanguageTwoPageOptions opts(qbsProduct); + // Add 'CharIs' item (Plain char is: signed/unsigned). + addOptionsGroup(QByteArrayLiteral("CharIs"), + {opts.plainCharacter}); + // Add 'IccFloatSemantics' item + // (Floatic-point semantics: strict/relaxed conformance). + addOptionsGroup(QByteArrayLiteral("IccFloatSemantics"), + {opts.floatingPointSemantic}); + // Add 'CCMultibyteSupport' item (Enable multibyte support). + addOptionsGroup(QByteArrayLiteral("CCMultibyteSupport"), + {opts.enableMultibyteSupport}); +} + +void Mcs51CompilerSettingsGroup::buildOptimizationsPage( + const ProductData &qbsProduct) +{ + const OptimizationsPageOptions opts(qbsProduct); + // Add 'CCOptStrategy', 'CCOptLevel' and + // 'CCOptLevelSlave' items (Level). + addOptionsGroup(QByteArrayLiteral("CCOptStrategy"), + {opts.optimizationStrategy}); + addOptionsGroup(QByteArrayLiteral("CCOptLevel"), + {opts.optimizationLevel}); + addOptionsGroup(QByteArrayLiteral("CCOptLevelSlave"), + {opts.optimizationLevelSlave}); + // Add 'CCAllowList2' item (Enabled transformations: 7 check boxes). + const QString transformations = QStringLiteral("%1%2%3%4%5%6%7") + .arg(opts.enableCommonSubexpressionElimination) + .arg(opts.enableLoopUnroll) + .arg(opts.enableFunctionInlining) + .arg(opts.enableCodeMotion) + .arg(opts.enableTypeBasedAliasAnalysis) + .arg(opts.enableCrossCall) + .arg(opts.disableRegisterBanks); + addOptionsGroup(QByteArrayLiteral("CCAllowList2"), + {transformations}); + // Add 'NoSizeConstraints' item (No size constraints). + addOptionsGroup(QByteArrayLiteral("NoSizeConstraints"), + {opts.disableSizeConstrains}); +} + +void Mcs51CompilerSettingsGroup::buildPreprocessorPage( + const QString &baseDirectory, + const ProductData &qbsProduct) +{ + const PreprocessorPageOptions opts(baseDirectory, qbsProduct); + // Add 'CCDefines' item (Defines symbols). + addOptionsGroup(QByteArrayLiteral("CCDefines"), + opts.defineSymbols); + // Add 'CCIncludePath2' item (Additional include directories). + addOptionsGroup(QByteArrayLiteral("CCIncludePath2"), + opts.includePaths); +} + +void Mcs51CompilerSettingsGroup::buildDiagnosticsPage( + const ProductData &qbsProduct) +{ + const DiagnosticsPageOptions opts(qbsProduct); + // Add 'CCDiagWarnAreErr' item (Treat all warnings as errors). + addOptionsGroup(QByteArrayLiteral("CCDiagWarnAreErr"), + {opts.warningsAsErrors}); +} + +void Mcs51CompilerSettingsGroup::buildCodePage( + const ProductData &qbsProduct) +{ + const CodePageOptions opts(qbsProduct); + // Add 'RomMonBpPadding' item (Padding for ROM-monitor breakpoints). + addOptionsGroup(QByteArrayLiteral("RomMonBpPadding"), + {opts.paddingForRomMonitorBreakpoints}); + // Add 'NoUBROFMessages' item (No UBROF messages in output files). + addOptionsGroup(QByteArrayLiteral("NoUBROFMessages"), + {opts.excludeUbrofMessagesInOutput}); +} + +} // namespace v10 +} // namespace mcs51 +} // namespace iarew +} // namespace qbs diff --git a/src/plugins/generator/iarew/archs/mcs51/mcs51compilersettingsgroup_v10.h b/src/plugins/generator/iarew/archs/mcs51/mcs51compilersettingsgroup_v10.h new file mode 100644 index 000000000..e68a7628f --- /dev/null +++ b/src/plugins/generator/iarew/archs/mcs51/mcs51compilersettingsgroup_v10.h @@ -0,0 +1,65 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt.io/licensing +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef QBS_IAREWMCS51COMPILERSETTINGSGROUP_V10_H +#define QBS_IAREWMCS51COMPILERSETTINGSGROUP_V10_H + +#include "../../iarewsettingspropertygroup.h" + +namespace qbs { +namespace iarew { +namespace mcs51 { +namespace v10 { + +class Mcs51CompilerSettingsGroup final : public IarewSettingsPropertyGroup +{ +public: + explicit Mcs51CompilerSettingsGroup( + const Project &qbsProject, + const ProductData &qbsProduct, + const std::vector<ProductData> &qbsProductDeps); + +private: + void buildOutputPage(const ProductData &qbsProduct); + void buildLanguageOnePage(const ProductData &qbsProduct); + void buildLanguageTwoPage(const ProductData &qbsProduct); + void buildOptimizationsPage(const ProductData &qbsProduct); + void buildPreprocessorPage(const QString &baseDirectory, + const ProductData &qbsProduct); + void buildDiagnosticsPage(const ProductData &qbsProduct); + void buildCodePage(const ProductData &qbsProduct); +}; + +} // namespace v10 +} // namespace mcs51 +} // namespace iarew +} // namespace qbs + +#endif // QBS_IAREWMCS51COMPILERSETTINGSGROUP_V10_H diff --git a/src/plugins/generator/iarew/archs/mcs51/mcs51generalsettingsgroup_v10.cpp b/src/plugins/generator/iarew/archs/mcs51/mcs51generalsettingsgroup_v10.cpp new file mode 100644 index 000000000..43c160045 --- /dev/null +++ b/src/plugins/generator/iarew/archs/mcs51/mcs51generalsettingsgroup_v10.cpp @@ -0,0 +1,1014 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt.io/licensing +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "mcs51generalsettingsgroup_v10.h" + +#include "../../iarewutils.h" + +namespace qbs { +namespace iarew { +namespace mcs51 { +namespace v10 { + +constexpr int kGeneralArchiveVersion = 4; +constexpr int kGeneralDataVersion = 9; + +namespace { + +// Target page options. + +struct TargetPageOptions final +{ + enum CpuCore { + CorePlain = 1, + CoreExtended1, + CoreExtended2 + }; + + enum CodeModel { + CodeModelNear = 1, + CodeModelBanked, + CodeModelFar, + CodeModelBankedExtended2 + }; + + enum DataModel { + DataModelTiny = 0, + DataModelSmall, + DataModelLarge, + DataModelGeneric, + DataModelFarGeneric, + DataModelFar + }; + + enum ConstantsMemoryPlacement { + RamMemoryPlace = 0, + RomMemoryPlace, + CodeMemoryPlace + }; + + enum CallingConvention { + DataOverlayConvention = 0, + IDataOverlayConvention, + IDataReentrantConvention, + PDataReentrantConvention, + XDataReentrantConvention, + ExtendedStackReentrantConvention + }; + + explicit TargetPageOptions(const ProductData &qbsProduct) + { + chipInfoPath = detectChipInfoPath(qbsProduct); + + const auto &qbsProps = qbsProduct.moduleProperties(); + const QStringList flags = IarewUtils::cppModuleCompilerFlags(qbsProps); + + // Should be parsed before the 'code_model' and + // 'data_model' options, as that options are depends on it. + const QString core = IarewUtils::flagValue( + flags, QStringLiteral("--core")) + .toLower(); + if (core == QLatin1String("plain")) { + cpuCore = TargetPageOptions::CorePlain; + } else if (core == QLatin1String("extended1")) { + cpuCore = TargetPageOptions::CoreExtended1; + } else if (core == QLatin1String("extended2")) { + cpuCore = TargetPageOptions::CoreExtended2; + } else { + // If the core variant is not set, then choose the + // default values (see the compiler datasheet for + // '--core' option). + cpuCore = TargetPageOptions::CorePlain; + } + + const QString cm = IarewUtils::flagValue( + flags, QStringLiteral("--code_model")) + .toLower(); + if (cm == QLatin1String("near")) { + codeModel = TargetPageOptions::CodeModelNear; + } else if (cm == QLatin1String("banked")) { + codeModel = TargetPageOptions::CodeModelBanked; + } else if (cm == QLatin1String("far")) { + codeModel = TargetPageOptions::CodeModelFar; + } else if (cm == QLatin1String("banked_ext2")) { + codeModel = TargetPageOptions::CodeModelBankedExtended2; + } else { + // If the code model is not set, then choose the + // default values (see the compiler datasheet for + // '--code_model' option). + if (cpuCore == TargetPageOptions::CorePlain) + codeModel = TargetPageOptions::CodeModelNear; + else if (cpuCore == TargetPageOptions::CoreExtended1) + codeModel = TargetPageOptions::CodeModelFar; + else if (cpuCore == TargetPageOptions::CoreExtended2) + codeModel = TargetPageOptions::CodeModelBankedExtended2; + } + + const QString dm = IarewUtils::flagValue( + flags, QStringLiteral("--data_model")).toLower(); + if (dm == QLatin1String("tiny")) { + dataModel = TargetPageOptions::DataModelTiny; + } else if (dm == QLatin1String("small")) { + dataModel = TargetPageOptions::DataModelSmall; + } else if (dm == QLatin1String("large")) { + dataModel = TargetPageOptions::DataModelLarge; + } else if (dm == QLatin1String("generic")) { + dataModel = TargetPageOptions::DataModelGeneric; + } else if (dm == QLatin1String("far_generic")) { + dataModel = TargetPageOptions::DataModelFarGeneric; + } else if (dm == QLatin1String("far")) { + dataModel = TargetPageOptions::DataModelFar; + } else { + // If the data model is not set, then choose the + // default values (see the compiler datasheet for + // '--data_model' option). + if (cpuCore == TargetPageOptions::CorePlain) + dataModel = TargetPageOptions::DataModelSmall; + else if (cpuCore == TargetPageOptions::CoreExtended1) + dataModel = TargetPageOptions::DataModelFar; + else if (cpuCore == TargetPageOptions::CoreExtended2) + dataModel = TargetPageOptions::DataModelLarge; + } + + useExtendedStack = flags.contains(QLatin1String("--extended_stack")); + + const int regsCount = IarewUtils::flagValue( + flags, QStringLiteral("--nr_virtual_regs")) + .toInt(); + enum { MinVRegsCount = 8, MaxVRegsCount = 32, VRegsOffset = 8 }; + // The registers index starts with 0: 0 - means 8 registers, + // 1 - means 9 registers and etc. Any invalid values we interpret + // as a default value in 8 registers. + virtualRegisters = (regsCount < MinVRegsCount || regsCount > MaxVRegsCount) + ? 0 : (regsCount - VRegsOffset); + + const QString constPlace = IarewUtils::flagValue( + flags, QStringLiteral("--place_constants")) + .toLower(); + if (constPlace == QLatin1String("data")) { + constPlacement = TargetPageOptions::RamMemoryPlace; + } else if (constPlace == QLatin1String("data_rom")) { + constPlacement = TargetPageOptions::RomMemoryPlace; + } else if (constPlace == QLatin1String("code")) { + constPlacement = TargetPageOptions::CodeMemoryPlace; + } else { + // If this option is not set, then choose the + // default value (see the compiler datasheet for + // '--place_constants' option). + constPlacement = TargetPageOptions::RamMemoryPlace; + } + + const QString cc = IarewUtils::flagValue( + flags, QStringLiteral("--calling_convention")).toLower(); + if (cc == QLatin1String("data_overlay")) { + callingConvention = TargetPageOptions::DataOverlayConvention; + } else if (cc == QLatin1String("idata_overlay")) { + callingConvention = TargetPageOptions::IDataOverlayConvention; + } else if (cc == QLatin1String("idata_reentrant")) { + callingConvention = TargetPageOptions::IDataReentrantConvention; + } else if (cc == QLatin1String("pdata_reentrant")) { + callingConvention = TargetPageOptions::PDataReentrantConvention; + } else if (cc == QLatin1String("xdata_reentrant")) { + callingConvention = TargetPageOptions::XDataReentrantConvention; + } else if (cc == QLatin1String("ext_stack_reentrant")) { + callingConvention = TargetPageOptions::ExtendedStackReentrantConvention; + } else { + // If this option is not set, then choose the + // default value (see the compiler datasheet for + // '--calling_convention' option). + callingConvention = TargetPageOptions::IDataReentrantConvention; + } + } + + // Trying to indirectly detect and build the chip config path, + // which uses to show a device name in "Device information" group box. + static QString detectChipInfoPath(const ProductData &qbsProduct) + { + const auto &qbsProps = qbsProduct.moduleProperties(); + + QVariantList configPaths; + + // Enumerate all product linker config files + // (which are set trough '-f' option). + const QStringList flags = IarewUtils::cppModuleLinkerFlags(qbsProps); + configPaths << IarewUtils::flagValues(flags, QStringLiteral("-f")); + + // Enumerate all product linker config files + // (which are set trough 'linkerscript' tag). + const auto qbsGroups = qbsProduct.groups(); + for (const auto &qbsGroup : qbsGroups) { + const auto qbsArtifacts = qbsGroup.sourceArtifacts(); + for (const auto &qbsArtifact : qbsArtifacts) { + const auto qbsTags = qbsArtifact.fileTags(); + if (!qbsTags.contains(QLatin1String("linkerscript"))) + continue; + const auto configPath = qbsArtifact.filePath(); + // Skip duplicates. + if (configPaths.contains(configPath)) + continue; + configPaths << qbsArtifact.filePath(); + } + } + + const QString toolkitPath = IarewUtils::toolkitRootPath(qbsProduct); + for (const QVariant &configPath : configPaths) { + const QString fullConfigPath = configPath.toString(); + // We interested only in a config paths shipped inside of a toolkit. + if (!fullConfigPath.startsWith(toolkitPath, Qt::CaseInsensitive)) + continue; + // Extract the chip name from the linker script name. + const int underscoreIndex = fullConfigPath.lastIndexOf(QLatin1Char('_')); + if (underscoreIndex == -1) + continue; + const int dotIndex = fullConfigPath.lastIndexOf(QLatin1Char('.')); + if (dotIndex == -1) + continue; + if (dotIndex <= underscoreIndex) + continue; + const QString chipName = fullConfigPath.mid( + underscoreIndex + 1, + dotIndex - underscoreIndex - 1); + // Construct full chip info path. + const QFileInfo fullChipInfoPath(QFileInfo(fullConfigPath).absolutePath() + + QLatin1Char('/') + chipName + + QLatin1String(".i51")); + if (fullChipInfoPath.exists()) + return fullChipInfoPath.absoluteFilePath(); + } + + return {}; + } + + QString chipInfoPath; + CpuCore cpuCore = CorePlain; + CodeModel codeModel = CodeModelNear; + DataModel dataModel = DataModelTiny; + int useExtendedStack = 0; + int virtualRegisters = 0; + ConstantsMemoryPlacement constPlacement = RamMemoryPlace; + CallingConvention callingConvention = DataOverlayConvention; +}; + +// System page options. + +struct StackHeapPageOptions final +{ + explicit StackHeapPageOptions(const ProductData &qbsProduct) + { + const auto &qbsProps = qbsProduct.moduleProperties(); + const QStringList defineSymbols = gen::utils::cppStringModuleProperties( + qbsProps, {QStringLiteral("defines")}); + const QStringList linkerFlags = gen::utils::cppStringModuleProperties( + qbsProps, {QStringLiteral("driverLinkerFlags")}); + + idataStack = IarewUtils::flagValue( + defineSymbols, QStringLiteral("_IDATA_STACK_SIZE")); + if (idataStack.isEmpty()) + idataStack = IarewUtils::flagValue( + linkerFlags, QStringLiteral("-D_IDATA_STACK_SIZE")); + if (idataStack.isEmpty()) + idataStack = QLatin1String("0x40"); // Default IDATA stack size. + pdataStack = IarewUtils::flagValue( + defineSymbols, QStringLiteral("_PDATA_STACK_SIZE")); + if (pdataStack.isEmpty()) + pdataStack = IarewUtils::flagValue( + linkerFlags, QStringLiteral("-D_PDATA_STACK_SIZE")); + if (pdataStack.isEmpty()) + pdataStack = QLatin1String("0x80"); // Default PDATA stack size. + xdataStack = IarewUtils::flagValue( + defineSymbols, QStringLiteral("_XDATA_STACK_SIZE")); + if (xdataStack.isEmpty()) + xdataStack = IarewUtils::flagValue( + linkerFlags, QStringLiteral("-D_XDATA_STACK_SIZE")); + if (xdataStack.isEmpty()) + xdataStack = QLatin1String("0xEFF"); // Default XDATA stack size. + extendedStack = IarewUtils::flagValue( + defineSymbols, QStringLiteral("_EXTENDED_STACK_SIZE")); + if (extendedStack.isEmpty()) + extendedStack = IarewUtils::flagValue( + linkerFlags, QStringLiteral("-D_EXTENDED_STACK_SIZE")); + if (extendedStack.isEmpty()) + extendedStack = QLatin1String("0x3FF"); // Default EXTENDED stack size. + + xdataHeap = IarewUtils::flagValue( + defineSymbols, QStringLiteral("_XDATA_HEAP_SIZE")); + if (xdataHeap.isEmpty()) + xdataHeap = IarewUtils::flagValue( + linkerFlags, QStringLiteral("-D_XDATA_HEAP_SIZE")); + if (xdataHeap.isEmpty()) + xdataHeap = QLatin1String("0xFF"); // Default XDATA heap size. + farHeap = IarewUtils::flagValue( + defineSymbols, QStringLiteral("_FAR_HEAP_SIZE")); + if (farHeap.isEmpty()) + farHeap = IarewUtils::flagValue( + linkerFlags, QStringLiteral("-D_FAR_HEAP_SIZE")); + if (farHeap.isEmpty()) + farHeap = QLatin1String("0xFFF"); // Default FAR heap size. + far22Heap = IarewUtils::flagValue( + defineSymbols, QStringLiteral("_FAR22_HEAP_SIZE")); + if (far22Heap.isEmpty()) + far22Heap = IarewUtils::flagValue( + linkerFlags, QStringLiteral("-D_FAR22_HEAP_SIZE")); + if (far22Heap.isEmpty()) + far22Heap = QLatin1String("0xFFF"); // Default FAR22 heap size. + hugeHeap = IarewUtils::flagValue( + defineSymbols, QStringLiteral("_HUGE_HEAP_SIZE")); + if (hugeHeap.isEmpty()) + hugeHeap = IarewUtils::flagValue( + linkerFlags, QStringLiteral("-D_HUGE_HEAP_SIZE")); + if (hugeHeap.isEmpty()) + hugeHeap = QLatin1String("0xFFF"); // Default HUGE heap size. + + extStackAddress = IarewUtils::flagValue( + defineSymbols, QStringLiteral("?ESP")); + if (extStackAddress.isEmpty()) + extStackAddress = IarewUtils::flagValue( + linkerFlags, QStringLiteral("-D?ESP")); + if (extStackAddress.isEmpty()) + extStackAddress = QLatin1String("0x9B"); // Default extended stack pointer address. + extStackMask = IarewUtils::flagValue( + defineSymbols, QStringLiteral("?ESP_MASK")); + if (extStackMask.isEmpty()) + extStackMask = IarewUtils::flagValue( + linkerFlags, QStringLiteral("-D?ESP_MASK")); + if (extStackMask.isEmpty()) + extStackMask = QLatin1String("0x03"); // Default extended stack pointer mask. + } + + // Stack sizes. + QString idataStack; + QString pdataStack; + QString xdataStack; + QString extendedStack; + // Heap sizes. + QString xdataHeap; + QString farHeap; + QString far22Heap; + QString hugeHeap; + // Extended stack. + QString extStackAddress; + QString extStackMask; + int extStackOffset = 0; + int extStackStartAddress = 0; +}; + +// Data pointer page options. + +struct DptrPageOptions final +{ + enum DptrSize { + Dptr16, + Dptr24 + }; + + enum DptrVisibility { + DptrShadowed, + DptrSeparate + }; + + enum SwitchMethod { + DptrIncludeMethod, + DptrMaskMethod + }; + + explicit DptrPageOptions(const ProductData &qbsProduct) + { + const auto &qbsProps = qbsProduct.moduleProperties(); + const QStringList flags = IarewUtils::cppModuleCompilerFlags(qbsProps); + + const QString core = IarewUtils::flagValue( + flags, QStringLiteral("--core")); + + const QString dptr = IarewUtils::flagValue( + flags, QStringLiteral("--dptr")); + enum ValueIndex { SizeIndex, NumbersIndex, + VisibilityIndex, SwitchMethodIndex }; + const QStringList dptrparts = dptr.split(QLatin1Char(',')); + for (auto index = 0; index < dptrparts.count(); ++index) { + const QString part = dptrparts.at(index).toLower(); + switch (index) { + case SizeIndex: + if (part == QLatin1String("16")) { + dptrSize = DptrPageOptions::Dptr16; + } else if (part == QLatin1String("24")) { + dptrSize = DptrPageOptions::Dptr24; + } else { + // If this option is not set, then choose the + // default value (see the compiler datasheet for + // '--dptr' option). + if (core == QLatin1String("extended1")) + dptrSize = DptrPageOptions::Dptr24; + else + dptrSize = DptrPageOptions::Dptr16; + } + break; + case NumbersIndex: { + const int count = part.toInt(); + if (count < 1 || count > 8) { + // If this option is not set, then choose the + // default value (see the compiler datasheet for + // '--dptr' option). + if (core == QLatin1String("extended1")) + dptrsCountIndex = 1; // 2 DPTR's + else + dptrsCountIndex = 0; // 1 DPTR's + } else { + dptrsCountIndex = (count - 1); // DPTR's count - 1 + } + } + break; + case VisibilityIndex: + if (part == QLatin1String("shadowed")) + dptrVisibility = DptrPageOptions::DptrShadowed; + else if (part == QLatin1String("separate")) + dptrVisibility = DptrPageOptions::DptrSeparate; + else + // If this option is not set, then choose the + // default value (see the compiler datasheet for + // '--dptr' option). + dptrVisibility = DptrPageOptions::DptrSeparate; + break; + case SwitchMethodIndex: + if (part == QLatin1String("inc")) { + dptrSwitchMethod = DptrPageOptions::DptrIncludeMethod; + } else if (part.startsWith(QLatin1String("xor"))) { + dptrSwitchMethod = DptrPageOptions::DptrMaskMethod; + const int firstIndex = part.indexOf(QLatin1Char('(')); + const int lastIndex = part.indexOf(QLatin1Char(')')); + dptrMask = part.mid(firstIndex + 1, part.size() - lastIndex); + } else { + // If this option is not set, then choose the + // default value (see the compiler datasheet for + // '--dptr' option). + if (core == QLatin1String("extended1")) { + dptrSwitchMethod = DptrPageOptions::DptrIncludeMethod; + } else if (core == QLatin1String("plain")) { + dptrSwitchMethod = DptrPageOptions::DptrMaskMethod; + dptrMask = QLatin1String("0x01"); + } + } + break; + default: + break; + } + } + + const QStringList defineSymbols = gen::utils::cppStringModuleProperties( + qbsProps, {QStringLiteral("defines")}); + const QStringList linkerFlags = gen::utils::cppStringModuleProperties( + qbsProps, {QStringLiteral("driverLinkerFlags")}); + + dptrPbank = IarewUtils::flagValue( + defineSymbols, QStringLiteral("?PBANK")); + if (dptrPbank.isEmpty()) + dptrPbank = IarewUtils::flagValue( + linkerFlags, QStringLiteral("-D?PBANK")); + if (dptrPbank.isEmpty()) + dptrPbank = QLatin1String("0x93"); // Default 8-15 regs address. + dptrPbankExt = IarewUtils::flagValue( + defineSymbols, QStringLiteral("?PBANK_EXT")); + if (dptrPbankExt.isEmpty()) + dptrPbankExt = IarewUtils::flagValue( + linkerFlags, QStringLiteral("-D?PBANK_EXT")); + + dpsAddress = IarewUtils::flagValue( + defineSymbols, QStringLiteral("?DPS")); + if (dpsAddress.isEmpty()) + dpsAddress = IarewUtils::flagValue( + linkerFlags, QStringLiteral("-D?DPS")); + dpcAddress = IarewUtils::flagValue( + defineSymbols, QStringLiteral("?DPC")); + if (dpcAddress.isEmpty()) + dpcAddress = IarewUtils::flagValue( + linkerFlags, QStringLiteral("-D?DPC")); + + for (auto index = 0; index < 8; ++index) { + if (index == 0) { + QString dpxAddress = IarewUtils::flagValue( + defineSymbols, QStringLiteral("?DPX")); + if (dpxAddress.isEmpty()) + dpxAddress = IarewUtils::flagValue( + linkerFlags, QStringLiteral("-D?DPX")); + if (!dpxAddress.isEmpty()) + dpxAddress.prepend(QLatin1String("-D?DPX=")); + if (!dptrAddresses.contains(dpxAddress)) + dptrAddresses.push_back(dpxAddress); + } else { + QString dplAddress = IarewUtils::flagValue( + defineSymbols, QStringLiteral("?DPL%1").arg(index)); + if (dplAddress.isEmpty()) + dplAddress = IarewUtils::flagValue( + linkerFlags, QStringLiteral("-D?DPL%1").arg(index)); + if (!dplAddress.isEmpty()) + dplAddress.prepend(QStringLiteral("-D?DPL%1=").arg(index)); + if (!dptrAddresses.contains(dplAddress)) + dptrAddresses.push_back(dplAddress); + + QString dphAddress = IarewUtils::flagValue( + defineSymbols, QStringLiteral("?DPH%1").arg(index)); + if (dphAddress.isEmpty()) + dphAddress = IarewUtils::flagValue( + linkerFlags, QStringLiteral("-D?DPH%1").arg(index)); + if (!dphAddress.isEmpty()) + dphAddress.prepend(QStringLiteral("-D?DPH%1=").arg(index)); + if (!dptrAddresses.contains(dphAddress)) + dptrAddresses.push_back(dphAddress); + + QString dpxAddress = IarewUtils::flagValue( + defineSymbols, QStringLiteral("?DPX%1").arg(index)); + if (dpxAddress.isEmpty()) + dpxAddress = IarewUtils::flagValue( + linkerFlags, QStringLiteral("-D?DPX%1").arg(index)); + if (!dpxAddress.isEmpty()) + dpxAddress.prepend(QStringLiteral("-D?DPX%1=").arg(index)); + if (!dptrAddresses.contains(dpxAddress)) + dptrAddresses.push_back(dpxAddress); + } + } + } + + int dptrsCountIndex = 0; + DptrSize dptrSize = Dptr16; + DptrVisibility dptrVisibility = DptrShadowed; + SwitchMethod dptrSwitchMethod = DptrIncludeMethod; + QString dptrMask; + QString dptrPbank; + QString dptrPbankExt; + QString dpsAddress; + QString dpcAddress; + QStringList dptrAddresses; +}; + +// Code bank page options. + +struct CodeBankPageOptions final +{ + explicit CodeBankPageOptions(const ProductData &qbsProduct) + { + const auto &qbsProps = qbsProduct.moduleProperties(); + const QStringList defineSymbols = gen::utils::cppStringModuleProperties( + qbsProps, {QStringLiteral("defines")}); + const QStringList linkerFlags = gen::utils::cppStringModuleProperties( + qbsProps, {QStringLiteral("driverLinkerFlags")}); + + banksCount = IarewUtils::flagValue( + defineSymbols, QStringLiteral("_NR_OF_BANKS")); + if (banksCount.isEmpty()) + banksCount = IarewUtils::flagValue( + linkerFlags, QStringLiteral("-D_NR_OF_BANKS")); + if (banksCount.isEmpty()) + banksCount = QLatin1String("0x03"); + registerAddress = IarewUtils::flagValue( + defineSymbols, QStringLiteral("?CBANK")); + if (registerAddress.isEmpty()) + registerAddress = IarewUtils::flagValue( + linkerFlags, QStringLiteral("-D?CBANK")); + if (registerAddress.isEmpty()) + registerAddress = QLatin1String("0xF0"); + registerMask = IarewUtils::flagValue( + defineSymbols, QStringLiteral("?CBANK_MASK")); + if (registerMask.isEmpty()) + registerMask = IarewUtils::flagValue( + linkerFlags, QStringLiteral("-D?CBANK_MASK")); + if (registerMask.isEmpty()) + registerMask = QLatin1String("0xFF"); + bankStart = IarewUtils::flagValue( + defineSymbols, QStringLiteral("_CODEBANK_START")); + if (bankStart.isEmpty()) + bankStart = IarewUtils::flagValue( + linkerFlags, QStringLiteral("-D_CODEBANK_START")); + if (bankStart.isEmpty()) + bankStart = QLatin1String("0x8000"); + bankEnd = IarewUtils::flagValue( + defineSymbols, QStringLiteral("_CODEBANK_END")); + if (bankEnd.isEmpty()) + bankEnd = IarewUtils::flagValue( + linkerFlags, QStringLiteral("-D_CODEBANK_END")); + if (bankEnd.isEmpty()) + bankEnd = QLatin1String("0xFFFF"); + } + + QString banksCount; + QString registerAddress; + QString registerMask; + QString bankStart; + QString bankEnd; +}; + +// Library options page options. + +struct LibraryOptionsPageOptions final +{ + enum PrintfFormatter { + PrintfAutoFormatter = 0, + PrintfLargeFormatter = 3, + PrintfMediumFormatter = 5, + PrintfSmallFormatter = 6 + }; + + enum ScanfFormatter { + ScanfAutoFormatter = 0, + ScanfLargeFormatter = 3, + ScanfMediumFormatter = 5 + }; + + explicit LibraryOptionsPageOptions(const ProductData &qbsProduct) + { + const auto &qbsProps = qbsProduct.moduleProperties(); + const QStringList flags = IarewUtils::cppModuleLinkerFlags(qbsProps); + for (const QString &flag : flags) { + if (flag.endsWith(QLatin1String("_formatted_write"), + Qt::CaseInsensitive)) { + const QString prop = flag.split( + QLatin1Char('=')).at(0).toLower(); + if (prop == QLatin1String("-e_large_write")) + printfFormatter = LibraryOptionsPageOptions::PrintfLargeFormatter; + else if (prop == QLatin1String("-e_medium_write")) + printfFormatter = LibraryOptionsPageOptions::PrintfMediumFormatter; + else if (prop == QLatin1String("-e_small_write")) + printfFormatter = LibraryOptionsPageOptions::PrintfSmallFormatter; + else + // If this option is not set, then choose the + // default value (see the compiler datasheet for + // '_formatted_write' option). + printfFormatter = LibraryOptionsPageOptions::PrintfMediumFormatter; + } else if (flag.endsWith(QLatin1String("_formatted_read"), + Qt::CaseInsensitive)) { + const QString prop = flag.split(QLatin1Char('=')) + .at(0).toLower(); + if (prop == QLatin1String("-e_large_read")) + scanfFormatter = LibraryOptionsPageOptions::ScanfLargeFormatter; + else if (prop == QLatin1String("-e_medium_read")) + scanfFormatter = LibraryOptionsPageOptions::ScanfMediumFormatter; + else + // If this option is not set, then choose the + // default value (see the compiler datasheet for + // '_formatted_read' option). + scanfFormatter = LibraryOptionsPageOptions::ScanfMediumFormatter; + } + } + } + + PrintfFormatter printfFormatter = PrintfAutoFormatter; + ScanfFormatter scanfFormatter = ScanfAutoFormatter; +}; + +// Library configuration page options. + +struct LibraryConfigPageOptions final +{ + enum RuntimeLibrary { + NoLibrary, + NormalDlibLibrary, + CustomDlibLibrary, + ClibLibrary, + CustomClibLibrary + }; + + explicit LibraryConfigPageOptions(const QString &baseDirectory, + const ProductData &qbsProduct) + { + const auto &qbsProps = qbsProduct.moduleProperties(); + const QStringList flags = IarewUtils::cppModuleCompilerFlags(qbsProps); + + const QStringList libraryPaths = gen::utils::cppStringModuleProperties( + qbsProps, {QStringLiteral("staticLibraries")}); + const auto libraryBegin = libraryPaths.cbegin(); + const auto libraryEnd = libraryPaths.cend(); + + const QFileInfo dlibConfigInfo(IarewUtils::flagValue( + flags, QStringLiteral("--dlib_config"))); + const QString dlibConfigFilePath = dlibConfigInfo.absoluteFilePath(); + if (!dlibConfigFilePath.isEmpty()) { + const QString dlibToolkitPath = IarewUtils::dlibToolkitRootPath( + qbsProduct); + if (dlibConfigFilePath.startsWith(dlibToolkitPath, + Qt::CaseInsensitive)) { + libraryType = LibraryConfigPageOptions::NormalDlibLibrary; + configPath = IarewUtils::toolkitRelativeFilePath( + baseDirectory, dlibConfigFilePath); + + // Find dlib library inside of IAR toolkit directory. + const auto libraryIt = std::find_if(libraryBegin, libraryEnd, + [dlibToolkitPath]( + const QString &libraryPath) { + return libraryPath.startsWith(dlibToolkitPath); + }); + if (libraryIt != libraryEnd) { + // This means that dlib library is 'standard' (placed inside + // of IAR toolkit directory). + libraryPath = IarewUtils::toolkitRelativeFilePath( + baseDirectory, *libraryIt); + } + } else { + // This means that dlib library is 'custom' + // (but we don't know its path). + libraryType = LibraryConfigPageOptions::CustomDlibLibrary; + configPath = IarewUtils::projectRelativeFilePath( + baseDirectory, dlibConfigFilePath); + } + } else { + // Find clib library inside of IAR toolkit directory. + const QString clibToolkitPath = IarewUtils::clibToolkitRootPath( + qbsProduct); + const auto libraryIt = std::find_if(libraryBegin, libraryEnd, + [clibToolkitPath]( + const QString &libraryPath) { + return libraryPath.startsWith(clibToolkitPath); + }); + if (libraryIt != libraryEnd) { + // This means that clib library is 'standard' (placed inside + // of IAR toolkit directory). + libraryType = LibraryConfigPageOptions::ClibLibrary; + libraryPath = IarewUtils::toolkitRelativeFilePath( + baseDirectory, *libraryIt); + } else { + // This means that no any libraries are used . + libraryType = LibraryConfigPageOptions::NoLibrary; + } + } + } + + RuntimeLibrary libraryType = NoLibrary; + QString configPath; + QString libraryPath; +}; + +// Output page options. + +struct OutputPageOptions final +{ + explicit OutputPageOptions(const QString &baseDirectory, + const ProductData &qbsProduct) + { + binaryType = IarewUtils::outputBinaryType(qbsProduct); + binaryDirectory = gen::utils::binaryOutputDirectory( + baseDirectory, qbsProduct); + objectDirectory = gen::utils::objectsOutputDirectory( + baseDirectory, qbsProduct); + listingDirectory = gen::utils::listingOutputDirectory( + baseDirectory, qbsProduct); + } + + IarewUtils::OutputBinaryType binaryType = IarewUtils::ApplicationOutputType; + QString binaryDirectory; + QString objectDirectory; + QString listingDirectory; +}; + +} // namespace + +// Mcs51GeneralSettingsGroup + +Mcs51GeneralSettingsGroup::Mcs51GeneralSettingsGroup( + const Project &qbsProject, + const ProductData &qbsProduct, + const std::vector<ProductData> &qbsProductDeps) +{ + Q_UNUSED(qbsProject) + Q_UNUSED(qbsProductDeps) + + setName(QByteArrayLiteral("General")); + setArchiveVersion(kGeneralArchiveVersion); + setDataVersion(kGeneralDataVersion); + setDataDebugInfo(gen::utils::debugInformation(qbsProduct)); + + const QString buildRootDirectory = gen::utils::buildRootPath(qbsProject); + + buildTargetPage(qbsProduct); + buildStackHeapPage(qbsProduct); + buildDataPointerPage(qbsProduct); + buildCodeBankPage(qbsProduct); + buildLibraryOptionsPage(qbsProduct); + buildLibraryConfigPage(buildRootDirectory, qbsProduct); + buildOutputPage(buildRootDirectory, qbsProduct); +} + +void Mcs51GeneralSettingsGroup::buildTargetPage( + const ProductData &qbsProduct) +{ + const TargetPageOptions opts(qbsProduct); + // Add 'OGChipConfigPath' item (Device: <chip name>). + addOptionsGroup(QByteArrayLiteral("OGChipConfigPath"), + {opts.chipInfoPath}); + + // Add 'CPU Core' and 'CPU Core Slave' items + // (CPU core: plain/extended{1|2}). + addOptionsGroup(QByteArrayLiteral("CPU Core"), + {opts.cpuCore}); + addOptionsGroup(QByteArrayLiteral("CPU Core Slave"), + {opts.cpuCore}); + // Add 'Code Memory Model' and 'Code Memory Model slave' items + // (Code model: near/banked/far/banked extended). + addOptionsGroup(QByteArrayLiteral("Code Memory Model"), + {opts.codeModel}); + addOptionsGroup(QByteArrayLiteral("Code Memory Model slave"), + {opts.codeModel}); + // Add 'Data Memory Model' and 'Data Memory Model slave' items + // (Data model: tiny/small/large/generic/far). + addOptionsGroup(QByteArrayLiteral("Data Memory Model"), + {opts.dataModel}); + addOptionsGroup(QByteArrayLiteral("Data Memory Model slave"), + {opts.dataModel}); + // Add 'Use extended stack' and 'Use extended stack slave' items + // (Use extended stack). + addOptionsGroup(QByteArrayLiteral("Use extended stack"), + {opts.useExtendedStack}); + addOptionsGroup(QByteArrayLiteral("Use extended stack slave"), + {opts.useExtendedStack}); + // Add 'Workseg Size' item (Number of virtual registers: 8...32). + addOptionsGroup(QByteArrayLiteral("Workseg Size"), + {opts.virtualRegisters}); + // Add 'Constant Placement' item + // (Location of constants and strings: ram/rom/code memories). + addOptionsGroup(QByteArrayLiteral("Constant Placement"), + {opts.constPlacement}); + // Add 'Calling convention' item (Calling convention). + addOptionsGroup(QByteArrayLiteral("Calling convention"), + {opts.callingConvention}); +} + +void Mcs51GeneralSettingsGroup::buildStackHeapPage( + const ProductData &qbsProduct) +{ + const StackHeapPageOptions opts(qbsProduct); + // Add 'General Idata Stack Size' item (Stack size: IDATA). + addOptionsGroup(QByteArrayLiteral("General Idata Stack Size"), + {opts.idataStack}); + // Add 'General Pdata Stack Size' item (Stack size: PDATA). + addOptionsGroup(QByteArrayLiteral("General Pdata Stack Size"), + {opts.pdataStack}); + // Add 'General Xdata Stack Size' item (Stack size: XDATA). + addOptionsGroup(QByteArrayLiteral("General Xdata Stack Size"), + {opts.xdataStack}); + // Add 'General Ext Stack Size' item (Stack size: Extended). + addOptionsGroup(QByteArrayLiteral("General Ext Stack Size"), + {opts.extendedStack}); + + // Add 'General Xdata Heap Size' item (Heap size: XDATA). + addOptionsGroup(QByteArrayLiteral("General Xdata Heap Size"), + {opts.xdataHeap}); + // Add 'General Far Heap Size' item (Heap size: Far). + addOptionsGroup(QByteArrayLiteral("General Far Heap Size"), + {opts.farHeap}); + // Add 'General Far22 Heap Size' item (Heap size: Far22). + addOptionsGroup(QByteArrayLiteral("General Far22 Heap Size"), + {opts.far22Heap}); + // Add 'General Huge Heap Size' item (Heap size: Huge). + addOptionsGroup(QByteArrayLiteral("General Huge Heap Size"), + {opts.hugeHeap}); + + // Add 'Extended stack address' item + // (Extended stack pointer address). + addOptionsGroup(QByteArrayLiteral("Extended stack address"), + {opts.extStackAddress}); + // Add 'Extended stack mask' item (Extended stack pointer mask). + addOptionsGroup(QByteArrayLiteral("Extended stack mask"), + {opts.extStackMask}); + // Add 'Extended stack is offset' item + // (Extended stack pointer is an offset). + addOptionsGroup(QByteArrayLiteral("Extended stack is offset"), + {opts.extStackOffset}); +} + +void Mcs51GeneralSettingsGroup::buildDataPointerPage( + const ProductData &qbsProduct) +{ + const DptrPageOptions opts(qbsProduct); + // Add 'Nr of Datapointers' item (Number of DPTRs: 1...8). + addOptionsGroup(QByteArrayLiteral("Nr of Datapointers"), + {opts.dptrsCountIndex}); + // Add 'Datapointer Size' item (DPTR size: 16/24). + addOptionsGroup(QByteArrayLiteral("Datapointer Size"), + {opts.dptrSize}); + // Add 'Sfr Visibility' item (DPTR address: shadowed/separate). + addOptionsGroup(QByteArrayLiteral("Sfr Visibility"), + {opts.dptrVisibility}); + // Add 'Switch Method' item (Switch method: inc/mask). + addOptionsGroup(QByteArrayLiteral("Switch Method"), + {opts.dptrSwitchMethod}); + // Add 'Mask Value' item (Switch method mask). + addOptionsGroup(QByteArrayLiteral("Mask Value"), + {opts.dptrMask}); + // Add 'PDATA 8-15 register address' item (Page register + // address (for bits 8-15). + addOptionsGroup(QByteArrayLiteral("PDATA 8-15 register address"), + {opts.dptrPbank}); + // Add 'PDATA 16-31 register address' item (Page register + // address (for bits 16-31). + addOptionsGroup(QByteArrayLiteral("PDATA 16-31 register address"), + {opts.dptrPbankExt}); + // Add 'DPS Address' item (Selected DPTR register). + addOptionsGroup(QByteArrayLiteral("DPS Address"), + {opts.dpsAddress}); + // Add 'DPC Address' item (Separate DPTR control register). + addOptionsGroup(QByteArrayLiteral("DPC Address"), + {opts.dpcAddress}); + // Add 'DPTR Addresses' item (DPTR addresses: Low/High/Ext). + const QString dptrAddresses = opts.dptrAddresses.join(QLatin1Char(' ')); + addOptionsGroup(QByteArrayLiteral("DPTR Addresses"), + {dptrAddresses}); +} + +void Mcs51GeneralSettingsGroup::buildCodeBankPage( + const ProductData &qbsProduct) +{ + const CodeBankPageOptions opts(qbsProduct); + // Add 'CodeBankReg' item (Register address). + addOptionsGroup(QByteArrayLiteral("CodeBankReg"), + {opts.registerAddress}); + // Add 'CodeBankRegMask' item (Register mask). + addOptionsGroup(QByteArrayLiteral("CodeBankRegMask"), + {opts.registerMask}); + // Add 'CodeBankNrOfs' item (Number of banks). + addOptionsGroup(QByteArrayLiteral("CodeBankNrOfs"), + {opts.banksCount}); + // Add 'CodeBankStart' item (Bank start). + addOptionsGroup(QByteArrayLiteral("CodeBankStart"), + {opts.bankStart}); + // Add 'CodeBankSize' item (Bank end). + addOptionsGroup(QByteArrayLiteral("CodeBankSize"), + {opts.bankEnd}); +} + +void Mcs51GeneralSettingsGroup::buildLibraryOptionsPage( + const ProductData &qbsProduct) +{ + const LibraryOptionsPageOptions opts(qbsProduct); + // Add 'Output variant' item (Printf formatter). + addOptionsGroup(QByteArrayLiteral("Output variant"), + {opts.printfFormatter}); + // Add 'Input variant' item (Printf formatter). + addOptionsGroup(QByteArrayLiteral("Input variant"), + {opts.scanfFormatter}); +} + +void Mcs51GeneralSettingsGroup::buildLibraryConfigPage( + const QString &baseDirectory, + const ProductData &qbsProduct) +{ + const LibraryConfigPageOptions opts(baseDirectory, qbsProduct); + // Add 'GRuntimeLibSelect2' and 'GRuntimeLibSelectSlave2' items + // (Link with runtime: none/dlib/clib/etc). + addOptionsGroup(QByteArrayLiteral("GRuntimeLibSelect2"), + {opts.libraryType}); + addOptionsGroup(QByteArrayLiteral("GRuntimeLibSelectSlave2"), + {opts.libraryType}); + // Add 'RTConfigPath' item (Runtime configuration file). + addOptionsGroup(QByteArrayLiteral("RTConfigPath"), + {opts.configPath}); + // Add 'RTLibraryPath' item (Runtime library file). + addOptionsGroup(QByteArrayLiteral("RTLibraryPath"), + {opts.libraryPath}); +} + +void Mcs51GeneralSettingsGroup::buildOutputPage( + const QString &baseDirectory, + const ProductData &qbsProduct) +{ + const OutputPageOptions opts(baseDirectory, qbsProduct); + // Add 'GOutputBinary' item (Output file: executable/library). + addOptionsGroup(QByteArrayLiteral("GOutputBinary"), + {opts.binaryType}); + // Add 'ExePath' item (Executable/binaries output directory). + addOptionsGroup(QByteArrayLiteral("ExePath"), + {opts.binaryDirectory}); + // Add 'ObjPath' item (Object files output directory). + addOptionsGroup(QByteArrayLiteral("ObjPath"), + {opts.objectDirectory}); + // Add 'ListPath' item (List files output directory). + addOptionsGroup(QByteArrayLiteral("ListPath"), + {opts.listingDirectory}); +} + +} // namespace v10 +} // namespace mcs51 +} // namespace iarew +} // namespace qbs diff --git a/src/plugins/generator/iarew/archs/mcs51/mcs51generalsettingsgroup_v10.h b/src/plugins/generator/iarew/archs/mcs51/mcs51generalsettingsgroup_v10.h new file mode 100644 index 000000000..1805a87af --- /dev/null +++ b/src/plugins/generator/iarew/archs/mcs51/mcs51generalsettingsgroup_v10.h @@ -0,0 +1,66 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt.io/licensing +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef QBS_IAREWMCS51GENERALSETTINGSGROUP_V10_H +#define QBS_IAREWMCS51GENERALSETTINGSGROUP_V10_H + +#include "../../iarewsettingspropertygroup.h" + +namespace qbs { +namespace iarew { +namespace mcs51 { +namespace v10 { + +class Mcs51GeneralSettingsGroup final : public IarewSettingsPropertyGroup +{ +public: + explicit Mcs51GeneralSettingsGroup( + const Project &qbsProject, + const ProductData &qbsProduct, + const std::vector<ProductData> &qbsProductDeps); + +private: + void buildTargetPage(const ProductData &qbsProduct); + void buildStackHeapPage(const ProductData &qbsProduct); + void buildDataPointerPage(const ProductData &qbsProduct); + void buildCodeBankPage(const ProductData &qbsProduct); + void buildLibraryOptionsPage(const ProductData &qbsProduct); + void buildLibraryConfigPage(const QString &baseDirectory, + const ProductData &qbsProduct); + void buildOutputPage(const QString &baseDirectory, + const ProductData &qbsProduct); +}; + +} // namespace v10 +} // namespace mcs51 +} // namespace iarew +} // namespace qbs + +#endif // QBS_IAREWMCS51GENERALSETTINGSGROUP_V10_H diff --git a/src/plugins/generator/iarew/archs/mcs51/mcs51linkersettingsgroup_v10.cpp b/src/plugins/generator/iarew/archs/mcs51/mcs51linkersettingsgroup_v10.cpp new file mode 100644 index 000000000..32b734d4a --- /dev/null +++ b/src/plugins/generator/iarew/archs/mcs51/mcs51linkersettingsgroup_v10.cpp @@ -0,0 +1,336 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt.io/licensing +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "mcs51linkersettingsgroup_v10.h" + +#include "../../iarewutils.h" + +#include <QtCore/qdir.h> + +namespace qbs { +namespace iarew { +namespace mcs51 { +namespace v10 { + +constexpr int kLinkerArchiveVersion = 4; +constexpr int kLinkerDataVersion = 21; + +namespace { + +// Config page options. + +struct ConfigPageOptions final +{ + explicit ConfigPageOptions(const QString &baseDirectory, + const ProductData &qbsProduct) + { + const auto &qbsProps = qbsProduct.moduleProperties(); + const QString toolkitPath = IarewUtils::toolkitRootPath(qbsProduct); + + entryPoint = gen::utils::cppStringModuleProperty( + qbsProps, QStringLiteral("entryPoint")); + + // Enumerate all product linker config files + // (which are set trough 'linkerscript' tag). + const auto qbsGroups = qbsProduct.groups(); + for (const auto &qbsGroup : qbsGroups) { + const auto qbsArtifacts = qbsGroup.sourceArtifacts(); + for (const auto &qbsArtifact : qbsArtifacts) { + const auto qbsTags = qbsArtifact.fileTags(); + if (!qbsTags.contains(QLatin1String("linkerscript"))) + continue; + const QString fullConfigPath = qbsArtifact.filePath(); + if (fullConfigPath.startsWith(toolkitPath, Qt::CaseInsensitive)) { + const QString path = IarewUtils::toolkitRelativeFilePath( + toolkitPath, fullConfigPath); + configFilePaths.push_back(path); + } else { + const QString path = IarewUtils::projectRelativeFilePath( + baseDirectory, fullConfigPath); + configFilePaths.push_back(path); + } + } + } + + // Enumerate all product linker config files + // (which are set trough '-f' option). + const QStringList flags = IarewUtils::cppModuleLinkerFlags(qbsProps); + const QVariantList configPathValues = IarewUtils::flagValues( + flags, QStringLiteral("-f")); + for (const QVariant &configPathValue : configPathValues) { + const QString fullConfigPath = configPathValue.toString(); + if (fullConfigPath.startsWith(toolkitPath, Qt::CaseInsensitive)) { + const QString path = IarewUtils::toolkitRelativeFilePath( + toolkitPath, fullConfigPath); + if (!configFilePaths.contains(path)) + configFilePaths.push_back(path); + } else { + const QString path =IarewUtils::projectRelativeFilePath( + baseDirectory, fullConfigPath); + if (!configFilePaths.contains(path)) + configFilePaths.push_back(path); + } + } + + // Add libraries search paths. + const QStringList libraryPaths = gen::utils::cppStringModuleProperties( + qbsProps, {QStringLiteral("libraryPaths")}); + for (const QString &libraryPath : libraryPaths) { + const QFileInfo libraryPathInfo(libraryPath); + const QString fullLibrarySearchPath = libraryPathInfo.absoluteFilePath(); + if (fullLibrarySearchPath.startsWith(toolkitPath, + Qt::CaseInsensitive)) { + const QString path = IarewUtils::toolkitRelativeFilePath( + toolkitPath, fullLibrarySearchPath); + librarySearchPaths.push_back(path); + } else { + const QString path = IarewUtils::projectRelativeFilePath( + baseDirectory, fullLibrarySearchPath); + librarySearchPaths.push_back(path); + } + } + } + + QVariantList configFilePaths; + QVariantList librarySearchPaths; + QString entryPoint; +}; + +// Output page options. + +struct OutputPageOptions final +{ + explicit OutputPageOptions(const ProductData &qbsProduct) + { + outputFile = gen::utils::targetBinary(qbsProduct); + } + + QString outputFile; +}; + +// List page options. + +struct ListPageOptions final +{ + enum ListingAction { + NoListing, + GenerateListing + }; + + explicit ListPageOptions(const ProductData &qbsProduct) + { + const auto &qbsProps = qbsProduct.moduleProperties(); + generateMap = gen::utils::cppBooleanModuleProperty( + qbsProps, QStringLiteral("generateMapFile")) + ? ListPageOptions::GenerateListing + : ListPageOptions::NoListing; + } + + ListingAction generateMap = NoListing; +}; + +// Define page options. + +struct DefinePageOptions final +{ + explicit DefinePageOptions(const ProductData &qbsProduct) + { + const auto &qbsProps = qbsProduct.moduleProperties(); + const QStringList flags = IarewUtils::cppModuleLinkerFlags(qbsProps); + // Enumerate all linker defines. + for (const QString &flag : flags) { + if (!flag.startsWith(QLatin1String("-D"))) + continue; + const QString symbol = flag.mid(2); + // Ignore system-defined macroses, because its already + // handled in "General Options" page. + if (symbol.startsWith(QLatin1Char('?')) + || symbol.startsWith(QLatin1Char('_')) + ) { + continue; + } + defineSymbols.push_back(symbol); + } + } + + QVariantList defineSymbols; +}; + +// Diagnostics page options. + +struct DiagnosticsPageOptions final +{ + explicit DiagnosticsPageOptions(const ProductData &qbsProduct) + { + const auto &qbsProps = qbsProduct.moduleProperties(); + const QString warningLevel = gen::utils::cppStringModuleProperty( + qbsProps, QStringLiteral("warningLevel")); + suppressAllWarnings = (warningLevel == QLatin1String("none")); + } + + int suppressAllWarnings = 0; +}; + +} // namespace + +// Mcs51LinkerSettingsGroup + +Mcs51LinkerSettingsGroup::Mcs51LinkerSettingsGroup( + const Project &qbsProject, + const ProductData &qbsProduct, + const std::vector<ProductData> &qbsProductDeps) +{ + Q_UNUSED(qbsProject) + Q_UNUSED(qbsProductDeps) + + setName(QByteArrayLiteral("XLINK")); + setArchiveVersion(kLinkerArchiveVersion); + setDataVersion(kLinkerDataVersion); + setDataDebugInfo(gen::utils::debugInformation(qbsProduct)); + + const QString buildRootDirectory = gen::utils::buildRootPath(qbsProject); + + buildConfigPage(buildRootDirectory, qbsProduct); + buildOutputPage(qbsProduct); + buildListPage(qbsProduct); + buildDefinePage(qbsProduct); + buildDiagnosticsPage(qbsProduct); + + // Should be called as latest stage! + buildExtraOptionsPage(qbsProduct); +} + +void Mcs51LinkerSettingsGroup::buildConfigPage( + const QString &baseDirectory, + const ProductData &qbsProduct) +{ + ConfigPageOptions opts(baseDirectory, qbsProduct); + + if (opts.configFilePaths.count() > 0) { + // Note: IAR IDE does not allow to specify a multiple config files, + // although the IAR linker support it. So, we use followig 'trick': + // we take a first config file and to add it as usual to required items; + // and then an other remainders we forward to the "Extra options page". + const QVariant configPath = opts.configFilePaths.takeFirst(); + // Add 'XclOverride' item (Override default). + addOptionsGroup(QByteArrayLiteral("XclOverride"), + {1}); + // Add 'XclFile' item (Linke configuration file). + addOptionsGroup(QByteArrayLiteral("XclFile"), + {configPath}); + + // Add remainder configuration files to the "Extra options page". + if (!opts.configFilePaths.isEmpty()) { + for (QVariant &configPath : opts.configFilePaths) + configPath = QLatin1String("-f ") + configPath.toString(); + + m_extraOptions << opts.configFilePaths; + } + } + + // Add 'xcProgramEntryLabel' item (Entry symbol). + addOptionsGroup(QByteArrayLiteral("xcProgramEntryLabel"), + {opts.entryPoint}); + // Add 'xcOverrideProgramEntryLabel' item + // (Override default program entry). + addOptionsGroup(QByteArrayLiteral("xcOverrideProgramEntryLabel"), + {1}); + // Add 'xcProgramEntryLabelSelect' item. + addOptionsGroup(QByteArrayLiteral("xcProgramEntryLabelSelect"), + {0}); + + // Add 'XIncludes' item (Libraries search paths). + addOptionsGroup(QByteArrayLiteral("XIncludes"), + opts.librarySearchPaths); +} + +void Mcs51LinkerSettingsGroup::buildOutputPage( + const ProductData &qbsProduct) +{ + const OutputPageOptions opts(qbsProduct); + // Add 'XOutOverride' item (Override default output file). + addOptionsGroup(QByteArrayLiteral("XOutOverride"), + {1}); + // Add 'OutputFile' item (Output file name). + addOptionsGroup(QByteArrayLiteral("OutputFile"), + {opts.outputFile}); +} + +void Mcs51LinkerSettingsGroup::buildListPage( + const ProductData &qbsProduct) +{ + const ListPageOptions opts(qbsProduct); + // Add 'XList' item (Generate linker listing). + addOptionsGroup(QByteArrayLiteral("XList"), + {opts.generateMap}); +} + +void Mcs51LinkerSettingsGroup::buildDefinePage( + const ProductData &qbsProduct) +{ + const DefinePageOptions opts(qbsProduct); + // Add 'XDefines' item (Defined symbols). + addOptionsGroup(QByteArrayLiteral("XDefines"), + opts.defineSymbols); +} + +void Mcs51LinkerSettingsGroup::buildDiagnosticsPage( + const ProductData &qbsProduct) +{ + const DiagnosticsPageOptions opts(qbsProduct); + // Add 'SuppressAllWarn' item (Suppress all warnings). + addOptionsGroup(QByteArrayLiteral("SuppressAllWarn"), + {opts.suppressAllWarnings}); +} + +void Mcs51LinkerSettingsGroup::buildExtraOptionsPage( + const ProductData &qbsProduct) +{ + const auto &qbsProps = qbsProduct.moduleProperties(); + const QStringList flags = IarewUtils::cppModuleLinkerFlags(qbsProps); + for (const QString &flag : flags) { + if (flag.startsWith(QLatin1String("-Z"))) + m_extraOptions.push_back(flag); + } + + if (!m_extraOptions.isEmpty()) { + // Add 'Linker Extra Options Check' (Use command line options). + addOptionsGroup(QByteArrayLiteral("Linker Extra Options Check"), + {1}); + // Add 'Linker Extra Options Edit' item (Command line options). + addOptionsGroup(QByteArrayLiteral("Linker Extra Options Edit"), + m_extraOptions); + } +} + +} // namespace v10 +} // namespace mcs51 +} // namespace iarew +} // namespace qbs diff --git a/src/plugins/generator/iarew/archs/mcs51/mcs51linkersettingsgroup_v10.h b/src/plugins/generator/iarew/archs/mcs51/mcs51linkersettingsgroup_v10.h new file mode 100644 index 000000000..fec80e5e6 --- /dev/null +++ b/src/plugins/generator/iarew/archs/mcs51/mcs51linkersettingsgroup_v10.h @@ -0,0 +1,68 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt.io/licensing +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef QBS_IAREWMCS51LINKERSETTINGSGROUP_V10_H +#define QBS_IAREWMCS51LINKERSETTINGSGROUP_V10_H + +#include "../../iarewsettingspropertygroup.h" + +namespace qbs { +namespace iarew { +namespace mcs51 { +namespace v10 { + +class Mcs51LinkerSettingsGroupPrivate; + +class Mcs51LinkerSettingsGroup final : public IarewSettingsPropertyGroup +{ +public: + explicit Mcs51LinkerSettingsGroup( + const Project &qbsProject, + const ProductData &qbsProduct, + const std::vector<ProductData> &qbsProductDeps); + +private: + void buildConfigPage(const QString &baseDirectory, + const ProductData &qbsProduct); + void buildOutputPage(const ProductData &qbsProduct); + void buildListPage(const ProductData &qbsProduct); + void buildDefinePage(const ProductData &qbsProduct); + void buildDiagnosticsPage(const ProductData &qbsProduct); + void buildExtraOptionsPage(const ProductData &qbsProduct); + + QVariantList m_extraOptions; +}; + +} // namespace v10 +} // namespace mcs51 +} // namespace iarew +} // namespace qbs + +#endif // QBS_IAREWMCS51LINKERSETTINGSGROUP_V10_H diff --git a/src/plugins/generator/iarew/archs/msp430/msp430archiversettingsgroup_v7.cpp b/src/plugins/generator/iarew/archs/msp430/msp430archiversettingsgroup_v7.cpp new file mode 100644 index 000000000..1258412d8 --- /dev/null +++ b/src/plugins/generator/iarew/archs/msp430/msp430archiversettingsgroup_v7.cpp @@ -0,0 +1,94 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt.io/licensing +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "msp430archiversettingsgroup_v7.h" + +#include "../../iarewutils.h" + +namespace qbs { +namespace iarew { +namespace msp430 { +namespace v7 { + +constexpr int kArchiverArchiveVersion = 4; +constexpr int kArchiverDataVersion = 0; + +namespace { + +// Output page options. + +struct OutputPageOptions final +{ + explicit OutputPageOptions(const QString &baseDirectory, + const ProductData &qbsProduct) + { + outputFile = QLatin1String("$PROJ_DIR$/") + + gen::utils::targetBinaryPath(baseDirectory, qbsProduct); + } + + QString outputFile; +}; + +} // namespace + +//Msp430ArchiverSettingsGroup + +Msp430ArchiverSettingsGroup::Msp430ArchiverSettingsGroup( + const Project &qbsProject, + const ProductData &qbsProduct, + const std::vector<ProductData> &qbsProductDeps) +{ + Q_UNUSED(qbsProductDeps) + + setName(QByteArrayLiteral("XAR")); + setArchiveVersion(kArchiverArchiveVersion); + setDataVersion(kArchiverDataVersion); + setDataDebugInfo(gen::utils::debugInformation(qbsProduct)); + + const QString buildRootDirectory = gen::utils::buildRootPath(qbsProject); + buildOutputPage(buildRootDirectory, qbsProduct); +} + +void Msp430ArchiverSettingsGroup::buildOutputPage(const QString &baseDirectory, + const ProductData &qbsProduct) +{ + const OutputPageOptions opts(baseDirectory, qbsProduct); + // Add 'XAROutOverride' item (Override default). + addOptionsGroup(QByteArrayLiteral("XAROutOverride"), + {1}); + // Add 'OutputFile' item (Output filename). + addOptionsGroup(QByteArrayLiteral("OutputFile"), + {opts.outputFile}); +} + +} // namespace v7 +} // namespace msp430 +} // namespace iarew +} // namespace qbs diff --git a/src/plugins/generator/iarew/archs/msp430/msp430archiversettingsgroup_v7.h b/src/plugins/generator/iarew/archs/msp430/msp430archiversettingsgroup_v7.h new file mode 100644 index 000000000..9da8d3445 --- /dev/null +++ b/src/plugins/generator/iarew/archs/msp430/msp430archiversettingsgroup_v7.h @@ -0,0 +1,59 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt.io/licensing +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef QBS_IAREWMSP430ARCHIVERSETTINGSGROUP_V7_H +#define QBS_IAREWMSP430ARCHIVERSETTINGSGROUP_V7_H + +#include "../../iarewsettingspropertygroup.h" + +namespace qbs { +namespace iarew { +namespace msp430 { +namespace v7 { + +class Msp430ArchiverSettingsGroup final : public IarewSettingsPropertyGroup +{ +public: + explicit Msp430ArchiverSettingsGroup( + const Project &qbsProject, + const ProductData &qbsProduct, + const std::vector<ProductData> &qbsProductDeps); + +private: + void buildOutputPage(const QString &baseDirectory, + const ProductData &qbsProduct); +}; + +} // namespace v7 +} // namespace msp430 +} // namespace iarew +} // namespace qbs + +#endif // QBS_IAREWMSP430ARCHIVERSETTINGSGROUP_V7_H diff --git a/src/plugins/generator/iarew/archs/msp430/msp430assemblersettingsgroup_v7.cpp b/src/plugins/generator/iarew/archs/msp430/msp430assemblersettingsgroup_v7.cpp new file mode 100644 index 000000000..51108e63c --- /dev/null +++ b/src/plugins/generator/iarew/archs/msp430/msp430assemblersettingsgroup_v7.cpp @@ -0,0 +1,229 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt.io/licensing +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "msp430assemblersettingsgroup_v7.h" + +#include "../../iarewutils.h" + +namespace qbs { +namespace iarew { +namespace msp430 { +namespace v7 { + +constexpr int kAssemblerArchiveVersion = 5; +constexpr int kAssemblerDataVersion = 14; + +namespace { + +// Language page options. + +struct LanguagePageOptions final +{ + enum MacroQuoteCharacter { + AngleBracketsQuote, + RoundBracketsQuote, + SquareBracketsQuote, + FigureBracketsQuote + }; + + explicit LanguagePageOptions(const ProductData &qbsProduct) + { + const auto &qbsProps = qbsProduct.moduleProperties(); + const QStringList flags = gen::utils::cppStringModuleProperties( + qbsProps, {QStringLiteral("assemblerFlags")}); + enableSymbolsCaseSensitive = flags.contains( + QLatin1String("-s+")); + enableMultibyteSupport = flags.contains( + QLatin1String("-n")); + + if (flags.contains(QLatin1String("-M<>"))) + macroQuoteCharacter = LanguagePageOptions::AngleBracketsQuote; + else if (flags.contains(QLatin1String("-M()"))) + macroQuoteCharacter = LanguagePageOptions::RoundBracketsQuote; + else if (flags.contains(QLatin1String("-M[]"))) + macroQuoteCharacter = LanguagePageOptions::SquareBracketsQuote; + else if (flags.contains(QLatin1String("-M{}"))) + macroQuoteCharacter = LanguagePageOptions::FigureBracketsQuote; + } + + int enableSymbolsCaseSensitive = 1; + int enableMultibyteSupport = 0; + + MacroQuoteCharacter macroQuoteCharacter = AngleBracketsQuote; +}; + +// Output page options. + +struct OutputPageOptions final +{ + explicit OutputPageOptions(const ProductData &qbsProduct) + { + debugInfo = gen::utils::debugInformation(qbsProduct); + } + + int debugInfo = 0; +}; + +// Preprocessor page options. + +struct PreprocessorPageOptions final +{ + explicit PreprocessorPageOptions(const QString &baseDirectory, + const ProductData &qbsProduct) + { + const auto &qbsProps = qbsProduct.moduleProperties(); + defineSymbols = gen::utils::cppVariantModuleProperties( + qbsProps, {QStringLiteral("defines")}); + + const QString toolkitPath = IarewUtils::toolkitRootPath(qbsProduct); + const QStringList fullIncludePaths = gen::utils::cppStringModuleProperties( + qbsProps, {QStringLiteral("includePaths"), + QStringLiteral("systemIncludePaths")}); + for (const auto &fullIncludePath : fullIncludePaths) { + const QFileInfo includeFileInfo(fullIncludePath); + const QString includeFilePath = includeFileInfo.absoluteFilePath(); + if (includeFilePath.startsWith(toolkitPath, Qt::CaseInsensitive)) { + const QString path = IarewUtils::toolkitRelativeFilePath( + toolkitPath, includeFilePath); + includePaths.push_back(path); + } else { + const QString path = IarewUtils::projectRelativeFilePath( + baseDirectory, includeFilePath); + includePaths.push_back(path); + } + } + } + + QVariantList defineSymbols; + QVariantList includePaths; +}; + +// Diagnostics page options. + +struct DiagnosticsPageOptions final +{ + explicit DiagnosticsPageOptions(const ProductData &qbsProduct) + { + const auto &qbsProps = qbsProduct.moduleProperties(); + const QString warningLevel = gen::utils::cppStringModuleProperty( + qbsProps, QStringLiteral("warningLevel")); + if (warningLevel == QLatin1String("all")) { + enableWarnings = 0; + enableAllWarnings = 0; + } else if (warningLevel == QLatin1String("none")) { + enableWarnings = 1; + enableAllWarnings = 0; + } else { + enableWarnings = 0; + enableAllWarnings = 1; + } + } + + int enableWarnings = 0; + int enableAllWarnings = 0; +}; + +} // namespace + +//Msp430AssemblerSettingsGroup + +Msp430AssemblerSettingsGroup::Msp430AssemblerSettingsGroup( + const Project &qbsProject, + const ProductData &qbsProduct, + const std::vector<ProductData> &qbsProductDeps) +{ + Q_UNUSED(qbsProductDeps) + + setName(QByteArrayLiteral("A430")); + setArchiveVersion(kAssemblerArchiveVersion); + setDataVersion(kAssemblerDataVersion); + setDataDebugInfo(gen::utils::debugInformation(qbsProduct)); + + const QString buildRootDirectory = gen::utils::buildRootPath(qbsProject); + + buildLanguagePage(qbsProduct); + buildOutputPage(qbsProduct); + buildPreprocessorPage(buildRootDirectory, qbsProduct); + buildDiagnosticsPage(qbsProduct); +} + +void Msp430AssemblerSettingsGroup::buildLanguagePage( + const ProductData &qbsProduct) +{ + const LanguagePageOptions opts(qbsProduct); + // Add 'ACaseSensitivity' item (User symbols are case sensitive). + addOptionsGroup(QByteArrayLiteral("ACaseSensitivity"), + {opts.enableSymbolsCaseSensitive}); + // Add 'AMultibyteSupport' item (Enable multibyte support). + addOptionsGroup(QByteArrayLiteral("AMultibyteSupport"), + {opts.enableMultibyteSupport}); + // Add 'MacroChars' item (Macro quote characters: ()/[]/{}/<>). + addOptionsGroup(QByteArrayLiteral("MacroChars"), + {opts.macroQuoteCharacter}); +} + +void Msp430AssemblerSettingsGroup::buildOutputPage( + const ProductData &qbsProduct) +{ + const OutputPageOptions opts(qbsProduct); + // Add 'ADebug' item (Generate debug information). + addOptionsGroup(QByteArrayLiteral("ADebug"), + {opts.debugInfo}); +} + +void Msp430AssemblerSettingsGroup::buildPreprocessorPage( + const QString &baseDirectory, + const ProductData &qbsProduct) +{ + const PreprocessorPageOptions opts(baseDirectory, qbsProduct); + // Add 'ADefines' item (Defined symbols). + addOptionsGroup(QByteArrayLiteral("ADefines"), + opts.defineSymbols); + // Add 'AUserIncludes' item (Additional include directories). + addOptionsGroup(QByteArrayLiteral("AUserIncludes"), + opts.includePaths); +} + +void Msp430AssemblerSettingsGroup::buildDiagnosticsPage( + const ProductData &qbsProduct) +{ + const DiagnosticsPageOptions opts(qbsProduct); + // Add 'AWarnEnable' item (Enable/disable warnings). + addOptionsGroup(QByteArrayLiteral("AWarnEnable"), + {opts.enableWarnings}); + // Add 'AWarnWhat' item (Enable/disable all warnings). + addOptionsGroup(QByteArrayLiteral("AWarnWhat"), + {opts.enableAllWarnings}); +} + +} // namespace v7 +} // namespace msp430 +} // namespace iarew +} // namespace qbs diff --git a/src/plugins/generator/iarew/archs/msp430/msp430assemblersettingsgroup_v7.h b/src/plugins/generator/iarew/archs/msp430/msp430assemblersettingsgroup_v7.h new file mode 100644 index 000000000..97a59f4cd --- /dev/null +++ b/src/plugins/generator/iarew/archs/msp430/msp430assemblersettingsgroup_v7.h @@ -0,0 +1,62 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt.io/licensing +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef QBS_IAREWMSP430ASSEMBLERSETTINGSGROUP_V7_H +#define QBS_IAREWMSP430ASSEMBLERSETTINGSGROUP_V7_H + +#include "../../iarewsettingspropertygroup.h" + +namespace qbs { +namespace iarew { +namespace msp430 { +namespace v7 { + +class Msp430AssemblerSettingsGroup final : public IarewSettingsPropertyGroup +{ +public: + explicit Msp430AssemblerSettingsGroup( + const Project &qbsProject, + const ProductData &qbsProduct, + const std::vector<ProductData> &qbsProductDeps); + +private: + void buildLanguagePage(const ProductData &qbsProduct); + void buildOutputPage(const ProductData &qbsProduct); + void buildPreprocessorPage(const QString &baseDirectory, + const ProductData &qbsProduct); + void buildDiagnosticsPage(const ProductData &qbsProduct); +}; + +} // namespace v7 +} // namespace msp430 +} // namespace iarew +} // namespace qbs + +#endif // QBS_IAREWMSP430ASSEMBLERSETTINGSGROUP_V7_H diff --git a/src/plugins/generator/iarew/archs/msp430/msp430buildconfigurationgroup_v7.cpp b/src/plugins/generator/iarew/archs/msp430/msp430buildconfigurationgroup_v7.cpp new file mode 100644 index 000000000..bd80cdd7f --- /dev/null +++ b/src/plugins/generator/iarew/archs/msp430/msp430buildconfigurationgroup_v7.cpp @@ -0,0 +1,98 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt.io/licensing +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "msp430archiversettingsgroup_v7.h" +#include "msp430assemblersettingsgroup_v7.h" +#include "msp430buildconfigurationgroup_v7.h" +#include "msp430compilersettingsgroup_v7.h" +#include "msp430generalsettingsgroup_v7.h" +#include "msp430linkersettingsgroup_v7.h" + +#include "../../iarewtoolchainpropertygroup.h" +#include "../../iarewutils.h" + +namespace qbs { +namespace iarew { +namespace msp430 { +namespace v7 { + +Msp430BuildConfigurationGroup::Msp430BuildConfigurationGroup( + const Project &qbsProject, + const ProductData &qbsProduct, + const std::vector<ProductData> &qbsProductDeps) + : gen::xml::PropertyGroup("configuration") +{ + // Append configuration name item. + const QString cfgName = gen::utils::buildConfigurationName(qbsProject); + appendProperty("name", cfgName); + + // Apend toolchain name group item. + appendChild<IarewToolchainPropertyGroup>("MSP430"); + + // Append debug info item. + const int debugBuild = gen::utils::debugInformation(qbsProduct); + appendProperty("debug", debugBuild); + + // Append settings group items. + appendChild<Msp430ArchiverSettingsGroup>( + qbsProject, qbsProduct, qbsProductDeps); + appendChild<Msp430AssemblerSettingsGroup>( + qbsProject, qbsProduct, qbsProductDeps); + appendChild<Msp430CompilerSettingsGroup>( + qbsProject, qbsProduct, qbsProductDeps); + appendChild<Msp430GeneralSettingsGroup>( + qbsProject, qbsProduct, qbsProductDeps); + appendChild<Msp430LinkerSettingsGroup>( + qbsProject, qbsProduct, qbsProductDeps); +} + +bool Msp430BuildConfigurationGroupFactory::canCreate( + gen::utils::Architecture arch, + const Version &version) const +{ + return arch == gen::utils::Architecture::Msp430 + && version.majorVersion() == 7; +} + +std::unique_ptr<gen::xml::PropertyGroup> +Msp430BuildConfigurationGroupFactory::create( + const Project &qbsProject, + const ProductData &qbsProduct, + const std::vector<ProductData> &qbsProductDeps) const +{ + const auto group = new Msp430BuildConfigurationGroup( + qbsProject, qbsProduct, qbsProductDeps); + return std::unique_ptr<Msp430BuildConfigurationGroup>(group); +} + +} // namespace v7 +} // namespace msp430 +} // namespace iarew +} // namespace qbs diff --git a/src/plugins/generator/iarew/archs/msp430/msp430buildconfigurationgroup_v7.h b/src/plugins/generator/iarew/archs/msp430/msp430buildconfigurationgroup_v7.h new file mode 100644 index 000000000..ba0404c0b --- /dev/null +++ b/src/plugins/generator/iarew/archs/msp430/msp430buildconfigurationgroup_v7.h @@ -0,0 +1,72 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt.io/licensing +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef QBS_IAREWMSP430BUILDCONFIGURATIONGROUP_V7_H +#define QBS_IAREWMSP430BUILDCONFIGURATIONGROUP_V7_H + +#include <generators/generatorutils.h> +#include <generators/xmlpropertygroup.h> + +namespace qbs { +namespace iarew { +namespace msp430 { +namespace v7 { + +class Msp430BuildConfigurationGroup final + : public gen::xml::PropertyGroup +{ +private: + explicit Msp430BuildConfigurationGroup( + const Project &qbsProject, + const ProductData &qbsProduct, + const std::vector<ProductData> &qbsProductDeps); + + friend class Msp430BuildConfigurationGroupFactory; +}; + +class Msp430BuildConfigurationGroupFactory final + : public gen::xml::PropertyGroupFactory +{ +public: + bool canCreate(gen::utils::Architecture arch, + const Version &version) const final; + + std::unique_ptr<gen::xml::PropertyGroup> create( + const Project &qbsProject, + const ProductData &qbsProduct, + const std::vector<ProductData> &qbsProductDeps) const final; +}; + +} // namespace v7 +} // namespace msp430 +} // namespace iarew +} // namespace qbs + +#endif // QBS_IAREWMSP430BUILDCONFIGURATIONGROUP_V7_H diff --git a/src/plugins/generator/iarew/archs/msp430/msp430compilersettingsgroup_v7.cpp b/src/plugins/generator/iarew/archs/msp430/msp430compilersettingsgroup_v7.cpp new file mode 100644 index 000000000..5728578b9 --- /dev/null +++ b/src/plugins/generator/iarew/archs/msp430/msp430compilersettingsgroup_v7.cpp @@ -0,0 +1,486 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt.io/licensing +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "msp430compilersettingsgroup_v7.h" + +#include "../../iarewutils.h" + +namespace qbs { +namespace iarew { +namespace msp430 { +namespace v7 { + +constexpr int kCompilerArchiveVersion = 4; +constexpr int kCompilerDataVersion = 38; + +namespace { + +// Output page options. + +struct OutputPageOptions final +{ + explicit OutputPageOptions(const ProductData &qbsProduct) + { + debugInfo = gen::utils::debugInformation(qbsProduct); + } + + int debugInfo = 0; +}; + +// Language one page options. + +struct LanguageOnePageOptions final +{ + enum LanguageExtension { + CLanguageExtension, + CxxLanguageExtension, + AutoLanguageExtension + }; + + enum CLanguageDialect { + C89LanguageDialect, + C99LanguageDialect + }; + + enum CxxLanguageDialect { + EmbeddedCPlusPlus, + ExtendedEmbeddedCPlusPlus + }; + + enum LanguageConformance { + AllowIarExtension, + RelaxedStandard, + StrictStandard + }; + + explicit LanguageOnePageOptions(const ProductData &qbsProduct) + { + const auto &qbsProps = qbsProduct.moduleProperties(); + const QStringList flags = IarewUtils::cppModuleCompilerFlags(qbsProps); + // File extension based by default. + languageExtension = LanguageOnePageOptions::AutoLanguageExtension; + // C language dialect. + const QStringList cLanguageVersion = gen::utils::cppStringModuleProperties( + qbsProps, {QStringLiteral("cLanguageVersion")}); + if (cLanguageVersion.contains(QLatin1String("c89"))) + cLanguageDialect = LanguageOnePageOptions::C89LanguageDialect; + else if (cLanguageVersion.contains(QLatin1String("c99"))) + cLanguageDialect = LanguageOnePageOptions::C99LanguageDialect; + // C++ language dialect. + if (flags.contains(QLatin1String("--ec++"))) + cxxLanguageDialect = LanguageOnePageOptions::EmbeddedCPlusPlus; + else if (flags.contains(QLatin1String("--eec++"))) + cxxLanguageDialect = LanguageOnePageOptions::ExtendedEmbeddedCPlusPlus; + // Language conformance. + if (flags.contains(QLatin1String("-e"))) + languageConformance = LanguageOnePageOptions::AllowIarExtension; + else if (flags.contains(QLatin1String("--strict"))) + languageConformance = LanguageOnePageOptions::StrictStandard; + else + languageConformance = LanguageOnePageOptions::RelaxedStandard; + + allowVla = flags.contains(QLatin1String("--vla")); + useCppInlineSemantics = flags.contains( + QLatin1String("--use_c++_inline")); + requirePrototypes = flags.contains( + QLatin1String("--require_prototypes")); + destroyStaticObjects = !flags.contains( + QLatin1String("--no_static_destruction")); + } + + LanguageExtension languageExtension = AutoLanguageExtension; + CLanguageDialect cLanguageDialect = C99LanguageDialect; + CxxLanguageDialect cxxLanguageDialect = EmbeddedCPlusPlus; + LanguageConformance languageConformance = AllowIarExtension; + int allowVla = 0; + int useCppInlineSemantics = 0; + int requirePrototypes = 0; + int destroyStaticObjects = 0; +}; + +// Language two page options. + +struct LanguageTwoPageOptions final +{ + enum PlainCharacter { + SignedCharacter, + UnsignedCharacter + }; + + enum FloatingPointSemantic { + StrictSemantic, + RelaxedSemantic + }; + + explicit LanguageTwoPageOptions(const ProductData &qbsProduct) + { + const auto &qbsProps = qbsProduct.moduleProperties(); + const QStringList flags = IarewUtils::cppModuleCompilerFlags(qbsProps); + plainCharacter = flags.contains(QLatin1String("--char_is_signed")) + ? LanguageTwoPageOptions::SignedCharacter + : LanguageTwoPageOptions::UnsignedCharacter; + floatingPointSemantic = flags.contains(QLatin1String("--relaxed_fp")) + ? LanguageTwoPageOptions::RelaxedSemantic + : LanguageTwoPageOptions::StrictSemantic; + enableMultibyteSupport = flags.contains( + QLatin1String("--enable_multibytes")); + guardCalls = flags.contains( + QLatin1String("--guard_calls")); + } + + PlainCharacter plainCharacter = UnsignedCharacter; + FloatingPointSemantic floatingPointSemantic = StrictSemantic; + int enableMultibyteSupport = 0; + int guardCalls = 0; +}; + +// Code page options. + +struct CodePageOptions final +{ + enum Utilization { + UtilizationNormalUse, + UtilizationRegVarVariables, + UtilizationNotUsed + }; + + explicit CodePageOptions(const ProductData &qbsProduct) + { + const auto &qbsProps = qbsProduct.moduleProperties(); + const QStringList flags = IarewUtils::cppModuleCompilerFlags(qbsProps); + // Detect R4 utilization. + if (flags.contains(QLatin1String("--lock_r4"))) + r4utilization = UtilizationNotUsed; + else if (flags.contains(QLatin1String("--regvar_r4"))) + r4utilization = UtilizationRegVarVariables; + // Detect R5 utilization. + if (flags.contains(QLatin1String("--lock_r5"))) + r5utilization = UtilizationNotUsed; + else if (flags.contains(QLatin1String("--regvar_r54"))) + r5utilization = UtilizationRegVarVariables; + // Detect reduce stack usage. + reduceStackUsage = flags.contains( + QLatin1String("--reduce_stack_usage")); + // Detect 20-bit context save on interrupt. + save20BitContextOnInterrupt = flags.contains( + QLatin1String("--save_reg20")); + } + + Utilization r4utilization = UtilizationNormalUse; + Utilization r5utilization = UtilizationNormalUse; + int reduceStackUsage = 0; + int save20BitContextOnInterrupt = 0; +}; + +// Optimizations page options. + +struct OptimizationsPageOptions final +{ + // Optimizations level radio-buttons with + // combo-box on "level" widget. + enum Strategy { + StrategyBalanced, + StrategySize, + StrategySpeed + }; + + enum Level { + LevelNone, + LevelLow, + LevelMedium, + LevelHigh + }; + + enum LevelSlave { + LevelSlave0, + LevelSlave1, + LevelSlave2, + LevelSlave3 + }; + + explicit OptimizationsPageOptions(const ProductData &qbsProduct) + { + const auto &qbsProps = qbsProduct.moduleProperties(); + const QString optimization = gen::utils::cppStringModuleProperty( + qbsProps, QStringLiteral("optimization")); + if (optimization == QLatin1String("none")) { + optimizationStrategy = OptimizationsPageOptions::StrategyBalanced; + optimizationLevel = OptimizationsPageOptions::LevelNone; + optimizationLevelSlave = OptimizationsPageOptions::LevelSlave0; + } else if (optimization == QLatin1String("fast")) { + optimizationStrategy = OptimizationsPageOptions::StrategySpeed; + optimizationLevel = OptimizationsPageOptions::LevelHigh; + optimizationLevelSlave = OptimizationsPageOptions::LevelSlave3; + } else if (optimization == QLatin1String("small")) { + optimizationStrategy = OptimizationsPageOptions::StrategySize; + optimizationLevel = OptimizationsPageOptions::LevelHigh; + optimizationLevelSlave = OptimizationsPageOptions::LevelSlave3; + } + + const QStringList flags = IarewUtils::cppModuleCompilerFlags(qbsProps); + + disableSizeConstraints = flags.contains( + QLatin1String("--no_size_constraints")); + + enableCommonSubexpressionElimination = !flags.contains( + QLatin1String("--no_cse")); + enableLoopUnroll = !flags.contains(QLatin1String("--no_unroll")); + enableFunctionInlining = !flags.contains(QLatin1String("--no_inline")); + enableCodeMotion = !flags.contains(QLatin1String("--no_code_motion")); + enableTypeBasedAliasAnalysis = !flags.contains( + QLatin1String("--no_tbaa")); + } + + Strategy optimizationStrategy = StrategyBalanced; + Level optimizationLevel = LevelNone; + LevelSlave optimizationLevelSlave = LevelSlave0; + // Separate "no size constraints" checkbox. + int disableSizeConstraints = 0; + + // Five bit-field flags on "enabled transformations" widget. + int enableCommonSubexpressionElimination = 0; // Common sub-expression elimination. + int enableLoopUnroll = 0; // Loop unrolling. + int enableFunctionInlining = 0; // Function inlining. + int enableCodeMotion = 0; // Code motion. + int enableTypeBasedAliasAnalysis = 0; // Type based alias analysis. +}; + +// Preprocessor page options. + +struct PreprocessorPageOptions final +{ + explicit PreprocessorPageOptions(const QString &baseDirectory, + const ProductData &qbsProduct) + { + const auto &qbsProps = qbsProduct.moduleProperties(); + defineSymbols = gen::utils::cppVariantModuleProperties( + qbsProps, {QStringLiteral("defines")}); + + const QString toolkitPath = IarewUtils::toolkitRootPath(qbsProduct); + const QStringList fullIncludePaths = gen::utils::cppStringModuleProperties( + qbsProps, {QStringLiteral("includePaths"), + QStringLiteral("systemIncludePaths")}); + for (const QString &fullIncludePath : fullIncludePaths) { + const QFileInfo includeFileInfo(fullIncludePath); + const QString includeFilePath = includeFileInfo.absoluteFilePath(); + if (includeFilePath.startsWith(toolkitPath, Qt::CaseInsensitive)) { + const QString path = IarewUtils::toolkitRelativeFilePath( + toolkitPath, includeFilePath); + includePaths.push_back(path); + } else { + const QString path = IarewUtils::projectRelativeFilePath( + baseDirectory, includeFilePath); + includePaths.push_back(path); + } + } + } + + QVariantList defineSymbols; + QVariantList includePaths; +}; + +// Diagnostics page options. + +struct DiagnosticsPageOptions final +{ + explicit DiagnosticsPageOptions(const ProductData &qbsProduct) + { + const auto &qbsProps = qbsProduct.moduleProperties(); + warningsAsErrors = gen::utils::cppIntegerModuleProperty( + qbsProps, QStringLiteral("treatWarningsAsErrors")); + } + + int warningsAsErrors = 0; +}; + +} // namespace + +//Msp430CompilerSettingsGroup + +Msp430CompilerSettingsGroup::Msp430CompilerSettingsGroup( + const Project &qbsProject, + const ProductData &qbsProduct, + const std::vector<ProductData> &qbsProductDeps) +{ + Q_UNUSED(qbsProductDeps) + + setName(QByteArrayLiteral("ICC430")); + setArchiveVersion(kCompilerArchiveVersion); + setDataVersion(kCompilerDataVersion); + setDataDebugInfo(gen::utils::debugInformation(qbsProduct)); + + const QString buildRootDirectory = gen::utils::buildRootPath(qbsProject); + + buildOutputPage(qbsProduct); + buildLanguageOnePage(qbsProduct); + buildLanguageTwoPage(qbsProduct); + buildOptimizationsPage(qbsProduct); + buildPreprocessorPage(buildRootDirectory, qbsProduct); + buildDiagnosticsPage(qbsProduct); +} + +void Msp430CompilerSettingsGroup::buildOutputPage( + const ProductData &qbsProduct) +{ + const OutputPageOptions opts(qbsProduct); + // Add 'CCDebugInfo' item (Generate debug info). + addOptionsGroup(QByteArrayLiteral("CCDebugInfo"), + {opts.debugInfo}); +} + +void Msp430CompilerSettingsGroup::buildLanguageOnePage( + const ProductData &qbsProduct) +{ + const LanguageOnePageOptions opts(qbsProduct); + // Add 'IccLang' item with 'auto-extension based' + // value (Language: C/C++/Auto). + addOptionsGroup(QByteArrayLiteral("IccLang"), + {opts.languageExtension}); + // Add 'IccCDialect' item (C dialect: c89/99/11). + addOptionsGroup(QByteArrayLiteral("IccCDialect"), + {opts.cLanguageDialect}); + // Add 'IccCppDialect' item (C++ dialect: embedded/extended). + addOptionsGroup(QByteArrayLiteral("IccCppDialect"), + {opts.cxxLanguageDialect}); + // Add 'CCExt' item + // (Language conformance: IAR/relaxed/strict). + addOptionsGroup(QByteArrayLiteral("CCExt"), + {opts.languageConformance}); + // Add 'IccAllowVLA' item (Allow VLA). + addOptionsGroup(QByteArrayLiteral("IccAllowVLA"), + {opts.allowVla}); + // Add 'IccCppInlineSemantics' item (C++ inline semantics). + addOptionsGroup(QByteArrayLiteral("IccCppInlineSemantics"), + {opts.useCppInlineSemantics}); + // Add 'IccRequirePrototypes' item (Require prototypes). + addOptionsGroup(QByteArrayLiteral("CCRequirePrototypes"), + {opts.requirePrototypes}); + // Add 'IccStaticDestr' item (Destroy static objects). + addOptionsGroup(QByteArrayLiteral("IccStaticDestr"), + {opts.destroyStaticObjects}); +} + +void Msp430CompilerSettingsGroup::buildLanguageTwoPage( + const ProductData &qbsProduct) +{ + const LanguageTwoPageOptions opts(qbsProduct); + // Add 'IccCharIs' item (Plain char is: signed/unsigned). + addOptionsGroup(QByteArrayLiteral("CCCharIs"), + {opts.plainCharacter}); + // Add 'IccFloatSemantics' item (Floatic-point + // semantics: strict/relaxed conformance). + addOptionsGroup(QByteArrayLiteral("IccFloatSemantics"), + {opts.floatingPointSemantic}); + // Add 'IccMultibyteSupport' item (Enable multibyte support). + addOptionsGroup(QByteArrayLiteral("CCMultibyteSupport"), + {opts.enableMultibyteSupport}); + // Add 'CCGuardCalls' and 'OCGuardCallsSlave' item (Guard calls). + addOptionsGroup(QByteArrayLiteral("CCGuardCalls"), + {opts.guardCalls}); +} + +void Msp430CompilerSettingsGroup::buildCodePage( + const ProductData &qbsProduct) +{ + const CodePageOptions opts(qbsProduct); + // Add 'OCCR4Utilize' item + // (R4 utilization: normal/regvar/disabled). + addOptionsGroup(QByteArrayLiteral("OCCR4Utilize"), + {opts.r4utilization}); + // Add 'OCCR5Utilize' item + // (R5 utilization: normal/regvar/disabled). + addOptionsGroup(QByteArrayLiteral("OCCR5Utilize"), + {opts.r5utilization}); + // Add 'ReduceStack' item + // (Reduce stack usage). + addOptionsGroup(QByteArrayLiteral("ReduceStack"), + {opts.reduceStackUsage}); + // Add 'Save20bit' item + // (20-bit context save on interrupt). + addOptionsGroup(QByteArrayLiteral("Save20bit"), + {opts.save20BitContextOnInterrupt}); +} + +void Msp430CompilerSettingsGroup::buildOptimizationsPage( + const ProductData &qbsProduct) +{ + const OptimizationsPageOptions opts(qbsProduct); + // Add 'CCOptStrategy', 'CCOptLevel' and + // 'CCOptLevelSlave' items (Level). + addOptionsGroup(QByteArrayLiteral("CCOptStrategy"), + {opts.optimizationStrategy}); + addOptionsGroup(QByteArrayLiteral("CCOptLevel"), + {opts.optimizationLevel}); + addOptionsGroup(QByteArrayLiteral("CCOptLevelSlave"), + {opts.optimizationLevelSlave}); + + // Add 'CCOptimizationNoSizeConstraints' item (no size constraints). + addOptionsGroup(QByteArrayLiteral("CCOptimizationNoSizeConstraints"), + {opts.disableSizeConstraints}); + + // Add 'CCAllowList' item + // (Enabled transformations: 5 check boxes). + const QString bitflags = QStringLiteral("%1%2%3%4%5%6") + .arg(opts.enableCommonSubexpressionElimination) + .arg(opts.enableLoopUnroll) + .arg(opts.enableFunctionInlining) + .arg(opts.enableCodeMotion) + .arg(opts.enableTypeBasedAliasAnalysis); + addOptionsGroup(QByteArrayLiteral("CCAllowList"), + {bitflags}); +} + +void Msp430CompilerSettingsGroup::buildPreprocessorPage( + const QString &baseDirectory, + const ProductData &qbsProduct) +{ + const PreprocessorPageOptions opts(baseDirectory, qbsProduct); + // Add 'CCDefines' item (Defines symbols). + addOptionsGroup(QByteArrayLiteral("CCDefines"), + opts.defineSymbols); + // Add 'newCCIncludePaths' item + // (Additional include directories). + addOptionsGroup(QByteArrayLiteral("newCCIncludePaths"), + opts.includePaths); +} + +void Msp430CompilerSettingsGroup::buildDiagnosticsPage( + const ProductData &qbsProduct) +{ + const DiagnosticsPageOptions opts(qbsProduct); + // Add 'CCDiagWarnAreErr' item (Treat all warnings as errors). + addOptionsGroup(QByteArrayLiteral("CCDiagWarnAreErr"), + {opts.warningsAsErrors}); +} + +} // namespace v7 +} // namespace msp430 +} // namespace iarew +} // namespace qbs diff --git a/src/plugins/generator/iarew/archs/msp430/msp430compilersettingsgroup_v7.h b/src/plugins/generator/iarew/archs/msp430/msp430compilersettingsgroup_v7.h new file mode 100644 index 000000000..498100881 --- /dev/null +++ b/src/plugins/generator/iarew/archs/msp430/msp430compilersettingsgroup_v7.h @@ -0,0 +1,65 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt.io/licensing +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef QBS_IAREWMSP430COMPILERSETTINGSGROUP_V7_H +#define QBS_IAREWMSP430COMPILERSETTINGSGROUP_V7_H + +#include "../../iarewsettingspropertygroup.h" + +namespace qbs { +namespace iarew { +namespace msp430 { +namespace v7 { + +class Msp430CompilerSettingsGroup final : public IarewSettingsPropertyGroup +{ +public: + explicit Msp430CompilerSettingsGroup( + const Project &qbsProject, + const ProductData &qbsProduct, + const std::vector<ProductData> &qbsProductDeps); + +private: + void buildOutputPage(const ProductData &qbsProduct); + void buildLanguageOnePage(const ProductData &qbsProduct); + void buildLanguageTwoPage(const ProductData &qbsProduct); + void buildCodePage(const ProductData &qbsProduct); + void buildOptimizationsPage(const ProductData &qbsProduct); + void buildPreprocessorPage(const QString &baseDirectory, + const ProductData &qbsProduct); + void buildDiagnosticsPage(const ProductData &qbsProduct); +}; + +} // namespace v7 +} // namespace msp430 +} // namespace iarew +} // namespace qbs + +#endif // QBS_IAREWMSP430COMPILERSETTINGSGROUP_V7_H diff --git a/src/plugins/generator/iarew/archs/msp430/msp430generalsettingsgroup_v7.cpp b/src/plugins/generator/iarew/archs/msp430/msp430generalsettingsgroup_v7.cpp new file mode 100644 index 000000000..ac1c475d1 --- /dev/null +++ b/src/plugins/generator/iarew/archs/msp430/msp430generalsettingsgroup_v7.cpp @@ -0,0 +1,483 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt.io/licensing +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "msp430generalsettingsgroup_v7.h" + +#include "../../iarewutils.h" + +namespace qbs { +namespace iarew { +namespace msp430 { +namespace v7 { + +constexpr int kGeneralArchiveVersion = 21; +constexpr int kGeneralDataVersion = 34; + +namespace { + +// Target page options. + +struct TargetPageOptions final +{ + enum CodeModel { + SmallCodeModel, + LargeCodeModel + }; + + enum DataModel { + SmallDataModel, + MediumDataModel, + LargeDataModel + }; + + enum FloatingPointDoubleSize { + DoubleSize32Bits, + DoubleSize64Bits + }; + + enum HardwareMultiplierType { + AllowDirectAccessMultiplier, + UseOnlyLibraryCallsMultiplier + }; + + explicit TargetPageOptions(const ProductData &qbsProduct) + { + const auto &qbsProps = qbsProduct.moduleProperties(); + const QStringList flags = gen::utils::cppStringModuleProperties( + qbsProps, {QStringLiteral("driverFlags")}); + // Detect target code model. + const QString codeModelValue = IarewUtils::flagValue( + flags, QStringLiteral("--code_model")); + if (codeModelValue == QLatin1String("small")) + codeModel = TargetPageOptions::SmallCodeModel; + else if (codeModelValue == QLatin1String("large")) + codeModel = TargetPageOptions::LargeCodeModel; + // Detect target data model. + const QString dataModelValue = IarewUtils::flagValue( + flags, QStringLiteral("--data_model")); + if (dataModelValue == QLatin1String("small")) + dataModel = TargetPageOptions::SmallDataModel; + else if (dataModelValue == QLatin1String("medium")) + dataModel = TargetPageOptions::MediumDataModel; + else if (dataModelValue == QLatin1String("large")) + dataModel = TargetPageOptions::LargeDataModel; + // Detect floating point double size. + const int doubleSize = IarewUtils::flagValue( + flags, QStringLiteral("--double")).toInt(); + if (doubleSize == 32) + floatingPointDoubleSize = DoubleSize32Bits; + else if (doubleSize == 64) + floatingPointDoubleSize = DoubleSize64Bits; + // Detect hardware multiplier. + const QString multiplier = IarewUtils::flagValue( + flags, QStringLiteral("--multiplier")); + enableHardwareMultiplier = (multiplier.compare(QLatin1String("16")) == 0 + || multiplier.compare(QLatin1String("16s")) == 0 + || multiplier.compare(QLatin1String("32")) == 0); + // Detect code and read-only data position-independence. + enableRopi = flags.contains(QLatin1String("--ropi")); + // No dynamic read-write initialization. + disableDynamicReadWriteInitialization = flags.contains( + QLatin1String("--no_rw_dynamic_init")); + + // Detect target device name. + detectDeviceMenu(qbsProduct); + } + + void detectDeviceMenu(const ProductData &qbsProduct) + { + const QString toolkitPath = IarewUtils::toolkitRootPath(qbsProduct); + + // Enumerate all product linker config files + // (which are set trough 'linkerscript' tag). + const auto qbsGroups = qbsProduct.groups(); + for (const auto &qbsGroup : qbsGroups) { + const auto qbsArtifacts = qbsGroup.sourceArtifacts(); + for (const auto &qbsArtifact : qbsArtifacts) { + const auto qbsTags = qbsArtifact.fileTags(); + if (!qbsTags.contains(QLatin1String("linkerscript"))) + continue; + const QString fullConfigPath = qbsArtifact.filePath(); + if (!fullConfigPath.startsWith(toolkitPath, Qt::CaseInsensitive)) + continue; + + const QFileInfo configInfo(fullConfigPath); + const QString configBase = configInfo.baseName(); + if (!configBase.startsWith(QLatin1String("lnk"))) + continue; + + // Remove 'lnk' prefix. + const QString deviceName = QStringLiteral("MSP%1") + .arg(configBase.mid(3).toUpper()); + + deviceMenu = QStringLiteral("%1\t%1").arg(deviceName); + return; + } + } + + // Falling back to generic menu. + if (deviceMenu.isEmpty()) { + const auto &qbsProps = qbsProduct.moduleProperties(); + const QStringList flags = IarewUtils::cppModuleCompilerFlags(qbsProps); + const QString cpuCore = IarewUtils::flagValue(flags, QStringLiteral("--core")); + if (cpuCore.isEmpty()) + return; + deviceMenu = QStringLiteral("MSP%1\tGeneric MSP%1 device").arg(cpuCore); + return; + } + } + + CodeModel codeModel = LargeCodeModel; + DataModel dataModel = SmallDataModel; + FloatingPointDoubleSize floatingPointDoubleSize = DoubleSize32Bits; + HardwareMultiplierType hardwareMultiplierType = AllowDirectAccessMultiplier; + int enableHardwareMultiplier = 0; + int enableRopi = 0; + int disableDynamicReadWriteInitialization = 0; + QString deviceMenu; +}; + +// Output page options. + +struct OutputPageOptions final +{ + explicit OutputPageOptions(const QString &baseDirectory, + const ProductData &qbsProduct) + { + binaryType = IarewUtils::outputBinaryType(qbsProduct); + binaryDirectory = gen::utils::binaryOutputDirectory( + baseDirectory, qbsProduct); + objectDirectory = gen::utils::objectsOutputDirectory( + baseDirectory, qbsProduct); + listingDirectory = gen::utils::listingOutputDirectory( + baseDirectory, qbsProduct); + } + + IarewUtils::OutputBinaryType binaryType = IarewUtils::ApplicationOutputType; + QString binaryDirectory; + QString objectDirectory; + QString listingDirectory; +}; + +// Library configuration page options. + +struct LibraryConfigPageOptions final +{ + enum RuntimeLibrary { + NoLibrary, + NormalDLibrary, + FullDLibrary, + CustomDLibrary, + CLibrary, // deprecated + CustomCLibrary, // deprecated + }; + + explicit LibraryConfigPageOptions(const QString &baseDirectory, + const ProductData &qbsProduct) + { + const auto &qbsProps = qbsProduct.moduleProperties(); + const QStringList flags = IarewUtils::cppModuleCompilerFlags(qbsProps); + + const QFileInfo configInfo(IarewUtils::flagValue( + flags, + QStringLiteral("--dlib_config"))); + const QString configFilePath = configInfo.absoluteFilePath(); + + if (!configFilePath.isEmpty()) { + const QString libToolkitPath = + IarewUtils::libToolkitRootPath(qbsProduct); + + if (configFilePath.startsWith(libToolkitPath, + Qt::CaseInsensitive)) { + if (configFilePath.endsWith(QLatin1String("n.h"), + Qt::CaseInsensitive)) { + libraryType = LibraryConfigPageOptions::NormalDLibrary; + } else if (configFilePath.endsWith(QLatin1String("f.h"), + Qt::CaseInsensitive)) { + libraryType = LibraryConfigPageOptions::FullDLibrary; + } else { + libraryType = LibraryConfigPageOptions::CustomDLibrary; + } + + configPath = IarewUtils::toolkitRelativeFilePath( + baseDirectory, configFilePath); + } else { + libraryType = LibraryConfigPageOptions::CustomDLibrary; + + configPath = configFilePath; + } + } + } + + RuntimeLibrary libraryType = NormalDLibrary; + QString libraryPath; + QString configPath; +}; + +// Library options page options. + +struct LibraryOptionsPageOptions final +{ + enum PrintfFormatter { + PrintfAutoFormatter = 0, + PrintfFullFormatter = 1, + PrintfFullNoMultibytesFormatter = 2, + PrintfLargeFormatter = 3, + PrintfLargeNoMultibytesFormatter = 4, + PrintfSmallFormatter = 5, + PrintfSmallNoMultibytesFormatter = 6, + PrintfTinyFormatter = 7 + }; + + enum ScanfFormatter { + ScanfAutoFormatter = 0, + ScanfFullFormatter = 1, + ScanfFullNoMultibytesFormatter = 2, + ScanfLargeFormatter = 3, + ScanfLargeNoMultibytesFormatter = 4, + ScanfSmallFormatter = 5, + ScanfSmallNoMultibytesFormatter = 6 + }; + + explicit LibraryOptionsPageOptions(const ProductData &qbsProduct) + { + const auto &qbsProps = qbsProduct.moduleProperties(); + const QStringList flags = IarewUtils::cppModuleLinkerFlags(qbsProps); + for (auto flagIt = flags.cbegin(); flagIt < flags.cend(); ++flagIt) { + if (flagIt->endsWith(QLatin1String("=_printf"), + Qt::CaseInsensitive)) { + const QString prop = flagIt->split( + QLatin1Char('=')).at(0).toLower(); + if (prop == QLatin1String("_printffull")) + printfFormatter = PrintfFullFormatter; + else if (prop == QLatin1String("_printffullnomb")) + printfFormatter = PrintfFullNoMultibytesFormatter; + else if (prop == QLatin1String("_printflarge")) + printfFormatter = PrintfLargeFormatter; + else if (prop == QLatin1String("_printflargenomb")) + printfFormatter = PrintfLargeFormatter; + else if (prop == QLatin1String("_printfsmall")) + printfFormatter = PrintfSmallFormatter; + else if (prop == QLatin1String("_printfsmallnomb")) + printfFormatter = PrintfSmallNoMultibytesFormatter; + else if (prop == QLatin1String("_printftiny")) + printfFormatter = PrintfTinyFormatter; + } else if (flagIt->endsWith(QLatin1String("=_scanf"), + Qt::CaseInsensitive)) { + const QString prop = flagIt->split( + QLatin1Char('=')).at(0).toLower(); + if (prop == QLatin1String("_scanffull")) + scanfFormatter = ScanfFullFormatter; + else if (prop == QLatin1String("_scanffullnomb")) + scanfFormatter = ScanfFullNoMultibytesFormatter; + else if (prop == QLatin1String("_scanflarge")) + scanfFormatter = ScanfLargeFormatter; + else if (prop == QLatin1String("_scanflargenomb")) + scanfFormatter = ScanfLargeFormatter; + else if (prop == QLatin1String("_scanfsmall")) + scanfFormatter = ScanfSmallFormatter; + else if (prop == QLatin1String("_scanfsmallnomb")) + scanfFormatter = ScanfSmallNoMultibytesFormatter; + } + } + } + + PrintfFormatter printfFormatter = PrintfAutoFormatter; + ScanfFormatter scanfFormatter = ScanfAutoFormatter; +}; + +// Stack/heap page options. + +struct StackHeapPageOptions final +{ + explicit StackHeapPageOptions(const ProductData &qbsProduct) + { + const auto &qbsProps = qbsProduct.moduleProperties(); + const QStringList flags = IarewUtils::cppModuleLinkerFlags(qbsProps); + + // Detect stack size. + stackSize = IarewUtils::flagValue( + flags, QStringLiteral("-D_STACK_SIZE")); + if (stackSize.isEmpty()) + stackSize = QLatin1String("A0"); + // Detect data heap16 size. + data16HeapSize = IarewUtils::flagValue( + flags, QStringLiteral("-D_DATA16_HEAP_SIZE")); + if (data16HeapSize.isEmpty()) + stackSize = QLatin1String("A0"); + // Detect data heap20 size. + data20HeapSize = IarewUtils::flagValue( + flags, QStringLiteral("-D_DATA20_HEAP_SIZE")); + if (data20HeapSize.isEmpty()) + stackSize = QLatin1String("50"); + } + + QString stackSize; + QString data16HeapSize; + QString data20HeapSize; +}; + +} // namespace + +//Msp430GeneralSettingsGroup + +Msp430GeneralSettingsGroup::Msp430GeneralSettingsGroup( + const Project &qbsProject, + const ProductData &qbsProduct, + const std::vector<ProductData> &qbsProductDeps) +{ + Q_UNUSED(qbsProductDeps) + + setName(QByteArrayLiteral("General")); + setArchiveVersion(kGeneralArchiveVersion); + setDataVersion(kGeneralDataVersion); + setDataDebugInfo(gen::utils::debugInformation(qbsProduct)); + + const QString buildRootDirectory = gen::utils::buildRootPath(qbsProject); + + buildTargetPage(qbsProduct); + buildOutputPage(buildRootDirectory, qbsProduct); + buildLibraryConfigPage(buildRootDirectory, qbsProduct); + buildLibraryOptionsPage(qbsProduct); + buildStackHeapPage(qbsProduct); +} + +void Msp430GeneralSettingsGroup::buildTargetPage( + const ProductData &qbsProduct) +{ + const TargetPageOptions opts(qbsProduct); + // Add 'OGChipSelectMenu' item + // (Device: xxx). + addOptionsGroup(QByteArrayLiteral("OGChipSelectMenu"), + {opts.deviceMenu}); + + // Add 'RadioCodeModelType' item + // (Code model: small/large). + addOptionsGroup(QByteArrayLiteral("RadioCodeModelType"), + {opts.codeModel}); + // Add 'RadioDataModelType' item + // (Data model: small/medium/large). + addOptionsGroup(QByteArrayLiteral("RadioDataModelType"), + {opts.dataModel}); + // Add 'OGDouble' item + // (Floating point double size: 32/64 bits). + addOptionsGroup(QByteArrayLiteral("OGDouble"), + {opts.floatingPointDoubleSize}); + // Add 'Hardware Multiplier' item + // (Hardware multiplier). + addOptionsGroup(QByteArrayLiteral("Hardware Multiplier"), + {opts.enableHardwareMultiplier}); + if (opts.enableHardwareMultiplier) { + // Add 'RadioHardwareMultiplierType' item. + addOptionsGroup(QByteArrayLiteral("Hardware RadioHardwareMultiplierType"), + {opts.hardwareMultiplierType}); + } + // Add 'Ropi' item. + // (Position independence: Code and read-only data). + addOptionsGroup(QByteArrayLiteral("Ropi"), + {opts.enableRopi}); + // Add 'NoRwDynamicInit' item. + // (Position independence: No dynamic read/write initialization). + addOptionsGroup(QByteArrayLiteral("NoRwDynamicInit"), + {opts.disableDynamicReadWriteInitialization}); +} + +void Msp430GeneralSettingsGroup::buildOutputPage( + const QString &baseDirectory, + const ProductData &qbsProduct) +{ + const OutputPageOptions opts(baseDirectory, qbsProduct); + // Add 'GOutputBinary' item (Output file: executable/library). + addOptionsGroup(QByteArrayLiteral("GOutputBinary"), + {opts.binaryType}); + // Add 'ExePath' item (Executable/binaries output directory). + addOptionsGroup(QByteArrayLiteral("ExePath"), + {opts.binaryDirectory}); + // Add 'ObjPath' item (Object files output directory). + addOptionsGroup(QByteArrayLiteral("ObjPath"), + {opts.objectDirectory}); + // Add 'ListPath' item (List files output directory). + addOptionsGroup(QByteArrayLiteral("ListPath"), + {opts.listingDirectory}); +} + +void Msp430GeneralSettingsGroup::buildLibraryConfigPage( + const QString &baseDirectory, + const ProductData &qbsProduct) +{ + const LibraryConfigPageOptions opts(baseDirectory, qbsProduct); + // Add 'GRuntimeLibSelect' and 'GRuntimeLibSelectSlave' items + // (Link with runtime: none/normal/full/custom). + addOptionsGroup(QByteArrayLiteral("GRuntimeLibSelect"), + {opts.libraryType}); + addOptionsGroup(QByteArrayLiteral("GRuntimeLibSelectSlave"), + {opts.libraryType}); + // Add 'RTConfigPath' item (Runtime configuration file). + addOptionsGroup(QByteArrayLiteral("RTConfigPath"), + {opts.configPath}); + // Add 'RTLibraryPath' item (Runtime library file). + addOptionsGroup(QByteArrayLiteral("RTLibraryPath"), + {opts.libraryPath}); +} + +void Msp430GeneralSettingsGroup::buildLibraryOptionsPage( + const ProductData &qbsProduct) +{ + const LibraryOptionsPageOptions opts(qbsProduct); + // Add 'Output variant' item (Printf formatter). + addOptionsGroup(QByteArrayLiteral("Output variant"), + {opts.printfFormatter}); + // Add 'Input variant' item (Scanf formatter). + addOptionsGroup(QByteArrayLiteral("Input variant"), + {opts.scanfFormatter}); +} + +void Msp430GeneralSettingsGroup::buildStackHeapPage( + const ProductData &qbsProduct) +{ + const StackHeapPageOptions opts(qbsProduct); + // Add 'GStackHeapOverride' item (Override default). + addOptionsGroup(QByteArrayLiteral("GStackHeapOverride"), + {1}); + // Add 'GStackSize2' item (Stack size). + addOptionsGroup(QByteArrayLiteral("GStackSize2"), + {opts.stackSize}); + // Add 'GHeapSize2' item (Heap16 size). + addOptionsGroup(QByteArrayLiteral("GHeapSize2"), + {opts.data16HeapSize}); + // Add 'GHeap20Size' item (Heap16 size). + addOptionsGroup(QByteArrayLiteral("GHeap20Size"), + {opts.data20HeapSize}); +} + +} // namespace v7 +} // namespace msp430 +} // namespace iarew +} // namespace qbs diff --git a/src/plugins/generator/iarew/archs/msp430/msp430generalsettingsgroup_v7.h b/src/plugins/generator/iarew/archs/msp430/msp430generalsettingsgroup_v7.h new file mode 100644 index 000000000..35e9e7b32 --- /dev/null +++ b/src/plugins/generator/iarew/archs/msp430/msp430generalsettingsgroup_v7.h @@ -0,0 +1,64 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt.io/licensing +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef QBS_IAREWMSP430GENERALSETTINGSGROUP_V7_H +#define QBS_IAREWMSP430GENERALSETTINGSGROUP_V7_H + +#include "../../iarewsettingspropertygroup.h" + +namespace qbs { +namespace iarew { +namespace msp430 { +namespace v7 { + +class Msp430GeneralSettingsGroup final : public IarewSettingsPropertyGroup +{ +public: + explicit Msp430GeneralSettingsGroup( + const Project &qbsProject, + const ProductData &qbsProduct, + const std::vector<ProductData> &qbsProductDeps); + +private: + void buildTargetPage(const ProductData &qbsProduct); + void buildOutputPage(const QString &baseDirectory, + const ProductData &qbsProduct); + void buildLibraryConfigPage(const QString &baseDirectory, + const ProductData &qbsProduct); + void buildLibraryOptionsPage(const ProductData &qbsProduct); + void buildStackHeapPage(const ProductData &qbsProduct); +}; + +} // namespace v7 +} // namespace msp430 +} // namespace iarew +} // namespace qbs + +#endif // QBS_IAREWMSP430GENERALSETTINGSGROUP_V7_H diff --git a/src/plugins/generator/iarew/archs/msp430/msp430linkersettingsgroup_v7.cpp b/src/plugins/generator/iarew/archs/msp430/msp430linkersettingsgroup_v7.cpp new file mode 100644 index 000000000..c7459dc49 --- /dev/null +++ b/src/plugins/generator/iarew/archs/msp430/msp430linkersettingsgroup_v7.cpp @@ -0,0 +1,290 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt.io/licensing +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "msp430linkersettingsgroup_v7.h" + +#include "../../iarewutils.h" + +#include <QtCore/qdir.h> + +namespace qbs { +namespace iarew { +namespace msp430 { +namespace v7 { + +constexpr int kLinkerArchiveVersion = 4; +constexpr int kLinkerDataVersion = 30; + +namespace { + +// Config page options. + +struct ConfigPageOptions final +{ + explicit ConfigPageOptions(const QString &baseDirectory, + const ProductData &qbsProduct) + { + const auto &qbsProps = qbsProduct.moduleProperties(); + const QString toolkitPath = IarewUtils::toolkitRootPath(qbsProduct); + + // Enumerate all product linker config files + // (which are set trough 'linkerscript' tag). + const auto qbsGroups = qbsProduct.groups(); + for (const auto &qbsGroup : qbsGroups) { + const auto qbsArtifacts = qbsGroup.sourceArtifacts(); + for (const auto &qbsArtifact : qbsArtifacts) { + const auto qbsTags = qbsArtifact.fileTags(); + if (!qbsTags.contains(QLatin1String("linkerscript"))) + continue; + const QString fullConfigPath = qbsArtifact.filePath(); + if (fullConfigPath.startsWith(toolkitPath, Qt::CaseInsensitive)) { + const QString path = IarewUtils::toolkitRelativeFilePath( + toolkitPath, fullConfigPath); + configFilePaths.push_back(path); + } else { + const QString path = IarewUtils::projectRelativeFilePath( + baseDirectory, fullConfigPath); + configFilePaths.push_back(path); + } + } + } + + // Enumerate all product linker config files + // (which are set trough '-f' option). + const QStringList flags = IarewUtils::cppModuleLinkerFlags(qbsProps); + const QVariantList configPathValues = IarewUtils::flagValues( + flags, QStringLiteral("-f")); + for (const QVariant &configPathValue : configPathValues) { + const QString fullConfigPath = configPathValue.toString(); + if (fullConfigPath.startsWith(toolkitPath, Qt::CaseInsensitive)) { + const QString path = IarewUtils::toolkitRelativeFilePath( + toolkitPath, fullConfigPath); + if (!configFilePaths.contains(path)) + configFilePaths.push_back(path); + } else { + const QString path = IarewUtils::projectRelativeFilePath( + baseDirectory, fullConfigPath); + if (!configFilePaths.contains(path)) + configFilePaths.push_back(path); + } + } + + // Library search paths. + librarySearchPaths = gen::utils::cppVariantModuleProperties( + qbsProps, {QStringLiteral("libraryPaths")}); + + // Entry point. + entryPoint = gen::utils::cppStringModuleProperty( + qbsProps, QStringLiteral("entryPoint")); + } + + QVariantList configFilePaths; + QVariantList librarySearchPaths; + QString entryPoint; +}; + +// Output page options. + +struct OutputPageOptions final +{ + explicit OutputPageOptions(const ProductData &qbsProduct) + { + outputFile = gen::utils::targetBinary(qbsProduct); + } + + QString outputFile; +}; + +// List page options. + +struct ListPageOptions final +{ + enum ListingAction { + NoListing, + GenerateListing + }; + + explicit ListPageOptions(const ProductData &qbsProduct) + { + const auto &qbsProps = qbsProduct.moduleProperties(); + generateMap = gen::utils::cppBooleanModuleProperty( + qbsProps, QStringLiteral("generateMapFile")) + ? ListPageOptions::GenerateListing + : ListPageOptions::NoListing; + } + + ListingAction generateMap = NoListing; +}; + +// Define page options. + +struct DefinePageOptions final +{ + explicit DefinePageOptions(const ProductData &qbsProduct) + { + const auto &qbsProps = qbsProduct.moduleProperties(); + const QStringList flags = IarewUtils::cppModuleLinkerFlags(qbsProps); + // Enumerate all linker defines. + for (const QString &flag : flags) { + if (!flag.startsWith(QLatin1String("-D"))) + continue; + const QString symbol = flag.mid(2); + // Ignore system-defined macroses, because its already + // handled in "General Options" page. + if (symbol.startsWith(QLatin1Char('?')) + || symbol.startsWith(QLatin1Char('_')) + ) { + continue; + } + defineSymbols.push_back(symbol); + } + } + + QVariantList defineSymbols; +}; + +} // namespace + +//Msp430LinkerSettingsGroup + +Msp430LinkerSettingsGroup::Msp430LinkerSettingsGroup( + const Project &qbsProject, + const ProductData &qbsProduct, + const std::vector<ProductData> &qbsProductDeps) +{ + Q_UNUSED(qbsProductDeps) + setName(QByteArrayLiteral("XLINK")); + setArchiveVersion(kLinkerArchiveVersion); + setDataVersion(kLinkerDataVersion); + setDataDebugInfo(gen::utils::debugInformation(qbsProduct)); + + const QString buildRootDirectory = gen::utils::buildRootPath(qbsProject); + + buildConfigPage(buildRootDirectory, qbsProduct); + buildOutputPage(qbsProduct); + buildListPage(qbsProduct); + buildDefinePage(qbsProduct); + + // Should be called as latest stage! + buildExtraOptionsPage(qbsProduct); +} + +void Msp430LinkerSettingsGroup::buildConfigPage( + const QString &baseDirectory, + const ProductData &qbsProduct) +{ + ConfigPageOptions opts(baseDirectory, qbsProduct); + + if (opts.configFilePaths.count() > 0) { + // Note: IAR IDE does not allow to specify a multiple config files, + // although the IAR linker support it. So, we use followig 'trick': + // we take a first config file and to add it as usual to required items; + // and then an other remainders we forward to the "Extra options page". + const QVariant configPath = opts.configFilePaths.takeFirst(); + // Add 'XclOverride' item (Override default). + addOptionsGroup(QByteArrayLiteral("XclOverride"), + {1}); + // Add 'XclFile' item (Linke configuration file). + addOptionsGroup(QByteArrayLiteral("XclFile"), + {configPath}); + + // Add remainder configuration files to the "Extra options page". + if (!opts.configFilePaths.isEmpty()) { + for (QVariant &configPath : opts.configFilePaths) + configPath = QLatin1String("-f ") + configPath.toString(); + + m_extraOptions << opts.configFilePaths; + } + } + + // Add 'xcOverrideProgramEntryLabel' item + // (Override default program entry). + addOptionsGroup(QByteArrayLiteral("xcOverrideProgramEntryLabel"), + {1}); + // Add 'xcProgramEntryLabel' item (Entry point name). + addOptionsGroup(QByteArrayLiteral("xcProgramEntryLabel"), + {opts.entryPoint}); + + // Add 'XIncludes' item (Entry point name). + addOptionsGroup(QByteArrayLiteral("XIncludes"), + {opts.librarySearchPaths}); +} + +void Msp430LinkerSettingsGroup::buildOutputPage( + const ProductData &qbsProduct) +{ + const OutputPageOptions opts(qbsProduct); + + // Add 'XOutOverride' item (Output file name). + addOptionsGroup(QByteArrayLiteral("XOutOverride"), + {1}); + // Add 'OutputFile' item (Output file name). + addOptionsGroup(QByteArrayLiteral("OutputFile"), + {opts.outputFile}); +} + +void Msp430LinkerSettingsGroup::buildListPage( + const ProductData &qbsProduct) +{ + const ListPageOptions opts(qbsProduct); + // Add 'XList' item (Generate linker map file). + addOptionsGroup(QByteArrayLiteral("XList"), + {opts.generateMap}); +} + +void Msp430LinkerSettingsGroup::buildDefinePage( + const ProductData &qbsProduct) +{ + const DefinePageOptions opts(qbsProduct); + // Add 'XDefines' item (Defined symbols). + addOptionsGroup(QByteArrayLiteral("XDefines"), + opts.defineSymbols); +} + +void Msp430LinkerSettingsGroup::buildExtraOptionsPage( + const ProductData &qbsProduct) +{ + Q_UNUSED(qbsProduct) + + if (m_extraOptions.isEmpty()) + return; + + // Add 'XExtraOptionsCheck' (Use command line options). + addOptionsGroup(QByteArrayLiteral("XExtraOptionsCheck"), + {1}); + // Add 'XExtraOptions' item (Command line options). + addOptionsGroup(QByteArrayLiteral("XExtraOptions"), + m_extraOptions); +} + +} // namespace v7 +} // namespace msp430 +} // namespace iarew +} // namespace qbs diff --git a/src/plugins/generator/iarew/archs/msp430/msp430linkersettingsgroup_v7.h b/src/plugins/generator/iarew/archs/msp430/msp430linkersettingsgroup_v7.h new file mode 100644 index 000000000..2b6f11514 --- /dev/null +++ b/src/plugins/generator/iarew/archs/msp430/msp430linkersettingsgroup_v7.h @@ -0,0 +1,65 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt.io/licensing +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef QBS_IAREWMSP430LINKERSETTINGSGROUP_V7_H +#define QBS_IAREWMSP430LINKERSETTINGSGROUP_V7_H + +#include "../../iarewsettingspropertygroup.h" + +namespace qbs { +namespace iarew { +namespace msp430 { +namespace v7 { + +class Msp430LinkerSettingsGroup final : public IarewSettingsPropertyGroup +{ +public: + explicit Msp430LinkerSettingsGroup( + const Project &qbsProject, + const ProductData &qbsProduct, + const std::vector<ProductData> &qbsProductDeps); + +private: + void buildConfigPage(const QString &baseDirectory, + const ProductData &qbsProduct); + void buildOutputPage(const ProductData &qbsProduct); + void buildListPage(const ProductData &qbsProduct); + void buildDefinePage(const ProductData &qbsProduct); + void buildExtraOptionsPage(const ProductData &qbsProduct); + + QVariantList m_extraOptions; +}; + +} // namespace v7 +} // namespace msp430 +} // namespace iarew +} // namespace qbs + +#endif // QBS_IAREWMSP430LINKERSETTINGSGROUP_V7_H diff --git a/src/plugins/generator/iarew/archs/stm8/stm8archiversettingsgroup_v3.cpp b/src/plugins/generator/iarew/archs/stm8/stm8archiversettingsgroup_v3.cpp new file mode 100644 index 000000000..b08b70bc5 --- /dev/null +++ b/src/plugins/generator/iarew/archs/stm8/stm8archiversettingsgroup_v3.cpp @@ -0,0 +1,94 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt.io/licensing +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "stm8archiversettingsgroup_v3.h" + +#include "../../iarewutils.h" + +namespace qbs { +namespace iarew { +namespace stm8 { +namespace v3 { + +constexpr int kArchiverArchiveVersion = 3; +constexpr int kArchiverDataVersion = 0; + +namespace { + +// Output page options. + +struct OutputPageOptions final +{ + explicit OutputPageOptions(const QString &baseDirectory, + const ProductData &qbsProduct) + { + outputFile = QLatin1String("$PROJ_DIR$/") + + gen::utils::targetBinaryPath(baseDirectory, qbsProduct); + } + + QString outputFile; +}; + +} // namespace + +// Stm8ArchiverSettingsGroup + +Stm8ArchiverSettingsGroup::Stm8ArchiverSettingsGroup( + const Project &qbsProject, + const ProductData &qbsProduct, + const std::vector<ProductData> &qbsProductDeps) +{ + Q_UNUSED(qbsProductDeps) + + setName(QByteArrayLiteral("IARCHIVE")); + setArchiveVersion(kArchiverArchiveVersion); + setDataVersion(kArchiverDataVersion); + setDataDebugInfo(gen::utils::debugInformation(qbsProduct)); + + const QString buildRootDirectory = gen::utils::buildRootPath(qbsProject); + buildOutputPage(buildRootDirectory, qbsProduct); +} + +void Stm8ArchiverSettingsGroup::buildOutputPage(const QString &baseDirectory, + const ProductData &qbsProduct) +{ + const OutputPageOptions opts(baseDirectory, qbsProduct); + // Add 'IarchiveOverride' item (Override default). + addOptionsGroup(QByteArrayLiteral("IarchiveOverride"), + {1}); + // Add 'IarchiveOutput' item (Output filename). + addOptionsGroup(QByteArrayLiteral("IarchiveOutput"), + {opts.outputFile}); +} + +} // namespace v3 +} // namespace stm8 +} // namespace iarew +} // namespace qbs diff --git a/src/plugins/generator/iarew/archs/stm8/stm8archiversettingsgroup_v3.h b/src/plugins/generator/iarew/archs/stm8/stm8archiversettingsgroup_v3.h new file mode 100644 index 000000000..754add3cb --- /dev/null +++ b/src/plugins/generator/iarew/archs/stm8/stm8archiversettingsgroup_v3.h @@ -0,0 +1,59 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt.io/licensing +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef QBS_IAREWSTM8ARCHIVERSETTINGSGROUP_V3_H +#define QBS_IAREWSTM8ARCHIVERSETTINGSGROUP_V3_H + +#include "../../iarewsettingspropertygroup.h" + +namespace qbs { +namespace iarew { +namespace stm8 { +namespace v3 { + +class Stm8ArchiverSettingsGroup final : public IarewSettingsPropertyGroup +{ +public: + explicit Stm8ArchiverSettingsGroup( + const Project &qbsProject, + const ProductData &qbsProduct, + const std::vector<ProductData> &qbsProductDeps); + +private: + void buildOutputPage(const QString &baseDirectory, + const ProductData &qbsProduct); +}; + +} // namespace v3 +} // namespace stm8 +} // namespace iarew +} // namespace qbs + +#endif // QBS_IAREWSTM8ARCHIVERSETTINGSGROUP_V3_H diff --git a/src/plugins/generator/iarew/archs/stm8/stm8assemblersettingsgroup_v3.cpp b/src/plugins/generator/iarew/archs/stm8/stm8assemblersettingsgroup_v3.cpp new file mode 100644 index 000000000..396ee7db2 --- /dev/null +++ b/src/plugins/generator/iarew/archs/stm8/stm8assemblersettingsgroup_v3.cpp @@ -0,0 +1,229 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt.io/licensing +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "stm8assemblersettingsgroup_v3.h" + +#include "../../iarewutils.h" + +namespace qbs { +namespace iarew { +namespace stm8 { +namespace v3 { + +constexpr int kAssemblerArchiveVersion = 3; +constexpr int kAssemblerDataVersion = 2; + +namespace { + +// Language page options. + +struct LanguagePageOptions final +{ + enum MacroQuoteCharacter { + AngleBracketsQuote, + RoundBracketsQuote, + SquareBracketsQuote, + FigureBracketsQuote + }; + + explicit LanguagePageOptions(const ProductData &qbsProduct) + { + const auto &qbsProps = qbsProduct.moduleProperties(); + const QStringList flags = gen::utils::cppStringModuleProperties( + qbsProps, {QStringLiteral("assemblerFlags")}); + enableSymbolsCaseSensitive = !flags.contains( + QLatin1String("--case_insensitive")); + enableMultibyteSupport = flags.contains( + QLatin1String("--enable_multibytes")); + allowFirstColumnMnemonics = flags.contains( + QLatin1String("--mnem_first")); + allowFirstColumnDirectives = flags.contains( + QLatin1String("--dir_first")); + + if (flags.contains(QLatin1String("-M<>"))) + macroQuoteCharacter = LanguagePageOptions::AngleBracketsQuote; + else if (flags.contains(QLatin1String("-M()"))) + macroQuoteCharacter = LanguagePageOptions::RoundBracketsQuote; + else if (flags.contains(QLatin1String("-M[]"))) + macroQuoteCharacter = LanguagePageOptions::SquareBracketsQuote; + else if (flags.contains(QLatin1String("-M{}"))) + macroQuoteCharacter = LanguagePageOptions::FigureBracketsQuote; + } + + int enableSymbolsCaseSensitive = 1; + int enableMultibyteSupport = 0; + int allowFirstColumnMnemonics = 0; + int allowFirstColumnDirectives = 0; + + MacroQuoteCharacter macroQuoteCharacter = AngleBracketsQuote; +}; + +// Output page options. + +struct OutputPageOptions final +{ + explicit OutputPageOptions(const ProductData &qbsProduct) + { + debugInfo = gen::utils::debugInformation(qbsProduct); + } + + int debugInfo = 0; +}; + +// Preprocessor page options. + +struct PreprocessorPageOptions final +{ + explicit PreprocessorPageOptions(const QString &baseDirectory, + const ProductData &qbsProduct) + { + const auto &qbsProps = qbsProduct.moduleProperties(); + defineSymbols = gen::utils::cppVariantModuleProperties( + qbsProps, {QStringLiteral("defines")}); + + const QString toolkitPath = IarewUtils::toolkitRootPath(qbsProduct); + const QStringList fullIncludePaths = gen::utils::cppStringModuleProperties( + qbsProps, {QStringLiteral("includePaths"), + QStringLiteral("systemIncludePaths")}); + for (const auto &fullIncludePath : fullIncludePaths) { + const QFileInfo includeFileInfo(fullIncludePath); + const QString includeFilePath = includeFileInfo.absoluteFilePath(); + if (includeFilePath.startsWith(toolkitPath, Qt::CaseInsensitive)) { + const QString path = IarewUtils::toolkitRelativeFilePath( + toolkitPath, includeFilePath); + includePaths.push_back(path); + } else { + const QString path = IarewUtils::projectRelativeFilePath( + baseDirectory, includeFilePath); + includePaths.push_back(path); + } + } + } + + QVariantList defineSymbols; + QVariantList includePaths; +}; + +// Diagnostics page options. + +struct DiagnosticsPageOptions final +{ + explicit DiagnosticsPageOptions(const ProductData &qbsProduct) + { + const auto &qbsProps = qbsProduct.moduleProperties(); + warningsAsErrors = gen::utils::cppIntegerModuleProperty( + qbsProps, QStringLiteral("treatWarningsAsErrors")); + } + + int warningsAsErrors = 0; +}; + +} // namespace + +// Stm8AssemblerSettingsGroup + +Stm8AssemblerSettingsGroup::Stm8AssemblerSettingsGroup( + const Project &qbsProject, + const ProductData &qbsProduct, + const std::vector<ProductData> &qbsProductDeps) +{ + Q_UNUSED(qbsProductDeps) + + setName(QByteArrayLiteral("ASTM8")); + setArchiveVersion(kAssemblerArchiveVersion); + setDataVersion(kAssemblerDataVersion); + setDataDebugInfo(gen::utils::debugInformation(qbsProduct)); + + const QString buildRootDirectory = gen::utils::buildRootPath(qbsProject); + + buildLanguagePage(qbsProduct); + buildOutputPage(qbsProduct); + buildPreprocessorPage(buildRootDirectory, qbsProduct); + buildDiagnosticsPage(qbsProduct); +} + +void Stm8AssemblerSettingsGroup::buildLanguagePage( + const ProductData &qbsProduct) +{ + const LanguagePageOptions opts(qbsProduct); + // Add 'AsmCaseSensitivity' item (User symbols are case sensitive). + addOptionsGroup(QByteArrayLiteral("AsmCaseSensitivity"), + {opts.enableSymbolsCaseSensitive}); + // Add 'AsmMultibyteSupport' item (Enable multibyte support). + addOptionsGroup(QByteArrayLiteral("AsmMultibyteSupport"), + {opts.enableMultibyteSupport}); + // Add 'AsmAllowMnemonics' item (Allow mnemonics in first column). + addOptionsGroup(QByteArrayLiteral("AsmAllowMnemonics"), + {opts.allowFirstColumnMnemonics}); + // Add 'AsmAllowDirectives' item (Allow directives in first column). + addOptionsGroup(QByteArrayLiteral("AsmAllowDirectives"), + {opts.allowFirstColumnDirectives}); + + // Add 'AsmMacroChars' item (Macro quote characters: ()/[]/{}/<>). + addOptionsGroup(QByteArrayLiteral("AsmMacroChars"), + {opts.macroQuoteCharacter}); +} + +void Stm8AssemblerSettingsGroup::buildOutputPage( + const ProductData &qbsProduct) +{ + const OutputPageOptions opts(qbsProduct); + // Add 'AsmDebugInfo' item (Generate debug information). + addOptionsGroup(QByteArrayLiteral("AsmDebugInfo"), + {opts.debugInfo}); +} + +void Stm8AssemblerSettingsGroup::buildPreprocessorPage( + const QString &baseDirectory, + const ProductData &qbsProduct) +{ + const PreprocessorPageOptions opts(baseDirectory, qbsProduct); + // Add 'AsmDefines' item (Defined symbols). + addOptionsGroup(QByteArrayLiteral("AsmDefines"), + opts.defineSymbols); + // Add 'AsmIncludePath' item (Additional include directories). + addOptionsGroup(QByteArrayLiteral("AsmIncludePath"), + opts.includePaths); +} + +void Stm8AssemblerSettingsGroup::buildDiagnosticsPage( + const ProductData &qbsProduct) +{ + const DiagnosticsPageOptions opts(qbsProduct); + // Add 'AsmDiagnosticsWarningsAreErrors' item. + // (Treat all warnings as errors). + addOptionsGroup(QByteArrayLiteral("AsmDiagnosticsWarningsAreErrors"), + {opts.warningsAsErrors}); +} + +} // namespace v3 +} // namespace stm8 +} // namespace iarew +} // namespace qbs diff --git a/src/plugins/generator/iarew/archs/stm8/stm8assemblersettingsgroup_v3.h b/src/plugins/generator/iarew/archs/stm8/stm8assemblersettingsgroup_v3.h new file mode 100644 index 000000000..4d7d0485b --- /dev/null +++ b/src/plugins/generator/iarew/archs/stm8/stm8assemblersettingsgroup_v3.h @@ -0,0 +1,62 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt.io/licensing +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef QBS_IAREWSTM8ASSEMBLERSETTINGSGROUP_V3_H +#define QBS_IAREWSTM8ASSEMBLERSETTINGSGROUP_V3_H + +#include "../../iarewsettingspropertygroup.h" + +namespace qbs { +namespace iarew { +namespace stm8 { +namespace v3 { + +class Stm8AssemblerSettingsGroup final : public IarewSettingsPropertyGroup +{ +public: + explicit Stm8AssemblerSettingsGroup( + const Project &qbsProject, + const ProductData &qbsProduct, + const std::vector<ProductData> &qbsProductDeps); + +private: + void buildLanguagePage(const ProductData &qbsProduct); + void buildOutputPage(const ProductData &qbsProduct); + void buildPreprocessorPage(const QString &baseDirectory, + const ProductData &qbsProduct); + void buildDiagnosticsPage(const ProductData &qbsProduct); +}; + +} // namespace v3 +} // namespace stm8 +} // namespace iarew +} // namespace qbs + +#endif // QBS_IAREWSTM8ASSEMBLERSETTINGSGROUP_V3_H diff --git a/src/plugins/generator/iarew/archs/stm8/stm8buildconfigurationgroup_v3.cpp b/src/plugins/generator/iarew/archs/stm8/stm8buildconfigurationgroup_v3.cpp new file mode 100644 index 000000000..06167f919 --- /dev/null +++ b/src/plugins/generator/iarew/archs/stm8/stm8buildconfigurationgroup_v3.cpp @@ -0,0 +1,98 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt.io/licensing +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "stm8archiversettingsgroup_v3.h" +#include "stm8assemblersettingsgroup_v3.h" +#include "stm8buildconfigurationgroup_v3.h" +#include "stm8compilersettingsgroup_v3.h" +#include "stm8generalsettingsgroup_v3.h" +#include "stm8linkersettingsgroup_v3.h" + +#include "../../iarewtoolchainpropertygroup.h" +#include "../../iarewutils.h" + +namespace qbs { +namespace iarew { +namespace stm8 { +namespace v3 { + +Stm8BuildConfigurationGroup::Stm8BuildConfigurationGroup( + const Project &qbsProject, + const ProductData &qbsProduct, + const std::vector<ProductData> &qbsProductDeps) + : gen::xml::PropertyGroup("configuration") +{ + // Append configuration name item. + const QString cfgName = gen::utils::buildConfigurationName(qbsProject); + appendProperty("name", cfgName); + + // Apend toolchain name group item. + appendChild<IarewToolchainPropertyGroup>("STM8"); + + // Append debug info item. + const int debugBuild = gen::utils::debugInformation(qbsProduct); + appendProperty("debug", debugBuild); + + // Append settings group items. + appendChild<Stm8ArchiverSettingsGroup>( + qbsProject, qbsProduct, qbsProductDeps); + appendChild<Stm8AssemblerSettingsGroup>( + qbsProject, qbsProduct, qbsProductDeps); + appendChild<Stm8CompilerSettingsGroup>( + qbsProject, qbsProduct, qbsProductDeps); + appendChild<Stm8GeneralSettingsGroup>( + qbsProject, qbsProduct, qbsProductDeps); + appendChild<Stm8LinkerSettingsGroup>( + qbsProject, qbsProduct, qbsProductDeps); +} + +bool Stm8BuildConfigurationGroupFactory::canCreate( + gen::utils::Architecture arch, + const Version &version) const +{ + return arch == gen::utils::Architecture::Stm8 + && version.majorVersion() == 3; +} + +std::unique_ptr<gen::xml::PropertyGroup> +Stm8BuildConfigurationGroupFactory::create( + const Project &qbsProject, + const ProductData &qbsProduct, + const std::vector<ProductData> &qbsProductDeps) const +{ + const auto group = new Stm8BuildConfigurationGroup( + qbsProject, qbsProduct, qbsProductDeps); + return std::unique_ptr<Stm8BuildConfigurationGroup>(group); +} + +} // namespace v3 +} // namespace stm8 +} // namespace iarew +} // namespace qbs diff --git a/src/plugins/generator/iarew/archs/stm8/stm8buildconfigurationgroup_v3.h b/src/plugins/generator/iarew/archs/stm8/stm8buildconfigurationgroup_v3.h new file mode 100644 index 000000000..c47819fef --- /dev/null +++ b/src/plugins/generator/iarew/archs/stm8/stm8buildconfigurationgroup_v3.h @@ -0,0 +1,72 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt.io/licensing +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef QBS_IAREWSTM8BUILDCONFIGURATIONGROUP_V3_H +#define QBS_IAREWSTM8BUILDCONFIGURATIONGROUP_V3_H + +#include <generators/generatorutils.h> +#include <generators/xmlpropertygroup.h> + +namespace qbs { +namespace iarew { +namespace stm8 { +namespace v3 { + +class Stm8BuildConfigurationGroup final + : public gen::xml::PropertyGroup +{ +private: + explicit Stm8BuildConfigurationGroup( + const Project &qbsProject, + const ProductData &qbsProduct, + const std::vector<ProductData> &qbsProductDeps); + + friend class Stm8BuildConfigurationGroupFactory; +}; + +class Stm8BuildConfigurationGroupFactory final + : public gen::xml::PropertyGroupFactory +{ +public: + bool canCreate(gen::utils::Architecture arch, + const Version &version) const final; + + std::unique_ptr<gen::xml::PropertyGroup> create( + const Project &qbsProject, + const ProductData &qbsProduct, + const std::vector<ProductData> &qbsProductDeps) const final; +}; + +} // namespace v3 +} // namespace stm8 +} // namespace iarew +} // namespace qbs + +#endif // QBS_IAREWSTM8BUILDCONFIGURATIONGROUP_V3_H diff --git a/src/plugins/generator/iarew/archs/stm8/stm8compilersettingsgroup_v3.cpp b/src/plugins/generator/iarew/archs/stm8/stm8compilersettingsgroup_v3.cpp new file mode 100644 index 000000000..912d94bd0 --- /dev/null +++ b/src/plugins/generator/iarew/archs/stm8/stm8compilersettingsgroup_v3.cpp @@ -0,0 +1,442 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt.io/licensing +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "stm8compilersettingsgroup_v3.h" + +#include "../../iarewutils.h" + +namespace qbs { +namespace iarew { +namespace stm8 { +namespace v3 { + +constexpr int kCompilerArchiveVersion = 3; +constexpr int kCompilerDataVersion = 9; + +namespace { + +// Output page options. + +struct OutputPageOptions final +{ + explicit OutputPageOptions(const ProductData &qbsProduct) + { + debugInfo = gen::utils::debugInformation(qbsProduct); + } + + int debugInfo = 0; +}; + +// Language one page options. + +struct LanguageOnePageOptions final +{ + enum LanguageExtension { + CLanguageExtension, + CxxLanguageExtension, + AutoLanguageExtension + }; + + enum CLanguageDialect { + C89LanguageDialect, + C99LanguageDialect + }; + + enum CxxLanguageDialect { + EmbeddedCPlusPlus, + ExtendedEmbeddedCPlusPlus + }; + + enum LanguageConformance { + AllowIarExtension, + RelaxedStandard, + StrictStandard + }; + + explicit LanguageOnePageOptions(const ProductData &qbsProduct) + { + const auto &qbsProps = qbsProduct.moduleProperties(); + const QStringList flags = IarewUtils::cppModuleCompilerFlags(qbsProps); + // File extension based by default. + languageExtension = LanguageOnePageOptions::AutoLanguageExtension; + // C language dialect. + const QStringList cLanguageVersion = gen::utils::cppStringModuleProperties( + qbsProps, {QStringLiteral("cLanguageVersion")}); + if (cLanguageVersion.contains(QLatin1String("c89"))) + cLanguageDialect = LanguageOnePageOptions::C89LanguageDialect; + else if (cLanguageVersion.contains(QLatin1String("c99"))) + cLanguageDialect = LanguageOnePageOptions::C99LanguageDialect; + // C++ language dialect. + if (flags.contains(QLatin1String("--ec++"))) + cxxLanguageDialect = LanguageOnePageOptions::EmbeddedCPlusPlus; + else if (flags.contains(QLatin1String("--eec++"))) + cxxLanguageDialect = LanguageOnePageOptions::ExtendedEmbeddedCPlusPlus; + // Language conformance. + if (flags.contains(QLatin1String("-e"))) + languageConformance = LanguageOnePageOptions::AllowIarExtension; + else if (flags.contains(QLatin1String("--strict"))) + languageConformance = LanguageOnePageOptions::StrictStandard; + else + languageConformance = LanguageOnePageOptions::RelaxedStandard; + + allowVla = flags.contains(QLatin1String("--vla")); + useCppInlineSemantics = flags.contains( + QLatin1String("--use_c++_inline")); + requirePrototypes = flags.contains( + QLatin1String("--require_prototypes")); + destroyStaticObjects = !flags.contains( + QLatin1String("--no_static_destruction")); + } + + LanguageExtension languageExtension = AutoLanguageExtension; + CLanguageDialect cLanguageDialect = C99LanguageDialect; + CxxLanguageDialect cxxLanguageDialect = EmbeddedCPlusPlus; + LanguageConformance languageConformance = AllowIarExtension; + int allowVla = 0; + int useCppInlineSemantics = 0; + int requirePrototypes = 0; + int destroyStaticObjects = 0; +}; + +// Language two page options. + +struct LanguageTwoPageOptions final +{ + enum PlainCharacter { + SignedCharacter, + UnsignedCharacter + }; + + enum FloatingPointSemantic { + StrictSemantic, + RelaxedSemantic + }; + + explicit LanguageTwoPageOptions(const ProductData &qbsProduct) + { + const auto &qbsProps = qbsProduct.moduleProperties(); + const QStringList flags = IarewUtils::cppModuleCompilerFlags(qbsProps); + plainCharacter = flags.contains(QLatin1String("--char_is_signed")) + ? LanguageTwoPageOptions::SignedCharacter + : LanguageTwoPageOptions::UnsignedCharacter; + floatingPointSemantic = flags.contains(QLatin1String("--relaxed_fp")) + ? LanguageTwoPageOptions::RelaxedSemantic + : LanguageTwoPageOptions::StrictSemantic; + enableMultibyteSupport = flags.contains( + QLatin1String("--enable_multibytes")); + } + + PlainCharacter plainCharacter = UnsignedCharacter; + FloatingPointSemantic floatingPointSemantic = StrictSemantic; + int enableMultibyteSupport = 0; +}; + +// Optimizations page options. + +struct OptimizationsPageOptions final +{ + // Optimizations level radio-buttons with + // combo-box on "level" widget. + enum Strategy { + StrategyBalanced, + StrategySize, + StrategySpeed + }; + + enum Level { + LevelNone, + LevelLow, + LevelMedium, + LevelHigh + }; + + enum LevelSlave { + LevelSlave0, + LevelSlave1, + LevelSlave2, + LevelSlave3 + }; + + enum VRegsNumber { + VRegs12, + VRegs16 + }; + + explicit OptimizationsPageOptions(const ProductData &qbsProduct) + { + const auto &qbsProps = qbsProduct.moduleProperties(); + const QString optimization = gen::utils::cppStringModuleProperty( + qbsProps, QStringLiteral("optimization")); + if (optimization == QLatin1String("none")) { + optimizationStrategy = OptimizationsPageOptions::StrategyBalanced; + optimizationLevel = OptimizationsPageOptions::LevelNone; + optimizationLevelSlave = OptimizationsPageOptions::LevelSlave0; + } else if (optimization == QLatin1String("fast")) { + optimizationStrategy = OptimizationsPageOptions::StrategySpeed; + optimizationLevel = OptimizationsPageOptions::LevelHigh; + optimizationLevelSlave = OptimizationsPageOptions::LevelSlave3; + } else if (optimization == QLatin1String("small")) { + optimizationStrategy = OptimizationsPageOptions::StrategySize; + optimizationLevel = OptimizationsPageOptions::LevelHigh; + optimizationLevelSlave = OptimizationsPageOptions::LevelSlave3; + } + + const QStringList flags = IarewUtils::cppModuleCompilerFlags(qbsProps); + + disableSizeConstraints = flags.contains( + QLatin1String("--no_size_constraints")); + + enableCommonSubexpressionElimination = !flags.contains( + QLatin1String("--no_cse")); + enableLoopUnroll = !flags.contains(QLatin1String("--no_unroll")); + enableFunctionInlining = !flags.contains(QLatin1String("--no_inline")); + enableCodeMotion = !flags.contains(QLatin1String("--no_code_motion")); + enableTypeBasedAliasAnalysis = !flags.contains( + QLatin1String("--no_tbaa")); + enableCrossCall = !flags.contains(QLatin1String("--no_cross_call")); + + const auto vregsCount = IarewUtils::flagValue( + flags, QStringLiteral("--vregs")).toInt(); + if (vregsCount == 12) + vregsNumber = VRegs12; + else if (vregsCount == 16) + vregsNumber = VRegs16; + } + + Strategy optimizationStrategy = StrategyBalanced; + Level optimizationLevel = LevelNone; + LevelSlave optimizationLevelSlave = LevelSlave0; + // Separate "no size constraints" checkbox. + int disableSizeConstraints = 0; + + // Six bit-field flags on "enabled transformations" widget. + int enableCommonSubexpressionElimination = 0; // Common sub-expression elimination. + int enableLoopUnroll = 0; // Loop unrolling. + int enableFunctionInlining = 0; // Function inlining. + int enableCodeMotion = 0; // Code motion. + int enableTypeBasedAliasAnalysis = 0; // Type based alias analysis. + int enableCrossCall = 0; // Cross call. + + VRegsNumber vregsNumber = VRegs16; +}; + +// Preprocessor page options. + +struct PreprocessorPageOptions final +{ + explicit PreprocessorPageOptions(const QString &baseDirectory, + const ProductData &qbsProduct) + { + const auto &qbsProps = qbsProduct.moduleProperties(); + defineSymbols = gen::utils::cppVariantModuleProperties( + qbsProps, {QStringLiteral("defines")}); + + const QString toolkitPath = IarewUtils::toolkitRootPath(qbsProduct); + const QStringList fullIncludePaths = gen::utils::cppStringModuleProperties( + qbsProps, {QStringLiteral("includePaths"), + QStringLiteral("systemIncludePaths")}); + for (const QString &fullIncludePath : fullIncludePaths) { + const QFileInfo includeFileInfo(fullIncludePath); + const QString includeFilePath = includeFileInfo.absoluteFilePath(); + if (includeFilePath.startsWith(toolkitPath, Qt::CaseInsensitive)) { + const QString path = IarewUtils::toolkitRelativeFilePath( + toolkitPath, includeFilePath); + includePaths.push_back(path); + } else { + const QString path = IarewUtils::projectRelativeFilePath( + baseDirectory, includeFilePath); + includePaths.push_back(path); + } + } + } + + QVariantList defineSymbols; + QVariantList includePaths; +}; + +// Diagnostics page options. + +struct DiagnosticsPageOptions final +{ + explicit DiagnosticsPageOptions(const ProductData &qbsProduct) + { + const auto &qbsProps = qbsProduct.moduleProperties(); + warningsAsErrors = gen::utils::cppIntegerModuleProperty( + qbsProps, QStringLiteral("treatWarningsAsErrors")); + } + + int warningsAsErrors = 0; +}; + +} // namespace + +// Stm8CompilerSettingsGroup + +Stm8CompilerSettingsGroup::Stm8CompilerSettingsGroup( + const Project &qbsProject, + const ProductData &qbsProduct, + const std::vector<ProductData> &qbsProductDeps) +{ + Q_UNUSED(qbsProductDeps) + + setName(QByteArrayLiteral("ICCSTM8")); + setArchiveVersion(kCompilerArchiveVersion); + setDataVersion(kCompilerDataVersion); + setDataDebugInfo(gen::utils::debugInformation(qbsProduct)); + + const QString buildRootDirectory = gen::utils::buildRootPath(qbsProject); + + buildOutputPage(qbsProduct); + buildLanguageOnePage(qbsProduct); + buildLanguageTwoPage(qbsProduct); + buildOptimizationsPage(qbsProduct); + buildPreprocessorPage(buildRootDirectory, qbsProduct); + buildDiagnosticsPage(qbsProduct); +} + +void Stm8CompilerSettingsGroup::buildOutputPage( + const ProductData &qbsProduct) +{ + const OutputPageOptions opts(qbsProduct); + // Add 'IccGenerateDebugInfo' item (Generate debug info). + addOptionsGroup(QByteArrayLiteral("IccGenerateDebugInfo"), + {opts.debugInfo}); +} + +void Stm8CompilerSettingsGroup::buildLanguageOnePage( + const ProductData &qbsProduct) +{ + const LanguageOnePageOptions opts(qbsProduct); + // Add 'IccLang' item with 'auto-extension based' + // value (Language: C/C++/Auto). + addOptionsGroup(QByteArrayLiteral("IccLang"), + {opts.languageExtension}); + // Add 'IccCDialect' item (C dialect: c89/99/11). + addOptionsGroup(QByteArrayLiteral("IccCDialect"), + {opts.cLanguageDialect}); + // Add 'IccCppDialect' item (C++ dialect: embedded/extended). + addOptionsGroup(QByteArrayLiteral("IccCppDialect"), + {opts.cxxLanguageDialect}); + // Add 'IccLanguageConformance' item + // (Language conformance: IAR/relaxed/strict). + addOptionsGroup(QByteArrayLiteral("IccLanguageConformance"), + {opts.languageConformance}); + // Add 'IccAllowVLA' item (Allow VLA). + addOptionsGroup(QByteArrayLiteral("IccAllowVLA"), + {opts.allowVla}); + // Add 'IccCppInlineSemantics' item (C++ inline semantics). + addOptionsGroup(QByteArrayLiteral("IccCppInlineSemantics"), + {opts.useCppInlineSemantics}); + // Add 'IccRequirePrototypes' item (Require prototypes). + addOptionsGroup(QByteArrayLiteral("IccRequirePrototypes"), + {opts.requirePrototypes}); + // Add 'IccStaticDestr' item (Destroy static objects). + addOptionsGroup(QByteArrayLiteral("IccStaticDestr"), + {opts.destroyStaticObjects}); +} + +void Stm8CompilerSettingsGroup::buildLanguageTwoPage( + const ProductData &qbsProduct) +{ + const LanguageTwoPageOptions opts(qbsProduct); + // Add 'IccCharIs' item (Plain char is: signed/unsigned). + addOptionsGroup(QByteArrayLiteral("IccCharIs"), + {opts.plainCharacter}); + // Add 'IccFloatSemantics' item (Floatic-point + // semantics: strict/relaxed conformance). + addOptionsGroup(QByteArrayLiteral("IccFloatSemantics"), + {opts.floatingPointSemantic}); + // Add 'IccMultibyteSupport' item (Enable multibyte support). + addOptionsGroup(QByteArrayLiteral("IccMultibyteSupport"), + {opts.enableMultibyteSupport}); +} + +void Stm8CompilerSettingsGroup::buildOptimizationsPage( + const ProductData &qbsProduct) +{ + const OptimizationsPageOptions opts(qbsProduct); + // Add 'IccOptStrategy', 'IccOptLevel' and + // 'CCOptLevelSlave' items (Level). + addOptionsGroup(QByteArrayLiteral("IccOptStrategy"), + {opts.optimizationStrategy}); + addOptionsGroup(QByteArrayLiteral("IccOptLevel"), + {opts.optimizationLevel}); + addOptionsGroup(QByteArrayLiteral("IccOptLevelSlave"), + {opts.optimizationLevelSlave}); + + // Add 'IccOptNoSizeConstraints' iten (no size constraints). + addOptionsGroup(QByteArrayLiteral("IccOptNoSizeConstraints"), + {opts.disableSizeConstraints}); + + // Add 'IccOptAllowList' item + // (Enabled optimizations: 6 check boxes). + const QString bitflags = QStringLiteral("%1%2%3%4%5%6") + .arg(opts.enableCommonSubexpressionElimination) + .arg(opts.enableLoopUnroll) + .arg(opts.enableFunctionInlining) + .arg(opts.enableCodeMotion) + .arg(opts.enableTypeBasedAliasAnalysis) + .arg(opts.enableCrossCall); + addOptionsGroup(QByteArrayLiteral("IccOptAllowList"), + {bitflags}); + + // Add 'IccNoVregs' item + // (Number of virtual registers (12/16). + addOptionsGroup(QByteArrayLiteral("IccNoVregs"), + {opts.vregsNumber}); +} + +void Stm8CompilerSettingsGroup::buildPreprocessorPage( + const QString &baseDirectory, + const ProductData &qbsProduct) +{ + const PreprocessorPageOptions opts(baseDirectory, qbsProduct); + // Add 'CCDefines' item (Defines symbols). + addOptionsGroup(QByteArrayLiteral("CCDefines"), + opts.defineSymbols); + // Add 'CCIncludePath2' item + // (Additional include directories). + addOptionsGroup(QByteArrayLiteral("CCIncludePath2"), + opts.includePaths); +} + +void Stm8CompilerSettingsGroup::buildDiagnosticsPage( + const ProductData &qbsProduct) +{ + const DiagnosticsPageOptions opts(qbsProduct); + // Add 'CCDiagWarnAreErr' item (Treat all warnings as errors). + addOptionsGroup(QByteArrayLiteral("CCDiagWarnAreErr"), + {opts.warningsAsErrors}); +} + +} // namespace v3 +} // namespace stm8 +} // namespace iarew +} // namespace qbs diff --git a/src/plugins/generator/iarew/archs/stm8/stm8compilersettingsgroup_v3.h b/src/plugins/generator/iarew/archs/stm8/stm8compilersettingsgroup_v3.h new file mode 100644 index 000000000..29bb5c2b3 --- /dev/null +++ b/src/plugins/generator/iarew/archs/stm8/stm8compilersettingsgroup_v3.h @@ -0,0 +1,64 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt.io/licensing +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef QBS_IAREWSTM8COMPILERSETTINGSGROUP_V3_H +#define QBS_IAREWSTM8COMPILERSETTINGSGROUP_V3_H + +#include "../../iarewsettingspropertygroup.h" + +namespace qbs { +namespace iarew { +namespace stm8 { +namespace v3 { + +class Stm8CompilerSettingsGroup final : public IarewSettingsPropertyGroup +{ +public: + explicit Stm8CompilerSettingsGroup( + const Project &qbsProject, + const ProductData &qbsProduct, + const std::vector<ProductData> &qbsProductDeps); + +private: + void buildOutputPage(const ProductData &qbsProduct); + void buildLanguageOnePage(const ProductData &qbsProduct); + void buildLanguageTwoPage(const ProductData &qbsProduct); + void buildOptimizationsPage(const ProductData &qbsProduct); + void buildPreprocessorPage(const QString &baseDirectory, + const ProductData &qbsProduct); + void buildDiagnosticsPage(const ProductData &qbsProduct); +}; + +} // namespace v3 +} // namespace stm8 +} // namespace iarew +} // namespace qbs + +#endif // QBS_IAREWSTM8COMPILERSETTINGSGROUP_V3_H diff --git a/src/plugins/generator/iarew/archs/stm8/stm8generalsettingsgroup_v3.cpp b/src/plugins/generator/iarew/archs/stm8/stm8generalsettingsgroup_v3.cpp new file mode 100644 index 000000000..9477bc36e --- /dev/null +++ b/src/plugins/generator/iarew/archs/stm8/stm8generalsettingsgroup_v3.cpp @@ -0,0 +1,366 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt.io/licensing +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "stm8generalsettingsgroup_v3.h" + +#include "../../iarewutils.h" + +namespace qbs { +namespace iarew { +namespace stm8 { +namespace v3 { + +constexpr int kGeneralArchiveVersion = 4; +constexpr int kGeneralDataVersion = 2; + +namespace { + +// Target page options. + +struct TargetPageOptions final +{ + enum CodeModel { + SmallCodeModel, + MediumCodeModel, + LargeCodeModel + }; + + enum DataModel { + SmallDataModel, + MediumDataModel, + LargeDataModel + }; + + explicit TargetPageOptions(const ProductData &qbsProduct) + { + const auto &qbsProps = qbsProduct.moduleProperties(); + const QStringList flags = gen::utils::cppStringModuleProperties( + qbsProps, {QStringLiteral("driverFlags")}); + // Detect target code model. + const QString codeModelValue = IarewUtils::flagValue( + flags, QStringLiteral("--code_model")); + if (codeModelValue == QLatin1String("small")) + codeModel = TargetPageOptions::SmallCodeModel; + else if (codeModelValue == QLatin1String("medium")) + codeModel = TargetPageOptions::MediumCodeModel; + else if (codeModelValue == QLatin1String("large")) + codeModel = TargetPageOptions::LargeCodeModel; + // Detect target data model. + const QString dataModelValue = IarewUtils::flagValue( + flags, QStringLiteral("--data_model")); + if (dataModelValue == QLatin1String("small")) + dataModel = TargetPageOptions::SmallDataModel; + else if (dataModelValue == QLatin1String("medium")) + dataModel = TargetPageOptions::MediumDataModel; + else if (dataModelValue == QLatin1String("large")) + dataModel = TargetPageOptions::LargeDataModel; + } + + CodeModel codeModel = MediumCodeModel; + DataModel dataModel = MediumDataModel; +}; + +// Output page options. + +struct OutputPageOptions final +{ + explicit OutputPageOptions(const QString &baseDirectory, + const ProductData &qbsProduct) + { + binaryType = IarewUtils::outputBinaryType(qbsProduct); + binaryDirectory = gen::utils::binaryOutputDirectory( + baseDirectory, qbsProduct); + objectDirectory = gen::utils::objectsOutputDirectory( + baseDirectory, qbsProduct); + listingDirectory = gen::utils::listingOutputDirectory( + baseDirectory, qbsProduct); + } + + IarewUtils::OutputBinaryType binaryType = IarewUtils::ApplicationOutputType; + QString binaryDirectory; + QString objectDirectory; + QString listingDirectory; +}; + +// Library configuration page options. + +struct LibraryConfigPageOptions final +{ + enum RuntimeLibrary { + NoLibrary, + NormalLibrary, + FullLibrary, + CustomLibrary + }; + + explicit LibraryConfigPageOptions(const QString &baseDirectory, + const ProductData &qbsProduct) + { + const auto &qbsProps = qbsProduct.moduleProperties(); + const QStringList flags = IarewUtils::cppModuleCompilerFlags(qbsProps); + + const QFileInfo configInfo(IarewUtils::flagValue( + flags, + QStringLiteral("--dlib_config"))); + const QString configFilePath = configInfo.absoluteFilePath(); + + if (!configFilePath.isEmpty()) { + const QString libToolkitPath = + IarewUtils::libToolkitRootPath(qbsProduct); + + if (configFilePath.startsWith(libToolkitPath, + Qt::CaseInsensitive)) { + if (configFilePath.endsWith(QLatin1String("n.h"), + Qt::CaseInsensitive)) { + libraryType = LibraryConfigPageOptions::NormalLibrary; + } else if (configFilePath.endsWith(QLatin1String("f.h"), + Qt::CaseInsensitive)) { + libraryType = LibraryConfigPageOptions::FullLibrary; + } else { + libraryType = LibraryConfigPageOptions::CustomLibrary; + } + + configPath = IarewUtils::toolkitRelativeFilePath( + baseDirectory, configFilePath); + } else { + libraryType = LibraryConfigPageOptions::CustomLibrary; + + configPath = configFilePath; + } + } else { + libraryType = LibraryConfigPageOptions::NoLibrary; + } + } + + RuntimeLibrary libraryType = NoLibrary; + QString configPath; +}; + +// Library options page options. + +struct LibraryOptionsPageOptions final +{ + enum PrintfFormatter { + PrintfAutoFormatter = 0, + PrintfFullFormatter = 1, + PrintfFullNoMultibytesFormatter = 2, + PrintfLargeFormatter = 3, + PrintfLargeNoMultibytesFormatter = 4, + PrintfSmallFormatter = 5, + PrintfSmallNoMultibytesFormatter = 6, + PrintfTinyFormatter = 7 + }; + + enum ScanfFormatter { + ScanfAutoFormatter = 0, + ScanfFullFormatter = 1, + ScanfFullNoMultibytesFormatter = 2, + ScanfLargeFormatter = 3, + ScanfLargeNoMultibytesFormatter = 4, + ScanfSmallFormatter = 5, + ScanfSmallNoMultibytesFormatter = 6 + }; + + explicit LibraryOptionsPageOptions(const ProductData &qbsProduct) + { + const auto &qbsProps = qbsProduct.moduleProperties(); + const QStringList flags = IarewUtils::cppModuleLinkerFlags(qbsProps); + for (auto flagIt = flags.cbegin(); flagIt < flags.cend(); ++flagIt) { + if (*flagIt != QLatin1String("--redirect")) + continue; + ++flagIt; + if (flagIt->startsWith(QLatin1String("_printf="), + Qt::CaseInsensitive)) { + const QString prop = flagIt->split( + QLatin1Char('=')).at(1).toLower(); + if (prop == QLatin1String("_printffull")) + printfFormatter = PrintfFullFormatter; + else if (prop == QLatin1String("_printffullnomb")) + printfFormatter = PrintfFullNoMultibytesFormatter; + else if (prop == QLatin1String("_printflarge")) + printfFormatter = PrintfLargeFormatter; + else if (prop == QLatin1String("_printflargenomb")) + printfFormatter = PrintfLargeFormatter; + else if (prop == QLatin1String("_printfsmall")) + printfFormatter = PrintfSmallFormatter; + else if (prop == QLatin1String("_printfsmallnomb")) + printfFormatter = PrintfSmallNoMultibytesFormatter; + else if (prop == QLatin1String("_printftiny")) + printfFormatter = PrintfTinyFormatter; + } else if (flagIt->startsWith(QLatin1String("_scanf="), + Qt::CaseInsensitive)) { + const QString prop = flagIt->split( + QLatin1Char('=')).at(1).toLower(); + if (prop == QLatin1String("_scanffull")) + scanfFormatter = ScanfFullFormatter; + else if (prop == QLatin1String("_scanffullnomb")) + scanfFormatter = ScanfFullNoMultibytesFormatter; + else if (prop == QLatin1String("_scanflarge")) + scanfFormatter = ScanfLargeFormatter; + else if (prop == QLatin1String("_scanflargenomb")) + scanfFormatter = ScanfLargeFormatter; + else if (prop == QLatin1String("_scanfsmall")) + scanfFormatter = ScanfSmallFormatter; + else if (prop == QLatin1String("_scanfsmallnomb")) + scanfFormatter = ScanfSmallNoMultibytesFormatter; + } + } + } + + PrintfFormatter printfFormatter = PrintfAutoFormatter; + ScanfFormatter scanfFormatter = ScanfAutoFormatter; +}; + +// Stack/heap page options. + +struct StackHeapPageOptions final +{ + explicit StackHeapPageOptions(const ProductData &qbsProduct) + { + const auto &qbsProps = qbsProduct.moduleProperties(); + const QStringList flags = IarewUtils::cppModuleLinkerFlags(qbsProps); + const auto configDefs = IarewUtils::flagValues( + flags, QStringLiteral("--config_def")); + for (const auto &configDef : configDefs) { + const auto def = configDef.toString(); + if (def.startsWith(QLatin1String("_CSTACK_SIZE="))) { + stackSize = def.split(QLatin1Char('=')).at(1); + } else if (def.startsWith(QLatin1String("_HEAP_SIZE="))) { + heapSize = def.split(QLatin1Char('=')).at(1); + } + } + } + + QString stackSize; + QString heapSize; +}; + +} // namespace + +// Stm8GeneralSettingsGroup + +Stm8GeneralSettingsGroup::Stm8GeneralSettingsGroup( + const Project &qbsProject, + const ProductData &qbsProduct, + const std::vector<ProductData> &qbsProductDeps) +{ + Q_UNUSED(qbsProductDeps) + + setName(QByteArrayLiteral("General")); + setArchiveVersion(kGeneralArchiveVersion); + setDataVersion(kGeneralDataVersion); + setDataDebugInfo(gen::utils::debugInformation(qbsProduct)); + + const QString buildRootDirectory = gen::utils::buildRootPath(qbsProject); + + buildTargetPage(qbsProduct); + buildOutputPage(buildRootDirectory, qbsProduct); + buildLibraryConfigPage(buildRootDirectory, qbsProduct); + buildLibraryOptionsPage(qbsProduct); + buildStackHeapPage(qbsProduct); +} + +void Stm8GeneralSettingsGroup::buildTargetPage( + const ProductData &qbsProduct) +{ + const TargetPageOptions opts(qbsProduct); + // Add 'GenCodeModel' item + // (Code model: small/medium/large). + addOptionsGroup(QByteArrayLiteral("GenCodeModel"), + {opts.codeModel}); + // Add 'GenDataModel' item + // (Data model: small/medium/large). + addOptionsGroup(QByteArrayLiteral("GenDataModel"), + {opts.dataModel}); +} + +void Stm8GeneralSettingsGroup::buildOutputPage( + const QString &baseDirectory, + const ProductData &qbsProduct) +{ + const OutputPageOptions opts(baseDirectory, qbsProduct); + // Add 'GOutputBinary' item (Output file: executable/library). + addOptionsGroup(QByteArrayLiteral("GOutputBinary"), + {opts.binaryType}); + // Add 'ExePath' item (Executable/binaries output directory). + addOptionsGroup(QByteArrayLiteral("ExePath"), + {opts.binaryDirectory}); + // Add 'ObjPath' item (Object files output directory). + addOptionsGroup(QByteArrayLiteral("ObjPath"), + {opts.objectDirectory}); + // Add 'ListPath' item (List files output directory). + addOptionsGroup(QByteArrayLiteral("ListPath"), + {opts.listingDirectory}); +} + +void Stm8GeneralSettingsGroup::buildLibraryConfigPage( + const QString &baseDirectory, + const ProductData &qbsProduct) +{ + const LibraryConfigPageOptions opts(baseDirectory, qbsProduct); + // Add 'GenRuntimeLibSelect' and 'GenRuntimeLibSelectSlave' items + // (Link with runtime: none/normal/full/custom). + addOptionsGroup(QByteArrayLiteral("GenRuntimeLibSelect"), + {opts.libraryType}); + addOptionsGroup(QByteArrayLiteral("GenRuntimeLibSelectSlave"), + {opts.libraryType}); + // Add 'GenRTConfigPath' item (Runtime configuration file). + addOptionsGroup(QByteArrayLiteral("GenRTConfigPath"), + {opts.configPath}); +} + +void Stm8GeneralSettingsGroup::buildLibraryOptionsPage( + const ProductData &qbsProduct) +{ + const LibraryOptionsPageOptions opts(qbsProduct); + // Add 'GenLibOutFormatter' item (Printf formatter). + addOptionsGroup(QByteArrayLiteral("GenLibOutFormatter"), + {opts.printfFormatter}); + // Add 'GenLibInFormatter' item (Scanf formatter). + addOptionsGroup(QByteArrayLiteral("GenLibInFormatter"), + {opts.scanfFormatter}); +} + +void Stm8GeneralSettingsGroup::buildStackHeapPage( + const ProductData &qbsProduct) +{ + const StackHeapPageOptions opts(qbsProduct); + // Add 'GenStackSize' item (Stack size). + addOptionsGroup(QByteArrayLiteral("GenStackSize"), + {opts.stackSize}); + // Add 'GenHeapSize' item (Heap size). + addOptionsGroup(QByteArrayLiteral("GenHeapSize"), + {opts.heapSize}); +} + +} // namespace v3 +} // namespace stm8 +} // namespace iarew +} // namespace qbs diff --git a/src/plugins/generator/iarew/archs/stm8/stm8generalsettingsgroup_v3.h b/src/plugins/generator/iarew/archs/stm8/stm8generalsettingsgroup_v3.h new file mode 100644 index 000000000..20def0fd5 --- /dev/null +++ b/src/plugins/generator/iarew/archs/stm8/stm8generalsettingsgroup_v3.h @@ -0,0 +1,64 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt.io/licensing +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef QBS_IAREWSTM8GENERALSETTINGSGROUP_V3_H +#define QBS_IAREWSTM8GENERALSETTINGSGROUP_V3_H + +#include "../../iarewsettingspropertygroup.h" + +namespace qbs { +namespace iarew { +namespace stm8 { +namespace v3 { + +class Stm8GeneralSettingsGroup final : public IarewSettingsPropertyGroup +{ +public: + explicit Stm8GeneralSettingsGroup( + const Project &qbsProject, + const ProductData &qbsProduct, + const std::vector<ProductData> &qbsProductDeps); + +private: + void buildTargetPage(const ProductData &qbsProduct); + void buildOutputPage(const QString &baseDirectory, + const ProductData &qbsProduct); + void buildLibraryConfigPage(const QString &baseDirectory, + const ProductData &qbsProduct); + void buildLibraryOptionsPage(const ProductData &qbsProduct); + void buildStackHeapPage(const ProductData &qbsProduct); +}; + +} // namespace v3 +} // namespace stm8 +} // namespace iarew +} // namespace qbs + +#endif // QBS_IAREWSTM8GENERALSETTINGSGROUP_V3_H diff --git a/src/plugins/generator/iarew/archs/stm8/stm8linkersettingsgroup_v3.cpp b/src/plugins/generator/iarew/archs/stm8/stm8linkersettingsgroup_v3.cpp new file mode 100644 index 000000000..731c8d91e --- /dev/null +++ b/src/plugins/generator/iarew/archs/stm8/stm8linkersettingsgroup_v3.cpp @@ -0,0 +1,411 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt.io/licensing +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "stm8linkersettingsgroup_v3.h" + +#include "../../iarewutils.h" + +#include <QtCore/qdir.h> + +namespace qbs { +namespace iarew { +namespace stm8 { +namespace v3 { + +constexpr int kLinkerArchiveVersion = 5; +constexpr int kLinkerDataVersion = 4; + +namespace { + +// Config page options. + +struct ConfigPageOptions final +{ + explicit ConfigPageOptions(const QString &baseDirectory, + const ProductData &qbsProduct) + { + const auto &qbsProps = qbsProduct.moduleProperties(); + const QString toolkitPath = IarewUtils::toolkitRootPath(qbsProduct); + + // Enumerate all product linker config files + // (which are set trough 'linkerscript' tag). + const auto qbsGroups = qbsProduct.groups(); + for (const auto &qbsGroup : qbsGroups) { + const auto qbsArtifacts = qbsGroup.sourceArtifacts(); + for (const auto &qbsArtifact : qbsArtifacts) { + const auto qbsTags = qbsArtifact.fileTags(); + if (!qbsTags.contains(QLatin1String("linkerscript"))) + continue; + const QString fullConfigPath = qbsArtifact.filePath(); + if (fullConfigPath.startsWith(toolkitPath, Qt::CaseInsensitive)) { + const QString path = IarewUtils::toolkitRelativeFilePath( + toolkitPath, fullConfigPath); + configFilePaths.push_back(path); + } else { + const QString path = IarewUtils::projectRelativeFilePath( + baseDirectory, fullConfigPath); + configFilePaths.push_back(path); + } + } + } + + // Enumerate all product linker config files + // (which are set trough '-config' option). + const QStringList flags = IarewUtils::cppModuleLinkerFlags(qbsProps); + const QVariantList configPathValues = IarewUtils::flagValues( + flags, QStringLiteral("--config")); + for (const QVariant &configPathValue : configPathValues) { + const QString fullConfigPath = configPathValue.toString(); + if (fullConfigPath.startsWith(toolkitPath, Qt::CaseInsensitive)) { + const QString path = IarewUtils::toolkitRelativeFilePath( + toolkitPath, fullConfigPath); + if (!configFilePaths.contains(path)) + configFilePaths.push_back(path); + } else { + const QString path = IarewUtils::projectRelativeFilePath( + baseDirectory, fullConfigPath); + if (!configFilePaths.contains(path)) + configFilePaths.push_back(path); + } + } + + // Enumerate all config definition symbols (except + // the CSTACK_SIZE and HEAP_SIZE which are handles + // on the general page). + configDefinitions = IarewUtils::flagValues( + flags, QStringLiteral("--config_def")); + configDefinitions.erase(std::remove_if( + configDefinitions.begin(), + configDefinitions.end(), + [](const auto &definition){ + const auto def = definition.toString(); + return def.startsWith(QLatin1String("_CSTACK_SIZE")) + || def.startsWith(QLatin1String("_HEAP_SIZE")); + }), configDefinitions.end()); + } + + QVariantList configFilePaths; + QVariantList configDefinitions; +}; + +struct LibraryPageOptions final +{ + explicit LibraryPageOptions(const QString &baseDirectory, + const ProductData &qbsProduct, + const std::vector<ProductData> &qbsProductDeps) + { + const auto &qbsProps = qbsProduct.moduleProperties(); + const QString toolkitPath = IarewUtils::toolkitRootPath(qbsProduct); + + entryPoint = gen::utils::cppStringModuleProperty( + qbsProps, QStringLiteral("entryPoint")); + + // Add static libraries paths. + const QStringList staticLibrariesProps = + gen::utils::cppStringModuleProperties( + qbsProps, {QStringLiteral("staticLibraries")}); + for (const QString &staticLibrary : staticLibrariesProps) { + const QFileInfo staticLibraryInfo(staticLibrary); + if (staticLibraryInfo.isAbsolute()) { + const QString fullStaticLibraryPath = + staticLibraryInfo.absoluteFilePath(); + if (fullStaticLibraryPath.startsWith(toolkitPath, + Qt::CaseInsensitive)) { + const QString path = IarewUtils::toolkitRelativeFilePath( + toolkitPath, fullStaticLibraryPath); + staticLibraries.push_back(path); + } else { + const QString path = IarewUtils::projectRelativeFilePath( + baseDirectory, fullStaticLibraryPath); + staticLibraries.push_back(path); + } + } else { + staticLibraries.push_back(staticLibrary); + } + } + + // Add static libraries from product dependencies. + for (const ProductData &qbsProductDep : qbsProductDeps) { + const QString depBinaryPath = QLatin1String("$PROJ_DIR$/") + + gen::utils::targetBinaryPath(baseDirectory, + qbsProductDep); + staticLibraries.push_back(depBinaryPath); + } + } + + QString entryPoint; + QVariantList staticLibraries; +}; + +struct OptimizationsPageOptions final +{ + explicit OptimizationsPageOptions(const ProductData &qbsProduct) + { + const auto &qbsProps = qbsProduct.moduleProperties(); + const QStringList flags = IarewUtils::cppModuleLinkerFlags(qbsProps); + + mergeDuplicateSections = flags.contains( + QLatin1String("--merge_duplicate_sections")); + } + + bool mergeDuplicateSections = 0; +}; + +// Output page options. + +struct OutputPageOptions final +{ + explicit OutputPageOptions(const ProductData &qbsProduct) + { + outputFile = gen::utils::targetBinary(qbsProduct); + const auto &qbsProps = qbsProduct.moduleProperties(); + const QStringList flags = IarewUtils::cppModuleLinkerFlags(qbsProps); + + enableDebugInfo = !flags.contains(QLatin1String("--strip")); + } + + QString outputFile; + bool enableDebugInfo = 1; +}; + +// List page options. + +struct ListPageOptions final +{ + enum ListingAction { + NoListing, + GenerateListing + }; + + explicit ListPageOptions(const ProductData &qbsProduct) + { + const auto &qbsProps = qbsProduct.moduleProperties(); + generateMap = gen::utils::cppBooleanModuleProperty( + qbsProps, QStringLiteral("generateMapFile")) + ? ListPageOptions::GenerateListing + : ListPageOptions::NoListing; + } + + ListingAction generateMap = NoListing; +}; + +// Define page options. + +struct DefinePageOptions final +{ + explicit DefinePageOptions(const ProductData &qbsProduct) + { + const auto &qbsProps = qbsProduct.moduleProperties(); + const QStringList flags = IarewUtils::cppModuleLinkerFlags(qbsProps); + + defineSymbols = IarewUtils::flagValues( + flags, QStringLiteral("--define_symbol")); + } + + QVariantList defineSymbols; +}; + +// Diagnostics page options. + +struct DiagnosticsPageOptions final +{ + explicit DiagnosticsPageOptions(const ProductData &qbsProduct) + { + const auto &qbsProps = qbsProduct.moduleProperties(); + warningsAsErrors = gen::utils::cppIntegerModuleProperty( + qbsProps, QStringLiteral("treatWarningsAsErrors")); + } + + int warningsAsErrors = 0; +}; + +} // namespace + +// Stm8LinkerSettingsGroup + +Stm8LinkerSettingsGroup::Stm8LinkerSettingsGroup( + const Project &qbsProject, + const ProductData &qbsProduct, + const std::vector<ProductData> &qbsProductDeps) +{ + setName(QByteArrayLiteral("ILINK")); + setArchiveVersion(kLinkerArchiveVersion); + setDataVersion(kLinkerDataVersion); + setDataDebugInfo(gen::utils::debugInformation(qbsProduct)); + + const QString buildRootDirectory = gen::utils::buildRootPath(qbsProject); + + buildConfigPage(buildRootDirectory, qbsProduct); + buildLibraryPage(buildRootDirectory, qbsProduct, qbsProductDeps); + buildOptimizationsPage(qbsProduct); + buildOutputPage(qbsProduct); + buildListPage(qbsProduct); + buildDefinePage(qbsProduct); + buildDiagnosticsPage(qbsProduct); + + // Should be called as latest stage! + buildExtraOptionsPage(qbsProduct); +} + +void Stm8LinkerSettingsGroup::buildConfigPage( + const QString &baseDirectory, + const ProductData &qbsProduct) +{ + ConfigPageOptions opts(baseDirectory, qbsProduct); + + if (opts.configFilePaths.count() > 0) { + // Note: IAR IDE does not allow to specify a multiple config files, + // although the IAR linker support it. So, we use followig 'trick': + // we take a first config file and to add it as usual to required items; + // and then an other remainders we forward to the "Extra options page". + const QVariant configPath = opts.configFilePaths.takeFirst(); + // Add 'IlinkIcfOverride' item (Override default). + addOptionsGroup(QByteArrayLiteral("IlinkIcfOverride"), + {1}); + // Add 'IlinkIcfFile' item (Linke configuration file). + addOptionsGroup(QByteArrayLiteral("IlinkIcfFile"), + {configPath}); + + // Add remainder configuration files to the "Extra options page". + if (!opts.configFilePaths.isEmpty()) { + for (QVariant &configPath : opts.configFilePaths) + configPath = QLatin1String("--config ") + configPath.toString(); + + m_extraOptions << opts.configFilePaths; + } + } + + // Add 'IlinkConfigDefines' item (Configuration file + // symbol definitions). + addOptionsGroup(QByteArrayLiteral("IlinkConfigDefines"), + opts.configDefinitions); +} + +void Stm8LinkerSettingsGroup::buildLibraryPage( + const QString &baseDirectory, + const ProductData &qbsProduct, + const std::vector<ProductData> &qbsProductDeps) +{ + LibraryPageOptions opts(baseDirectory, qbsProduct, qbsProductDeps); + + // Add 'IlinkOverrideProgramEntryLabel' item + // (Override default program entry). + addOptionsGroup(QByteArrayLiteral("IlinkOverrideProgramEntryLabel"), + {1}); + + if (opts.entryPoint.isEmpty()) { + // Add 'IlinkProgramEntryLabelSelect' item + // (Defined by application). + addOptionsGroup(QByteArrayLiteral("IlinkProgramEntryLabelSelect"), + {1}); + } else { + // Add 'IlinkProgramEntryLabel' item + // (Entry symbol). + addOptionsGroup(QByteArrayLiteral("IlinkProgramEntryLabel"), + {opts.entryPoint}); + } + + // Add 'IlinkAdditionalLibs' item (Additional libraries). + addOptionsGroup(QByteArrayLiteral("IlinkAdditionalLibs"), + {opts.staticLibraries}); +} + +void Stm8LinkerSettingsGroup::buildOptimizationsPage( + const ProductData &qbsProduct) +{ + OptimizationsPageOptions opts(qbsProduct); + + // Add 'IlinkOptMergeDuplSections' item + // (Merge duplicate sections). + addOptionsGroup(QByteArrayLiteral("IlinkOptMergeDuplSections"), + {opts.mergeDuplicateSections}); +} + +void Stm8LinkerSettingsGroup::buildOutputPage( + const ProductData &qbsProduct) +{ + const OutputPageOptions opts(qbsProduct); + + // Add 'IlinkOutputFile' item (Output file name). + addOptionsGroup(QByteArrayLiteral("IlinkOutputFile"), + {opts.outputFile}); + // Add 'IlinkDebugInfoEnable' item + // (Include debug information in output). + addOptionsGroup(QByteArrayLiteral("IlinkDebugInfoEnable"), + {opts.enableDebugInfo}); +} + +void Stm8LinkerSettingsGroup::buildListPage( + const ProductData &qbsProduct) +{ + const ListPageOptions opts(qbsProduct); + // Add 'IlinkMapFile' item (Generate linker map file). + addOptionsGroup(QByteArrayLiteral("IlinkMapFile"), + {opts.generateMap}); +} + +void Stm8LinkerSettingsGroup::buildDefinePage( + const ProductData &qbsProduct) +{ + const DefinePageOptions opts(qbsProduct); + // Add 'IlinkDefines' item (Defined symbols). + addOptionsGroup(QByteArrayLiteral("IlinkDefines"), + opts.defineSymbols); +} + +void Stm8LinkerSettingsGroup::buildDiagnosticsPage( + const ProductData &qbsProduct) +{ + const DiagnosticsPageOptions opts(qbsProduct); + // Add 'IlinkWarningsAreErrors' item (Treat all warnings as errors). + addOptionsGroup(QByteArrayLiteral("IlinkWarningsAreErrors"), + {opts.warningsAsErrors}); +} + +void Stm8LinkerSettingsGroup::buildExtraOptionsPage( + const ProductData &qbsProduct) +{ + Q_UNUSED(qbsProduct) + + if (m_extraOptions.isEmpty()) + return; + + // Add 'IlinkUseExtraOptions' (Use command line options). + addOptionsGroup(QByteArrayLiteral("IlinkUseExtraOptions"), + {1}); + // Add 'IlinkExtraOptions' item (Command line options). + addOptionsGroup(QByteArrayLiteral("IlinkExtraOptions"), + m_extraOptions); +} + +} // namespace v3 +} // namespace stm8 +} // namespace iarew +} // namespace qbs diff --git a/src/plugins/generator/iarew/archs/stm8/stm8linkersettingsgroup_v3.h b/src/plugins/generator/iarew/archs/stm8/stm8linkersettingsgroup_v3.h new file mode 100644 index 000000000..b214ebe35 --- /dev/null +++ b/src/plugins/generator/iarew/archs/stm8/stm8linkersettingsgroup_v3.h @@ -0,0 +1,73 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt.io/licensing +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef QBS_IAREWSTM8LINKERSETTINGSGROUP_V3_H +#define QBS_IAREWSTM8LINKERSETTINGSGROUP_V3_H + +#include "../../iarewsettingspropertygroup.h" + +namespace qbs { +namespace iarew { +namespace stm8 { +namespace v3 { + +class Stm8LinkerSettingsGroup final : public IarewSettingsPropertyGroup +{ +public: + explicit Stm8LinkerSettingsGroup( + const Project &qbsProject, + const ProductData &qbsProduct, + const std::vector<ProductData> &qbsProductDeps); + +private: + void buildConfigPage(const QString &baseDirectory, + const ProductData &qbsProduct); + void buildLibraryPage(const QString &baseDirectory, + const ProductData &qbsProduct, + const std::vector<ProductData> &qbsProductDeps); + void buildOptimizationsPage(const ProductData &qbsProduct); + + + + void buildOutputPage(const ProductData &qbsProduct); + void buildListPage(const ProductData &qbsProduct); + void buildDefinePage(const ProductData &qbsProduct); + void buildDiagnosticsPage(const ProductData &qbsProduct); + void buildExtraOptionsPage(const ProductData &qbsProduct); + + QVariantList m_extraOptions; +}; + +} // namespace v3 +} // namespace stm8 +} // namespace iarew +} // namespace qbs + +#endif // QBS_IAREWSTM8LINKERSETTINGSGROUP_V3_H diff --git a/src/plugins/generator/iarew/iarew.pro b/src/plugins/generator/iarew/iarew.pro new file mode 100644 index 000000000..7de474a45 --- /dev/null +++ b/src/plugins/generator/iarew/iarew.pro @@ -0,0 +1,133 @@ +include(../../plugins.pri) +include(../../../shared/json/json.pri) + +TARGET = iarewgenerator + +QT = core + +# Plugin file. + +SOURCES += \ + $$PWD/iarewgeneratorplugin.cpp \ + +# Common files. + +HEADERS += \ + $$PWD/iarewfileversionproperty.h \ + $$PWD/iarewgenerator.h \ + $$PWD/iarewoptionpropertygroup.h \ + $$PWD/iarewproject.h \ + $$PWD/iarewprojectwriter.h \ + $$PWD/iarewsettingspropertygroup.h \ + $$PWD/iarewsourcefilepropertygroup.h \ + $$PWD/iarewsourcefilespropertygroup.h \ + $$PWD/iarewtoolchainpropertygroup.h \ + $$PWD/iarewutils.h \ + $$PWD/iarewversioninfo.h \ + $$PWD/iarewworkspace.h \ + $$PWD/iarewworkspacewriter.h + +SOURCES += \ + $$PWD/iarewfileversionproperty.cpp \ + $$PWD/iarewgenerator.cpp \ + $$PWD/iarewoptionpropertygroup.cpp \ + $$PWD/iarewproject.cpp \ + $$PWD/iarewprojectwriter.cpp \ + $$PWD/iarewsettingspropertygroup.cpp \ + $$PWD/iarewsourcefilepropertygroup.cpp \ + $$PWD/iarewsourcefilespropertygroup.cpp \ + $$PWD/iarewtoolchainpropertygroup.cpp \ + $$PWD/iarewutils.cpp \ + $$PWD/iarewversioninfo.cpp \ + $$PWD/iarewworkspace.cpp \ + $$PWD/iarewworkspacewriter.cpp + +# For ARM architecture. + +HEADERS += \ + $$PWD/archs/arm/armarchiversettingsgroup_v8.h \ + $$PWD/archs/arm/armassemblersettingsgroup_v8.h \ + $$PWD/archs/arm/armbuildconfigurationgroup_v8.h \ + $$PWD/archs/arm/armcompilersettingsgroup_v8.h \ + $$PWD/archs/arm/armgeneralsettingsgroup_v8.h \ + $$PWD/archs/arm/armlinkersettingsgroup_v8.h + +SOURCES += \ + $$PWD/archs/arm/armarchiversettingsgroup_v8.cpp \ + $$PWD/archs/arm/armassemblersettingsgroup_v8.cpp \ + $$PWD/archs/arm/armbuildconfigurationgroup_v8.cpp \ + $$PWD/archs/arm/armcompilersettingsgroup_v8.cpp \ + $$PWD/archs/arm/armgeneralsettingsgroup_v8.cpp \ + $$PWD/archs/arm/armlinkersettingsgroup_v8.cpp + +# For AVR architecture. + +HEADERS += \ + $$PWD/archs/avr/avrarchiversettingsgroup_v7.h \ + $$PWD/archs/avr/avrassemblersettingsgroup_v7.h \ + $$PWD/archs/avr/avrbuildconfigurationgroup_v7.h \ + $$PWD/archs/avr/avrcompilersettingsgroup_v7.h \ + $$PWD/archs/avr/avrgeneralsettingsgroup_v7.h \ + $$PWD/archs/avr/avrlinkersettingsgroup_v7.h + +SOURCES += \ + $$PWD/archs/avr/avrarchiversettingsgroup_v7.cpp \ + $$PWD/archs/avr/avrassemblersettingsgroup_v7.cpp \ + $$PWD/archs/avr/avrbuildconfigurationgroup_v7.cpp \ + $$PWD/archs/avr/avrcompilersettingsgroup_v7.cpp \ + $$PWD/archs/avr/avrgeneralsettingsgroup_v7.cpp \ + $$PWD/archs/avr/avrlinkersettingsgroup_v7.cpp + +# For MCS51 architecture. + +HEADERS += \ + $$PWD/archs/mcs51/mcs51archiversettingsgroup_v10.h \ + $$PWD/archs/mcs51/mcs51assemblersettingsgroup_v10.h \ + $$PWD/archs/mcs51/mcs51buildconfigurationgroup_v10.h \ + $$PWD/archs/mcs51/mcs51compilersettingsgroup_v10.h \ + $$PWD/archs/mcs51/mcs51generalsettingsgroup_v10.h \ + $$PWD/archs/mcs51/mcs51linkersettingsgroup_v10.h + +SOURCES += \ + $$PWD/archs/mcs51/mcs51archiversettingsgroup_v10.cpp \ + $$PWD/archs/mcs51/mcs51assemblersettingsgroup_v10.cpp \ + $$PWD/archs/mcs51/mcs51buildconfigurationgroup_v10.cpp \ + $$PWD/archs/mcs51/mcs51compilersettingsgroup_v10.cpp \ + $$PWD/archs/mcs51/mcs51generalsettingsgroup_v10.cpp \ + $$PWD/archs/mcs51/mcs51linkersettingsgroup_v10.cpp + +# For STM8 architecture. + +HEADERS += \ + $$PWD/archs/stm8/stm8archiversettingsgroup_v3.h \ + $$PWD/archs/stm8/stm8assemblersettingsgroup_v3.h \ + $$PWD/archs/stm8/stm8buildconfigurationgroup_v3.h \ + $$PWD/archs/stm8/stm8compilersettingsgroup_v3.h \ + $$PWD/archs/stm8/stm8generalsettingsgroup_v3.h \ + $$PWD/archs/stm8/stm8linkersettingsgroup_v3.h + +SOURCES += \ + $$PWD/archs/stm8/stm8archiversettingsgroup_v3.cpp \ + $$PWD/archs/stm8/stm8assemblersettingsgroup_v3.cpp \ + $$PWD/archs/stm8/stm8buildconfigurationgroup_v3.cpp \ + $$PWD/archs/stm8/stm8compilersettingsgroup_v3.cpp \ + $$PWD/archs/stm8/stm8generalsettingsgroup_v3.cpp \ + $$PWD/archs/stm8/stm8linkersettingsgroup_v3.cpp + +# For MSP430 architecture. + +HEADERS += \ + $$PWD/archs/msp430/msp430archiversettingsgroup_v7.h \ + $$PWD/archs/msp430/msp430assemblersettingsgroup_v7.h \ + $$PWD/archs/msp430/msp430buildconfigurationgroup_v7.h \ + $$PWD/archs/msp430/msp430compilersettingsgroup_v7.h \ + $$PWD/archs/msp430/msp430generalsettingsgroup_v7.h \ + $$PWD/archs/msp430/msp430linkersettingsgroup_v7.h + +SOURCES += \ + $$PWD/archs/msp430/msp430archiversettingsgroup_v7.cpp \ + $$PWD/archs/msp430/msp430assemblersettingsgroup_v7.cpp \ + $$PWD/archs/msp430/msp430buildconfigurationgroup_v7.cpp \ + $$PWD/archs/msp430/msp430compilersettingsgroup_v7.cpp \ + $$PWD/archs/msp430/msp430generalsettingsgroup_v7.cpp \ + $$PWD/archs/msp430/msp430linkersettingsgroup_v7.cpp diff --git a/src/plugins/generator/iarew/iarew.qbs b/src/plugins/generator/iarew/iarew.qbs new file mode 100644 index 000000000..7b2270426 --- /dev/null +++ b/src/plugins/generator/iarew/iarew.qbs @@ -0,0 +1,132 @@ +import qbs +import "../../qbsplugin.qbs" as QbsPlugin + +QbsPlugin { + Depends { name: "qbsjson" } + + name: "iarewgenerator" + + files: ["iarewgeneratorplugin.cpp"] + + Group { + name: "IAR EW generator common" + files: [ + "iarewfileversionproperty.cpp", + "iarewfileversionproperty.h", + "iarewgenerator.cpp", + "iarewgenerator.h", + "iarewoptionpropertygroup.cpp", + "iarewoptionpropertygroup.h", + "iarewproject.cpp", + "iarewproject.h", + "iarewprojectwriter.cpp", + "iarewprojectwriter.h", + "iarewsettingspropertygroup.cpp", + "iarewsettingspropertygroup.h", + "iarewsourcefilepropertygroup.cpp", + "iarewsourcefilepropertygroup.h", + "iarewsourcefilespropertygroup.cpp", + "iarewsourcefilespropertygroup.h", + "iarewtoolchainpropertygroup.cpp", + "iarewtoolchainpropertygroup.h", + "iarewutils.cpp", + "iarewutils.h", + "iarewversioninfo.cpp", + "iarewversioninfo.h", + "iarewworkspace.cpp", + "iarewworkspace.h", + "iarewworkspacewriter.cpp", + "iarewworkspacewriter.h", + ] + } + Group { + name: "IAR EW generator for ARM" + prefix: "archs/arm/" + files: [ + "armarchiversettingsgroup_v8.cpp", + "armarchiversettingsgroup_v8.h", + "armassemblersettingsgroup_v8.cpp", + "armassemblersettingsgroup_v8.h", + "armbuildconfigurationgroup_v8.cpp", + "armbuildconfigurationgroup_v8.h", + "armcompilersettingsgroup_v8.cpp", + "armcompilersettingsgroup_v8.h", + "armgeneralsettingsgroup_v8.cpp", + "armgeneralsettingsgroup_v8.h", + "armlinkersettingsgroup_v8.cpp", + "armlinkersettingsgroup_v8.h", + ] + } + Group { + name: "IAR EW generator for AVR" + prefix: "archs/avr/" + files: [ + "avrarchiversettingsgroup_v7.cpp", + "avrarchiversettingsgroup_v7.h", + "avrassemblersettingsgroup_v7.cpp", + "avrassemblersettingsgroup_v7.h", + "avrbuildconfigurationgroup_v7.cpp", + "avrbuildconfigurationgroup_v7.h", + "avrcompilersettingsgroup_v7.cpp", + "avrcompilersettingsgroup_v7.h", + "avrgeneralsettingsgroup_v7.cpp", + "avrgeneralsettingsgroup_v7.h", + "avrlinkersettingsgroup_v7.cpp", + "avrlinkersettingsgroup_v7.h", + ] + } + Group { + name: "IAR EW generator for MCS51" + prefix: "archs/mcs51/" + files: [ + "mcs51archiversettingsgroup_v10.cpp", + "mcs51archiversettingsgroup_v10.h", + "mcs51assemblersettingsgroup_v10.cpp", + "mcs51assemblersettingsgroup_v10.h", + "mcs51buildconfigurationgroup_v10.cpp", + "mcs51buildconfigurationgroup_v10.h", + "mcs51compilersettingsgroup_v10.cpp", + "mcs51compilersettingsgroup_v10.h", + "mcs51generalsettingsgroup_v10.cpp", + "mcs51generalsettingsgroup_v10.h", + "mcs51linkersettingsgroup_v10.cpp", + "mcs51linkersettingsgroup_v10.h", + ] + } + Group { + name: "IAR EW generator for STM8" + prefix: "archs/stm8/" + files: [ + "stm8archiversettingsgroup_v3.cpp", + "stm8archiversettingsgroup_v3.h", + "stm8assemblersettingsgroup_v3.cpp", + "stm8assemblersettingsgroup_v3.h", + "stm8buildconfigurationgroup_v3.cpp", + "stm8buildconfigurationgroup_v3.h", + "stm8compilersettingsgroup_v3.cpp", + "stm8compilersettingsgroup_v3.h", + "stm8generalsettingsgroup_v3.cpp", + "stm8generalsettingsgroup_v3.h", + "stm8linkersettingsgroup_v3.cpp", + "stm8linkersettingsgroup_v3.h", + ] + } + Group { + name: "IAR EW generator for MSP430" + prefix: "archs/msp430/" + files: [ + "msp430archiversettingsgroup_v7.cpp", + "msp430archiversettingsgroup_v7.h", + "msp430assemblersettingsgroup_v7.cpp", + "msp430assemblersettingsgroup_v7.h", + "msp430buildconfigurationgroup_v7.cpp", + "msp430buildconfigurationgroup_v7.h", + "msp430compilersettingsgroup_v7.cpp", + "msp430compilersettingsgroup_v7.h", + "msp430generalsettingsgroup_v7.cpp", + "msp430generalsettingsgroup_v7.h", + "msp430linkersettingsgroup_v7.cpp", + "msp430linkersettingsgroup_v7.h", + ] + } +} diff --git a/src/plugins/generator/iarew/iarewfileversionproperty.cpp b/src/plugins/generator/iarew/iarewfileversionproperty.cpp new file mode 100644 index 000000000..446b385b8 --- /dev/null +++ b/src/plugins/generator/iarew/iarewfileversionproperty.cpp @@ -0,0 +1,57 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt.io/licensing +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "iarewfileversionproperty.h" +#include "iarewversioninfo.h" + +namespace qbs { + +static QByteArray buildFileVersion(const IarewVersionInfo &versionInfo) +{ + switch (versionInfo.marketingVersion()) { + case 3: + case 7: + case 8: + case 10: + return QByteArrayLiteral('3'); + default: + return {}; + } +} + +IarewFileVersionProperty::IarewFileVersionProperty( + const IarewVersionInfo &versionInfo) +{ + setName(QByteArrayLiteral("fileVersion")); + const QByteArray fileVersion = buildFileVersion(versionInfo); + setValue(fileVersion); +} + +} // namespace qbs diff --git a/src/plugins/generator/iarew/iarewfileversionproperty.h b/src/plugins/generator/iarew/iarewfileversionproperty.h new file mode 100644 index 000000000..d377979fa --- /dev/null +++ b/src/plugins/generator/iarew/iarewfileversionproperty.h @@ -0,0 +1,49 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt.io/licensing +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef QBS_IAREWFILEVERSIONPROPERTY_H +#define QBS_IAREWFILEVERSIONPROPERTY_H + +#include <generators/xmlproperty.h> + +namespace qbs { + +class IarewVersionInfo; + +class IarewFileVersionProperty final : public gen::xml::Property +{ +public: + explicit IarewFileVersionProperty( + const IarewVersionInfo &versionInfo); +}; + +} // namespace qbs + +#endif // QBS_IAREWFILEVERSIONPROPERTY_H diff --git a/src/plugins/generator/iarew/iarewgenerator.cpp b/src/plugins/generator/iarew/iarewgenerator.cpp new file mode 100644 index 000000000..e6b308182 --- /dev/null +++ b/src/plugins/generator/iarew/iarewgenerator.cpp @@ -0,0 +1,158 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt.io/licensing +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "iarewgenerator.h" +#include "iarewproject.h" +#include "iarewprojectwriter.h" +#include "iarewworkspace.h" +#include "iarewworkspacewriter.h" + +#include <generators/generatableprojectiterator.h> + +#include <logging/logger.h> +#include <logging/translator.h> + +#include <tools/filesaver.h> + +namespace qbs { + +static QString targetFilePath(const QString &baseName, + const QString &baseBuildDirectory) +{ + return QDir(baseBuildDirectory).absoluteFilePath( + baseName + QStringLiteral(".ewp")); +} + +static QString targetFilePath(const GeneratableProductData &product, + const QString &baseBuildDirectory) +{ + return targetFilePath(product.name(), baseBuildDirectory); +} + +static void writeProjectFiles(const std::map<QString, + std::shared_ptr<IarewProject>> &projects, + const Internal::Logger &logger) +{ + for (const auto &item : projects) { + const QString projectFilePath = item.first; + Internal::FileSaver file(projectFilePath.toStdString()); + if (!file.open()) + throw ErrorInfo(Internal::Tr::tr("Cannot open %s for writing") + .arg(projectFilePath)); + + std::shared_ptr<IarewProject> project = item.second; + IarewProjectWriter writer(file.device()); + if (!(writer.write(project.get()) && file.commit())) + throw ErrorInfo(Internal::Tr::tr("Failed to generate %1") + .arg(projectFilePath)); + + logger.qbsInfo() << Internal::Tr::tr("Generated %1").arg( + QFileInfo(projectFilePath).fileName()); + } +} + +static void writeWorkspace(const std::shared_ptr<IarewWorkspace> &wokspace, + const QString &workspaceFilePath, + const Internal::Logger &logger) +{ + Internal::FileSaver file(workspaceFilePath.toStdString()); + if (!file.open()) + throw ErrorInfo(Internal::Tr::tr("Cannot open %s for writing") + .arg(workspaceFilePath)); + + IarewWorkspaceWriter writer(file.device()); + if (!(writer.write(wokspace.get()) && file.commit())) + throw ErrorInfo(Internal::Tr::tr("Failed to generate %1") + .arg(workspaceFilePath)); + + logger.qbsInfo() << Internal::Tr::tr("Generated %1").arg( + QFileInfo(workspaceFilePath).fileName()); +} + +IarewGenerator::IarewGenerator(const IarewVersionInfo &versionInfo) + : m_versionInfo(versionInfo) +{ +} + +QString IarewGenerator::generatorName() const +{ + return QStringLiteral("iarew%1").arg(m_versionInfo.marketingVersion()); +} + +void IarewGenerator::reset() +{ + m_workspace.reset(); + m_workspaceFilePath.clear(); + m_projects.clear(); +} + +void IarewGenerator::generate() +{ + GeneratableProjectIterator it(project()); + it.accept(this); + + writeProjectFiles(m_projects, logger()); + writeWorkspace(m_workspace, m_workspaceFilePath, logger()); + + reset(); +} + +void IarewGenerator::visitProject(const GeneratableProject &project) +{ + const QDir buildDir = project.baseBuildDirectory(); + + m_workspaceFilePath = buildDir.absoluteFilePath( + project.name() + QStringLiteral(".eww")); + m_workspace = std::make_shared<IarewWorkspace>(m_workspaceFilePath); +} + +void IarewGenerator::visitProjectData(const GeneratableProject &project, + const GeneratableProjectData &projectData) +{ + Q_UNUSED(project) + Q_UNUSED(projectData) +} + +void IarewGenerator::visitProduct(const GeneratableProject &project, + const GeneratableProjectData &projectData, + const GeneratableProductData &productData) +{ + Q_UNUSED(projectData); + const QString projectFilePath = targetFilePath( + productData, project.baseBuildDirectory().absolutePath()); + const auto targetProject = std::make_shared<IarewProject>( + project, productData, + m_versionInfo); + + m_projects.insert({projectFilePath, targetProject}); + m_workspace->addProject(projectFilePath); +} + +} // namespace qbs diff --git a/src/plugins/generator/iarew/iarewgenerator.h b/src/plugins/generator/iarew/iarewgenerator.h new file mode 100644 index 000000000..f8c1298f0 --- /dev/null +++ b/src/plugins/generator/iarew/iarewgenerator.h @@ -0,0 +1,70 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt.io/licensing +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef QBS_IAREWGENERATOR_H +#define QBS_IAREWGENERATOR_H + +#include "iarewversioninfo.h" + +#include <generators/generator.h> +#include <generators/igeneratableprojectvisitor.h> + +namespace qbs { + +class IarewProject; +class IarewWorkspace; + +class IarewGenerator final : public ProjectGenerator, private IGeneratableProjectVisitor +{ +public: + explicit IarewGenerator(const IarewVersionInfo &versionInfo); + + QString generatorName() const final; + void generate() final; + +private: + void reset(); + + void visitProject(const GeneratableProject &project) final; + void visitProjectData(const GeneratableProject &project, + const GeneratableProjectData &projectData) final; + void visitProduct(const GeneratableProject &project, + const GeneratableProjectData &projectData, + const GeneratableProductData &productData) final; + + const IarewVersionInfo m_versionInfo; + std::shared_ptr<IarewWorkspace> m_workspace; + QString m_workspaceFilePath; + std::map<QString, std::shared_ptr<IarewProject>> m_projects; +}; + +} // namespace qbs + +#endif // QBS_IAREWGENERATOR_H diff --git a/src/plugins/generator/iarew/iarewgeneratorplugin.cpp b/src/plugins/generator/iarew/iarewgeneratorplugin.cpp new file mode 100644 index 000000000..9f0798573 --- /dev/null +++ b/src/plugins/generator/iarew/iarewgeneratorplugin.cpp @@ -0,0 +1,67 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qbs. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "iarewgenerator.h" +#include "iarewversioninfo.h" + +#include <tools/projectgeneratormanager.h> +#include <tools/qbspluginmanager.h> + +static void QbsIarewGeneratorPluginLoad() +{ + for (const auto &info : qbs::IarewVersionInfo::knownVersions()) { + qbs::ProjectGeneratorManager::registerGenerator( + std::make_shared<qbs::IarewGenerator>(info)); + } +} + +static void QbsIarewGeneratorPluginUnload() +{ +} + +#ifndef GENERATOR_EXPORT +#if defined(WIN32) || defined(_WIN32) +#define GENERATOR_EXPORT __declspec(dllexport) +#else +#define GENERATOR_EXPORT __attribute__((visibility("default"))) +#endif +#endif + +QBS_REGISTER_STATIC_PLUGIN(extern "C" GENERATOR_EXPORT, QbsIarewGeneratorPlugin, + QbsIarewGeneratorPluginLoad, QbsIarewGeneratorPluginUnload) diff --git a/src/plugins/generator/iarew/iarewoptionpropertygroup.cpp b/src/plugins/generator/iarew/iarewoptionpropertygroup.cpp new file mode 100644 index 000000000..8b9f79f1c --- /dev/null +++ b/src/plugins/generator/iarew/iarewoptionpropertygroup.cpp @@ -0,0 +1,57 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt.io/licensing +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "iarewoptionpropertygroup.h" + +namespace qbs { + +IarewOptionPropertyGroup::IarewOptionPropertyGroup( + QByteArray name, const QVariantList &states, int version) + : gen::xml::PropertyGroup(QByteArrayLiteral("option")) +{ + // Append name property item. + appendChild<gen::xml::Property>(QByteArrayLiteral("name"), + std::move(name)); + + // Append version property item. + if (version >= 0) + appendChild<gen::xml::Property>(QByteArrayLiteral("version"), + std::move(version)); + + // Append state property items. + for (const auto &state : states) { + if (state.isNull()) + continue; + appendChild<gen::xml::Property>(QByteArrayLiteral("state"), + std::move(state)); + } +} + +} // namespace qbs diff --git a/src/plugins/generator/iarew/iarewoptionpropertygroup.h b/src/plugins/generator/iarew/iarewoptionpropertygroup.h new file mode 100644 index 000000000..d24fe3a9d --- /dev/null +++ b/src/plugins/generator/iarew/iarewoptionpropertygroup.h @@ -0,0 +1,51 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt.io/licensing +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef QBS_IAREWOPTIONPROPERTYGROUP_H +#define QBS_IAREWOPTIONPROPERTYGROUP_H + +#include <generators/xmlpropertygroup.h> + +//#include <QtCore/qvariant.h> + +namespace qbs { + +class IarewOptionPropertyGroup final + : public gen::xml::PropertyGroup +{ +public: + explicit IarewOptionPropertyGroup( + QByteArray name, const QVariantList &states, + int version = -1); +}; + +} // namespace qbs + +#endif // QBS_IAREWOPTIONPROPERTYGROUP_H diff --git a/src/plugins/generator/iarew/iarewproject.cpp b/src/plugins/generator/iarew/iarewproject.cpp new file mode 100644 index 000000000..3e6a03ac2 --- /dev/null +++ b/src/plugins/generator/iarew/iarewproject.cpp @@ -0,0 +1,130 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt.io/licensing +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "iarewfileversionproperty.h" +#include "iarewproject.h" +#include "iarewsourcefilespropertygroup.h" +#include "iarewutils.h" +#include "iarewversioninfo.h" + +#include "archs/arm/armbuildconfigurationgroup_v8.h" +#include "archs/avr/avrbuildconfigurationgroup_v7.h" +#include "archs/mcs51/mcs51buildconfigurationgroup_v10.h" +#include "archs/stm8/stm8buildconfigurationgroup_v3.h" +#include "archs/msp430/msp430buildconfigurationgroup_v7.h" + +#include <logging/translator.h> + +namespace qbs { + +IarewProject::IarewProject(const GeneratableProject &genProject, + const GeneratableProductData &genProduct, + const IarewVersionInfo &versionInfo) +{ + Q_ASSERT(genProject.projects.size() == genProject.commandLines.size()); + Q_ASSERT(genProject.projects.size() == genProduct.data.size()); + + // Create available configuration group factories. + m_factories.push_back(std::make_unique< + iarew::arm::v8::ArmBuildConfigurationGroupFactory>()); + m_factories.push_back(std::make_unique< + iarew::avr::v7::AvrBuildConfigurationGroupFactory>()); + m_factories.push_back(std::make_unique< + iarew::mcs51::v10::Mcs51BuildConfigurationGroupFactory>()); + m_factories.push_back(std::make_unique< + iarew::stm8::v3::Stm8BuildConfigurationGroupFactory>()); + m_factories.push_back(std::make_unique< + iarew::msp430::v7::Msp430BuildConfigurationGroupFactory>()); + + // Construct file version item. + appendChild<IarewFileVersionProperty>(versionInfo); + + // Construct all build configurations items. + const int configsCount = std::max(genProject.projects.size(), + genProduct.data.size()); + for (auto configIndex = 0; configIndex < configsCount; ++configIndex) { + const qbs::Project qbsProject = genProject.projects + .values().at(configIndex); + const ProductData qbsProduct = genProduct.data.values().at(configIndex); + const QString confName = gen::utils::buildConfigurationName(qbsProject); + const std::vector<ProductData> qbsProductDeps = gen::utils::dependenciesOf + (qbsProduct, genProject, confName); + + const auto arch = gen::utils::architecture(qbsProject); + if (arch == gen::utils::Architecture::Unknown) + throw ErrorInfo(Internal::Tr::tr("Target architecture is not set," + " please use the 'profile' option")); + + // Construct the build configuration item, which are depend from + // the architecture and the version. + const auto factoryEnd = m_factories.cend(); + const auto factoryIt = std::find_if( + m_factories.cbegin(), factoryEnd, + [arch, versionInfo](const auto &factory) { + return factory->canCreate(arch, versionInfo.version()); + }); + if (factoryIt == factoryEnd) { + throw ErrorInfo(Internal::Tr::tr("Incompatible target architecture '%1'" + " for IAR EW version %2xxx") + .arg(gen::utils::architectureName(arch)) + .arg(versionInfo.marketingVersion())); + } + auto configGroup = (*factoryIt)->create( + qbsProject, qbsProduct, qbsProductDeps); + appendChild(std::move(configGroup)); + } + + // Construct all file groups items. + QMapIterator<QString, qbs::ProductData> dataIt(genProduct.data); + while (dataIt.hasNext()) { + dataIt.next(); + const auto groups = dataIt.value().groups(); + for (const auto &group : groups) { + // Ignore disabled groups (e.g. when its condition property is false). + if (!group.isEnabled()) + continue; + auto sourceArtifacts = group.sourceArtifacts(); + // Remove the linker script artifacts. + sourceArtifacts.erase(std::remove_if(sourceArtifacts.begin(), + sourceArtifacts.end(), + [](const auto &artifact){ + const auto tags = artifact.fileTags(); + return tags.contains(QLatin1String("linkerscript")); + }), sourceArtifacts.end()); + + if (sourceArtifacts.isEmpty()) + continue; + appendChild<IarewSourceFilesPropertyGroup>( + genProject, group.name(), sourceArtifacts); + } + } +} + +} // namespace qbs diff --git a/src/plugins/generator/iarew/iarewproject.h b/src/plugins/generator/iarew/iarewproject.h new file mode 100644 index 000000000..567a58c55 --- /dev/null +++ b/src/plugins/generator/iarew/iarewproject.h @@ -0,0 +1,56 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt.io/licensing +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef QBS_IAREWPROJECT_H +#define QBS_IAREWPROJECT_H + +#include <generators/generatordata.h> +#include <generators/xmlproject.h> +#include <generators/xmlpropertygroup.h> + +#include <memory> + +namespace qbs { + +class IarewVersionInfo; + +class IarewProject final : public gen::xml::Project +{ +public: + explicit IarewProject(const GeneratableProject &genProject, + const GeneratableProductData &genProduct, + const IarewVersionInfo &versionInfo); +private: + std::vector<std::unique_ptr<gen::xml::PropertyGroupFactory>> m_factories; +}; + +} // namespace qbs + +#endif // QBS_IAREWPROJECT_H diff --git a/src/plugins/generator/iarew/iarewprojectwriter.cpp b/src/plugins/generator/iarew/iarewprojectwriter.cpp new file mode 100644 index 000000000..fcb2103fe --- /dev/null +++ b/src/plugins/generator/iarew/iarewprojectwriter.cpp @@ -0,0 +1,52 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt.io/licensing +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "iarewprojectwriter.h" + +namespace qbs { + +IarewProjectWriter::IarewProjectWriter(std::ostream *device) + : gen::xml::ProjectWriter(device) +{ +} + +void IarewProjectWriter::visitProjectStart(const gen::xml::Project *project) +{ + Q_UNUSED(project) + writer()->writeStartElement(QStringLiteral("project")); +} + +void IarewProjectWriter::visitProjectEnd(const gen::xml::Project *project) +{ + Q_UNUSED(project) + writer()->writeEndElement(); +} + +} // namespace qbs diff --git a/src/plugins/generator/iarew/iarewprojectwriter.h b/src/plugins/generator/iarew/iarewprojectwriter.h new file mode 100644 index 000000000..9356dbec4 --- /dev/null +++ b/src/plugins/generator/iarew/iarewprojectwriter.h @@ -0,0 +1,51 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt.io/licensing +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef QBS_IAREWPROJECTWRITER_H +#define QBS_IAREWPROJECTWRITER_H + +#include <generators/xmlprojectwriter.h> + +namespace qbs { + +class IarewProjectWriter final : public gen::xml::ProjectWriter +{ + Q_DISABLE_COPY(IarewProjectWriter) +public: + explicit IarewProjectWriter(std::ostream *device); + +private: + void visitProjectStart(const gen::xml::Project *project) final; + void visitProjectEnd(const gen::xml::Project *project) final; +}; + +} // namespace qbs + +#endif // QBS_IAREWPROJECTWRITER_H diff --git a/src/plugins/generator/iarew/iarewsettingspropertygroup.cpp b/src/plugins/generator/iarew/iarewsettingspropertygroup.cpp new file mode 100644 index 000000000..3e7b6dae7 --- /dev/null +++ b/src/plugins/generator/iarew/iarewsettingspropertygroup.cpp @@ -0,0 +1,106 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt.io/licensing +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "iarewoptionpropertygroup.h" +#include "iarewsettingspropertygroup.h" + +namespace qbs { + +constexpr int kDataWantNonLocalPropertyValue = 1; + +IarewSettingsPropertyGroup::IarewSettingsPropertyGroup() + : gen::xml::PropertyGroup(QByteArrayLiteral("settings")) +{ + // Append name property item. + m_nameProperty = appendChild<gen::xml::Property>( + QByteArrayLiteral("name"), QVariant{}); + + // Append archive version property item. + m_archiveVersionProperty = appendChild<gen::xml::Property>( + QByteArrayLiteral("archiveVersion"), QVariant{}); + + // Append data property group item. + m_dataPropertyGroup = appendChild<gen::xml::PropertyGroup>( + QByteArrayLiteral("data")); + // Append data version property item. + m_dataVersionProperty = m_dataPropertyGroup->appendChild< + gen::xml::Property>( + QByteArrayLiteral("version"), QVariant{}); + // Append data want non-local property item. + m_dataPropertyGroup->appendChild<gen::xml::Property>( + QByteArrayLiteral("wantNonLocal"), + kDataWantNonLocalPropertyValue); + // Append data debug property item. + m_dataDebugProperty = m_dataPropertyGroup->appendChild< + gen::xml::Property>( + QByteArrayLiteral("debug"), QVariant{}); +} + +void IarewSettingsPropertyGroup::setName(QByteArray name) +{ + m_nameProperty->setValue(std::move(name)); +} + +QByteArray IarewSettingsPropertyGroup::name() const +{ + return m_nameProperty->value().toByteArray(); +} + +void IarewSettingsPropertyGroup::setArchiveVersion( + int archiveVersion) +{ + m_archiveVersionProperty->setValue(archiveVersion); +} + +int IarewSettingsPropertyGroup::archiveVersion() const +{ + return m_archiveVersionProperty->value().toInt(); +} + +void IarewSettingsPropertyGroup::setDataVersion(int dataVersion) +{ + m_dataVersionProperty->setValue(dataVersion); +} + +void IarewSettingsPropertyGroup::setDataDebugInfo(int debugInfo) +{ + m_dataDebugProperty->setValue(debugInfo); +} + +void IarewSettingsPropertyGroup::addOptionsGroup( + QByteArray name, + const QVariantList &states, + int version) +{ + m_dataPropertyGroup->appendChild<IarewOptionPropertyGroup>( + std::move(name), states, std::move(version)); +} + +} // namespace qbs diff --git a/src/plugins/generator/iarew/iarewsettingspropertygroup.h b/src/plugins/generator/iarew/iarewsettingspropertygroup.h new file mode 100644 index 000000000..4dea76f1a --- /dev/null +++ b/src/plugins/generator/iarew/iarewsettingspropertygroup.h @@ -0,0 +1,68 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt.io/licensing +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef QBS_IAREWSETTINGSPROPERTYGROUP_H +#define QBS_IAREWSETTINGSPROPERTYGROUP_H + +#include <generators/xmlpropertygroup.h> + +namespace qbs { + +class IarewSettingsPropertyGroup : public gen::xml::PropertyGroup +{ +public: + explicit IarewSettingsPropertyGroup(); + + void setName(QByteArray name); + QByteArray name() const; + + void setArchiveVersion(int archiveVersion); + int archiveVersion() const; + +protected: + void setDataVersion(int dataVersion); + void setDataDebugInfo(int debugInfo); + + void addOptionsGroup(QByteArray name, const QVariantList &states, + int version = -1); + +private: + // Don't delete all this RAW pointers explicitly! + gen::xml::Property *m_nameProperty = nullptr; + gen::xml::Property *m_archiveVersionProperty = nullptr; + + gen::xml::Property *m_dataPropertyGroup = nullptr; + gen::xml::Property *m_dataVersionProperty = nullptr; + gen::xml::Property *m_dataDebugProperty = nullptr; +}; + +} // namespace qbs + +#endif // QBS_IAREWSETTINGSPROPERTYGROUP_H diff --git a/src/plugins/generator/iarew/iarewsourcefilepropertygroup.cpp b/src/plugins/generator/iarew/iarewsourcefilepropertygroup.cpp new file mode 100644 index 000000000..33c26e8b8 --- /dev/null +++ b/src/plugins/generator/iarew/iarewsourcefilepropertygroup.cpp @@ -0,0 +1,54 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt.io/licensing +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "iarewsourcefilepropertygroup.h" +#include "iarewutils.h" + +#include <generators/generatordata.h> + +#include <tools/stringconstants.h> + +namespace qbs { + +IarewSourceFilePropertyGroup::IarewSourceFilePropertyGroup( + const GeneratableProject &genProject, + const ArtifactData &sourceArtifact) + : gen::xml::PropertyGroup(QByteArrayLiteral("file")) +{ + // Create file path property item. + const QString fullFilePath = sourceArtifact.filePath(); + const QString relativeFilePath = IarewUtils::projectRelativeFilePath( + genProject.baseBuildDirectory().absolutePath(), + fullFilePath); + appendChild<gen::xml::Property>(QByteArrayLiteral("name"), + relativeFilePath); +} + +} // namespace qbs diff --git a/src/plugins/generator/iarew/iarewsourcefilepropertygroup.h b/src/plugins/generator/iarew/iarewsourcefilepropertygroup.h new file mode 100644 index 000000000..5f88cec27 --- /dev/null +++ b/src/plugins/generator/iarew/iarewsourcefilepropertygroup.h @@ -0,0 +1,52 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt.io/licensing +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef QBS_IAREWSOURCEFILEPROPERTYGROUP_H +#define QBS_IAREWSOURCEFILEPROPERTYGROUP_H + +#include <generators/xmlpropertygroup.h> + +namespace qbs { + +class ArtifactData; +class GeneratableProject; + +class IarewSourceFilePropertyGroup final + : public gen::xml::PropertyGroup +{ +public: + explicit IarewSourceFilePropertyGroup( + const GeneratableProject &genProject, + const ArtifactData &sourceArtifact); +}; + +} // namespace qbs + +#endif // QBS_IAREWSOURCEFILEPROPERTYGROUP_H diff --git a/src/plugins/generator/iarew/iarewsourcefilespropertygroup.cpp b/src/plugins/generator/iarew/iarewsourcefilespropertygroup.cpp new file mode 100644 index 000000000..adb5925b2 --- /dev/null +++ b/src/plugins/generator/iarew/iarewsourcefilespropertygroup.cpp @@ -0,0 +1,56 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt.io/licensing +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "iarewsourcefilepropertygroup.h" +#include "iarewsourcefilespropertygroup.h" + +#include <generators/generatordata.h> + +#include <tools/stringconstants.h> + +namespace qbs { + +IarewSourceFilesPropertyGroup::IarewSourceFilesPropertyGroup( + const GeneratableProject &genProject, + const QString &filesGroupName, + const QList<ArtifactData> &sourceFiles) + : gen::xml::PropertyGroup(QByteArrayLiteral("group")) +{ + // Create group name property item. + appendChild<gen::xml::Property>(QByteArrayLiteral("name"), + filesGroupName); + + // Create file paths property items. + for (const auto &sourceFile : sourceFiles) + appendChild<IarewSourceFilePropertyGroup>(genProject, + sourceFile); +} + +} // namespace qbs diff --git a/src/plugins/generator/iarew/iarewsourcefilespropertygroup.h b/src/plugins/generator/iarew/iarewsourcefilespropertygroup.h new file mode 100644 index 000000000..8d8a4be0c --- /dev/null +++ b/src/plugins/generator/iarew/iarewsourcefilespropertygroup.h @@ -0,0 +1,50 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt.io/licensing +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef QBS_IAREWSOURCEFILESPROPERTYGROUP_H +#define QBS_IAREWSOURCEFILESPROPERTYGROUP_H + +#include <generators/xmlpropertygroup.h> + +namespace qbs { + +class IarewSourceFilesPropertyGroup final + : public gen::xml::PropertyGroup +{ +public: + explicit IarewSourceFilesPropertyGroup( + const GeneratableProject &genProject, + const QString &filesGroupName, + const QList<ArtifactData> &sourceFiles); +}; + +} // namespace qbs + +#endif // QBS_IAREWSOURCEFILESPROPERTYGROUP_H diff --git a/src/plugins/generator/iarew/iarewtoolchainpropertygroup.cpp b/src/plugins/generator/iarew/iarewtoolchainpropertygroup.cpp new file mode 100644 index 000000000..dba5015bf --- /dev/null +++ b/src/plugins/generator/iarew/iarewtoolchainpropertygroup.cpp @@ -0,0 +1,43 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt.io/licensing +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "iarewtoolchainpropertygroup.h" + +namespace qbs { + +IarewToolchainPropertyGroup::IarewToolchainPropertyGroup( + const QByteArray &toolchainName) + : gen::xml::PropertyGroup(QByteArrayLiteral("toolchain")) +{ + // Append toolchain name property item. + appendProperty(QByteArrayLiteral("name"), toolchainName); +} + +} // namespace qbs diff --git a/src/plugins/generator/iarew/iarewtoolchainpropertygroup.h b/src/plugins/generator/iarew/iarewtoolchainpropertygroup.h new file mode 100644 index 000000000..e5bd6f071 --- /dev/null +++ b/src/plugins/generator/iarew/iarewtoolchainpropertygroup.h @@ -0,0 +1,48 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt.io/licensing +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef QBS_IAREWTOOLCHAINPROPERTYGROUP_H +#define QBS_IAREWTOOLCHAINPROPERTYGROUP_H + +#include <generators/xmlpropertygroup.h> + +namespace qbs { + +class IarewToolchainPropertyGroup final + : public gen::xml::PropertyGroup +{ +public: + explicit IarewToolchainPropertyGroup( + const QByteArray &toolchainName); +}; + +} // namespace qbs + +#endif // QBS_IAREWTOOLCHAINPROPERTYGROUP_H diff --git a/src/plugins/generator/iarew/iarewutils.cpp b/src/plugins/generator/iarew/iarewutils.cpp new file mode 100644 index 000000000..f00fce026 --- /dev/null +++ b/src/plugins/generator/iarew/iarewutils.cpp @@ -0,0 +1,156 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt.io/licensing +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "iarewutils.h" + +#include <generators/generatorutils.h> + +namespace qbs { +namespace IarewUtils { + +QString toolkitRootPath(const ProductData &qbsProduct) +{ + QDir dir(qbsProduct.moduleProperties() + .getModuleProperty(Internal::StringConstants::cppModule(), + QStringLiteral("toolchainInstallPath")) + .toString()); + dir.cdUp(); + return dir.absolutePath(); +} + +QString dlibToolkitRootPath(const ProductData &qbsProduct) +{ + return toolkitRootPath(qbsProduct) + QLatin1String("/lib/dlib"); +} + +QString clibToolkitRootPath(const ProductData &qbsProduct) +{ + return toolkitRootPath(qbsProduct) + QLatin1String("/lib/clib"); +} + +QString libToolkitRootPath(const ProductData &qbsProduct) +{ + return toolkitRootPath(qbsProduct) + QLatin1String("/lib"); +} + +QString toolkitRelativeFilePath(const QString &basePath, + const QString &fullFilePath) +{ + return QLatin1String("$TOOLKIT_DIR$/") + + gen::utils::relativeFilePath(basePath, fullFilePath); +} + +QString projectRelativeFilePath(const QString &basePath, + const QString &fullFilePath) +{ + return QLatin1String("$PROJ_DIR$/") + + gen::utils::relativeFilePath(basePath, fullFilePath); +} + +OutputBinaryType outputBinaryType(const ProductData &qbsProduct) +{ + const auto qbsProductType = qbsProduct.type(); + if (qbsProductType.contains(QLatin1String("application"))) + return ApplicationOutputType; + if (qbsProductType.contains(QLatin1String("staticlibrary"))) + return LibraryOutputType; + return ApplicationOutputType; +} + +QString flagValue(const QStringList &flags, const QString &flagKey) +{ + // Seach for full 'flagKey' option matching. + const auto flagBegin = flags.cbegin(); + const auto flagEnd = flags.cend(); + auto flagIt = std::find_if(flagBegin, flagEnd, [flagKey](const QString &flag) { + return flag == flagKey; + }); + if (flagIt == flagEnd) { + // Search for start/end of 'flagKey' matching. + flagIt = std::find_if(flagBegin, flagEnd, [flagKey](const QString &flag) { + return flag.startsWith(flagKey) || flag.endsWith(flagKey); + }); + if (flagIt == flagEnd) + return {}; + } + + QString value; + // Check that option is in form of 'flagKey=<flagValue>'. + if (flagIt->contains(QLatin1Char('='))) { + value = flagIt->split(QLatin1Char('=')).at(1).trimmed(); + } else if (flagKey.count() < flagIt->count()) { + // In this case an option is in form of 'flagKey<flagValue>'. + value = flagIt->mid(flagKey.count()).trimmed(); + } else { + // In this case an option is in form of 'flagKey <flagValue>'. + ++flagIt; + if (flagIt < flagEnd) + value = (*flagIt).trimmed(); + else + return {}; + } + return value; +} + +QVariantList flagValues(const QStringList &flags, const QString &flagKey) +{ + QVariantList values; + for (auto flagIt = flags.cbegin(); flagIt < flags.cend(); ++flagIt) { + if (*flagIt != flagKey) + continue; + ++flagIt; + values.push_back(*flagIt); + } + return values; +} + +QStringList cppModuleCompilerFlags(const PropertyMap &qbsProps) +{ + return gen::utils::cppStringModuleProperties( + qbsProps, {QStringLiteral("driverFlags"), QStringLiteral("cFlags"), + QStringLiteral("cppFlags"), QStringLiteral("cxxFlags"), + QStringLiteral("commonCompilerFlags")}); +} + +QStringList cppModuleAssemblerFlags(const PropertyMap &qbsProps) +{ + return gen::utils::cppStringModuleProperties( + qbsProps, {QStringLiteral("assemblerFlags")}); +} + +QStringList cppModuleLinkerFlags(const PropertyMap &qbsProps) +{ + return gen::utils::cppStringModuleProperties( + qbsProps, {QStringLiteral("driverFlags"), + QStringLiteral("driverLinkerFlags")}); +} + +} // namespace IarewUtils +} // namespace qbs diff --git a/src/plugins/generator/iarew/iarewutils.h b/src/plugins/generator/iarew/iarewutils.h new file mode 100644 index 000000000..2d32ac188 --- /dev/null +++ b/src/plugins/generator/iarew/iarewutils.h @@ -0,0 +1,75 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt.io/licensing +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef QBS_IAREWUTILS_H +#define QBS_IAREWUTILS_H + +#include <qbs.h> + +#include <tools/stringconstants.h> + +namespace qbs { +namespace IarewUtils { + +enum OutputBinaryType { + ApplicationOutputType, + LibraryOutputType +}; + +OutputBinaryType outputBinaryType(const ProductData &qbsProduct); + +QString toolkitRootPath(const ProductData &qbsProduct); + +QString dlibToolkitRootPath(const ProductData &qbsProduct); + +QString clibToolkitRootPath(const ProductData &qbsProduct); + +QString libToolkitRootPath(const ProductData &qbsProduct); + +QString toolkitRelativeFilePath(const QString &basePath, + const QString &fullFilePath); + +QString projectRelativeFilePath(const QString &basePath, + const QString &fullFilePath); + +QString flagValue(const QStringList &flags, const QString &flagKey); + +QVariantList flagValues(const QStringList &flags, const QString &flagKey); + +QStringList cppModuleCompilerFlags(const PropertyMap &qbsProps); + +QStringList cppModuleAssemblerFlags(const PropertyMap &qbsProps); + +QStringList cppModuleLinkerFlags(const PropertyMap &qbsProps); + +} // namespace IarewUtils +} // namespace qbs + +#endif // QBS_IAREWUTILS_H diff --git a/src/plugins/generator/iarew/iarewversioninfo.cpp b/src/plugins/generator/iarew/iarewversioninfo.cpp new file mode 100644 index 000000000..41a788e98 --- /dev/null +++ b/src/plugins/generator/iarew/iarewversioninfo.cpp @@ -0,0 +1,77 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qbs. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "iarewversioninfo.h" + +#include <QtCore/qdebug.h> + +namespace qbs { + +IarewVersionInfo::IarewVersionInfo( + const Version &version, + const std::set<gen::utils::Architecture> &archs) + : gen::VersionInfo(version, archs) +{ +} + +std::set<IarewVersionInfo> IarewVersionInfo::knownVersions() +{ + static const std::set<IarewVersionInfo> known = { + {Version(8), {gen::utils::Architecture::Arm}}, + {Version(7), {gen::utils::Architecture::Avr, + gen::utils::Architecture::Msp430}}, + {Version(10), {gen::utils::Architecture::Mcs51}}, + {Version(3), {gen::utils::Architecture::Stm8}}, + }; + return known; +} + +int IarewVersionInfo::marketingVersion() const +{ + const auto mv = gen::VersionInfo::marketingVersion(); + for (const IarewVersionInfo &known : knownVersions()) { + if (known.version().majorVersion() == mv) + return mv; + } + qWarning() << QStringLiteral("Unrecognized IAR EW version: ") + << version().toString(); + return 0; +} + +} // namespace qbs diff --git a/src/plugins/generator/iarew/iarewversioninfo.h b/src/plugins/generator/iarew/iarewversioninfo.h new file mode 100644 index 000000000..4fd1b1fbc --- /dev/null +++ b/src/plugins/generator/iarew/iarewversioninfo.h @@ -0,0 +1,61 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qbs. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QBS_IAREWVERSIONINFO_H +#define QBS_IAREWVERSIONINFO_H + +#include <generators/generatorutils.h> +#include <generators/generatorversioninfo.h> + +namespace qbs { + +class IarewVersionInfo final : public gen::VersionInfo +{ +public: + IarewVersionInfo(const Version &version, + const std::set<gen::utils::Architecture> &archs); + + int marketingVersion() const final; + + static std::set<IarewVersionInfo> knownVersions(); +}; + +} // namespace qbs + +#endif // QBS_IAREWVERSIONINFO_H diff --git a/src/plugins/generator/iarew/iarewworkspace.cpp b/src/plugins/generator/iarew/iarewworkspace.cpp new file mode 100644 index 000000000..bfe22aea7 --- /dev/null +++ b/src/plugins/generator/iarew/iarewworkspace.cpp @@ -0,0 +1,63 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qbs. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "iarewworkspace.h" + +#include <generators/xmlpropertygroup.h> + +namespace qbs { + +IarewWorkspace::IarewWorkspace(const QString &workspacePath) + : gen::xml::Workspace(workspacePath) +{ + appendChild<gen::xml::PropertyGroup>( + QByteArrayLiteral("batchBuild")); +} + +void IarewWorkspace::addProject(const QString &projectFilePath) +{ + const QString relativeProjectPath = QLatin1String("$WS_DIR$/") + + m_baseDirectory.relativeFilePath(projectFilePath); + + const auto projectGroup = appendChild<gen::xml::PropertyGroup>( + QByteArrayLiteral("project")); + projectGroup->appendProperty("path", relativeProjectPath); +} + +} // namespace qbs diff --git a/src/plugins/generator/iarew/iarewworkspace.h b/src/plugins/generator/iarew/iarewworkspace.h new file mode 100644 index 000000000..ea14e4174 --- /dev/null +++ b/src/plugins/generator/iarew/iarewworkspace.h @@ -0,0 +1,58 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qbs. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QBS_IAREWWORKSPACE_H +#define QBS_IAREWWORKSPACE_H + +#include <generators/xmlworkspace.h> + +#include <QtCore/qdir.h> + +namespace qbs { + +class IarewWorkspace final : public gen::xml::Workspace +{ +public: + explicit IarewWorkspace(const QString &workspacePath); + void addProject(const QString &projectPath) final; +}; + +} // namespace qbs + +#endif // QBS_IAREWWORKSPACE_H diff --git a/src/plugins/generator/iarew/iarewworkspacewriter.cpp b/src/plugins/generator/iarew/iarewworkspacewriter.cpp new file mode 100644 index 000000000..b06080e3a --- /dev/null +++ b/src/plugins/generator/iarew/iarewworkspacewriter.cpp @@ -0,0 +1,52 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt.io/licensing +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "iarewworkspacewriter.h" + +namespace qbs { + +IarewWorkspaceWriter::IarewWorkspaceWriter(std::ostream *device) + : gen::xml::WorkspaceWriter(device) +{ +} + +void IarewWorkspaceWriter::visitWorkspaceStart(const gen::xml::Workspace *workspace) +{ + Q_UNUSED(workspace) + writer()->writeStartElement(QStringLiteral("workspace")); +} + +void IarewWorkspaceWriter::visitWorkspaceEnd(const gen::xml::Workspace *workspace) +{ + Q_UNUSED(workspace) + writer()->writeEndElement(); +} + +} // namespace qbs diff --git a/src/plugins/generator/iarew/iarewworkspacewriter.h b/src/plugins/generator/iarew/iarewworkspacewriter.h new file mode 100644 index 000000000..e60b102d3 --- /dev/null +++ b/src/plugins/generator/iarew/iarewworkspacewriter.h @@ -0,0 +1,51 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt.io/licensing +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef QBS_IAREWWORKSPACEWRITER_H +#define QBS_IAREWWORKSPACEWRITER_H + +#include <generators/xmlworkspacewriter.h> + +namespace qbs { + +class IarewWorkspaceWriter final : public gen::xml::WorkspaceWriter +{ + Q_DISABLE_COPY(IarewWorkspaceWriter) +public: + explicit IarewWorkspaceWriter(std::ostream *device); + +private: + void visitWorkspaceStart(const gen::xml::Workspace *workspace) final; + void visitWorkspaceEnd(const gen::xml::Workspace *workspace) final; +}; + +} // namespace qbs + +#endif // QBS_IAREWWORKSPACEWRITER_H diff --git a/src/plugins/generator/keiluv/archs/arm/armbuildtargetgroup_v5.cpp b/src/plugins/generator/keiluv/archs/arm/armbuildtargetgroup_v5.cpp new file mode 100644 index 000000000..c5cb5f040 --- /dev/null +++ b/src/plugins/generator/keiluv/archs/arm/armbuildtargetgroup_v5.cpp @@ -0,0 +1,108 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt.io/licensing +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "armbuildtargetgroup_v5.h" +#include "armcommonpropertygroup_v5.h" +#include "armdebugoptiongroup_v5.h" +#include "armdlloptiongroup_v5.h" +#include "armtargetcommonoptionsgroup_v5.h" +#include "armtargetgroup_v5.h" +#include "armutilitiesgroup_v5.h" + +#include "../../keiluvconstants.h" +#include "../../keiluvfilesgroupspropertygroup.h" + +namespace qbs { +namespace keiluv { +namespace arm { +namespace v5 { + +ArmBuildTargetGroup::ArmBuildTargetGroup( + const qbs::Project &qbsProject, + const qbs::ProductData &qbsProduct, + const std::vector<qbs::ProductData> &qbsProductDeps) + : gen::xml::PropertyGroup("Target") +{ + // Append target name item (it is a build configuration name). + const QString targetName = gen::utils::buildConfigurationName( + qbsProject); + appendProperty(QByteArrayLiteral("TargetName"), targetName); + // Append toolset number group item. + appendChild<gen::xml::Property>(QByteArrayLiteral("ToolsetNumber"), + QByteArrayLiteral("0x4")); + // Append toolset name group item. + appendChild<gen::xml::Property>(QByteArrayLiteral("ToolsetName"), + QByteArrayLiteral("ARM-ADS")); + + // Append target option group item. + const auto targetOptionGroup = appendChild<gen::xml::PropertyGroup>( + QByteArrayLiteral("TargetOption")); + + targetOptionGroup->appendChild<ArmTargetCommonOptionsGroup>( + qbsProject, qbsProduct); + targetOptionGroup->appendChild<ArmCommonPropertyGroup>( + qbsProject, qbsProduct); + targetOptionGroup->appendChild<ArmDllOptionGroup>( + qbsProject, qbsProduct); + targetOptionGroup->appendChild<ArmDebugOptionGroup>( + qbsProject, qbsProduct); + targetOptionGroup->appendChild<ArmUtilitiesGroup>( + qbsProject, qbsProduct); + targetOptionGroup->appendChild<ArmTargetGroup>( + qbsProject, qbsProduct); + + // Append files group. + appendChild<KeiluvFilesGroupsPropertyGroup>(qbsProject, qbsProduct, + qbsProductDeps); +} + +bool ArmBuildTargetGroupFactory::canCreate( + gen::utils::Architecture arch, + const Version &version) const +{ + return arch == gen::utils::Architecture::Arm + && version.majorVersion() == qbs::KeiluvConstants::v5::kUVisionVersion; +} + +std::unique_ptr<gen::xml::PropertyGroup> +ArmBuildTargetGroupFactory::create( + const qbs::Project &qbsProject, + const qbs::ProductData &qbsProduct, + const std::vector<qbs::ProductData> &qbsProductDeps) const +{ + const auto group = new ArmBuildTargetGroup( + qbsProject, qbsProduct, qbsProductDeps); + return std::unique_ptr<ArmBuildTargetGroup>(group); +} + +} // namespace v5 +} // namespace arm +} // namespace keiluv +} // namespace qbs diff --git a/src/plugins/generator/keiluv/archs/arm/armbuildtargetgroup_v5.h b/src/plugins/generator/keiluv/archs/arm/armbuildtargetgroup_v5.h new file mode 100644 index 000000000..9b8d9fe26 --- /dev/null +++ b/src/plugins/generator/keiluv/archs/arm/armbuildtargetgroup_v5.h @@ -0,0 +1,70 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt.io/licensing +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef QBS_KEILUVARMBUILDTARGETGROUP_V5_H +#define QBS_KEILUVARMBUILDTARGETGROUP_V5_H + +#include <generators/xmlpropertygroup.h> + +namespace qbs { +namespace keiluv { +namespace arm { +namespace v5 { + +class ArmBuildTargetGroup final : public gen::xml::PropertyGroup +{ +private: + explicit ArmBuildTargetGroup( + const qbs::Project &qbsProject, + const qbs::ProductData &qbsProduct, + const std::vector<qbs::ProductData> &qbsProductDeps); + + friend class ArmBuildTargetGroupFactory; +}; + +class ArmBuildTargetGroupFactory final + : public gen::xml::PropertyGroupFactory +{ +public: + bool canCreate(gen::utils::Architecture arch, + const Version &version) const final; + + std::unique_ptr<gen::xml::PropertyGroup> create( + const qbs::Project &qbsProject, + const qbs::ProductData &qbsProduct, + const std::vector<qbs::ProductData> &qbsProductDeps) const final; +}; + +} // namespace v5 +} // namespace arm +} // namespace keiluv +} // namespace qbs + +#endif // QBS_KEILUVARMBUILDTARGETGROUP_V5_H diff --git a/src/plugins/generator/keiluv/archs/arm/armcommonpropertygroup_v5.cpp b/src/plugins/generator/keiluv/archs/arm/armcommonpropertygroup_v5.cpp new file mode 100644 index 000000000..e7a738235 --- /dev/null +++ b/src/plugins/generator/keiluv/archs/arm/armcommonpropertygroup_v5.cpp @@ -0,0 +1,50 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt.io/licensing +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "armcommonpropertygroup_v5.h" + +namespace qbs { +namespace keiluv { +namespace arm { +namespace v5 { + +ArmCommonPropertyGroup::ArmCommonPropertyGroup( + const qbs::Project &qbsProject, + const qbs::ProductData &qbsProduct) + : gen::xml::PropertyGroup("CommonProperty") +{ + Q_UNUSED(qbsProject) + Q_UNUSED(qbsProduct) +} + +} // namespace v5 +} // namespace arm +} // namespace keiluv +} // namespace qbs diff --git a/src/plugins/generator/keiluv/archs/arm/armcommonpropertygroup_v5.h b/src/plugins/generator/keiluv/archs/arm/armcommonpropertygroup_v5.h new file mode 100644 index 000000000..4d45decc4 --- /dev/null +++ b/src/plugins/generator/keiluv/archs/arm/armcommonpropertygroup_v5.h @@ -0,0 +1,54 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt.io/licensing +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef QBS_KEILUVARMCOMMONPROPERTYGROUP_V5_H +#define QBS_KEILUVARMCOMMONPROPERTYGROUP_V5_H + +#include <generators/xmlpropertygroup.h> + +namespace qbs { +namespace keiluv { +namespace arm { +namespace v5 { + +class ArmCommonPropertyGroup final : public gen::xml::PropertyGroup +{ +public: + explicit ArmCommonPropertyGroup( + const qbs::Project &qbsProject, + const qbs::ProductData &qbsProduct); +}; + +} // namespace v5 +} // namespace arm +} // namespace keiluv +} // namespace qbs + +#endif // QBS_MCS51COMMONPROPERTYGROUP_V5_H diff --git a/src/plugins/generator/keiluv/archs/arm/armdebugoptiongroup_v5.cpp b/src/plugins/generator/keiluv/archs/arm/armdebugoptiongroup_v5.cpp new file mode 100644 index 000000000..553df646d --- /dev/null +++ b/src/plugins/generator/keiluv/archs/arm/armdebugoptiongroup_v5.cpp @@ -0,0 +1,50 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt.io/licensing +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "armdebugoptiongroup_v5.h" + +namespace qbs { +namespace keiluv { +namespace arm { +namespace v5 { + +ArmDebugOptionGroup::ArmDebugOptionGroup( + const qbs::Project &qbsProject, + const qbs::ProductData &qbsProduct) + : gen::xml::PropertyGroup("DebugOption") +{ + Q_UNUSED(qbsProject) + Q_UNUSED(qbsProduct) +} + +} // namespace v5 +} // namespace arm +} // namespace keiluv +} // namespace qbs diff --git a/src/plugins/generator/keiluv/archs/arm/armdebugoptiongroup_v5.h b/src/plugins/generator/keiluv/archs/arm/armdebugoptiongroup_v5.h new file mode 100644 index 000000000..22d5bb88f --- /dev/null +++ b/src/plugins/generator/keiluv/archs/arm/armdebugoptiongroup_v5.h @@ -0,0 +1,54 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt.io/licensing +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef QBS_KEILUVARMDEBUGOPTIONGROUP_V5_H +#define QBS_KEILUVARMDEBUGOPTIONGROUP_V5_H + +#include <generators/xmlpropertygroup.h> + +namespace qbs { +namespace keiluv { +namespace arm { +namespace v5 { + +class ArmDebugOptionGroup final : public gen::xml::PropertyGroup +{ +public: + explicit ArmDebugOptionGroup( + const qbs::Project &qbsProject, + const qbs::ProductData &qbsProduct); +}; + +} // namespace v5 +} // namespace arm +} // namespace keiluv +} // namespace qbs + +#endif // QBS_KEILUVARMDEBUGOPTIONGROUP_V5_H diff --git a/src/plugins/generator/keiluv/archs/arm/armdlloptiongroup_v5.cpp b/src/plugins/generator/keiluv/archs/arm/armdlloptiongroup_v5.cpp new file mode 100644 index 000000000..9e1bdff02 --- /dev/null +++ b/src/plugins/generator/keiluv/archs/arm/armdlloptiongroup_v5.cpp @@ -0,0 +1,50 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt.io/licensing +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "armdlloptiongroup_v5.h" + +namespace qbs { +namespace keiluv { +namespace arm { +namespace v5 { + +ArmDllOptionGroup::ArmDllOptionGroup( + const qbs::Project &qbsProject, + const qbs::ProductData &qbsProduct) + : gen::xml::PropertyGroup("DllOption") +{ + Q_UNUSED(qbsProject) + Q_UNUSED(qbsProduct) +} + +} // namespace v5 +} // namespace arm +} // namespace keiluv +} // namespace qbs diff --git a/src/plugins/generator/keiluv/archs/arm/armdlloptiongroup_v5.h b/src/plugins/generator/keiluv/archs/arm/armdlloptiongroup_v5.h new file mode 100644 index 000000000..948eb1568 --- /dev/null +++ b/src/plugins/generator/keiluv/archs/arm/armdlloptiongroup_v5.h @@ -0,0 +1,54 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt.io/licensing +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef QBS_KEILUVARMDLLOPTIONGROUP_V5_H +#define QBS_KEILUVARMDLLOPTIONGROUP_V5_H + +#include <generators/xmlpropertygroup.h> + +namespace qbs { +namespace keiluv { +namespace arm { +namespace v5 { + +class ArmDllOptionGroup final : public gen::xml::PropertyGroup +{ +public: + explicit ArmDllOptionGroup( + const qbs::Project &qbsProject, + const qbs::ProductData &qbsProduct); +}; + +} // namespace v5 +} // namespace arm +} // namespace keiluv +} // namespace qbs + +#endif // QBS_KEILUVARMDLLOPTIONGROUP_V5_H diff --git a/src/plugins/generator/keiluv/archs/arm/armtargetassemblergroup_v5.cpp b/src/plugins/generator/keiluv/archs/arm/armtargetassemblergroup_v5.cpp new file mode 100644 index 000000000..424cb3353 --- /dev/null +++ b/src/plugins/generator/keiluv/archs/arm/armtargetassemblergroup_v5.cpp @@ -0,0 +1,154 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt.io/licensing +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "armtargetassemblergroup_v5.h" + +#include "../../keiluvutils.h" + +namespace qbs { +namespace keiluv { +namespace arm { +namespace v5 { + +namespace { + +struct AssemblerPageOptions final +{ + explicit AssemblerPageOptions(const Project &qbsProject, + const ProductData &qbsProduct) + { + Q_UNUSED(qbsProject) + + const auto &qbsProps = qbsProduct.moduleProperties(); + const auto flags = qbs::KeiluvUtils::cppModuleAssemblerFlags(qbsProps); + + // Read-only position independent. + enableRopi = flags.contains(QLatin1String("/ropi")); + // Read-write position independent. + enableRwpi = flags.contains(QLatin1String("/rwpi")); + // Enable thumb mode. + enableThumbMode = flags.contains(QLatin1String("--16")); + // Split load and store multiple. + splitLdm = flags.contains(QLatin1String("--split_ldm")); + // Generation code. + generateExecuteOnlyCode = flags.contains(QLatin1String("--execute_only")); + + // Warning levels. + const QString wLevel = gen::utils::cppStringModuleProperty( + qbsProps, QStringLiteral("warningLevel")); + disableWarnings = wLevel == QLatin1String("none"); + + // Define symbols. + defineSymbols = qbs::KeiluvUtils::defines(qbsProps); + // Include paths. + includePaths = qbs::KeiluvUtils::includes(qbsProps); + + // Interpret other compiler flags as a misc controls (exclude only + // that flags which are was already handled). + for (auto flagIt = flags.cbegin(); flagIt < flags.cend(); ++flagIt) { + if (flagIt->contains(QLatin1String("/ropi")) + || flagIt->contains(QLatin1String("/rwpi")) + || flagIt->contains(QLatin1String("--16")) + || flagIt->contains(QLatin1String("--split_ldm")) + || flagIt->contains(QLatin1String("--execute_only")) + || flagIt->contains(QLatin1String("--nowarn")) + ) { + continue; + } + if (flagIt->startsWith(QLatin1String("-I")) + || flagIt->startsWith(QLatin1String("--cpu")) + || flagIt->startsWith(QLatin1String("--fpu")) + || flagIt->startsWith(QLatin1String("-pd")) + ) { + ++flagIt; + continue; + } + miscControls.push_back(*flagIt); + } + } + + int enableRopi = 0; + int enableRwpi = 0; + int enableThumbMode = 0; + int disableWarnings = 0; + int splitLdm = 0; + int generateExecuteOnlyCode = 0; + + QStringList defineSymbols; + QStringList includePaths; + QStringList miscControls; +}; + +} // namespace + +ArmTargetAssemblerGroup::ArmTargetAssemblerGroup( + const qbs::Project &qbsProject, + const qbs::ProductData &qbsProduct) + : gen::xml::PropertyGroup("Aads") +{ + const AssemblerPageOptions opts(qbsProject, qbsProduct); + + // Add 'ROPI' item. + appendProperty(QByteArrayLiteral("Ropi"), opts.enableRopi); + // Add 'RWPI' item. + appendProperty(QByteArrayLiteral("Rwpi"), opts.enableRwpi); + // Add 'Use thumb mode' item. + appendProperty(QByteArrayLiteral("thumb"), opts.enableThumbMode); + // Add 'Slpit LDM' item. + appendProperty(QByteArrayLiteral("SplitLS"), opts.splitLdm); + // Add 'Disable warnings' item. + appendProperty(QByteArrayLiteral("NoWarn"), opts.disableWarnings); + // Add 'Generate code exedutable only' item. + appendProperty(QByteArrayLiteral("useXo"), opts.generateExecuteOnlyCode); + + // Add other various controls. + // Note: A sub-items order makes sense! + const auto variousControlsGroup = appendChild<gen::xml::PropertyGroup>( + QByteArrayLiteral("VariousControls")); + // Add 'Misc Controls' item. + variousControlsGroup->appendMultiLineProperty( + QByteArrayLiteral("MiscControls"), + opts.miscControls, QLatin1Char(' ')); + // Add 'Define' item. + variousControlsGroup->appendMultiLineProperty( + QByteArrayLiteral("Define"), opts.defineSymbols); + // Add an empty 'Undefine' item. + variousControlsGroup->appendProperty( + QByteArrayLiteral("Undefine"), {}); + // Add 'Include Paths' item. + variousControlsGroup->appendMultiLineProperty( + QByteArrayLiteral("IncludePath"), + opts.includePaths, QLatin1Char(';')); +} + +} // namespace v5 +} // namespace arm +} // namespace keiluv +} // namespace qbs diff --git a/src/plugins/generator/keiluv/archs/arm/armtargetassemblergroup_v5.h b/src/plugins/generator/keiluv/archs/arm/armtargetassemblergroup_v5.h new file mode 100644 index 000000000..d61b11fe5 --- /dev/null +++ b/src/plugins/generator/keiluv/archs/arm/armtargetassemblergroup_v5.h @@ -0,0 +1,54 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt.io/licensing +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef QBS_KEILUVARMTARGETASSEMBLERGROUP_V3 +#define QBS_KEILUVARMTARGETASSEMBLERGROUP_V3 + +#include <generators/xmlpropertygroup.h> + +namespace qbs { +namespace keiluv { +namespace arm { +namespace v5 { + +class ArmTargetAssemblerGroup final : public gen::xml::PropertyGroup +{ +public: + explicit ArmTargetAssemblerGroup( + const qbs::Project &qbsProject, + const qbs::ProductData &qbsProduct); +}; + +} // namespace v5 +} // namespace arm +} // namespace keiluv +} // namespace qbs + +#endif // QBS_KEILUVARMTARGETASSEMBLERGROUP_V3 diff --git a/src/plugins/generator/keiluv/archs/arm/armtargetcommonoptionsgroup_v5.cpp b/src/plugins/generator/keiluv/archs/arm/armtargetcommonoptionsgroup_v5.cpp new file mode 100644 index 000000000..0ffbcaa5b --- /dev/null +++ b/src/plugins/generator/keiluv/archs/arm/armtargetcommonoptionsgroup_v5.cpp @@ -0,0 +1,208 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt.io/licensing +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "armtargetcommonoptionsgroup_v5.h" + +#include "../../keiluvutils.h" + +#include <generators/generatorutils.h> + +namespace qbs { +namespace keiluv { +namespace arm { +namespace v5 { + +namespace { + +static const struct DeviceEntry { + QByteArray cpu; // CPU option. + std::set<QByteArray> fpus; // FPU's options. + QByteArray device; // Project file entry. +} deviceDict[] = { + {"8-M.Base", {}, "ARMv8MBL"}, + {"8-M.Main", {"FPv5-SP"}, "ARMv8MML_SP"}, + {"8-M.Main", {"FPv5_D16"}, "ARMv8MML_DP"}, + {"8-M.Main", {"SoftVFP"},"ARMv8MML"}, + {"8-M.Main.dsp", {"FPv5-SP"}, "ARMv8MML_DSP_SP"}, + {"8-M.Main.dsp", {"FPv5_D16"}, "ARMv8MML_DSP_DP"}, + {"8-M.Main.dsp", {"SoftVFP"}, "ARMv8MML_DSP"}, + {"Cortex-M0", {}, "ARMCM0"}, + {"Cortex-M0+", {}, "ARMCM0P"}, + {"Cortex-M0plus", {}, "ARMCM0P"}, + {"Cortex-M23", {}, "ARMCM23"}, // same as ARMCM23_TZ + {"Cortex-M3", {}, "ARMCM3"}, + {"Cortex-M4", {}, "ARMCM4"}, + {"Cortex-M4.fp", {}, "ARMCM4_FP"}, + {"Cortex-M7", {"SoftVFP"}, "ARMCM7"}, + {"Cortex-M7.fp.dp", {}, "ARMCM7_DP"}, + {"Cortex-M7.fp.sp", {}, "ARMCM7_SP"}, + {"SC000", {}, "ARMSC000"}, + {"SC300", {}, "ARMSC300"}, + {"Cortex-M33.no_dsp", {"SoftVFP"}, "ARMCM33"}, // same as ARMCM33_TZ + {"Cortex-M33", {"FPv5-SP", "softvfp+vfpv2"}, "ARMCM33_DSP_FP"}, // same as ARMCM33_DSP_FP_TZ +}; + +struct CommonPageOptions final +{ + explicit CommonPageOptions(const Project &qbsProject, + const ProductData &qbsProduct) + { + Q_UNUSED(qbsProject) + + const auto &qbsProps = qbsProduct.moduleProperties(); + const auto flags = KeiluvUtils::cppModuleCompilerFlags(qbsProps); + + // Browse information. + // ??? + + // Debug information. + debugInfo = gen::utils::debugInformation(qbsProduct); + + // Output parameters. + executableName = gen::utils::targetBinary(qbsProduct); + // Fix output binary name if it is a library. Because + // the IDE appends an additional suffix (.LIB) to end + // of an output library name. + if (executableName.endsWith(QLatin1String(".lib"))) + executableName = qbsProduct.targetName(); + + const QString baseDirectory = gen::utils::buildRootPath(qbsProject); + objectDirectory = QDir::toNativeSeparators( + gen::utils::objectsOutputDirectory( + baseDirectory, qbsProduct)); + listingDirectory = QDir::toNativeSeparators( + gen::utils::listingOutputDirectory( + baseDirectory, qbsProduct)); + + // Target type. + targetType = KeiluvUtils::outputBinaryType(qbsProduct); + + // Detect the device name from the command line options + // (like --cpu and --fpu). + const auto cpu = gen::utils::firstFlagValue( + flags, QStringLiteral("--cpu")).toLatin1(); + const auto fpus = gen::utils::allFlagValues( + flags, QStringLiteral("--fpu")); + + for (const auto &deviceEntry : deviceDict) { + // Since Qt 5.12 we can use QByteArray::compare(..., Qt::CaseInsensitive) + // instead. + if (cpu.toLower() != deviceEntry.cpu.toLower()) + continue; + + size_t fpuMatches = 0; + const auto dictFpuBegin = std::cbegin(deviceDict->fpus); + const auto dictFpuEnd = std::cend(deviceDict->fpus); + for (const auto &fpu : fpus) { + const auto dictFpuIt = std::find_if( + dictFpuBegin, dictFpuEnd, + [fpu](const QByteArray &dictFpu) { + return fpu.compare(QString::fromLatin1(dictFpu), + Qt::CaseInsensitive) == 0; + }); + if (dictFpuIt != dictFpuEnd) + ++fpuMatches; + } + + if (fpuMatches < deviceEntry.fpus.size()) + continue; + + deviceName = QString::fromLatin1(deviceEntry.device); + cpuType = QString::fromLatin1(deviceEntry.cpu); + break; + } + } + + int debugInfo = false; + int browseInfo = false; + QString deviceName; + QString cpuType; + QString executableName; + QString objectDirectory; + QString listingDirectory; + KeiluvUtils::OutputBinaryType targetType = + KeiluvUtils::ApplicationOutputType; +}; + +} // namespace + +ArmTargetCommonOptionsGroup::ArmTargetCommonOptionsGroup( + const qbs::Project &qbsProject, + const qbs::ProductData &qbsProduct) + : gen::xml::PropertyGroup("TargetCommonOption") +{ + const CommonPageOptions opts(qbsProject, qbsProduct); + + // Fill device items. + appendProperty(QByteArrayLiteral("Device"), + opts.deviceName); + appendProperty(QByteArrayLiteral("Vendor"), + QByteArrayLiteral("ARM")); + appendProperty(QByteArrayLiteral("PackID"), + QByteArrayLiteral("ARM.CMSIS.5.6.0")); + appendProperty(QByteArrayLiteral("PackURL"), + QByteArrayLiteral("http://www.keil.com/pack/")); + + const auto cpuType = QStringLiteral("CPUTYPE(\"%1\")") + .arg(opts.cpuType); + appendProperty(QByteArrayLiteral("Cpu"), cpuType); + + // Add 'Debug Information' item. + appendProperty(QByteArrayLiteral("DebugInformation"), + opts.debugInfo); + // Add 'Browse Information' item. + appendProperty(QByteArrayLiteral("BrowseInformation"), + opts.browseInfo); + + // Add 'Name of Executable'. + appendProperty(QByteArrayLiteral("OutputName"), + opts.executableName); + // Add 'Output objects directory'. + appendProperty(QByteArrayLiteral("OutputDirectory"), + opts.objectDirectory); + // Add 'Output listing directory'. + appendProperty(QByteArrayLiteral("ListingPath"), + opts.listingDirectory); + + // Add 'Create Executable/Library' item. + const int isExecutable = (opts.targetType + == KeiluvUtils::ApplicationOutputType); + const int isLibrary = (opts.targetType + == KeiluvUtils::LibraryOutputType); + appendProperty(QByteArrayLiteral("CreateExecutable"), + isExecutable); + appendProperty(QByteArrayLiteral("CreateLib"), + isLibrary); +} + +} // namespace v5 +} // namespace arm +} // namespace keiluv +} // namespace qbs diff --git a/src/plugins/generator/keiluv/archs/arm/armtargetcommonoptionsgroup_v5.h b/src/plugins/generator/keiluv/archs/arm/armtargetcommonoptionsgroup_v5.h new file mode 100644 index 000000000..b7d4ffee2 --- /dev/null +++ b/src/plugins/generator/keiluv/archs/arm/armtargetcommonoptionsgroup_v5.h @@ -0,0 +1,54 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt.io/licensing +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef QBS_KEILUVARMTARGETCOMMONOPTIONSGROUP_V5_H +#define QBS_KEILUVARMTARGETCOMMONOPTIONSGROUP_V5_H + +#include <generators/xmlpropertygroup.h> + +namespace qbs { +namespace keiluv { +namespace arm { +namespace v5 { + +class ArmTargetCommonOptionsGroup final : public gen::xml::PropertyGroup +{ +public: + explicit ArmTargetCommonOptionsGroup( + const qbs::Project &qbsProject, + const qbs::ProductData &qbsProduct); +}; + +} // namespace v5 +} // namespace arm +} // namespace keiluv +} // namespace qbs + +#endif // QBS_KEILUVARMTARGETCOMMONOPTIONSGROUP_V5_H diff --git a/src/plugins/generator/keiluv/archs/arm/armtargetcompilergroup_v5.cpp b/src/plugins/generator/keiluv/archs/arm/armtargetcompilergroup_v5.cpp new file mode 100644 index 000000000..c923bd9b9 --- /dev/null +++ b/src/plugins/generator/keiluv/archs/arm/armtargetcompilergroup_v5.cpp @@ -0,0 +1,218 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt.io/licensing +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "armtargetcompilergroup_v5.h" + +#include "../../keiluvutils.h" + +namespace qbs { +namespace keiluv { +namespace arm { +namespace v5 { + +namespace { + +struct CompilerPageOptions final +{ + enum WarningLevel { + WarningLevelUnspecified = 0, + WarningLevelNone, + WarningLevelAll + }; + + enum OptimizationLevel { + OptimizationLevelUnspecified = 0, + OptimizationLevelNone, + OptimizationLevelOne, + OptimizationLevelTwo, + OptimizationLevelThree, + }; + + explicit CompilerPageOptions(const Project &qbsProject, + const ProductData &qbsProduct) + { + Q_UNUSED(qbsProject) + + const auto &qbsProps = qbsProduct.moduleProperties(); + const auto flags = qbs::KeiluvUtils::cppModuleCompilerFlags(qbsProps); + + // Warning levels. + const QString wLevel = gen::utils::cppStringModuleProperty( + qbsProps, QStringLiteral("warningLevel")); + if (wLevel == QLatin1String("none")) + warningLevel = WarningLevelNone; + else if (wLevel == QLatin1String("all")) + warningLevel = WarningLevelAll; + else + warningLevel = WarningLevelUnspecified; + + // Generation code. + generateExecuteOnlyCode = flags.contains(QLatin1String("--execute_only")); + + // Optimization levels. + const QString oLevel = gen::utils::cppStringModuleProperty( + qbsProps, QStringLiteral("optimization")); + if (oLevel == QLatin1String("fast")) + enableTimeOptimization = 1; + else if (oLevel == QLatin1String("small")) + optimizationLevel = OptimizationLevelThree; + else if (oLevel == QLatin1String("none")) + optimizationLevel = OptimizationLevelNone; + + // Split load and store multiple. + splitLdm = flags.contains(QLatin1String("--split_ldm")); + // One ELF section per function. + splitSections = flags.contains(QLatin1String("--split_sections")); + // String ANSI C. + useStrictAnsiC = flags.contains(QLatin1String("--strict")); + // Enum container always int. + forceEnumAsInt = flags.contains(QLatin1String("--enum_is_int")); + // Plain char is signed. + useSignedChar = flags.contains(QLatin1String("--signed_chars")); + // Read-only position independent. + enableRopi = flags.contains(QLatin1String("/ropi")); + // Read-write position independent. + enableRwpi = flags.contains(QLatin1String("/rwpi")); + + // C-language version. + const QString clVersion = gen::utils::cppStringModuleProperty( + qbsProps, QStringLiteral("cLanguageVersion")); + // C99 mode. + useC99Language = clVersion.contains(QLatin1String("c99")); + + // Define symbols. + defineSymbols = qbs::KeiluvUtils::defines(qbsProps); + // Include paths. + includePaths = qbs::KeiluvUtils::includes(qbsProps); + + // Interpret other compiler flags as a misc controls (exclude only + // that flags which are was already handled). + for (auto flagIt = flags.cbegin(); flagIt < flags.cend(); ++flagIt) { + if (flagIt->contains(QLatin1String("--execute_only")) + || flagIt->contains(QLatin1String("--split_ldm")) + || flagIt->contains(QLatin1String("--split_sections")) + || flagIt->contains(QLatin1String("--strict")) + || flagIt->contains(QLatin1String("--enum_is_int")) + || flagIt->contains(QLatin1String("--signed_chars")) + || flagIt->contains(QLatin1String("/ropi")) + || flagIt->contains(QLatin1String("/rwpi")) + || flagIt->contains(QLatin1String("--c99")) + ) { + continue; + } + if (flagIt->startsWith(QLatin1String("-O")) + || flagIt->startsWith(QLatin1String("-W")) + || flagIt->startsWith(QLatin1String("-D")) + || flagIt->startsWith(QLatin1String("-I")) + || flagIt->startsWith(QLatin1String("--cpu")) + || flagIt->startsWith(QLatin1String("--fpu")) + ) { + ++flagIt; + continue; + } + miscControls.push_back(*flagIt); + } + } + + WarningLevel warningLevel = WarningLevelAll; + OptimizationLevel optimizationLevel = OptimizationLevelUnspecified; + int enableTimeOptimization = 0; + int generateExecuteOnlyCode = 0; + int splitLdm = 0; + int splitSections = 0; + int useStrictAnsiC = 0; + int forceEnumAsInt = 0; + int useSignedChar = 0; + int enableRopi = 0; + int enableRwpi = 0; + int useC99Language = 0; + + QStringList defineSymbols; + QStringList includePaths; + QStringList miscControls; +}; + +} // namespace + +ArmTargetCompilerGroup::ArmTargetCompilerGroup( + const qbs::Project &qbsProject, + const qbs::ProductData &qbsProduct) + : gen::xml::PropertyGroup("Cads") +{ + const CompilerPageOptions opts(qbsProject, qbsProduct); + + // Add 'Code Optimization' items. + appendProperty(QByteArrayLiteral("Optim"), opts.optimizationLevel); + appendProperty(QByteArrayLiteral("oTime"), opts.enableTimeOptimization); + // Add 'Slpit LDM' item. + appendProperty(QByteArrayLiteral("SplitLS"), opts.splitLdm); + // Add 'Slpit sections' item. + appendProperty(QByteArrayLiteral("OneElfS"), opts.splitSections); + // Add 'Strict ANSI C' item. + appendProperty(QByteArrayLiteral("Strict"), opts.useStrictAnsiC); + // Add 'Enums as int' item. + appendProperty(QByteArrayLiteral("EnumInt"), opts.forceEnumAsInt); + // Add 'Plain char as signed' item. + appendProperty(QByteArrayLiteral("PlainCh"), opts.useSignedChar); + // Add 'ROPI' item. + appendProperty(QByteArrayLiteral("Ropi"), opts.enableRopi); + // Add 'RWPI' item. + appendProperty(QByteArrayLiteral("Rwpi"), opts.enableRwpi); + // Add 'Warnings' item. + appendProperty(QByteArrayLiteral("wLevel"), opts.warningLevel); + // Add 'Use C99' item. + appendProperty(QByteArrayLiteral("uC99"), opts.useC99Language); + // Add 'Generate code exedutable only' item. + appendProperty(QByteArrayLiteral("useXo"), opts.generateExecuteOnlyCode); + + // Add other various controls. + // Note: A sub-items order makes sense! + const auto variousControlsGroup = appendChild<gen::xml::PropertyGroup>( + QByteArrayLiteral("VariousControls")); + // Add 'Misc Controls' item. + variousControlsGroup->appendMultiLineProperty( + QByteArrayLiteral("MiscControls"), + opts.miscControls, QLatin1Char(' ')); + // Add 'Define' item. + variousControlsGroup->appendMultiLineProperty( + QByteArrayLiteral("Define"), opts.defineSymbols); + // Add an empty 'Undefine' item. + variousControlsGroup->appendProperty( + QByteArrayLiteral("Undefine"), {}); + // Add 'Include Paths' item. + variousControlsGroup->appendMultiLineProperty( + QByteArrayLiteral("IncludePath"), + opts.includePaths, QLatin1Char(';')); +} + +} // namespace v5 +} // namespace arm +} // namespace keiluv +} // namespace qbs diff --git a/src/plugins/generator/keiluv/archs/arm/armtargetcompilergroup_v5.h b/src/plugins/generator/keiluv/archs/arm/armtargetcompilergroup_v5.h new file mode 100644 index 000000000..89759ee0b --- /dev/null +++ b/src/plugins/generator/keiluv/archs/arm/armtargetcompilergroup_v5.h @@ -0,0 +1,54 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt.io/licensing +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef QBS_KEILUVARMTARGETCOMPILERGROUP_V5_H +#define QBS_KEILUVARMTARGETCOMPILERGROUP_V5_H + +#include <generators/xmlpropertygroup.h> + +namespace qbs { +namespace keiluv { +namespace arm { +namespace v5 { + +class ArmTargetCompilerGroup final : public gen::xml::PropertyGroup +{ +public: + explicit ArmTargetCompilerGroup( + const qbs::Project &qbsProject, + const qbs::ProductData &qbsProduct); +}; + +} // namespace v5 +} // namespace arm +} // namespace keiluv +} // namespace qbs + +#endif // QBS_KEILUVARMTARGETCOMPILERGROUP_V5_H diff --git a/src/plugins/generator/keiluv/archs/arm/armtargetgroup_v5.cpp b/src/plugins/generator/keiluv/archs/arm/armtargetgroup_v5.cpp new file mode 100644 index 000000000..61c7b5667 --- /dev/null +++ b/src/plugins/generator/keiluv/archs/arm/armtargetgroup_v5.cpp @@ -0,0 +1,56 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt.io/licensing +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "armtargetassemblergroup_v5.h" +#include "armtargetcompilergroup_v5.h" +#include "armtargetgroup_v5.h" +#include "armtargetlinkergroup_v5.h" +#include "armtargetmiscgroup_v5.h" + +namespace qbs { +namespace keiluv { +namespace arm { +namespace v5 { + +ArmTargetGroup::ArmTargetGroup( + const qbs::Project &qbsProject, + const qbs::ProductData &qbsProduct) + : gen::xml::PropertyGroup("TargetArmAds") +{ + appendChild<ArmTargetMiscGroup>(qbsProject, qbsProduct); + appendChild<ArmTargetCompilerGroup>(qbsProject, qbsProduct); + appendChild<ArmTargetAssemblerGroup>(qbsProject, qbsProduct); + appendChild<ArmTargetLinkerGroup>(qbsProject, qbsProduct); +} + +} // namespace v5 +} // namespace arm +} // namespace keiluv +} // namespace qbs diff --git a/src/plugins/generator/keiluv/archs/arm/armtargetgroup_v5.h b/src/plugins/generator/keiluv/archs/arm/armtargetgroup_v5.h new file mode 100644 index 000000000..7472fe675 --- /dev/null +++ b/src/plugins/generator/keiluv/archs/arm/armtargetgroup_v5.h @@ -0,0 +1,54 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt.io/licensing +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef QBS_KEILUVARMTARGETGROUP_V5_H +#define QBS_KEILUVARMTARGETGROUP_V5_H + +#include <generators/xmlpropertygroup.h> + +namespace qbs { +namespace keiluv { +namespace arm { +namespace v5 { + +class ArmTargetGroup final : public gen::xml::PropertyGroup +{ +public: + explicit ArmTargetGroup( + const qbs::Project &qbsProject, + const qbs::ProductData &qbsProduct); +}; + +} // namespace v5 +} // namespace arm +} // namespace keiluv +} // namespace qbs + +#endif // QBS_KEILUVARMTARGETGROUP_V5_H diff --git a/src/plugins/generator/keiluv/archs/arm/armtargetlinkergroup_v5.cpp b/src/plugins/generator/keiluv/archs/arm/armtargetlinkergroup_v5.cpp new file mode 100644 index 000000000..930aae020 --- /dev/null +++ b/src/plugins/generator/keiluv/archs/arm/armtargetlinkergroup_v5.cpp @@ -0,0 +1,164 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt.io/licensing +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "armtargetlinkergroup_v5.h" + +#include "../../keiluvutils.h" + +#include <generators/generatorutils.h> + +namespace qbs { +namespace keiluv { +namespace arm { +namespace v5 { + +namespace { + +struct LinkerPageOptions final +{ + explicit LinkerPageOptions(const Project &qbsProject, + const ProductData &qbsProduct) + { + Q_UNUSED(qbsProject) + + const auto &qbsProps = qbsProduct.moduleProperties(); + const auto flags = qbs::KeiluvUtils::cppModuleLinkerFlags(qbsProps); + + // Read-only position independent. + enableRopi = flags.contains(QLatin1String("--ropi")); + // Read-write position independent. + enableRwpi = flags.contains(QLatin1String("--rwpi")); + // Don't search standard libraries. + dontSearchLibs = flags.contains(QLatin1String("--noscanlib")); + // Report 'might fail' conditions as errors. + enableReportMightFail = flags.contains(QLatin1String("--strict")); + + QStringList scatterFiles; + + // Enumerate all product linker config files + // (which are set trough 'linkerscript' tag). + const auto qbsGroups = qbsProduct.groups(); + for (const auto &qbsGroup : qbsGroups) { + if (!qbsGroup.isEnabled()) + continue; + const auto qbsArtifacts = qbsGroup.sourceArtifacts(); + for (const auto &qbsArtifact : qbsArtifacts) { + const auto qbsTags = qbsArtifact.fileTags(); + if (!qbsTags.contains(QLatin1String("linkerscript"))) + continue; + const QString scatterFile = QFileInfo(qbsArtifact.filePath()) + .absoluteFilePath(); + scatterFiles.push_back(scatterFile); + } + } + + // Enumerate all scatter files + // (which are set trough '--scatter' option). + const QStringList scatters = gen::utils::allFlagValues( + flags, QStringLiteral("--scatter")); + for (const auto &scatter : scatters) { + const QString scatterFile = QFileInfo(scatter) + .absoluteFilePath(); + if (!scatterFiles.contains(scatterFile)) + scatterFiles.push_back(scatterFile); + } + + // Transform all paths to relative. + const QString baseDirectory = qbs::gen::utils::buildRootPath(qbsProject); + std::transform(scatterFiles.begin(), scatterFiles.end(), + std::back_inserter(scatterFiles), + [baseDirectory](const QString &scatterFile) { + return gen::utils::relativeFilePath(baseDirectory, scatterFile); + }); + + // Make a first scatter file as a main scatter file. + // Other scatter files will be interpretes as a misc controls. + if (scatterFiles.count() > 0) + mainScatterFile = scatterFiles.takeFirst(); + + for (const auto &scatterFile : qAsConst(scatterFiles)) { + const auto control = QStringLiteral("--scatter %1").arg(scatterFile); + miscControls.push_back(control); + } + + // Interpret other compiler flags as a misc controls (exclude only + // that flags which are was already handled). + for (auto flagIt = flags.cbegin(); flagIt < flags.cend(); ++flagIt) { + if (flagIt->contains(QLatin1String("--ropi")) + || flagIt->contains(QLatin1String("--rwpi")) + || flagIt->contains(QLatin1String("--noscanlib")) + || flagIt->contains(QLatin1String("--strict")) + ) { + continue; + } + if (flagIt->startsWith(QLatin1String("--scatter")) + ) { + ++flagIt; + continue; + } + miscControls.push_back(*flagIt); + } + } + + int enableRopi = 0; + int enableRwpi = 0; + int dontSearchLibs = 0; + int enableReportMightFail = 0; + + QString mainScatterFile; + QStringList miscControls; +}; + +} // namespace + +ArmTargetLinkerGroup::ArmTargetLinkerGroup( + const qbs::Project &qbsProject, + const qbs::ProductData &qbsProduct) + : gen::xml::PropertyGroup("LDads") +{ + const LinkerPageOptions opts(qbsProject, qbsProduct); + + // Add 'ROPI' item. + appendProperty(QByteArrayLiteral("Ropi"), opts.enableRopi); + // Add 'RWPI' item. + appendProperty(QByteArrayLiteral("Rwpi"), opts.enableRwpi); + // Add 'Don't search standard libraries' item. + appendProperty(QByteArrayLiteral("noStLib"), opts.dontSearchLibs); + // Add 'Report might fail' item. + appendProperty(QByteArrayLiteral("RepFail"), opts.enableReportMightFail); + // Add 'Scatter file' item. + appendProperty(QByteArrayLiteral("ScatterFile"), + QDir::toNativeSeparators(opts.mainScatterFile)); +} + +} // namespace v5 +} // namespace arm +} // namespace keiluv +} // namespace qbs diff --git a/src/plugins/generator/keiluv/archs/arm/armtargetlinkergroup_v5.h b/src/plugins/generator/keiluv/archs/arm/armtargetlinkergroup_v5.h new file mode 100644 index 000000000..db82d4bc2 --- /dev/null +++ b/src/plugins/generator/keiluv/archs/arm/armtargetlinkergroup_v5.h @@ -0,0 +1,54 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt.io/licensing +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef QBS_KEILUVARMTARGETLINKERGROUP_V5_H +#define QBS_KEILUVARMTARGETLINKERGROUP_V5_H + +#include <generators/xmlpropertygroup.h> + +namespace qbs { +namespace keiluv { +namespace arm { +namespace v5 { + +class ArmTargetLinkerGroup final : public gen::xml::PropertyGroup +{ +public: + explicit ArmTargetLinkerGroup( + const qbs::Project &qbsProject, + const qbs::ProductData &qbsProduct); +}; + +} // namespace v5 +} // namespace arm +} // namespace keiluv +} // namespace qbs + +#endif // QBS_KEILUVARMTARGETLINKERGROUP_V5_H diff --git a/src/plugins/generator/keiluv/archs/arm/armtargetmiscgroup_v5.cpp b/src/plugins/generator/keiluv/archs/arm/armtargetmiscgroup_v5.cpp new file mode 100644 index 000000000..511a16ab8 --- /dev/null +++ b/src/plugins/generator/keiluv/archs/arm/armtargetmiscgroup_v5.cpp @@ -0,0 +1,75 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt.io/licensing +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "armtargetmiscgroup_v5.h" + +#include "../../keiluvutils.h" + +namespace qbs { +namespace keiluv { +namespace arm { +namespace v5 { + +namespace { + +struct MiscPageOptions final +{ + explicit MiscPageOptions(const Project &qbsProject, + const ProductData &qbsProduct) + { + Q_UNUSED(qbsProject) + + const auto &qbsProps = qbsProduct.moduleProperties(); + const auto flags = qbs::KeiluvUtils::cppModuleCompilerFlags(qbsProps); + + generateLinkerMap = gen::utils::cppBooleanModuleProperty( + qbsProps, QStringLiteral("generateMapFile")); + } + + int generateLinkerMap = 0; +}; + +} // namespace + +ArmTargetMiscGroup::ArmTargetMiscGroup( + const qbs::Project &qbsProject, + const qbs::ProductData &qbsProduct) + : gen::xml::PropertyGroup("ArmAdsMisc") +{ + const MiscPageOptions opts(qbsProject, qbsProduct); + + // Add 'Generate linker map file' item. + appendProperty(QByteArrayLiteral("AdsLLst"), opts.generateLinkerMap); +} + +} // namespace v5 +} // namespace arm +} // namespace keiluv +} // namespace qbs diff --git a/src/plugins/generator/keiluv/archs/arm/armtargetmiscgroup_v5.h b/src/plugins/generator/keiluv/archs/arm/armtargetmiscgroup_v5.h new file mode 100644 index 000000000..025b2796d --- /dev/null +++ b/src/plugins/generator/keiluv/archs/arm/armtargetmiscgroup_v5.h @@ -0,0 +1,54 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt.io/licensing +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef QBS_KEILUVARMTARGETMISCGROUP_V5_H +#define QBS_KEILUVARMTARGETMISCGROUP_V5_H + +#include <generators/xmlpropertygroup.h> + +namespace qbs { +namespace keiluv { +namespace arm { +namespace v5 { + +class ArmTargetMiscGroup final : public gen::xml::PropertyGroup +{ +public: + explicit ArmTargetMiscGroup( + const qbs::Project &qbsProject, + const qbs::ProductData &qbsProduct); +}; + +} // namespace v5 +} // namespace arm +} // namespace keiluv +} // namespace qbs + +#endif // QBS_KEILUVARMTARGETMISCGROUP_V5_H diff --git a/src/plugins/generator/keiluv/archs/arm/armutilitiesgroup_v5.cpp b/src/plugins/generator/keiluv/archs/arm/armutilitiesgroup_v5.cpp new file mode 100644 index 000000000..eab3cc56c --- /dev/null +++ b/src/plugins/generator/keiluv/archs/arm/armutilitiesgroup_v5.cpp @@ -0,0 +1,50 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt.io/licensing +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "armutilitiesgroup_v5.h" + +namespace qbs { +namespace keiluv { +namespace arm { +namespace v5 { + +ArmUtilitiesGroup::ArmUtilitiesGroup( + const qbs::Project &qbsProject, + const qbs::ProductData &qbsProduct) + : gen::xml::PropertyGroup("Utilities") +{ + Q_UNUSED(qbsProject) + Q_UNUSED(qbsProduct) +} + +} // namespace v5 +} // namespace arm +} // namespace keiluv +} // namespace qbs diff --git a/src/plugins/generator/keiluv/archs/arm/armutilitiesgroup_v5.h b/src/plugins/generator/keiluv/archs/arm/armutilitiesgroup_v5.h new file mode 100644 index 000000000..a34a3a395 --- /dev/null +++ b/src/plugins/generator/keiluv/archs/arm/armutilitiesgroup_v5.h @@ -0,0 +1,54 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt.io/licensing +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef QBS_KEILUVARMUTILITIESGROUP_V5_H +#define QBS_KEILUVARMUTILITIESGROUP_V5_H + +#include <generators/xmlpropertygroup.h> + +namespace qbs { +namespace keiluv { +namespace arm { +namespace v5 { + +class ArmUtilitiesGroup final : public gen::xml::PropertyGroup +{ +public: + explicit ArmUtilitiesGroup( + const qbs::Project &qbsProject, + const qbs::ProductData &qbsProduct); +}; + +} // namespace v5 +} // namespace arm +} // namespace keiluv +} // namespace qbs + +#endif // QBS_KEILUVARMUTILITIESGROUP_V5_H diff --git a/src/plugins/generator/keiluv/archs/mcs51/mcs51buildtargetgroup_v5.cpp b/src/plugins/generator/keiluv/archs/mcs51/mcs51buildtargetgroup_v5.cpp new file mode 100644 index 000000000..87b3100db --- /dev/null +++ b/src/plugins/generator/keiluv/archs/mcs51/mcs51buildtargetgroup_v5.cpp @@ -0,0 +1,109 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt.io/licensing +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "mcs51buildtargetgroup_v5.h" +#include "mcs51commonpropertygroup_v5.h" +#include "mcs51debugoptiongroup_v5.h" +#include "mcs51dlloptiongroup_v5.h" +#include "mcs51targetcommonoptionsgroup_v5.h" +#include "mcs51targetgroup_v5.h" +#include "mcs51utilitiesgroup_v5.h" +#include "mcs51utils.h" + +#include "../../keiluvconstants.h" +#include "../../keiluvfilesgroupspropertygroup.h" + +namespace qbs { +namespace keiluv { +namespace mcs51 { +namespace v5 { + +Mcs51BuildTargetGroup::Mcs51BuildTargetGroup( + const qbs::Project &qbsProject, + const qbs::ProductData &qbsProduct, + const std::vector<qbs::ProductData> &qbsProductDeps) + : gen::xml::PropertyGroup("Target") +{ + // Append target name item (it is a build configuration name). + const QString targetName = gen::utils::buildConfigurationName( + qbsProject); + appendProperty(QByteArrayLiteral("TargetName"), targetName); + // Append toolset number group item. + appendChild<gen::xml::Property>(QByteArrayLiteral("ToolsetNumber"), + QByteArrayLiteral("0x0")); + // Append toolset name group item. + appendChild<gen::xml::Property>(QByteArrayLiteral("ToolsetName"), + QByteArrayLiteral("MCS-51")); + + // Append target option group item. + const auto targetOptionGroup = appendChild<gen::xml::PropertyGroup>( + QByteArrayLiteral("TargetOption")); + + targetOptionGroup->appendChild<Mcs51TargetCommonOptionsGroup>( + qbsProject, qbsProduct); + targetOptionGroup->appendChild<Mcs51CommonPropertyGroup>( + qbsProject, qbsProduct); + targetOptionGroup->appendChild<Mcs51DllOptionGroup>( + qbsProject, qbsProduct); + targetOptionGroup->appendChild<Mcs51DebugOptionGroup>( + qbsProject, qbsProduct); + targetOptionGroup->appendChild<Mcs51UtilitiesGroup>( + qbsProject, qbsProduct); + targetOptionGroup->appendChild<Mcs51TargetGroup>( + qbsProject, qbsProduct); + + // Append files group. + appendChild<KeiluvFilesGroupsPropertyGroup>(qbsProject, qbsProduct, + qbsProductDeps); +} + +bool Mcs51BuildTargetGroupFactory::canCreate( + gen::utils::Architecture arch, + const Version &version) const +{ + return arch == gen::utils::Architecture::Mcs51 + && version.majorVersion() == qbs::KeiluvConstants::v5::kUVisionVersion; +} + +std::unique_ptr<gen::xml::PropertyGroup> +Mcs51BuildTargetGroupFactory::create( + const qbs::Project &qbsProject, + const qbs::ProductData &qbsProduct, + const std::vector<qbs::ProductData> &qbsProductDeps) const +{ + const auto group = new Mcs51BuildTargetGroup( + qbsProject, qbsProduct, qbsProductDeps); + return std::unique_ptr<Mcs51BuildTargetGroup>(group); +} + +} // namespace v5 +} // namespace mcs51 +} // namespace keiluv +} // namespace qbs diff --git a/src/plugins/generator/keiluv/archs/mcs51/mcs51buildtargetgroup_v5.h b/src/plugins/generator/keiluv/archs/mcs51/mcs51buildtargetgroup_v5.h new file mode 100644 index 000000000..ef0c0ccba --- /dev/null +++ b/src/plugins/generator/keiluv/archs/mcs51/mcs51buildtargetgroup_v5.h @@ -0,0 +1,70 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt.io/licensing +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef QBS_KEILUVMCS51BUILDTARGETGROUP_V5_H +#define QBS_KEILUVMCS51BUILDTARGETGROUP_V5_H + +#include <generators/xmlpropertygroup.h> + +namespace qbs { +namespace keiluv { +namespace mcs51 { +namespace v5 { + +class Mcs51BuildTargetGroup final : public gen::xml::PropertyGroup +{ +private: + explicit Mcs51BuildTargetGroup( + const qbs::Project &qbsProject, + const qbs::ProductData &qbsProduct, + const std::vector<qbs::ProductData> &qbsProductDeps); + + friend class Mcs51BuildTargetGroupFactory; +}; + +class Mcs51BuildTargetGroupFactory final + : public gen::xml::PropertyGroupFactory +{ +public: + bool canCreate(gen::utils::Architecture arch, + const Version &version) const final; + + std::unique_ptr<gen::xml::PropertyGroup> create( + const qbs::Project &qbsProject, + const qbs::ProductData &qbsProduct, + const std::vector<qbs::ProductData> &qbsProductDeps) const final; +}; + +} // namespace v5 +} // namespace mcs51 +} // namespace keiluv +} // namespace qbs + +#endif // QBS_KEILUVMCS51BUILDTARGETGROUP_V5_H diff --git a/src/plugins/generator/keiluv/archs/mcs51/mcs51commonpropertygroup_v5.cpp b/src/plugins/generator/keiluv/archs/mcs51/mcs51commonpropertygroup_v5.cpp new file mode 100644 index 000000000..3d4d33046 --- /dev/null +++ b/src/plugins/generator/keiluv/archs/mcs51/mcs51commonpropertygroup_v5.cpp @@ -0,0 +1,50 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt.io/licensing +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "mcs51commonpropertygroup_v5.h" + +namespace qbs { +namespace keiluv { +namespace mcs51 { +namespace v5 { + +Mcs51CommonPropertyGroup::Mcs51CommonPropertyGroup( + const qbs::Project &qbsProject, + const qbs::ProductData &qbsProduct) + : gen::xml::PropertyGroup("CommonProperty") +{ + Q_UNUSED(qbsProject) + Q_UNUSED(qbsProduct) +} + +} // namespace v5 +} // namespace mcs51 +} // namespace keiluv +} // namespace qbs diff --git a/src/plugins/generator/keiluv/archs/mcs51/mcs51commonpropertygroup_v5.h b/src/plugins/generator/keiluv/archs/mcs51/mcs51commonpropertygroup_v5.h new file mode 100644 index 000000000..66dfc7a3e --- /dev/null +++ b/src/plugins/generator/keiluv/archs/mcs51/mcs51commonpropertygroup_v5.h @@ -0,0 +1,54 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt.io/licensing +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef QBS_KEILUVMCS51COMMONPROPERTYGROUP_V5_H +#define QBS_KEILUVMCS51COMMONPROPERTYGROUP_V5_H + +#include <generators/xmlpropertygroup.h> + +namespace qbs { +namespace keiluv { +namespace mcs51 { +namespace v5 { + +class Mcs51CommonPropertyGroup final : public gen::xml::PropertyGroup +{ +public: + explicit Mcs51CommonPropertyGroup( + const qbs::Project &qbsProject, + const qbs::ProductData &qbsProduct); +}; + +} // namespace v5 +} // namespace mcs51 +} // namespace keiluv +} // namespace qbs + +#endif // QBS_MCS51COMMONPROPERTYGROUP_V5_H diff --git a/src/plugins/generator/keiluv/archs/mcs51/mcs51debugoptiongroup_v5.cpp b/src/plugins/generator/keiluv/archs/mcs51/mcs51debugoptiongroup_v5.cpp new file mode 100644 index 000000000..2175cc488 --- /dev/null +++ b/src/plugins/generator/keiluv/archs/mcs51/mcs51debugoptiongroup_v5.cpp @@ -0,0 +1,50 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt.io/licensing +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "mcs51debugoptiongroup_v5.h" + +namespace qbs { +namespace keiluv { +namespace mcs51 { +namespace v5 { + +Mcs51DebugOptionGroup::Mcs51DebugOptionGroup( + const qbs::Project &qbsProject, + const qbs::ProductData &qbsProduct) + : gen::xml::PropertyGroup("DebugOption") +{ + Q_UNUSED(qbsProject) + Q_UNUSED(qbsProduct) +} + +} // namespace v5 +} // namespace mcs51 +} // namespace keiluv +} // namespace qbs diff --git a/src/plugins/generator/keiluv/archs/mcs51/mcs51debugoptiongroup_v5.h b/src/plugins/generator/keiluv/archs/mcs51/mcs51debugoptiongroup_v5.h new file mode 100644 index 000000000..473cf605c --- /dev/null +++ b/src/plugins/generator/keiluv/archs/mcs51/mcs51debugoptiongroup_v5.h @@ -0,0 +1,54 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt.io/licensing +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef QBS_KEILUVMCS51DEBUGOPTIONGROUP_V5_H +#define QBS_KEILUVMCS51DEBUGOPTIONGROUP_V5_H + +#include <generators/xmlpropertygroup.h> + +namespace qbs { +namespace keiluv { +namespace mcs51 { +namespace v5 { + +class Mcs51DebugOptionGroup final : public gen::xml::PropertyGroup +{ +public: + explicit Mcs51DebugOptionGroup( + const qbs::Project &qbsProject, + const qbs::ProductData &qbsProduct); +}; + +} // namespace v5 +} // namespace mcs51 +} // namespace keiluv +} // namespace qbs + +#endif // QBS_KEILUVMCS51DEBUGOPTIONGROUP_V5_H diff --git a/src/plugins/generator/keiluv/archs/mcs51/mcs51dlloptiongroup_v5.cpp b/src/plugins/generator/keiluv/archs/mcs51/mcs51dlloptiongroup_v5.cpp new file mode 100644 index 000000000..59aec721d --- /dev/null +++ b/src/plugins/generator/keiluv/archs/mcs51/mcs51dlloptiongroup_v5.cpp @@ -0,0 +1,50 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt.io/licensing +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "mcs51dlloptiongroup_v5.h" + +namespace qbs { +namespace keiluv { +namespace mcs51 { +namespace v5 { + +Mcs51DllOptionGroup::Mcs51DllOptionGroup( + const qbs::Project &qbsProject, + const qbs::ProductData &qbsProduct) + : gen::xml::PropertyGroup("DllOption") +{ + Q_UNUSED(qbsProject) + Q_UNUSED(qbsProduct) +} + +} // namespace v5 +} // namespace mcs51 +} // namespace keiluv +} // namespace qbs diff --git a/src/plugins/generator/keiluv/archs/mcs51/mcs51dlloptiongroup_v5.h b/src/plugins/generator/keiluv/archs/mcs51/mcs51dlloptiongroup_v5.h new file mode 100644 index 000000000..e16833acc --- /dev/null +++ b/src/plugins/generator/keiluv/archs/mcs51/mcs51dlloptiongroup_v5.h @@ -0,0 +1,54 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt.io/licensing +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef QBS_KEILUVMCS51DLLOPTIONGROUP_V5_H +#define QBS_KEILUVMCS51DLLOPTIONGROUP_V5_H + +#include <generators/xmlpropertygroup.h> + +namespace qbs { +namespace keiluv { +namespace mcs51 { +namespace v5 { + +class Mcs51DllOptionGroup final : public gen::xml::PropertyGroup +{ +public: + explicit Mcs51DllOptionGroup( + const qbs::Project &qbsProject, + const qbs::ProductData &qbsProduct); +}; + +} // namespace v5 +} // namespace mcs51 +} // namespace keiluv +} // namespace qbs + +#endif // QBS_KEILUVMCS51DLLOPTIONGROUP_V5_H diff --git a/src/plugins/generator/keiluv/archs/mcs51/mcs51targetassemblergroup_v5.cpp b/src/plugins/generator/keiluv/archs/mcs51/mcs51targetassemblergroup_v5.cpp new file mode 100644 index 000000000..8d7257713 --- /dev/null +++ b/src/plugins/generator/keiluv/archs/mcs51/mcs51targetassemblergroup_v5.cpp @@ -0,0 +1,143 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt.io/licensing +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "mcs51targetassemblergroup_v5.h" +#include "mcs51utils.h" + +#include "../../keiluvutils.h" + +namespace qbs { +namespace keiluv { +namespace mcs51 { +namespace v5 { + +namespace { + +struct AssemblerPageOptions final +{ + explicit AssemblerPageOptions(const Project &qbsProject, + const ProductData &qbsProduct) + { + Q_UNUSED(qbsProject) + + const auto &qbsProps = qbsProduct.moduleProperties(); + const auto flags = qbs::KeiluvUtils::cppModuleAssemblerFlags(qbsProps); + + // Don't use standard macro. + if (flags.contains(QLatin1String("NOMACRO"), Qt::CaseInsensitive)) + useStandardMacroProcessor = false; + + // Use MPL. + if (flags.contains(QLatin1String("MPL"), Qt::CaseInsensitive)) + useMacroProcessingLanguage = true; + + // Define 8051 SFR names. + if (flags.contains(QLatin1String("NOMOD51"), Qt::CaseInsensitive)) + suppressSfrNames = true; + + // Define symbols. + defineSymbols = qbs::KeiluvUtils::defines(qbsProps); + // Include paths. + includePaths = qbs::KeiluvUtils::includes(qbsProps); + + // Interpret other assembler flags as a misc controls (exclude only + // that flags which are was already handled). + for (const auto &flag : flags) { + if (flag.compare(QLatin1String("NOMACRO"), + Qt::CaseInsensitive) == 0 + || flag.compare(QLatin1String("MACRO"), + Qt::CaseInsensitive) == 0 + || flag.compare(QLatin1String("NOMPL"), + Qt::CaseInsensitive) == 0 + || flag.compare(QLatin1String("MPL"), + Qt::CaseInsensitive) == 0 + || flag.compare(QLatin1String("NOMOD51"), + Qt::CaseInsensitive) == 0 + || flag.compare(QLatin1String("MOD51"), + Qt::CaseInsensitive) == 0 + ) { + continue; + } + miscControls.push_back(flag); + } + } + + int useStandardMacroProcessor = true; + int useMacroProcessingLanguage = false; + int suppressSfrNames = false; + QStringList defineSymbols; + QStringList includePaths; + QStringList miscControls; +}; + +} // namespace + +Mcs51TargetAssemblerGroup::Mcs51TargetAssemblerGroup( + const qbs::Project &qbsProject, + const qbs::ProductData &qbsProduct) + : gen::xml::PropertyGroup("Ax51") +{ + const AssemblerPageOptions opts(qbsProject, qbsProduct); + + // Add 'Macro processor (Standard)' + appendProperty(QByteArrayLiteral("UseStandard"), + opts.useStandardMacroProcessor); + // Add 'Macro processor (MPL)' + appendProperty(QByteArrayLiteral("UseMpl"), + opts.useMacroProcessingLanguage); + // Add 'Define 8051 SFR names' + appendProperty(QByteArrayLiteral("UseMod51"), + opts.suppressSfrNames); + + // Add other various controls. + // Note: A sub-items order makes sense! + const auto variousControlsGroup = appendChild<gen::xml::PropertyGroup>( + QByteArrayLiteral("VariousControls")); + // Add 'Misc Controls' item. + variousControlsGroup->appendMultiLineProperty( + QByteArrayLiteral("MiscControls"), + opts.miscControls, QLatin1Char(' ')); + // Add 'Define' item. + variousControlsGroup->appendMultiLineProperty( + QByteArrayLiteral("Define"), + opts.defineSymbols); + // Add an empty 'Undefine' item. + variousControlsGroup->appendProperty( + QByteArrayLiteral("Undefine"), {}); + // Add 'Include Paths' item. + variousControlsGroup->appendMultiLineProperty( + QByteArrayLiteral("IncludePath"), + opts.includePaths, QLatin1Char(';')); +} + +} // namespace v5 +} // namespace mcs51 +} // namespace keiluv +} // namespace qbs diff --git a/src/plugins/generator/keiluv/archs/mcs51/mcs51targetassemblergroup_v5.h b/src/plugins/generator/keiluv/archs/mcs51/mcs51targetassemblergroup_v5.h new file mode 100644 index 000000000..f9a82304d --- /dev/null +++ b/src/plugins/generator/keiluv/archs/mcs51/mcs51targetassemblergroup_v5.h @@ -0,0 +1,54 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt.io/licensing +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef QBS_KEILUVMCS51TARGETASSEMBLERGROUP_V3 +#define QBS_KEILUVMCS51TARGETASSEMBLERGROUP_V3 + +#include <generators/xmlpropertygroup.h> + +namespace qbs { +namespace keiluv { +namespace mcs51 { +namespace v5 { + +class Mcs51TargetAssemblerGroup final : public gen::xml::PropertyGroup +{ +public: + explicit Mcs51TargetAssemblerGroup( + const qbs::Project &qbsProject, + const qbs::ProductData &qbsProduct); +}; + +} // namespace v5 +} // namespace mcs51 +} // namespace keiluv +} // namespace qbs + +#endif // QBS_KEILUVMCS51TARGETASSEMBLERGROUP_V3 diff --git a/src/plugins/generator/keiluv/archs/mcs51/mcs51targetcommonoptionsgroup_v5.cpp b/src/plugins/generator/keiluv/archs/mcs51/mcs51targetcommonoptionsgroup_v5.cpp new file mode 100644 index 000000000..de1be1ef6 --- /dev/null +++ b/src/plugins/generator/keiluv/archs/mcs51/mcs51targetcommonoptionsgroup_v5.cpp @@ -0,0 +1,140 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt.io/licensing +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "mcs51targetcommonoptionsgroup_v5.h" + +#include "../../keiluvutils.h" + +#include <generators/generatorutils.h> + +namespace qbs { +namespace keiluv { +namespace mcs51 { +namespace v5 { + +namespace { + +struct CommonPageOptions final +{ + explicit CommonPageOptions(const Project &qbsProject, + const ProductData &qbsProduct) + { + Q_UNUSED(qbsProject) + + const auto &qbsProps = qbsProduct.moduleProperties(); + const auto flags = KeiluvUtils::cppModuleCompilerFlags(qbsProps); + + // Browse information. + if (flags.contains(QLatin1String("BROWSE"), Qt::CaseInsensitive)) + browseInfo = true; + + // Debug information. + debugInfo = gen::utils::debugInformation(qbsProduct); + + // Output parameters. + executableName = gen::utils::targetBinary(qbsProduct); + // Fix output binary name if it is a library. Because + // the IDE appends an additional suffix (.LIB) to end + // of an output library name. + if (executableName.endsWith(QLatin1String(".lib"))) + executableName = qbsProduct.targetName(); + + const QString baseDirectory = gen::utils::buildRootPath(qbsProject); + objectDirectory = QDir::toNativeSeparators( + gen::utils::objectsOutputDirectory( + baseDirectory, qbsProduct)); + listingDirectory = QDir::toNativeSeparators( + gen::utils::listingOutputDirectory( + baseDirectory, qbsProduct)); + + // Target type. + targetType = KeiluvUtils::outputBinaryType(qbsProduct); + } + + int browseInfo = false; + int debugInfo = false; + QString executableName; + QString objectDirectory; + QString listingDirectory; + KeiluvUtils::OutputBinaryType targetType = + KeiluvUtils::ApplicationOutputType; +}; + +} // namespace + +Mcs51TargetCommonOptionsGroup::Mcs51TargetCommonOptionsGroup( + const qbs::Project &qbsProject, + const qbs::ProductData &qbsProduct) + : gen::xml::PropertyGroup("TargetCommonOption") +{ + const CommonPageOptions opts(qbsProject, qbsProduct); + + // Add 'Generic 8051 device' items, + // because we can't detect a target device + // form the present command lines. + appendProperty(QByteArrayLiteral("Device"), + QByteArrayLiteral("8051 (all Variants)")); + appendProperty(QByteArrayLiteral("Vendor"), + QByteArrayLiteral("Generic")); + appendProperty(QByteArrayLiteral("DeviceId"), + QByteArrayLiteral("2994")); + + // Add 'Debug Information' item. + appendProperty(QByteArrayLiteral("DebugInformation"), + opts.debugInfo); + // Add 'Browse Information' item. + appendProperty(QByteArrayLiteral("BrowseInformation"), + opts.browseInfo); + + // Add 'Name of Executable'. + appendProperty(QByteArrayLiteral("OutputName"), + opts.executableName); + // Add 'Output objects directory'. + appendProperty(QByteArrayLiteral("OutputDirectory"), + opts.objectDirectory); + // Add 'Output listing directory'. + appendProperty(QByteArrayLiteral("ListingPath"), + opts.listingDirectory); + + // Add 'Create Executable/Library' item. + const int isExecutable = (opts.targetType + == KeiluvUtils::ApplicationOutputType); + const int isLibrary = (opts.targetType + == KeiluvUtils::LibraryOutputType); + appendProperty(QByteArrayLiteral("CreateExecutable"), + isExecutable); + appendProperty(QByteArrayLiteral("CreateLib"), + isLibrary); +} + +} // namespace v5 +} // namespace mcs51 +} // namespace keiluv +} // namespace qbs diff --git a/src/plugins/generator/keiluv/archs/mcs51/mcs51targetcommonoptionsgroup_v5.h b/src/plugins/generator/keiluv/archs/mcs51/mcs51targetcommonoptionsgroup_v5.h new file mode 100644 index 000000000..eccd9d42d --- /dev/null +++ b/src/plugins/generator/keiluv/archs/mcs51/mcs51targetcommonoptionsgroup_v5.h @@ -0,0 +1,54 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt.io/licensing +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef QBS_KEILUVMCS51TARGETCOMMONOPTIONSGROUP_V5_H +#define QBS_KEILUVMCS51TARGETCOMMONOPTIONSGROUP_V5_H + +#include <generators/xmlpropertygroup.h> + +namespace qbs { +namespace keiluv { +namespace mcs51 { +namespace v5 { + +class Mcs51TargetCommonOptionsGroup final : public gen::xml::PropertyGroup +{ +public: + explicit Mcs51TargetCommonOptionsGroup( + const qbs::Project &qbsProject, + const qbs::ProductData &qbsProduct); +}; + +} // namespace v5 +} // namespace mcs51 +} // namespace keiluv +} // namespace qbs + +#endif // QBS_KEILUVMCS51TARGETCOMMONOPTIONSGROUP_V5_H diff --git a/src/plugins/generator/keiluv/archs/mcs51/mcs51targetcompilergroup_v5.cpp b/src/plugins/generator/keiluv/archs/mcs51/mcs51targetcompilergroup_v5.cpp new file mode 100644 index 000000000..e33c0c211 --- /dev/null +++ b/src/plugins/generator/keiluv/archs/mcs51/mcs51targetcompilergroup_v5.cpp @@ -0,0 +1,281 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt.io/licensing +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "mcs51targetcompilergroup_v5.h" +#include "mcs51utils.h" + +#include "../../keiluvutils.h" + +namespace qbs { +namespace keiluv { +namespace mcs51 { +namespace v5 { + +namespace { + +struct CompilerPageOptions final +{ + enum WarningLevel { + WarningLevelNone = 0, + WarningLevelOne, + WarningLevelTwo + }; + + enum OptimizationLevel { + ConstantFoldingOptimizationLevel = 0, + DeadCodeEliminationOptimizationLevel, + DataOverlayingOptimizationLevel, + PeepholeOptimizationLevel, + RegisterVariablesOptimizationLevel, + CommonSubexpressionEliminationOptimizationLevel, + LoopRotationOptimizationLevel, + ExtendedIndexAccessOptimizationLevel, + ReuseCommonEntryCodeOptimizationLevel, + CommonBlockSubroutinesOptimizationLevel, + RearrangeCodeOptimizationLevel, + ReuseCommonExitCodeOptimizationLevel + }; + + enum OptimizationEmphasis { + FavorSizeOptimizationEmphasis = 0, + FavorSpeedOptimizationEmphasis + }; + + enum FloatFuzzyBits { + NoFloatFuzzyBits = 0, + OneFloatFuzzyBit, + TwoFloatFuzzyBits, + ThreeFloatFuzzyBits, + FourFloatFuzzyBits, + FiveFloatFuzzyBits, + SixFloatFuzzyBits, + SevenFloatFuzzyBits + }; + + explicit CompilerPageOptions(const Project &qbsProject, + const ProductData &qbsProduct) + { + Q_UNUSED(qbsProject) + + const auto &qbsProps = qbsProduct.moduleProperties(); + const auto flags = qbs::KeiluvUtils::cppModuleCompilerFlags(qbsProps); + + // Warnings. + const QString level = gen::utils::cppStringModuleProperty( + qbsProps, QStringLiteral("warningLevel")); + if (level == QLatin1String("none")) { + warningLevel = WarningLevelNone; + } else if (level == QLatin1String("all")) { + warningLevel = WarningLevelTwo; + } else { + // In this case take it directly from the compiler command line, + // e.g. parse the line in a form: 'WARNINGLEVEL (2)' + const auto warnValue = KeiluvUtils::flagValue( + flags, QStringLiteral("WARNINGLEVEL")); + bool ok = false; + const auto level = warnValue.toInt(&ok); + if (ok && gen::utils::inBounds( + level, int(WarningLevelNone),int(WarningLevelTwo))) { + warningLevel = static_cast<WarningLevel>(level); + } + } + + // Optimizations. + const QString optimization = gen::utils::cppStringModuleProperty( + qbsProps, QStringLiteral("optimization")); + if (optimization == QLatin1String("fast")) { + optimizationEmphasis = FavorSpeedOptimizationEmphasis; + } else if (level == QLatin1String("small")) { + optimizationEmphasis = FavorSizeOptimizationEmphasis; + } else if (level == QLatin1String("small")) { + // Don't supported by C51 compiler. + } else { + // In this case take it directly from the compiler command line, + // e.g. parse the line in a form: 'OPTIMIZE (8, SPEED)' + const auto optValue = KeiluvUtils::flagValue( + flags, QStringLiteral("OPTIMIZE")); + const auto parts = KeiluvUtils::flagValueParts(optValue); + for (const auto &part : parts) { + bool ok = false; + const auto level = part.toInt(&ok); + if (ok && (level >= ConstantFoldingOptimizationLevel) + && (level <= ReuseCommonExitCodeOptimizationLevel)) { + optimizationLevel = static_cast<OptimizationLevel>(level); + } else if (part.compare(QLatin1String("SIZE"), + Qt::CaseInsensitive) == 0) { + optimizationEmphasis = FavorSizeOptimizationEmphasis; + } else if (part.compare(QLatin1String("SPEED"), + Qt::CaseInsensitive) == 0) { + optimizationEmphasis = FavorSpeedOptimizationEmphasis; + } + } + } + + // Don't use absolute register accesses. + if (flags.contains(QLatin1String("NOAREGS"), Qt::CaseInsensitive)) + dontuseAbsoluteRegsAccess = true; + + // Enable ANSI integer promotion rules. + if (flags.contains(QLatin1String("NOINTPROMOTE"), Qt::CaseInsensitive)) + enableIntegerPromotionRules = false; + + // Keep variables in order. + if (flags.contains(QLatin1String("ORDER"), Qt::CaseInsensitive)) + keepVariablesInOrder = true; + + // Don't use interrupt vector. + if (flags.contains(QLatin1String("NOINTVECTOR"), Qt::CaseInsensitive)) + useInterruptVector = false; + + // Interrupt vector address. + interruptVectorAddress = KeiluvUtils::flagValue( + flags, QStringLiteral("INTVECTOR")); + + // Float fuzzy bits count. + const auto bitsValue = KeiluvUtils::flagValue( + flags, QStringLiteral("FLOATFUZZY")); + bool ok = false; + const auto bits = bitsValue.toInt(&ok); + if (ok && gen::utils::inBounds( + bits, int(NoFloatFuzzyBits), int(SevenFloatFuzzyBits))) { + floatFuzzyBits = static_cast<FloatFuzzyBits>(bits); + } + + // Define symbols. + defineSymbols = qbs::KeiluvUtils::defines(qbsProps); + // Include paths. + includePaths = qbs::KeiluvUtils::includes(qbsProps); + + // Interpret other compiler flags as a misc controls (exclude only + // that flags which are was already handled). + for (const auto &flag : flags) { + if (flag.startsWith(QLatin1String("WARNINGLEVEL"), + Qt::CaseInsensitive) + || flag.startsWith(QLatin1String("OPTIMIZE"), + Qt::CaseInsensitive) + || flag.startsWith(QLatin1String("FLOATFUZZY"), + Qt::CaseInsensitive) + || flag.compare(QLatin1String("NOAREGS"), + Qt::CaseInsensitive) == 0 + || flag.compare(QLatin1String("AREGS"), + Qt::CaseInsensitive) == 0 + || flag.compare(QLatin1String("NOINTPROMOTE"), + Qt::CaseInsensitive) == 0 + || flag.compare(QLatin1String("INTPROMOTE"), + Qt::CaseInsensitive) == 0 + || flag.compare(QLatin1String("NOINTVECTOR"), + Qt::CaseInsensitive) == 0 + || flag.compare(QLatin1String("INTVECTOR"), + Qt::CaseInsensitive) == 0 + || flag.compare(QLatin1String("ORDER"), + Qt::CaseInsensitive) == 0 + || flag.compare(QLatin1String("BROSWE"), + Qt::CaseInsensitive) == 0 + ) { + continue; + } + miscControls.push_back(flag); + } + } + + WarningLevel warningLevel = WarningLevelTwo; + OptimizationLevel optimizationLevel = ReuseCommonEntryCodeOptimizationLevel; + OptimizationEmphasis optimizationEmphasis = FavorSpeedOptimizationEmphasis; + FloatFuzzyBits floatFuzzyBits = ThreeFloatFuzzyBits; + int dontuseAbsoluteRegsAccess = false; + int enableIntegerPromotionRules = true; + int keepVariablesInOrder = false; + int useInterruptVector = true; + QString interruptVectorAddress; + QStringList defineSymbols; + QStringList includePaths; + QStringList miscControls; +}; + +} // namespace + +Mcs51TargetCompilerGroup::Mcs51TargetCompilerGroup( + const qbs::Project &qbsProject, + const qbs::ProductData &qbsProduct) + : gen::xml::PropertyGroup("C51") +{ + const CompilerPageOptions opts(qbsProject, qbsProduct); + + // Add 'Code Optimization' options. + appendProperty(QByteArrayLiteral("Optimize"), + opts.optimizationLevel); + appendProperty(QByteArrayLiteral("SizeSpeed"), + opts.optimizationEmphasis); + // Add 'Warnings' options. + appendProperty(QByteArrayLiteral("WarningLevel"), + opts.warningLevel); + // Add 'Don't use absolute register access' item. + appendProperty(QByteArrayLiteral("uAregs"), + opts.dontuseAbsoluteRegsAccess); + // Add 'Enable integer promotion rules' item. + appendProperty(QByteArrayLiteral("IntegerPromotion"), + opts.enableIntegerPromotionRules); + // Add 'Keep variables in order' item. + appendProperty(QByteArrayLiteral("VariablesInOrder"), + opts.keepVariablesInOrder); + // Add 'Use interrupt vector' item. + appendProperty(QByteArrayLiteral("UseInterruptVector"), + opts.useInterruptVector); + appendProperty(QByteArrayLiteral("InterruptVectorAddress"), + opts.interruptVectorAddress); + // Add 'Float fuzzy bits' item. + appendProperty(QByteArrayLiteral("Fuzzy"), + opts.floatFuzzyBits); + + // Add other various controls. + // Note: A sub-items order makes sense! + const auto variousControlsGroup = appendChild<gen::xml::PropertyGroup>( + QByteArrayLiteral("VariousControls")); + // Add 'Misc Controls' item. + variousControlsGroup->appendMultiLineProperty( + QByteArrayLiteral("MiscControls"), + opts.miscControls, QLatin1Char(' ')); + // Add 'Define' item. + variousControlsGroup->appendMultiLineProperty( + QByteArrayLiteral("Define"), + opts.defineSymbols); + // Add an empty 'Undefine' item. + variousControlsGroup->appendProperty( + QByteArrayLiteral("Undefine"), {}); + // Add 'Include Paths' item. + variousControlsGroup->appendMultiLineProperty( + QByteArrayLiteral("IncludePath"), + opts.includePaths, QLatin1Char(';')); +} + +} // namespace v5 +} // namespace mcs51 +} // namespace keiluv +} // namespace qbs diff --git a/src/plugins/generator/keiluv/archs/mcs51/mcs51targetcompilergroup_v5.h b/src/plugins/generator/keiluv/archs/mcs51/mcs51targetcompilergroup_v5.h new file mode 100644 index 000000000..0f1e52ce4 --- /dev/null +++ b/src/plugins/generator/keiluv/archs/mcs51/mcs51targetcompilergroup_v5.h @@ -0,0 +1,54 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt.io/licensing +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef QBS_KEILUVMCS51TARGETCOMPILERGROUP_V5_H +#define QBS_KEILUVMCS51TARGETCOMPILERGROUP_V5_H + +#include <generators/xmlpropertygroup.h> + +namespace qbs { +namespace keiluv { +namespace mcs51 { +namespace v5 { + +class Mcs51TargetCompilerGroup final : public gen::xml::PropertyGroup +{ +public: + explicit Mcs51TargetCompilerGroup( + const qbs::Project &qbsProject, + const qbs::ProductData &qbsProduct); +}; + +} // namespace v5 +} // namespace mcs51 +} // namespace keiluv +} // namespace qbs + +#endif // QBS_KEILUVMCS51TARGETCOMPILERGROUP_V5_H diff --git a/src/plugins/generator/keiluv/archs/mcs51/mcs51targetgroup_v5.cpp b/src/plugins/generator/keiluv/archs/mcs51/mcs51targetgroup_v5.cpp new file mode 100644 index 000000000..2a05649dd --- /dev/null +++ b/src/plugins/generator/keiluv/archs/mcs51/mcs51targetgroup_v5.cpp @@ -0,0 +1,56 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt.io/licensing +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "mcs51targetassemblergroup_v5.h" +#include "mcs51targetcompilergroup_v5.h" +#include "mcs51targetgroup_v5.h" +#include "mcs51targetlinkergroup_v5.h" +#include "mcs51targetmiscgroup_v5.h" + +namespace qbs { +namespace keiluv { +namespace mcs51 { +namespace v5 { + +Mcs51TargetGroup::Mcs51TargetGroup( + const qbs::Project &qbsProject, + const qbs::ProductData &qbsProduct) + : gen::xml::PropertyGroup("Target51") +{ + appendChild<Mcs51TargetMiscGroup>(qbsProject, qbsProduct); + appendChild<Mcs51TargetCompilerGroup>(qbsProject, qbsProduct); + appendChild<Mcs51TargetAssemblerGroup>(qbsProject, qbsProduct); + appendChild<Mcs51TargetLinkerGroup>(qbsProject, qbsProduct); +} + +} // namespace v5 +} // namespace mcs51 +} // namespace keiluv +} // namespace qbs diff --git a/src/plugins/generator/keiluv/archs/mcs51/mcs51targetgroup_v5.h b/src/plugins/generator/keiluv/archs/mcs51/mcs51targetgroup_v5.h new file mode 100644 index 000000000..d256dfcc7 --- /dev/null +++ b/src/plugins/generator/keiluv/archs/mcs51/mcs51targetgroup_v5.h @@ -0,0 +1,54 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt.io/licensing +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef QBS_KEILUVMCS51TARGETGROUP_V5_H +#define QBS_KEILUVMCS51TARGETGROUP_V5_H + +#include <generators/xmlpropertygroup.h> + +namespace qbs { +namespace keiluv { +namespace mcs51 { +namespace v5 { + +class Mcs51TargetGroup final : public gen::xml::PropertyGroup +{ +public: + explicit Mcs51TargetGroup( + const qbs::Project &qbsProject, + const qbs::ProductData &qbsProduct); +}; + +} // namespace v5 +} // namespace mcs51 +} // namespace keiluv +} // namespace qbs + +#endif // QBS_KEILUVMCS51TARGETGROUP_V5_H diff --git a/src/plugins/generator/keiluv/archs/mcs51/mcs51targetlinkergroup_v5.cpp b/src/plugins/generator/keiluv/archs/mcs51/mcs51targetlinkergroup_v5.cpp new file mode 100644 index 000000000..4d52b627a --- /dev/null +++ b/src/plugins/generator/keiluv/archs/mcs51/mcs51targetlinkergroup_v5.cpp @@ -0,0 +1,240 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt.io/licensing +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "mcs51targetlinkergroup_v5.h" +#include "mcs51utils.h" + +#include "../../keiluvutils.h" + +namespace qbs { +namespace keiluv { +namespace mcs51 { +namespace v5 { + +namespace { + +struct LinkerPageOptions final +{ + explicit LinkerPageOptions(const Project &qbsProject, + const ProductData &qbsProduct) + { + Q_UNUSED(qbsProject) + + const auto &qbsProps = qbsProduct.moduleProperties(); + const auto flags = qbs::KeiluvUtils::cppModuleLinkerFlags(qbsProps); + + // Handle all 'BIT' memory flags. + parseMemory(flags, QStringLiteral("BIT"), + bitAddresses, bitSegments); + // Handle all 'CODE' memory flags. + parseMemory(flags, QStringLiteral("CODE"), + codeAddresses, codeSegments); + // Handle all 'DATA' memory flags. + parseMemory(flags, QStringLiteral("DATA"), + dataAddresses, dataSegments); + // Handle all 'IDATA' memory flags. + parseMemory(flags, QStringLiteral("IDATA"), + idataAddresses, idataSegments); + // Handle all 'PDATA' memory flags. + parseMemory(flags, QStringLiteral("PDATA"), + pdataAddresses, pdataSegments); + // Handle all 'XDATA' memory flags. + parseMemory(flags, QStringLiteral("XDATA"), + xdataAddresses, xdataSegments); + + // Enumerate all flags in a form like: + // 'PRECEDE(foo, bar) PRECEDE(baz)'. + const auto precedeValues = KeiluvUtils::flagValues( + flags, QStringLiteral("PRECEDE")); + for (const auto &precedeValue : precedeValues) { + const auto parts = KeiluvUtils::flagValueParts(precedeValue); + precedeSegments.reserve(precedeSegments.size() + parts.count()); + std::copy(parts.cbegin(), parts.cend(), + std::back_inserter(precedeSegments)); + } + + // Enumerate all flags in a form like: + // 'STACK(foo, bar) STACK(baz)'. + const auto stackValues = KeiluvUtils::flagValues( + flags, QStringLiteral("STACK")); + for (const auto &stackValue : stackValues) { + const auto parts = KeiluvUtils::flagValueParts(stackValue); + stackSegments.reserve(stackSegments.size() + parts.count()); + std::copy(parts.cbegin(), parts.cend(), + std::back_inserter(stackSegments)); + } + + // Interpret other linker flags as a misc controls (exclude only + // that flags which are was already handled). + for (const auto &flag : flags) { + if (flag.startsWith(QLatin1String("BIT"), + Qt::CaseInsensitive) + || flag.startsWith(QLatin1String("CODE"), + Qt::CaseInsensitive) + || flag.startsWith(QLatin1String("DATA"), + Qt::CaseInsensitive) + || flag.startsWith(QLatin1String("IDATA"), + Qt::CaseInsensitive) + || flag.startsWith(QLatin1String("PDATA"), + Qt::CaseInsensitive) + || flag.startsWith(QLatin1String("XDATA"), + Qt::CaseInsensitive) + || flag.startsWith(QLatin1String("PRECEDE"), + Qt::CaseInsensitive) + || flag.startsWith(QLatin1String("STACK"), + Qt::CaseInsensitive) + ) { + continue; + } + miscControls.push_back(flag); + } + } + + static void parseMemory(const QStringList &flags, + const QString &flagKey, + QStringList &destAddresses, + QStringList &destSegments) + { + // Handle all flags in a form like: + // 'FLAGKEY(0x00-0x20, 30, foo, bar(0x40)) FLAGKEY(baz)'. + const auto values = KeiluvUtils::flagValues(flags, flagKey); + for (const auto &value : values) { + const auto parts = KeiluvUtils::flagValueParts(value); + for (const auto &part : parts) { + if (part.contains(QLatin1Char('-'))) { + // Seems, it is an address range. + destAddresses.push_back(part); + } else { + // Check on address (specified in decimal + // or hexadecimal form). + bool ok = false; + part.toInt(&ok, 16); + if (!ok) + part.toInt(&ok, 10); + if (ok) { + // Seems, it is just a single address. + destAddresses.push_back(part); + } else { + // Seems it is a segment name. + destSegments.push_back(part); + } + } + } + } + } + + QStringList bitAddresses; + QStringList bitSegments; + QStringList codeAddresses; + QStringList codeSegments; + QStringList dataAddresses; + QStringList dataSegments; + QStringList idataAddresses; + QStringList idataSegments; + QStringList pdataAddresses; + QStringList pdataSegments; + QStringList xdataAddresses; + QStringList xdataSegments; + + QStringList precedeSegments; + QStringList stackSegments; + + QStringList miscControls; +}; + +} // namespace + +Mcs51TargetLinkerGroup::Mcs51TargetLinkerGroup( + const qbs::Project &qbsProject, + const qbs::ProductData &qbsProduct) + : gen::xml::PropertyGroup("Lx51") +{ + const LinkerPageOptions opts(qbsProject, qbsProduct); + + // Add 'Misc Controls' item. + appendMultiLineProperty(QByteArrayLiteral("MiscControls"), + opts.miscControls, QLatin1Char(' ')); + + // Add 'Use Memory Layout from Target Dialog' item. + // Note: we always disable it, as we expect that + // the layout will be specified from the linker's + // command line. + appendProperty(QByteArrayLiteral("UseMemoryFromTarget"), + 0); + + // Add 'Bit Range' item. + appendMultiLineProperty(QByteArrayLiteral("BitBaseAddress"), + opts.bitAddresses); + // Add 'Code Range' item. + appendMultiLineProperty(QByteArrayLiteral("CodeBaseAddress"), + opts.codeAddresses); + // Add 'Data Range' item. + appendMultiLineProperty(QByteArrayLiteral("DataBaseAddress"), + opts.dataAddresses); + // Add 'IData Range' item. + appendMultiLineProperty(QByteArrayLiteral("IDataBaseAddress"), + opts.idataAddresses); + // Add 'PData Range' item. + appendMultiLineProperty(QByteArrayLiteral("PDataBaseAddress"), + opts.pdataAddresses); + // Add 'XData Range' item. + appendMultiLineProperty(QByteArrayLiteral("XDataBaseAddress"), + opts.xdataAddresses); + + // Add 'Bit Segment' item. + appendMultiLineProperty(QByteArrayLiteral("BitSegmentName"), + opts.bitSegments); + // Add 'Code Segment' item. + appendMultiLineProperty(QByteArrayLiteral("CodeSegmentName"), + opts.codeSegments); + // Add 'Data Segment' item. + appendMultiLineProperty(QByteArrayLiteral("DataSegmentName"), + opts.dataSegments); + // Add 'IData Segment' item. + appendMultiLineProperty(QByteArrayLiteral("IDataSegmentName"), + opts.idataSegments); + + // Note: PData has not segments! + + // Add 'XData Segment' item. + appendMultiLineProperty(QByteArrayLiteral("XDataSegmentName"), + opts.xdataSegments); + // Add 'Precede' item. + appendMultiLineProperty(QByteArrayLiteral("Precede"), + opts.precedeSegments); + // Add 'Stack' item. + appendMultiLineProperty(QByteArrayLiteral("Stack"), + opts.stackSegments); +} + +} // namespace v5 +} // namespace mcs51 +} // namespace keiluv +} // namespace qbs diff --git a/src/plugins/generator/keiluv/archs/mcs51/mcs51targetlinkergroup_v5.h b/src/plugins/generator/keiluv/archs/mcs51/mcs51targetlinkergroup_v5.h new file mode 100644 index 000000000..d701c5e0e --- /dev/null +++ b/src/plugins/generator/keiluv/archs/mcs51/mcs51targetlinkergroup_v5.h @@ -0,0 +1,54 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt.io/licensing +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef QBS_KEILUVMCS51TARGETLINKERGROUP_V5_H +#define QBS_KEILUVMCS51TARGETLINKERGROUP_V5_H + +#include <generators/xmlpropertygroup.h> + +namespace qbs { +namespace keiluv { +namespace mcs51 { +namespace v5 { + +class Mcs51TargetLinkerGroup final : public gen::xml::PropertyGroup +{ +public: + explicit Mcs51TargetLinkerGroup( + const qbs::Project &qbsProject, + const qbs::ProductData &qbsProduct); +}; + +} // namespace v5 +} // namespace mcs51 +} // namespace keiluv +} // namespace qbs + +#endif // QBS_KEILUVMCS51TARGETLINKERGROUP_V5_H diff --git a/src/plugins/generator/keiluv/archs/mcs51/mcs51targetmiscgroup_v5.cpp b/src/plugins/generator/keiluv/archs/mcs51/mcs51targetmiscgroup_v5.cpp new file mode 100644 index 000000000..5d95d443f --- /dev/null +++ b/src/plugins/generator/keiluv/archs/mcs51/mcs51targetmiscgroup_v5.cpp @@ -0,0 +1,104 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt.io/licensing +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "mcs51targetmiscgroup_v5.h" +#include "mcs51utils.h" + +#include "../../keiluvutils.h" + +namespace qbs { +namespace keiluv { +namespace mcs51 { +namespace v5 { + +namespace { + +struct MiscPageOptions final +{ + enum MemoryModel { + SmallMemoryModel = 0, + CompactMemoryModel, + LargeMemoryModel + }; + + enum CodeRomSize { + SmallCodeRomSize = 0, + CompactCodeRomSize, + LargeCodeRomSize + }; + + explicit MiscPageOptions(const Project &qbsProject, + const ProductData &qbsProduct) + { + Q_UNUSED(qbsProject) + + const auto &qbsProps = qbsProduct.moduleProperties(); + const auto flags = qbs::KeiluvUtils::cppModuleCompilerFlags(qbsProps); + + // Memory model. + if (flags.contains(QLatin1String("COMPACT"), Qt::CaseInsensitive)) + memoryModel = CompactMemoryModel; + else if (flags.contains(QLatin1String("LARGE"), Qt::CaseInsensitive)) + memoryModel = LargeMemoryModel; + + // Code ROM size. + const auto sizeValue = KeiluvUtils::flagValue( + flags, QStringLiteral("ROM")); + if (sizeValue == QLatin1String("SMALL")) + coderomSize = SmallCodeRomSize; + else if (sizeValue == QLatin1String("COMPACT")) + coderomSize = CompactCodeRomSize; + } + + MemoryModel memoryModel = SmallMemoryModel; + CodeRomSize coderomSize = LargeCodeRomSize; +}; + +} // namespace + +Mcs51TargetMiscGroup::Mcs51TargetMiscGroup( + const qbs::Project &qbsProject, + const qbs::ProductData &qbsProduct) + : gen::xml::PropertyGroup("Target51Misc") +{ + const MiscPageOptions opts(qbsProject, qbsProduct); + + // Add 'Memory Model' options item. + appendProperty(QByteArrayLiteral("MemoryModel"), + opts.memoryModel); + // Add 'ROM Size' options item. + appendProperty(QByteArrayLiteral("RomSize"), + opts.coderomSize); +} + +} // namespace v5 +} // namespace mcs51 +} // namespace keiluv +} // namespace qbs diff --git a/src/plugins/generator/keiluv/archs/mcs51/mcs51targetmiscgroup_v5.h b/src/plugins/generator/keiluv/archs/mcs51/mcs51targetmiscgroup_v5.h new file mode 100644 index 000000000..f1680d927 --- /dev/null +++ b/src/plugins/generator/keiluv/archs/mcs51/mcs51targetmiscgroup_v5.h @@ -0,0 +1,54 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt.io/licensing +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef QBS_KEILUVMCS51TARGETMISCGROUP_V5_H +#define QBS_KEILUVMCS51TARGETMISCGROUP_V5_H + +#include <generators/xmlpropertygroup.h> + +namespace qbs { +namespace keiluv { +namespace mcs51 { +namespace v5 { + +class Mcs51TargetMiscGroup final : public gen::xml::PropertyGroup +{ +public: + explicit Mcs51TargetMiscGroup( + const qbs::Project &qbsProject, + const qbs::ProductData &qbsProduct); +}; + +} // namespace v5 +} // namespace mcs51 +} // namespace keiluv +} // namespace qbs + +#endif // QBS_KEILUVMCS51TARGETMISCGROUP_V5_H diff --git a/src/plugins/generator/keiluv/archs/mcs51/mcs51utilitiesgroup_v5.cpp b/src/plugins/generator/keiluv/archs/mcs51/mcs51utilitiesgroup_v5.cpp new file mode 100644 index 000000000..8e8307f72 --- /dev/null +++ b/src/plugins/generator/keiluv/archs/mcs51/mcs51utilitiesgroup_v5.cpp @@ -0,0 +1,50 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt.io/licensing +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "mcs51utilitiesgroup_v5.h" + +namespace qbs { +namespace keiluv { +namespace mcs51 { +namespace v5 { + +Mcs51UtilitiesGroup::Mcs51UtilitiesGroup( + const qbs::Project &qbsProject, + const qbs::ProductData &qbsProduct) + : gen::xml::PropertyGroup("Utilities") +{ + Q_UNUSED(qbsProject) + Q_UNUSED(qbsProduct) +} + +} // namespace v5 +} // namespace mcs51 +} // namespace keiluv +} // namespace qbs diff --git a/src/plugins/generator/keiluv/archs/mcs51/mcs51utilitiesgroup_v5.h b/src/plugins/generator/keiluv/archs/mcs51/mcs51utilitiesgroup_v5.h new file mode 100644 index 000000000..f95ec67c4 --- /dev/null +++ b/src/plugins/generator/keiluv/archs/mcs51/mcs51utilitiesgroup_v5.h @@ -0,0 +1,54 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt.io/licensing +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef QBS_KEILUVMCS51UTILITIESGROUP_V5_H +#define QBS_KEILUVMCS51UTILITIESGROUP_V5_H + +#include <generators/xmlpropertygroup.h> + +namespace qbs { +namespace keiluv { +namespace mcs51 { +namespace v5 { + +class Mcs51UtilitiesGroup final : public gen::xml::PropertyGroup +{ +public: + explicit Mcs51UtilitiesGroup( + const qbs::Project &qbsProject, + const qbs::ProductData &qbsProduct); +}; + +} // namespace v5 +} // namespace mcs51 +} // namespace keiluv +} // namespace qbs + +#endif // QBS_KEILUVMCS51UTILITIESGROUP_V5_H diff --git a/src/plugins/generator/keiluv/archs/mcs51/mcs51utils.cpp b/src/plugins/generator/keiluv/archs/mcs51/mcs51utils.cpp new file mode 100644 index 000000000..698f0df78 --- /dev/null +++ b/src/plugins/generator/keiluv/archs/mcs51/mcs51utils.cpp @@ -0,0 +1,83 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt.io/licensing +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "mcs51utils.h" + +namespace qbs { +namespace keiluv { +namespace mcs51 { + +namespace KeiluvUtils { + +static QString extractValue(const QString &flag) +{ + const auto openBracketIndex = flag.indexOf(QLatin1Char('(')); + const auto closeBracketIndex = flag.indexOf(QLatin1Char(')')); + const auto n = closeBracketIndex - openBracketIndex - 1; + return flag.mid(openBracketIndex + 1, n); +} + +QStringList flagValues(const QStringList &flags, const QString &flagKey) +{ + QStringList values; + for (const auto &flag : flags) { + if (!flag.startsWith(flagKey, Qt::CaseInsensitive)) + continue; + const auto value = extractValue(flag); + values.push_back(value); + } + return values; +} + +QString flagValue(const QStringList &flags, const QString &flagKey) +{ + const auto flagEnd = flags.cend(); + const auto flagIt = std::find_if(flags.cbegin(), flagEnd, + [flagKey](const auto &flag) { + return flag.startsWith(flagKey, Qt::CaseInsensitive); + }); + if (flagIt == flagEnd) + return {}; // Flag key not found. + return extractValue(*flagIt); +} + +QStringList flagValueParts(const QString &flagValue, const QLatin1Char &sep) +{ + auto parts = flagValue.split(sep); + std::transform(parts.begin(), parts.end(), parts.begin(), + [](const auto &part) { return part.trimmed(); }); + return parts; +} + +} // namespace KeiluvUtils + +} // namespace mcs51 +} // namespace keiluv +} // namespace qbs diff --git a/src/plugins/generator/keiluv/archs/mcs51/mcs51utils.h b/src/plugins/generator/keiluv/archs/mcs51/mcs51utils.h new file mode 100644 index 000000000..a1a9706e4 --- /dev/null +++ b/src/plugins/generator/keiluv/archs/mcs51/mcs51utils.h @@ -0,0 +1,56 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt.io/licensing +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef QBS_KEILUVMCS51UTILS_H +#define QBS_KEILUVMCS51UTILS_H + +#include <QtCore/qstringlist.h> + +namespace qbs { + +namespace keiluv { +namespace mcs51 { + +namespace KeiluvUtils { + +QStringList flagValues(const QStringList &flags, const QString &flagKey); + +QString flagValue(const QStringList &flags, const QString &flagKey); + +QStringList flagValueParts(const QString &flagValue, + const QLatin1Char &sep = QLatin1Char(',')); + +} // namespace KeiluvUtils + +} // namespace mcs51 +} // namespace keiluv +} // namespace qbs + +#endif // QBS_KEILUVMCS51UTILS_H diff --git a/src/plugins/generator/keiluv/keiluv.pro b/src/plugins/generator/keiluv/keiluv.pro new file mode 100644 index 000000000..ba3e4d27b --- /dev/null +++ b/src/plugins/generator/keiluv/keiluv.pro @@ -0,0 +1,92 @@ +include(../../plugins.pri) +include(../../../shared/json/json.pri) + +TARGET = keiluvgenerator + +QT = core + +# Plugin file. + +SOURCES += \ + $$PWD/keiluvgeneratorplugin.cpp \ + +# Common files. + +HEADERS += \ + $$PWD/keiluvconstants.h \ + $$PWD/keiluvfilesgroupspropertygroup.h \ + $$PWD/keiluvgenerator.h \ + $$PWD/keiluvproject.h \ + $$PWD/keiluvprojectwriter.h \ + $$PWD/keiluvutils.h \ + $$PWD/keiluvversioninfo.h \ + $$PWD/keiluvworkspace.h \ + $$PWD/keiluvworkspacewriter.h + +SOURCES += \ + $$PWD/keiluvfilesgroupspropertygroup.cpp \ + $$PWD/keiluvgenerator.cpp \ + $$PWD/keiluvproject.cpp \ + $$PWD/keiluvprojectwriter.cpp \ + $$PWD/keiluvutils.cpp \ + $$PWD/keiluvversioninfo.cpp \ + $$PWD/keiluvworkspace.cpp \ + $$PWD/keiluvworkspacewriter.cpp + +# For MCS51 architecture. + +HEADERS += \ + $$PWD/archs/mcs51/mcs51buildtargetgroup_v5.h \ + $$PWD/archs/mcs51/mcs51commonpropertygroup_v5.h \ + $$PWD/archs/mcs51/mcs51debugoptiongroup_v5.h \ + $$PWD/archs/mcs51/mcs51dlloptiongroup_v5.h \ + $$PWD/archs/mcs51/mcs51targetassemblergroup_v5.h \ + $$PWD/archs/mcs51/mcs51targetcommonoptionsgroup_v5.h \ + $$PWD/archs/mcs51/mcs51targetcompilergroup_v5.h \ + $$PWD/archs/mcs51/mcs51targetgroup_v5.h \ + $$PWD/archs/mcs51/mcs51targetlinkergroup_v5.h \ + $$PWD/archs/mcs51/mcs51targetmiscgroup_v5.h \ + $$PWD/archs/mcs51/mcs51utilitiesgroup_v5.h \ + $$PWD/archs/mcs51/mcs51utils.h + +SOURCES += \ + $$PWD/archs/mcs51/mcs51buildtargetgroup_v5.cpp \ + $$PWD/archs/mcs51/mcs51commonpropertygroup_v5.cpp \ + $$PWD/archs/mcs51/mcs51debugoptiongroup_v5.cpp \ + $$PWD/archs/mcs51/mcs51dlloptiongroup_v5.cpp \ + $$PWD/archs/mcs51/mcs51targetassemblergroup_v5.cpp \ + $$PWD/archs/mcs51/mcs51targetcommonoptionsgroup_v5.cpp \ + $$PWD/archs/mcs51/mcs51targetcompilergroup_v5.cpp \ + $$PWD/archs/mcs51/mcs51targetgroup_v5.cpp \ + $$PWD/archs/mcs51/mcs51targetlinkergroup_v5.cpp \ + $$PWD/archs/mcs51/mcs51targetmiscgroup_v5.cpp \ + $$PWD/archs/mcs51/mcs51utilitiesgroup_v5.cpp \ + $$PWD/archs/mcs51/mcs51utils.cpp + +# For ARM architecture. + +HEADERS += \ + $$PWD/archs/arm/armbuildtargetgroup_v5.h \ + $$PWD/archs/arm/armcommonpropertygroup_v5.h \ + $$PWD/archs/arm/armdebugoptiongroup_v5.h \ + $$PWD/archs/arm/armdlloptiongroup_v5.h \ + $$PWD/archs/arm/armtargetassemblergroup_v5.h \ + $$PWD/archs/arm/armtargetcommonoptionsgroup_v5.h \ + $$PWD/archs/arm/armtargetcompilergroup_v5.h \ + $$PWD/archs/arm/armtargetgroup_v5.h \ + $$PWD/archs/arm/armtargetlinkergroup_v5.h \ + $$PWD/archs/arm/armtargetmiscgroup_v5.h \ + $$PWD/archs/arm/armutilitiesgroup_v5.h + +SOURCES += \ + $$PWD/archs/arm/armbuildtargetgroup_v5.cpp \ + $$PWD/archs/arm/armcommonpropertygroup_v5.cpp \ + $$PWD/archs/arm/armdebugoptiongroup_v5.cpp \ + $$PWD/archs/arm/armdlloptiongroup_v5.cpp \ + $$PWD/archs/arm/armtargetassemblergroup_v5.cpp \ + $$PWD/archs/arm/armtargetcommonoptionsgroup_v5.cpp \ + $$PWD/archs/arm/armtargetcompilergroup_v5.cpp \ + $$PWD/archs/arm/armtargetgroup_v5.cpp \ + $$PWD/archs/arm/armtargetlinkergroup_v5.cpp \ + $$PWD/archs/arm/armtargetmiscgroup_v5.cpp \ + $$PWD/archs/arm/armutilitiesgroup_v5.cpp diff --git a/src/plugins/generator/keiluv/keiluv.qbs b/src/plugins/generator/keiluv/keiluv.qbs new file mode 100644 index 000000000..65bf6d65b --- /dev/null +++ b/src/plugins/generator/keiluv/keiluv.qbs @@ -0,0 +1,90 @@ +import qbs +import "../../qbsplugin.qbs" as QbsPlugin + +QbsPlugin { + Depends { name: "qbsjson" } + + name: "keiluvgenerator" + + files: ["keiluvgeneratorplugin.cpp"] + + Group { + name: "KEIL UV generator common" + files: [ + "keiluvfilesgroupspropertygroup.cpp", + "keiluvfilesgroupspropertygroup.h", + "keiluvgenerator.cpp", + "keiluvgenerator.h", + "keiluvproject.cpp", + "keiluvproject.h", + "keiluvprojectwriter.cpp", + "keiluvprojectwriter.h", + "keiluvutils.cpp", + "keiluvutils.h", + "keiluvversioninfo.cpp", + "keiluvversioninfo.h", + "keiluvworkspace.cpp", + "keiluvworkspace.h", + "keiluvworkspacewriter.cpp", + "keiluvworkspacewriter.h", + ] + } + Group { + name: "KEIL UV generator for MCS51" + prefix: "archs/mcs51/" + files: [ + "mcs51buildtargetgroup_v5.cpp", + "mcs51buildtargetgroup_v5.h", + "mcs51commonpropertygroup_v5.cpp", + "mcs51commonpropertygroup_v5.h", + "mcs51debugoptiongroup_v5.cpp", + "mcs51debugoptiongroup_v5.h", + "mcs51dlloptiongroup_v5.cpp", + "mcs51dlloptiongroup_v5.h", + "mcs51targetassemblergroup_v5.cpp", + "mcs51targetassemblergroup_v5.h", + "mcs51targetcommonoptionsgroup_v5.cpp", + "mcs51targetcommonoptionsgroup_v5.h", + "mcs51targetcompilergroup_v5.cpp", + "mcs51targetcompilergroup_v5.h", + "mcs51targetgroup_v5.cpp", + "mcs51targetgroup_v5.h", + "mcs51targetlinkergroup_v5.cpp", + "mcs51targetlinkergroup_v5.h", + "mcs51targetmiscgroup_v5.cpp", + "mcs51targetmiscgroup_v5.h", + "mcs51utilitiesgroup_v5.cpp", + "mcs51utilitiesgroup_v5.h", + "mcs51utils.cpp", + "mcs51utils.h", + ] + } + Group { + name: "KEIL UV generator for ARM" + prefix: "archs/arm/" + files: [ + "armbuildtargetgroup_v5.cpp", + "armbuildtargetgroup_v5.h", + "armcommonpropertygroup_v5.cpp", + "armcommonpropertygroup_v5.h", + "armdebugoptiongroup_v5.cpp", + "armdebugoptiongroup_v5.h", + "armdlloptiongroup_v5.cpp", + "armdlloptiongroup_v5.h", + "armtargetassemblergroup_v5.cpp", + "armtargetassemblergroup_v5.h", + "armtargetcommonoptionsgroup_v5.cpp", + "armtargetcommonoptionsgroup_v5.h", + "armtargetcompilergroup_v5.cpp", + "armtargetcompilergroup_v5.h", + "armtargetgroup_v5.cpp", + "armtargetgroup_v5.h", + "armtargetlinkergroup_v5.cpp", + "armtargetlinkergroup_v5.h", + "armtargetmiscgroup_v5.cpp", + "armtargetmiscgroup_v5.h", + "armutilitiesgroup_v5.cpp", + "armutilitiesgroup_v5.h", + ] + } +} diff --git a/src/plugins/generator/keiluv/keiluvconstants.h b/src/plugins/generator/keiluv/keiluvconstants.h new file mode 100644 index 000000000..0d27ab81d --- /dev/null +++ b/src/plugins/generator/keiluv/keiluvconstants.h @@ -0,0 +1,44 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt.io/licensing +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef QBS_KEILUVCONSTANTS_H +#define QBS_KEILUVCONSTANTS_H + +namespace qbs { +namespace KeiluvConstants { + +namespace v5 { +constexpr int kUVisionVersion = 5; +} + +} // namespace KeiluvConstants +} // namespace qbs + +#endif // QBS_KEILUVCONSTANTS_H diff --git a/src/plugins/generator/keiluv/keiluvfilesgroupspropertygroup.cpp b/src/plugins/generator/keiluv/keiluvfilesgroupspropertygroup.cpp new file mode 100644 index 000000000..b9a234d6a --- /dev/null +++ b/src/plugins/generator/keiluv/keiluvfilesgroupspropertygroup.cpp @@ -0,0 +1,197 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt.io/licensing +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "keiluvfilesgroupspropertygroup.h" +#include "keiluvutils.h" + +#include <generators/generatordata.h> + +#include <tools/stringconstants.h> + +namespace qbs { + +class KeiluvFilePropertyGroup final : public gen::xml::PropertyGroup +{ +public: + explicit KeiluvFilePropertyGroup( + const QString &fullFilePath, + const QString &baseDirectory) + : gen::xml::PropertyGroup("File") + { + const QFileInfo fileInfo(fullFilePath); + const auto fileName = fileInfo.fileName(); + const auto fileType = encodeFileType(fileInfo.suffix()); + const auto filePath = QDir::toNativeSeparators( + gen::utils::relativeFilePath( + baseDirectory, + fileInfo.absoluteFilePath())); + + appendChild<gen::xml::Property>(QByteArrayLiteral("FileName"), + fileName); + appendChild<gen::xml::Property>(QByteArrayLiteral("FileType"), + fileType); + appendChild<gen::xml::Property>(QByteArrayLiteral("FilePath"), + filePath); + } + +private: + enum FileType { + UnknownFileType = 0, + CSourceFileType = 1, + AssemblerFileType = 2, + LibraryFileType = 4, + TextFileType = 5, + CppSourceFileType = 8, + }; + + static FileType encodeFileType(const QString &fileSuffix) + { + if (fileSuffix.compare(QLatin1String("c"), + Qt::CaseInsensitive) == 0) { + return CSourceFileType; + } else if (fileSuffix.compare(QLatin1String("cpp"), + Qt::CaseInsensitive) == 0) { + return CppSourceFileType; + } else if (fileSuffix.compare(QLatin1String("s"), + Qt::CaseInsensitive) == 0 + || fileSuffix.compare(QLatin1String("a51"), + Qt::CaseInsensitive) == 0) { + return AssemblerFileType; + } else if (fileSuffix.compare(QLatin1String("lib"), + Qt::CaseInsensitive) == 0) { + return LibraryFileType; + } else { + // All header files, text files and include files + // interpretes as a text file types. + return TextFileType; + } + } +}; + +class KeiluvFilesPropertyGroup final : public gen::xml::PropertyGroup +{ +public: + explicit KeiluvFilesPropertyGroup( + const QList<ArtifactData> &sourceArtifacts, + const QString &baseDirectory) + : gen::xml::PropertyGroup("Files") + { + for (const auto &artifact : sourceArtifacts) + appendChild<KeiluvFilePropertyGroup>(artifact.filePath(), + baseDirectory); + } + + explicit KeiluvFilesPropertyGroup( + const QStringList &filePaths, + const QString &baseDirectory) + : gen::xml::PropertyGroup("Files") + { + for (const auto &filePath : filePaths) + appendChild<KeiluvFilePropertyGroup>(filePath, + baseDirectory); + } +}; + +class KeiluvFileGroupPropertyGroup final : public gen::xml::PropertyGroup +{ +public: + explicit KeiluvFileGroupPropertyGroup( + const QString &groupName, + const QList<ArtifactData> &sourceArtifacts, + const QString &baseDirectory) + : gen::xml::PropertyGroup("Group") + { + appendChild<gen::xml::Property>(QByteArrayLiteral("GroupName"), + groupName); + + appendChild<KeiluvFilesPropertyGroup>(sourceArtifacts, + baseDirectory); + } + + explicit KeiluvFileGroupPropertyGroup( + const QString &groupName, + const QStringList &filePaths, + const QString &baseDirectory) + : gen::xml::PropertyGroup("Group") + { + appendChild<gen::xml::Property>(QByteArrayLiteral("GroupName"), + groupName); + + appendChild<KeiluvFilesPropertyGroup>(filePaths, + baseDirectory); + } +}; + +KeiluvFilesGroupsPropertyGroup::KeiluvFilesGroupsPropertyGroup( + const Project &qbsProject, + const ProductData &qbsProduct, + const std::vector<ProductData> &qbsProductDeps) + : gen::xml::PropertyGroup(QByteArrayLiteral("Groups")) +{ + const auto baseDirectory = gen::utils::buildRootPath(qbsProject); + + // Build source items. + const auto groups = qbsProduct.groups(); + for (const auto &group : groups) { + // Ignore disabled groups (e.g. when its condition property is false). + if (!group.isEnabled()) + continue; + auto sourceArtifacts = group.sourceArtifacts(); + // Remove the linker script artifacts. + sourceArtifacts.erase(std::remove_if(sourceArtifacts.begin(), + sourceArtifacts.end(), + [](const auto &artifact){ + const auto tags = artifact.fileTags(); + return tags.contains(QLatin1String("linkerscript")); + }), sourceArtifacts.end()); + + if (sourceArtifacts.isEmpty()) + continue; + appendChild<KeiluvFileGroupPropertyGroup>( + group.name(), sourceArtifacts, baseDirectory); + } + + // Build local static library items. + const auto &qbsProps = qbsProduct.moduleProperties(); + const auto staticLibs = KeiluvUtils::staticLibraries(qbsProps); + if (!staticLibs.isEmpty()) { + appendChild<KeiluvFileGroupPropertyGroup>( + QStringLiteral("Static Libs"), staticLibs, baseDirectory); + } + + // Build dependency library items. + const auto deps = KeiluvUtils::dependencies(qbsProductDeps); + if (!deps.isEmpty()) { + appendChild<KeiluvFileGroupPropertyGroup>( + QStringLiteral("Dependencies"), deps, baseDirectory); + } +} + +} // namespace qbs diff --git a/src/plugins/generator/keiluv/keiluvfilesgroupspropertygroup.h b/src/plugins/generator/keiluv/keiluvfilesgroupspropertygroup.h new file mode 100644 index 000000000..bde86b89c --- /dev/null +++ b/src/plugins/generator/keiluv/keiluvfilesgroupspropertygroup.h @@ -0,0 +1,52 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt.io/licensing +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef QBS_KEILUVFILESGROUPSPROPERTYGROUP_H +#define QBS_KEILUVFILESGROUPSPROPERTYGROUP_H + +#include <generators/xmlpropertygroup.h> + +#include <generators/generatordata.h> + +namespace qbs { + +class KeiluvFilesGroupsPropertyGroup final + : public gen::xml::PropertyGroup +{ +public: + explicit KeiluvFilesGroupsPropertyGroup( + const qbs::Project &qbsProject, + const qbs::ProductData &qbsProduct, + const std::vector<qbs::ProductData> &qbsProductDeps); +}; + +} // namespace qbs + +#endif // QBS_KEILUVFILESGROUPSPROPERTYGROUP_H diff --git a/src/plugins/generator/keiluv/keiluvgenerator.cpp b/src/plugins/generator/keiluv/keiluvgenerator.cpp new file mode 100644 index 000000000..e3c959e8d --- /dev/null +++ b/src/plugins/generator/keiluv/keiluvgenerator.cpp @@ -0,0 +1,149 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt.io/licensing +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "keiluvgenerator.h" +#include "keiluvproject.h" +#include "keiluvprojectwriter.h" +#include "keiluvworkspace.h" +#include "keiluvworkspacewriter.h" + +#include <generators/generatableprojectiterator.h> +#include <generators/generatorutils.h> + +#include <logging/logger.h> +#include <logging/translator.h> + +#include <tools/filesaver.h> + +namespace qbs { + +static void writeProjectFiles(const std::map<QString, + std::shared_ptr<KeiluvProject>> &projects, + const Internal::Logger &logger) +{ + for (const auto &item : projects) { + const QString projectFilePath = item.first; + Internal::FileSaver file(projectFilePath.toStdString()); + if (!file.open()) + throw ErrorInfo(Internal::Tr::tr("Cannot open %s for writing") + .arg(projectFilePath)); + + std::shared_ptr<KeiluvProject> project = item.second; + KeiluvProjectWriter writer(file.device()); + if (!(writer.write(project.get()) && file.commit())) + throw ErrorInfo(Internal::Tr::tr("Failed to generate %1") + .arg(projectFilePath)); + + logger.qbsInfo() << Internal::Tr::tr("Generated %1").arg( + QFileInfo(projectFilePath).fileName()); + } +} + +static void writeWorkspace(const std::shared_ptr<KeiluvWorkspace> &wokspace, + const QString &workspaceFilePath, + const Internal::Logger &logger) +{ + Internal::FileSaver file(workspaceFilePath.toStdString()); + if (!file.open()) + throw ErrorInfo(Internal::Tr::tr("Cannot open %s for writing") + .arg(workspaceFilePath)); + + KeiluvWorkspaceWriter writer(file.device()); + if (!(writer.write(wokspace.get()) && file.commit())) + throw ErrorInfo(Internal::Tr::tr("Failed to generate %1") + .arg(workspaceFilePath)); + + logger.qbsInfo() << Internal::Tr::tr("Generated %1").arg( + QFileInfo(workspaceFilePath).fileName()); +} + +KeiluvGenerator::KeiluvGenerator(const KeiluvVersionInfo &versionInfo) + : m_versionInfo(versionInfo) +{ +} + +QString KeiluvGenerator::generatorName() const +{ + return QStringLiteral("keiluv%1").arg(m_versionInfo.marketingVersion()); +} + +void KeiluvGenerator::reset() +{ + m_workspace.reset(); + m_workspaceFilePath.clear(); + m_projects.clear(); +} + +void KeiluvGenerator::generate() +{ + GeneratableProjectIterator it(project()); + it.accept(this); + + writeProjectFiles(m_projects, logger()); + writeWorkspace(m_workspace, m_workspaceFilePath, logger()); + + reset(); +} + +void KeiluvGenerator::visitProject(const GeneratableProject &project) +{ + const QDir buildDir = project.baseBuildDirectory(); + + m_workspaceFilePath = buildDir.absoluteFilePath( + project.name() + QStringLiteral(".uvmpw")); + m_workspace = std::make_shared<KeiluvWorkspace>(m_workspaceFilePath); +} + +void KeiluvGenerator::visitProjectData( + const GeneratableProject &project, + const GeneratableProjectData &projectData) +{ + Q_UNUSED(project) + Q_UNUSED(projectData) +} + +void KeiluvGenerator::visitProduct( + const GeneratableProject &project, + const GeneratableProjectData &projectData, + const GeneratableProductData &productData) +{ + Q_UNUSED(projectData); + + const QDir baseBuildDir(project.baseBuildDirectory().absolutePath()); + const QString projFileName = productData.name() + QLatin1String(".uvprojx"); + const QString projectFilePath = baseBuildDir.absoluteFilePath(projFileName); + const auto targetProject = std::make_shared<KeiluvProject>( + project, productData, m_versionInfo); + + m_projects.insert({projectFilePath, targetProject}); + m_workspace->addProject(projectFilePath); +} + +} // namespace qbs diff --git a/src/plugins/generator/keiluv/keiluvgenerator.h b/src/plugins/generator/keiluv/keiluvgenerator.h new file mode 100644 index 000000000..769519562 --- /dev/null +++ b/src/plugins/generator/keiluv/keiluvgenerator.h @@ -0,0 +1,71 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt.io/licensing +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef QBS_KEILUVGENERATOR_H +#define QBS_KEILUVGENERATOR_H + +#include "keiluvversioninfo.h" + +#include <generators/generator.h> +#include <generators/igeneratableprojectvisitor.h> + +namespace qbs { + +class KeiluvProject; +class KeiluvWorkspace; + +class KeiluvGenerator final : public ProjectGenerator, + private IGeneratableProjectVisitor +{ +public: + explicit KeiluvGenerator(const KeiluvVersionInfo &versionInfo); + + QString generatorName() const final; + void generate() final; + +private: + void reset(); + + void visitProject(const GeneratableProject &project) final; + void visitProjectData(const GeneratableProject &project, + const GeneratableProjectData &projectData) final; + void visitProduct(const GeneratableProject &project, + const GeneratableProjectData &projectData, + const GeneratableProductData &productData) final; + + const KeiluvVersionInfo m_versionInfo; + std::shared_ptr<KeiluvWorkspace> m_workspace; + QString m_workspaceFilePath; + std::map<QString, std::shared_ptr<KeiluvProject>> m_projects; +}; + +} // namespace qbs + +#endif // QBS_KEILUVGENERATOR_H diff --git a/src/plugins/generator/keiluv/keiluvgeneratorplugin.cpp b/src/plugins/generator/keiluv/keiluvgeneratorplugin.cpp new file mode 100644 index 000000000..33e552936 --- /dev/null +++ b/src/plugins/generator/keiluv/keiluvgeneratorplugin.cpp @@ -0,0 +1,67 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qbs. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "keiluvgenerator.h" +#include "keiluvversioninfo.h" + +#include <tools/projectgeneratormanager.h> +#include <tools/qbspluginmanager.h> + +static void QbsKeiluvGeneratorPluginLoad() +{ + for (const auto &info : qbs::KeiluvVersionInfo::knownVersions()) { + qbs::ProjectGeneratorManager::registerGenerator( + std::make_shared<qbs::KeiluvGenerator>(info)); + } +} + +static void QbsKeiluvGeneratorPluginUnload() +{ +} + +#ifndef GENERATOR_EXPORT +#if defined(WIN32) || defined(_WIN32) +#define GENERATOR_EXPORT __declspec(dllexport) +#else +#define GENERATOR_EXPORT __attribute__((visibility("default"))) +#endif +#endif + +QBS_REGISTER_STATIC_PLUGIN(extern "C" GENERATOR_EXPORT, QbsKeiluvGeneratorPlugin, + QbsKeiluvGeneratorPluginLoad, QbsKeiluvGeneratorPluginUnload) diff --git a/src/plugins/generator/keiluv/keiluvproject.cpp b/src/plugins/generator/keiluv/keiluvproject.cpp new file mode 100644 index 000000000..476ce8e69 --- /dev/null +++ b/src/plugins/generator/keiluv/keiluvproject.cpp @@ -0,0 +1,114 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt.io/licensing +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "keiluvconstants.h" +#include "keiluvproject.h" +#include "keiluvutils.h" +#include "keiluvversioninfo.h" + +#include "archs/mcs51/mcs51buildtargetgroup_v5.h" +#include "archs/arm/armbuildtargetgroup_v5.h" + +#include <logging/translator.h> + +namespace qbs { + +static QString keilProjectSchema(const KeiluvVersionInfo &info) +{ + const auto v = info.marketingVersion(); + switch (v) { + case KeiluvConstants::v5::kUVisionVersion: + return QStringLiteral("2.1"); + default: + return {}; + } +} + +KeiluvProject::KeiluvProject( + const qbs::GeneratableProject &genProject, + const qbs::GeneratableProductData &genProduct, + const KeiluvVersionInfo &versionInfo) +{ + Q_ASSERT(genProject.projects.size() == genProject.commandLines.size()); + Q_ASSERT(genProject.projects.size() == genProduct.data.size()); + + // Create available configuration group factories. + m_factories.push_back(std::make_unique< + keiluv::mcs51::v5::Mcs51BuildTargetGroupFactory>()); + m_factories.push_back(std::make_unique< + keiluv::arm::v5::ArmBuildTargetGroupFactory>()); + + // Construct schema version item (is it depends on a project version?). + const auto schema = keilProjectSchema(versionInfo); + appendChild<gen::xml::Property>(QByteArrayLiteral("SchemaVersion"), + schema); + + // Construct targets group. + const auto targetsGroup = appendChild<gen::xml::PropertyGroup>( + QByteArrayLiteral("Targets")); + + // Construct all build target items. + const int configsCount = std::max(genProject.projects.size(), + genProduct.data.size()); + for (auto configIndex = 0; configIndex < configsCount; ++configIndex) { + const qbs::Project qbsProject = genProject.projects + .values().at(configIndex); + const qbs::ProductData qbsProduct = genProduct.data + .values().at(configIndex); + const QString confName = gen::utils::buildConfigurationName(qbsProject); + const std::vector<ProductData> qbsProductDeps = gen::utils::dependenciesOf + (qbsProduct, genProject, confName); + + const auto arch = gen::utils::architecture(qbsProject); + if (arch == gen::utils::Architecture::Unknown) + throw ErrorInfo(Internal::Tr::tr("Target architecture is not set," + " please use the 'profile' option")); + + // Construct the build target item, which are depend from + // the architecture and the version. + const auto factoryEnd = m_factories.cend(); + const auto factoryIt = std::find_if(m_factories.cbegin(), factoryEnd, + [arch, versionInfo](const auto &factory) { + return factory->canCreate(arch, versionInfo.version()); + }); + if (factoryIt == factoryEnd) { + throw ErrorInfo(Internal::Tr::tr("Incompatible target architecture '%1'" + " for KEIL UV version %2") + .arg(gen::utils::architectureName(arch)) + .arg(versionInfo.marketingVersion())); + } + + auto targetGroup = (*factoryIt)->create( + qbsProject, qbsProduct, qbsProductDeps); + targetsGroup->appendChild(std::move(targetGroup)); + } +} + +} // namespace qbs diff --git a/src/plugins/generator/keiluv/keiluvproject.h b/src/plugins/generator/keiluv/keiluvproject.h new file mode 100644 index 000000000..98b2815ed --- /dev/null +++ b/src/plugins/generator/keiluv/keiluvproject.h @@ -0,0 +1,58 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt.io/licensing +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef QBS_KEILUVPROJECT_H +#define QBS_KEILUVPROJECT_H + +#include <generators/generatordata.h> + +#include <generators/xmlproject.h> +#include <generators/xmlpropertygroup.h> + +#include <memory> + +namespace qbs { + +class KeiluvVersionInfo; + +class KeiluvProject final : public gen::xml::Project +{ +public: + explicit KeiluvProject( + const qbs::GeneratableProject &genProject, + const qbs::GeneratableProductData &genProduct, + const KeiluvVersionInfo &versionInfo); +private: + std::vector<std::unique_ptr<gen::xml::PropertyGroupFactory>> m_factories; +}; + +} // namespace qbs + +#endif // QBS_KEILUVPROJECT_H diff --git a/src/plugins/generator/keiluv/keiluvprojectwriter.cpp b/src/plugins/generator/keiluv/keiluvprojectwriter.cpp new file mode 100644 index 000000000..77616335c --- /dev/null +++ b/src/plugins/generator/keiluv/keiluvprojectwriter.cpp @@ -0,0 +1,58 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt.io/licensing +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "keiluvprojectwriter.h" + +namespace qbs { + +KeiluvProjectWriter::KeiluvProjectWriter(std::ostream *device) + : gen::xml::ProjectWriter(device) +{ +} + +void KeiluvProjectWriter::visitProjectStart(const gen::xml::Project *project) +{ + Q_UNUSED(project) + writer()->writeStartElement(QStringLiteral("Project")); + writer()->writeAttribute( + QStringLiteral("xmlns:xsi"), + QStringLiteral("http://www.w3.org/2001/XMLSchema-instance")); + writer()->writeAttribute( + QStringLiteral("xsi:noNamespaceSchemaLocation"), + QStringLiteral("project_proj.xsd")); +} + +void KeiluvProjectWriter::visitProjectEnd(const gen::xml::Project *project) +{ + Q_UNUSED(project) + writer()->writeEndElement(); +} + +} // namespace qbs diff --git a/src/plugins/generator/keiluv/keiluvprojectwriter.h b/src/plugins/generator/keiluv/keiluvprojectwriter.h new file mode 100644 index 000000000..6f890c8e8 --- /dev/null +++ b/src/plugins/generator/keiluv/keiluvprojectwriter.h @@ -0,0 +1,51 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt.io/licensing +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef QBS_KEILUVPROJECTWRITER_H +#define QBS_KEILUVPROJECTWRITER_H + +#include <generators/xmlprojectwriter.h> + +namespace qbs { + +class KeiluvProjectWriter final : public gen::xml::ProjectWriter +{ + Q_DISABLE_COPY(KeiluvProjectWriter) +public: + explicit KeiluvProjectWriter(std::ostream *device); + +private: + void visitProjectStart(const gen::xml::Project *project) final; + void visitProjectEnd(const gen::xml::Project *project) final; +}; + +} // namespace qbs + +#endif // QBS_KEILUVPROJECTWRITER_H diff --git a/src/plugins/generator/keiluv/keiluvutils.cpp b/src/plugins/generator/keiluv/keiluvutils.cpp new file mode 100644 index 000000000..8932f0f16 --- /dev/null +++ b/src/plugins/generator/keiluv/keiluvutils.cpp @@ -0,0 +1,123 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt.io/licensing +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "keiluvutils.h" + +#include <generators/generatorutils.h> + +namespace qbs { +namespace KeiluvUtils { + +OutputBinaryType outputBinaryType(const ProductData &qbsProduct) +{ + const auto qbsProductType = qbsProduct.type(); + if (qbsProductType.contains(QLatin1String("application"))) + return ApplicationOutputType; + if (qbsProductType.contains(QLatin1String("staticlibrary"))) + return LibraryOutputType; + return ApplicationOutputType; +} + +QString toolkitRootPath(const ProductData &qbsProduct) +{ + QDir dir(qbsProduct.moduleProperties() + .getModuleProperty(Internal::StringConstants::cppModule(), + QStringLiteral("toolchainInstallPath")) + .toString()); + dir.cdUp(); + const auto path = dir.absolutePath(); + return QDir::toNativeSeparators(path); +} + +QStringList cppModuleCompilerFlags(const PropertyMap &qbsProps) +{ + return gen::utils::cppStringModuleProperties( + qbsProps, {QStringLiteral("driverFlags"), QStringLiteral("cFlags"), + QStringLiteral("cppFlags"), QStringLiteral("cxxFlags"), + QStringLiteral("commonCompilerFlags")}); +} + +QStringList cppModuleAssemblerFlags(const PropertyMap &qbsProps) +{ + return gen::utils::cppStringModuleProperties( + qbsProps, {QStringLiteral("assemblerFlags")}); +} + +QStringList cppModuleLinkerFlags(const PropertyMap &qbsProps) +{ + return gen::utils::cppStringModuleProperties( + qbsProps, {QStringLiteral("driverLinkerFlags")}); +} + +QStringList includes(const PropertyMap &qbsProps) +{ + auto paths = gen::utils::cppStringModuleProperties( + qbsProps, {QStringLiteral("includePaths"), + QStringLiteral("systemIncludePaths")}); + // Transform include path separators to native. + std::transform(paths.begin(), paths.end(), paths.begin(), + [](const auto &path) { + return QDir::toNativeSeparators(path); + }); + return paths; +} + +QStringList defines(const PropertyMap &qbsProps) +{ + return gen::utils::cppStringModuleProperties( + qbsProps, {QStringLiteral("defines")}); +} + +QStringList staticLibraries(const PropertyMap &qbsProps) +{ + auto libs = gen::utils::cppStringModuleProperties( + qbsProps, {QStringLiteral("staticLibraries")}); + // Transform library path separators to native. + std::transform(libs.begin(), libs.end(), libs.begin(), + [](const auto &path) { + return QDir::toNativeSeparators(path); + }); + return libs; +} + +QStringList dependencies(const std::vector<ProductData> &qbsProductDeps) +{ + QStringList deps; + for (const ProductData &qbsProductDep : qbsProductDeps) { + const auto path = qbsProductDep.buildDirectory() + + QLatin1String("/obj/") + + gen::utils::targetBinary(qbsProductDep); + deps.push_back(QDir::toNativeSeparators(path)); + } + return deps; +} + +} // namespace KeiluvUtils +} // namespace qbs diff --git a/src/plugins/generator/keiluv/keiluvutils.h b/src/plugins/generator/keiluv/keiluvutils.h new file mode 100644 index 000000000..92209dc53 --- /dev/null +++ b/src/plugins/generator/keiluv/keiluvutils.h @@ -0,0 +1,64 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt.io/licensing +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef QBS_KEILUVUTILS_H +#define QBS_KEILUVUTILS_H + +#include <qbs.h> + +#include <tools/stringconstants.h> + +namespace qbs { +namespace KeiluvUtils { + +enum OutputBinaryType { + ApplicationOutputType, + LibraryOutputType +}; + +OutputBinaryType outputBinaryType(const ProductData &qbsProduct); + +QString toolkitRootPath(const ProductData &qbsProduct); + +QStringList cppModuleCompilerFlags(const PropertyMap &qbsProps); + +QStringList cppModuleAssemblerFlags(const PropertyMap &qbsProps); + +QStringList cppModuleLinkerFlags(const PropertyMap &qbsProps); + +QStringList includes(const PropertyMap &qbsProps); +QStringList defines(const PropertyMap &qbsProps); +QStringList staticLibraries(const PropertyMap &qbsProps); +QStringList dependencies(const std::vector<ProductData> &qbsProductDeps); + +} // namespace KeiluvUtils +} // namespace qbs + +#endif // QBS_KEILUVUTILS_H diff --git a/src/plugins/generator/keiluv/keiluvversioninfo.cpp b/src/plugins/generator/keiluv/keiluvversioninfo.cpp new file mode 100644 index 000000000..973d0a420 --- /dev/null +++ b/src/plugins/generator/keiluv/keiluvversioninfo.cpp @@ -0,0 +1,76 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qbs. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "keiluvconstants.h" +#include "keiluvversioninfo.h" + +#include <QtCore/qdebug.h> + +namespace qbs { + +KeiluvVersionInfo::KeiluvVersionInfo( + const Version &version, + const std::set<gen::utils::Architecture> &archs) + : gen::VersionInfo(version, archs) +{ +} + +std::set<KeiluvVersionInfo> KeiluvVersionInfo::knownVersions() +{ + static const std::set<KeiluvVersionInfo> known = { + {Version(KeiluvConstants::v5::kUVisionVersion), + {gen::utils::Architecture::Mcs51, + gen::utils::Architecture::Arm}}, + }; + return known; +} + +int KeiluvVersionInfo::marketingVersion() const +{ + const auto mv = gen::VersionInfo::marketingVersion(); + for (const KeiluvVersionInfo &known : knownVersions()) { + if (known.version().majorVersion() == mv) + return mv; + } + qWarning() << QStringLiteral("Unrecognized KEIL UV version: ") + << version().toString(); + return 0; +} + +} // namespace qbs diff --git a/src/plugins/generator/keiluv/keiluvversioninfo.h b/src/plugins/generator/keiluv/keiluvversioninfo.h new file mode 100644 index 000000000..a64513492 --- /dev/null +++ b/src/plugins/generator/keiluv/keiluvversioninfo.h @@ -0,0 +1,61 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qbs. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QBS_KEILUVVERSIONINFO_H +#define QBS_KEILUVVERSIONINFO_H + +#include <generators/generatorutils.h> +#include <generators/generatorversioninfo.h> + +namespace qbs { + +class KeiluvVersionInfo final : public gen::VersionInfo +{ +public: + KeiluvVersionInfo(const Version &version, + const std::set<gen::utils::Architecture> &archs); + + int marketingVersion() const final; + + static std::set<KeiluvVersionInfo> knownVersions(); +}; + +} // namespace qbs + +#endif // QBS_KEILUVVERSIONINFO_H diff --git a/src/plugins/generator/keiluv/keiluvworkspace.cpp b/src/plugins/generator/keiluv/keiluvworkspace.cpp new file mode 100644 index 000000000..b4df92001 --- /dev/null +++ b/src/plugins/generator/keiluv/keiluvworkspace.cpp @@ -0,0 +1,68 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qbs. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "keiluvworkspace.h" + +#include <generators/xmlpropertygroup.h> + +namespace qbs { + +KeiluvWorkspace::KeiluvWorkspace(const QString &workspacePath) + : gen::xml::Workspace(workspacePath) +{ + // Construct schema version item. + appendChild<gen::xml::Property>(QByteArrayLiteral("SchemaVersion"), + QStringLiteral("1.0")); + + // Construct workspace name item. + appendChild<gen::xml::Property>(QByteArrayLiteral("WorkspaceName"), + QStringLiteral("WorkSpace")); +} + +void KeiluvWorkspace::addProject(const QString &projectFilePath) +{ + const QString relativeProjectPath = QDir::toNativeSeparators( + m_baseDirectory.relativeFilePath(projectFilePath)); + + const auto projectGroup = appendChild<gen::xml::PropertyGroup>( + QByteArrayLiteral("project")); + projectGroup->appendProperty("PathAndName", relativeProjectPath); +} + +} // namespace qbs diff --git a/src/plugins/generator/keiluv/keiluvworkspace.h b/src/plugins/generator/keiluv/keiluvworkspace.h new file mode 100644 index 000000000..2b274c99f --- /dev/null +++ b/src/plugins/generator/keiluv/keiluvworkspace.h @@ -0,0 +1,56 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qbs. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QBS_KEILUVWORKSPACE_H +#define QBS_KEILUVWORKSPACE_H + +#include <generators/xmlworkspace.h> + +namespace qbs { + +class KeiluvWorkspace final : public gen::xml::Workspace +{ +public: + explicit KeiluvWorkspace(const QString &workspacePath); + void addProject(const QString &projectPath) final; +}; + +} // namespace qbs + +#endif // QBS_KEILUVWORKSPACE_H diff --git a/src/plugins/generator/keiluv/keiluvworkspacewriter.cpp b/src/plugins/generator/keiluv/keiluvworkspacewriter.cpp new file mode 100644 index 000000000..c886b0e6e --- /dev/null +++ b/src/plugins/generator/keiluv/keiluvworkspacewriter.cpp @@ -0,0 +1,58 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt.io/licensing +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "keiluvworkspacewriter.h" + +namespace qbs { + +KeiluvWorkspaceWriter::KeiluvWorkspaceWriter(std::ostream *device) + : gen::xml::WorkspaceWriter(device) +{ +} + +void KeiluvWorkspaceWriter::visitWorkspaceStart(const gen::xml::Workspace *workspace) +{ + Q_UNUSED(workspace) + writer()->writeStartElement(QStringLiteral("ProjectWorkspace")); + writer()->writeAttribute( + QStringLiteral("xmlns:xsi"), + QStringLiteral("http://www.w3.org/2001/XMLSchema-instance")); + writer()->writeAttribute( + QStringLiteral("xsi:noNamespaceSchemaLocation"), + QStringLiteral("project_mpw.xsd")); +} + +void KeiluvWorkspaceWriter::visitWorkspaceEnd(const gen::xml::Workspace *workspace) +{ + Q_UNUSED(workspace) + writer()->writeEndElement(); +} + +} // namespace qbs diff --git a/src/plugins/generator/keiluv/keiluvworkspacewriter.h b/src/plugins/generator/keiluv/keiluvworkspacewriter.h new file mode 100644 index 000000000..2419ad761 --- /dev/null +++ b/src/plugins/generator/keiluv/keiluvworkspacewriter.h @@ -0,0 +1,51 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt.io/licensing +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef QBS_KEILUVWORKSPACEWRITER_H +#define QBS_KEILUVWORKSPACEWRITER_H + +#include <generators/xmlworkspacewriter.h> + +namespace qbs { + +class KeiluvWorkspaceWriter final : public gen::xml::WorkspaceWriter +{ + Q_DISABLE_COPY(KeiluvWorkspaceWriter) +public: + explicit KeiluvWorkspaceWriter(std::ostream *device); + +private: + void visitWorkspaceStart(const gen::xml::Workspace *workspace) final; + void visitWorkspaceEnd(const gen::xml::Workspace *workspace) final; +}; + +} // namespace qbs + +#endif // QBS_KEILUVWORKSPACEWRITER_H diff --git a/src/plugins/plugins.qbs b/src/plugins/plugins.qbs index dcc1ded87..ee101f60e 100644 --- a/src/plugins/plugins.qbs +++ b/src/plugins/plugins.qbs @@ -6,6 +6,8 @@ Project { "generator/clangcompilationdb/clangcompilationdb.qbs", "generator/makefilegenerator/makefilegenerator.qbs", "generator/visualstudio/visualstudio.qbs", + "generator/iarew/iarew.qbs", + "generator/keiluv/keiluv.qbs", "scanner/cpp/cpp.qbs", "scanner/qt/qt.qbs" ] |