diff options
author | Denis Shienkov <denis.shienkov@gmail.com> | 2019-07-13 15:40:04 +0300 |
---|---|---|
committer | Denis Shienkov <denis.shienkov@gmail.com> | 2019-07-18 14:44:23 +0000 |
commit | 62e0c4710cc0c146cd057840d2b02ae06313c359 (patch) | |
tree | 3c9488b0de0d9db6f6ea22706f9122653047ee9b /src/plugins/generator/iarew | |
parent | 973ec011fda30243579e76800ba52b1fab77eb39 (diff) |
baremetal: Long live the IAR EW project generator for 8051
Right now it is possible to generate a native projects for the
IAR Embedded Workbench IDE, e.g. using the following command:
qbs generate -g iarew10 -d <path/to/build/directory> -f <path/to/qbs/project> profile:<your/qbs/profile>
We need in a valid IAR EW QBS profile, from which the generator take
a desired target architecture and other stuff.
The IAR EW generator has a semi-intelligent logic, it parses a source
QBS project and converts a compiler flags and other stuff to an
appropriate configurations of the native IAR EW project.
Currently it is supported only one 'iarew10' generator which allow to
generate a projects for the IAR EW for 8051 for all versions of 10 series.
Tested with the IAR EW for 8051 v10.10.1, using as the QBS
bare-metal examples, and as other projects.
Change-Id: If8a7397bebf6176010d42cfda41230e50a499a69
Reviewed-by: Ivan Komissarov <ABBAPOH@gmail.com>
Reviewed-by: Christian Kandeler <christian.kandeler@qt.io>
Diffstat (limited to 'src/plugins/generator/iarew')
16 files changed, 2585 insertions, 0 deletions
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..81bbdb3e7 --- /dev/null +++ b/src/plugins/generator/iarew/archs/mcs51/mcs51archiversettingsgroup_v10.cpp @@ -0,0 +1,93 @@ +/**************************************************************************** +** +** 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 "../../iarewproperty.h" +#include "../../iarewutils.h" + +namespace qbs { +namespace v10 { + +constexpr int kArchiverArchiveVersion = 2; +constexpr int kArchiverDataVersion = 1; + +namespace ArmArchiver { + +// Output page options. + +struct OutputPageOptions final +{ + explicit OutputPageOptions(const QString &baseDirectory, + const ProductData &qbsProduct) + { + outputFile = QLatin1String("$PROJ_DIR$/") + + IarewUtils::targetBinaryPath(baseDirectory, qbsProduct); + } + + QString outputFile; +}; + +} // namespace ArmArchiver + +// 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(IarewUtils::debugInformation(qbsProduct)); + + const QString buildRootDirectory = IarewUtils::buildRootPath(qbsProject); + buildOutputPage(buildRootDirectory, qbsProduct); +} + +void Mcs51ArchiverSettingsGroup::buildOutputPage( + const QString &baseDirectory, + const ProductData &qbsProduct) +{ + const ArmArchiver::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 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..d8d8b266c --- /dev/null +++ b/src/plugins/generator/iarew/archs/mcs51/mcs51archiversettingsgroup_v10.h @@ -0,0 +1,55 @@ +/**************************************************************************** +** +** 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_MCS51ARCHIVERSETTINGSGROUP_V10_H +#define QBS_MCS51ARCHIVERSETTINGSGROUP_V10_H + +#include "../../iarewsettingspropertygroup.h" + +namespace qbs { +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 qbs + +#endif // QBS_MCS51ARCHIVERSETTINGSGROUP_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..8cfc94be2 --- /dev/null +++ b/src/plugins/generator/iarew/archs/mcs51/mcs51assemblersettingsgroup_v10.cpp @@ -0,0 +1,223 @@ +/**************************************************************************** +** +** 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 v10 { + +constexpr int kAssemblerArchiveVersion = 2; +constexpr int kAssemblerDataVersion = 6; + +namespace Mcs51Assembler { + +// 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::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 = IarewUtils::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 = IarewUtils::cppVariantModuleProperties( + qbsProps, {QStringLiteral("defines")}); + + const QString toolkitPath = IarewUtils::toolkitRootPath(qbsProduct); + const QStringList fullIncludePaths = IarewUtils::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 = IarewUtils::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 Mcs51Assembler + +// 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(IarewUtils::debugInformation(qbsProduct)); + + const QString buildRootDirectory = IarewUtils::buildRootPath(qbsProject); + + buildLanguagePage(qbsProduct); + buildOutputPage(qbsProduct); + buildPreprocessorPage(buildRootDirectory, qbsProduct); + buildDiagnosticsPage(qbsProduct); +} + +void Mcs51AssemblerSettingsGroup::buildLanguagePage( + const ProductData &qbsProduct) +{ + const Mcs51Assembler::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"), + {0}, {!opts.macroQuoteCharacter}); +} + +void Mcs51AssemblerSettingsGroup::buildOutputPage( + const ProductData &qbsProduct) +{ + const Mcs51Assembler::OutputPageOptions opts(qbsProduct); + // Add 'Debug' item (Generate debug information). + addOptionsGroup(QByteArrayLiteral("Debug"), + {}, {opts.debugInfo}); +} + +void Mcs51AssemblerSettingsGroup::buildPreprocessorPage( + const QString &baseDirectory, + const ProductData &qbsProduct) +{ + const Mcs51Assembler::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 Mcs51Assembler::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 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..55bbddde3 --- /dev/null +++ b/src/plugins/generator/iarew/archs/mcs51/mcs51assemblersettingsgroup_v10.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_MCS51ASSEMBLERSETTINGSGROUP_V10_H +#define QBS_MCS51ASSEMBLERSETTINGSGROUP_V10_H + +#include "../../iarewsettingspropertygroup.h" + +namespace qbs { +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 qbs + +#endif // QBS_MCS51ASSEMBLERSETTINGSGROUP_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..9f69c88a6 --- /dev/null +++ b/src/plugins/generator/iarew/archs/mcs51/mcs51buildconfigurationgroup_v10.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 "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 v10 { + +Mcs51BuildConfigurationGroup::Mcs51BuildConfigurationGroup( + const Project &qbsProject, + const ProductData &qbsProduct, + const std::vector<ProductData> &qbsProductDeps) + : IarewPropertyGroup("configuration") +{ + // Append configuration name item. + const QString cfgName = IarewUtils::buildConfigurationName(qbsProject); + appendProperty("name", cfgName); + + // Apend toolchain name group item. + appendChild<IarewToolchainPropertyGroup>("8051"); + + // Append debug info item. + const int debugBuild = IarewUtils::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( + IarewUtils::Architecture architecture, const Version &version) const +{ + return architecture == IarewUtils::Architecture::Mcs51Architecture + && version.majorVersion() == 10; +} + +std::unique_ptr<IarewPropertyGroup> 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 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..53dd71f32 --- /dev/null +++ b/src/plugins/generator/iarew/archs/mcs51/mcs51buildconfigurationgroup_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_MCS51BUILDCONFIGURATIONGROUP_V10_H +#define QBS_MCS51BUILDCONFIGURATIONGROUP_V10_H + +#include "../../iarewpropertygroup.h" + +namespace qbs { +namespace v10 { + +class Mcs51BuildConfigurationGroup final : public IarewPropertyGroup +{ +private: + explicit Mcs51BuildConfigurationGroup( + const Project &qbsProject, + const ProductData &qbsProduct, + const std::vector<ProductData> &qbsProductDeps); + + friend class Mcs51BuildConfigurationGroupFactory; +}; + +class Mcs51BuildConfigurationGroupFactory final : public IarewPropertyGroupFactory +{ +public: + bool canCreate(IarewUtils::Architecture architecture, + const Version &version) const final; + + std::unique_ptr<IarewPropertyGroup> create( + const Project &qbsProject, + const ProductData &qbsProduct, + const std::vector<ProductData> &qbsProductDeps) const final; +}; + +} // namespace v10 +} // namespace qbs + +#endif // QBS_MCS51BUILDCONFIGURATIONGROUP_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..f66399837 --- /dev/null +++ b/src/plugins/generator/iarew/archs/mcs51/mcs51compilersettingsgroup_v10.cpp @@ -0,0 +1,453 @@ +/**************************************************************************** +** +** 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 v10 { + +constexpr int kCompilerArchiveVersion = 7; +constexpr int kCompilerDataVersion = 12; + +namespace Mcs51Compiler { + +// 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 = IarewUtils::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 = IarewUtils::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 = IarewUtils::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 = IarewUtils::cppVariantModuleProperties( + qbsProps, {QStringLiteral("defines")}); + + const QString toolkitPath = IarewUtils::toolkitRootPath(qbsProduct); + const QStringList fullIncludePaths = IarewUtils::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 = IarewUtils::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 Mcs51Compiler + +// 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(IarewUtils::debugInformation(qbsProduct)); + + const QString buildRootDirectory = IarewUtils::buildRootPath(qbsProject); + + buildOutputPage(qbsProduct); + buildLanguageOnePage(qbsProduct); + buildLanguageTwoPage(qbsProduct); + buildOptimizationsPage(qbsProduct); + buildPreprocessorPage(buildRootDirectory, qbsProduct); + buildDiagnosticsPage(qbsProduct); +} + +void Mcs51CompilerSettingsGroup::buildOutputPage( + const ProductData &qbsProduct) +{ + const Mcs51Compiler::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 Mcs51Compiler::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 Mcs51Compiler::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 Mcs51Compiler::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 Mcs51Compiler::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 Mcs51Compiler::DiagnosticsPageOptions opts(qbsProduct); + // Add 'CCDiagWarnAreErr' item (Treat all warnings as errors). + addOptionsGroup(QByteArrayLiteral("CCDiagWarnAreErr"), + {}, {opts.warningsAsErrors}); +} + +void Mcs51CompilerSettingsGroup::buildCodePage( + const ProductData &qbsProduct) +{ + const Mcs51Compiler::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 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..e032f0a70 --- /dev/null +++ b/src/plugins/generator/iarew/archs/mcs51/mcs51compilersettingsgroup_v10.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_MCS51COMPILERSETTINGSGROUP_V10_H +#define QBS_MCS51COMPILERSETTINGSGROUP_V10_H + +#include "../../iarewsettingspropertygroup.h" + +namespace qbs { +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 qbs + +#endif // QBS_MCS51COMPILERSETTINGSGROUP_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..815e905d5 --- /dev/null +++ b/src/plugins/generator/iarew/archs/mcs51/mcs51generalsettingsgroup_v10.cpp @@ -0,0 +1,990 @@ +/**************************************************************************** +** +** 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 v10 { + +constexpr int kGeneralArchiveVersion = 4; +constexpr int kGeneralDataVersion = 9; + +namespace Mcs51General { + +// 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 = IarewUtils::cppStringModuleProperties( + qbsProps, {QStringLiteral("defines")}); + const QStringList linkerFlags = IarewUtils::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 = IarewUtils::cppStringModuleProperties( + qbsProps, {QStringLiteral("defines")}); + const QStringList linkerFlags = IarewUtils::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 = IarewUtils::cppStringModuleProperties( + qbsProps, {QStringLiteral("defines")}); + const QStringList linkerFlags = IarewUtils::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 = IarewUtils::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 = IarewUtils::binaryOutputDirectory( + baseDirectory, qbsProduct); + objectDirectory = IarewUtils::objectsOutputDirectory( + baseDirectory, qbsProduct); + listingDirectory = IarewUtils::listingOutputDirectory( + baseDirectory, qbsProduct); + } + + IarewUtils::OutputBinaryType binaryType = IarewUtils::ApplicationOutputType; + QString binaryDirectory; + QString objectDirectory; + QString listingDirectory; +}; + +} // namespace Mcs51General + +// 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(IarewUtils::debugInformation(qbsProduct)); + + const QString buildRootDirectory = IarewUtils::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 Mcs51General::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 Mcs51General::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 Mcs51General::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 Mcs51General::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 Mcs51General::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 Mcs51General::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 Mcs51General::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 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..4189aebdc --- /dev/null +++ b/src/plugins/generator/iarew/archs/mcs51/mcs51generalsettingsgroup_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_MCS51GENERALSETTINGSGROUP_V10_H +#define QBS_MCS51GENERALSETTINGSGROUP_V10_H + +#include "../../iarewsettingspropertygroup.h" + +namespace qbs { +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 qbs + +#endif // QBS_MCS51GENERALSETTINGSGROUP_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..7f45e245d --- /dev/null +++ b/src/plugins/generator/iarew/archs/mcs51/mcs51linkersettingsgroup_v10.cpp @@ -0,0 +1,330 @@ +/**************************************************************************** +** +** 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 v10 { + +constexpr int kLinkerArchiveVersion = 4; +constexpr int kLinkerDataVersion = 21; + +namespace Mcs51Linker { + +// 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 = IarewUtils::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 = IarewUtils::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 = IarewUtils::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 = IarewUtils::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 = IarewUtils::cppStringModuleProperty( + qbsProps, QStringLiteral("warningLevel")); + suppressAllWarnings = (warningLevel == QLatin1String("none")); + } + + int suppressAllWarnings = 0; +}; + +} // namespace Mcs51Linker + +// 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(IarewUtils::debugInformation(qbsProduct)); + + const QString buildRootDirectory = IarewUtils::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) +{ + Mcs51Linker::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 Mcs51Linker::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 Mcs51Linker::ListPageOptions opts(qbsProduct); + // Add 'XList' item (Generate linker listing). + addOptionsGroup(QByteArrayLiteral("XList"), + {}, {opts.generateMap}); +} + +void Mcs51LinkerSettingsGroup::buildDefinePage( + const ProductData &qbsProduct) +{ + const Mcs51Linker::DefinePageOptions opts(qbsProduct); + // Add 'XDefines' item (Defined symbols). + addOptionsGroup(QByteArrayLiteral("XDefines"), + {}, opts.defineSymbols); +} + +void Mcs51LinkerSettingsGroup::buildDiagnosticsPage( + const ProductData &qbsProduct) +{ + const Mcs51Linker::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 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..ecfd077e9 --- /dev/null +++ b/src/plugins/generator/iarew/archs/mcs51/mcs51linkersettingsgroup_v10.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_MCS51LINKERSETTINGSGROUP_V10_H +#define QBS_MCS51LINKERSETTINGSGROUP_V10_H + +#include "../../iarewsettingspropertygroup.h" + +namespace qbs { +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 qbs + +#endif // QBS_MCS51LINKERSETTINGSGROUP_V10_H diff --git a/src/plugins/generator/iarew/iarew.pro b/src/plugins/generator/iarew/iarew.pro index 1239941bd..59e4be2f3 100644 --- a/src/plugins/generator/iarew/iarew.pro +++ b/src/plugins/generator/iarew/iarew.pro @@ -82,3 +82,21 @@ SOURCES += \ $$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 \ diff --git a/src/plugins/generator/iarew/iarew.qbs b/src/plugins/generator/iarew/iarew.qbs index 7143f5592..e7d69f60b 100644 --- a/src/plugins/generator/iarew/iarew.qbs +++ b/src/plugins/generator/iarew/iarew.qbs @@ -80,4 +80,22 @@ QbsPlugin { "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", + ] + } } diff --git a/src/plugins/generator/iarew/iarewproject.cpp b/src/plugins/generator/iarew/iarewproject.cpp index fe4bb476f..9a18e807e 100644 --- a/src/plugins/generator/iarew/iarewproject.cpp +++ b/src/plugins/generator/iarew/iarewproject.cpp @@ -37,6 +37,7 @@ #include "archs/arm/armbuildconfigurationgroup_v8.h" #include "archs/avr/avrbuildconfigurationgroup_v7.h" +#include "archs/mcs51/mcs51buildconfigurationgroup_v10.h" #include <logging/translator.h> @@ -52,6 +53,7 @@ IarewProject::IarewProject(const GeneratableProject &genProject, // Create available configuration group factories. m_factories.push_back(std::make_unique<v8::ArmBuildConfigurationGroupFactory>()); m_factories.push_back(std::make_unique<v7::AvrBuildConfigurationGroupFactory>()); + m_factories.push_back(std::make_unique<v10::Mcs51BuildConfigurationGroupFactory>()); // Construct file version item. appendChild<IarewFileVersionProperty>(versionInfo); diff --git a/src/plugins/generator/iarew/iarewversioninfo.cpp b/src/plugins/generator/iarew/iarewversioninfo.cpp index 734aa1452..f0293b998 100644 --- a/src/plugins/generator/iarew/iarewversioninfo.cpp +++ b/src/plugins/generator/iarew/iarewversioninfo.cpp @@ -57,6 +57,7 @@ std::set<IarewVersionInfo> IarewVersionInfo::knownVersions() static const std::set<IarewVersionInfo> known = { {Version(8), {IarewUtils::Architecture::ArmArchitecture}}, {Version(7), {IarewUtils::Architecture::AvrArchitecture}}, + {Version(10), {IarewUtils::Architecture::Mcs51Architecture}}, }; return known; } |