/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "msp430generalsettingsgroup_v7.h" #include "../../iarewutils.h" namespace qbs { namespace iarew { namespace msp430 { namespace v7 { constexpr int kGeneralArchiveVersion = 21; constexpr int kGeneralDataVersion = 34; namespace { // Target page options. struct TargetPageOptions final { enum CodeModel { SmallCodeModel, LargeCodeModel }; enum DataModel { SmallDataModel, MediumDataModel, LargeDataModel }; enum FloatingPointDoubleSize { DoubleSize32Bits, DoubleSize64Bits }; enum HardwareMultiplierType { AllowDirectAccessMultiplier, UseOnlyLibraryCallsMultiplier }; explicit TargetPageOptions(const ProductData &qbsProduct) { const auto &qbsProps = qbsProduct.moduleProperties(); const QStringList flags = gen::utils::cppStringModuleProperties( qbsProps, {QStringLiteral("driverFlags")}); // Detect target code model. const QString codeModelValue = IarewUtils::flagValue( flags, QStringLiteral("--code_model")); if (codeModelValue == QLatin1String("small")) codeModel = TargetPageOptions::SmallCodeModel; else if (codeModelValue == QLatin1String("large")) codeModel = TargetPageOptions::LargeCodeModel; // Detect target data model. const QString dataModelValue = IarewUtils::flagValue( flags, QStringLiteral("--data_model")); if (dataModelValue == QLatin1String("small")) dataModel = TargetPageOptions::SmallDataModel; else if (dataModelValue == QLatin1String("medium")) dataModel = TargetPageOptions::MediumDataModel; else if (dataModelValue == QLatin1String("large")) dataModel = TargetPageOptions::LargeDataModel; // Detect floating point double size. const int doubleSize = IarewUtils::flagValue( flags, QStringLiteral("--double")).toInt(); if (doubleSize == 32) floatingPointDoubleSize = DoubleSize32Bits; else if (doubleSize == 64) floatingPointDoubleSize = DoubleSize64Bits; // Detect hardware multiplier. const QString multiplier = IarewUtils::flagValue( flags, QStringLiteral("--multiplier")); enableHardwareMultiplier = (multiplier.compare(QLatin1String("16")) == 0 || multiplier.compare(QLatin1String("16s")) == 0 || multiplier.compare(QLatin1String("32")) == 0); // Detect code and read-only data position-independence. enableRopi = flags.contains(QLatin1String("--ropi")); // No dynamic read-write initialization. disableDynamicReadWriteInitialization = flags.contains( QLatin1String("--no_rw_dynamic_init")); // Detect target device name. detectDeviceMenu(qbsProduct); } void detectDeviceMenu(const ProductData &qbsProduct) { const QString toolkitPath = IarewUtils::toolkitRootPath(qbsProduct); // Enumerate all product linker config files // (which are set trough 'linkerscript' tag). const auto qbsGroups = qbsProduct.groups(); for (const auto &qbsGroup : qbsGroups) { const auto qbsArtifacts = qbsGroup.sourceArtifacts(); for (const auto &qbsArtifact : qbsArtifacts) { const auto qbsTags = qbsArtifact.fileTags(); if (!qbsTags.contains(QLatin1String("linkerscript"))) continue; const QString fullConfigPath = qbsArtifact.filePath(); if (!fullConfigPath.startsWith(toolkitPath, Qt::CaseInsensitive)) continue; const QFileInfo configInfo(fullConfigPath); const QString configBase = configInfo.baseName(); if (!configBase.startsWith(QLatin1String("lnk"))) continue; // Remove 'lnk' prefix. const QString deviceName = QStringLiteral("MSP%1") .arg(configBase.mid(3).toUpper()); deviceMenu = QStringLiteral("%1\t%1").arg(deviceName); return; } } // Falling back to generic menu. if (deviceMenu.isEmpty()) { const auto &qbsProps = qbsProduct.moduleProperties(); const QStringList flags = IarewUtils::cppModuleCompilerFlags(qbsProps); const QString cpuCore = IarewUtils::flagValue(flags, QStringLiteral("--core")); if (cpuCore.isEmpty()) return; deviceMenu = QStringLiteral("MSP%1\tGeneric MSP%1 device").arg(cpuCore); return; } } CodeModel codeModel = LargeCodeModel; DataModel dataModel = SmallDataModel; FloatingPointDoubleSize floatingPointDoubleSize = DoubleSize32Bits; HardwareMultiplierType hardwareMultiplierType = AllowDirectAccessMultiplier; int enableHardwareMultiplier = 0; int enableRopi = 0; int disableDynamicReadWriteInitialization = 0; QString deviceMenu; }; // Output page options. struct OutputPageOptions final { explicit OutputPageOptions(const QString &baseDirectory, const ProductData &qbsProduct) { binaryType = IarewUtils::outputBinaryType(qbsProduct); binaryDirectory = gen::utils::binaryOutputDirectory( baseDirectory, qbsProduct); objectDirectory = gen::utils::objectsOutputDirectory( baseDirectory, qbsProduct); listingDirectory = gen::utils::listingOutputDirectory( baseDirectory, qbsProduct); } IarewUtils::OutputBinaryType binaryType = IarewUtils::ApplicationOutputType; QString binaryDirectory; QString objectDirectory; QString listingDirectory; }; // Library configuration page options. struct LibraryConfigPageOptions final { enum RuntimeLibrary { NoLibrary, NormalDLibrary, FullDLibrary, CustomDLibrary, CLibrary, // deprecated CustomCLibrary, // deprecated }; explicit LibraryConfigPageOptions(const QString &baseDirectory, const ProductData &qbsProduct) { const auto &qbsProps = qbsProduct.moduleProperties(); const QStringList flags = IarewUtils::cppModuleCompilerFlags(qbsProps); const QFileInfo configInfo(IarewUtils::flagValue( flags, QStringLiteral("--dlib_config"))); const QString configFilePath = configInfo.absoluteFilePath(); if (!configFilePath.isEmpty()) { const QString libToolkitPath = IarewUtils::libToolkitRootPath(qbsProduct); if (configFilePath.startsWith(libToolkitPath, Qt::CaseInsensitive)) { if (configFilePath.endsWith(QLatin1String("n.h"), Qt::CaseInsensitive)) { libraryType = LibraryConfigPageOptions::NormalDLibrary; } else if (configFilePath.endsWith(QLatin1String("f.h"), Qt::CaseInsensitive)) { libraryType = LibraryConfigPageOptions::FullDLibrary; } else { libraryType = LibraryConfigPageOptions::CustomDLibrary; } configPath = IarewUtils::toolkitRelativeFilePath( baseDirectory, configFilePath); } else { libraryType = LibraryConfigPageOptions::CustomDLibrary; configPath = configFilePath; } } } RuntimeLibrary libraryType = NormalDLibrary; QString libraryPath; QString configPath; }; // Library options page options. struct LibraryOptionsPageOptions final { enum PrintfFormatter { PrintfAutoFormatter = 0, PrintfFullFormatter = 1, PrintfFullNoMultibytesFormatter = 2, PrintfLargeFormatter = 3, PrintfLargeNoMultibytesFormatter = 4, PrintfSmallFormatter = 5, PrintfSmallNoMultibytesFormatter = 6, PrintfTinyFormatter = 7 }; enum ScanfFormatter { ScanfAutoFormatter = 0, ScanfFullFormatter = 1, ScanfFullNoMultibytesFormatter = 2, ScanfLargeFormatter = 3, ScanfLargeNoMultibytesFormatter = 4, ScanfSmallFormatter = 5, ScanfSmallNoMultibytesFormatter = 6 }; explicit LibraryOptionsPageOptions(const ProductData &qbsProduct) { const auto &qbsProps = qbsProduct.moduleProperties(); const QStringList flags = IarewUtils::cppModuleLinkerFlags(qbsProps); for (auto flagIt = flags.cbegin(); flagIt < flags.cend(); ++flagIt) { if (flagIt->endsWith(QLatin1String("=_printf"), Qt::CaseInsensitive)) { const QString prop = flagIt->split( QLatin1Char('=')).at(0).toLower(); if (prop == QLatin1String("_printffull")) printfFormatter = PrintfFullFormatter; else if (prop == QLatin1String("_printffullnomb")) printfFormatter = PrintfFullNoMultibytesFormatter; else if (prop == QLatin1String("_printflarge")) printfFormatter = PrintfLargeFormatter; else if (prop == QLatin1String("_printflargenomb")) printfFormatter = PrintfLargeFormatter; else if (prop == QLatin1String("_printfsmall")) printfFormatter = PrintfSmallFormatter; else if (prop == QLatin1String("_printfsmallnomb")) printfFormatter = PrintfSmallNoMultibytesFormatter; else if (prop == QLatin1String("_printftiny")) printfFormatter = PrintfTinyFormatter; } else if (flagIt->endsWith(QLatin1String("=_scanf"), Qt::CaseInsensitive)) { const QString prop = flagIt->split( QLatin1Char('=')).at(0).toLower(); if (prop == QLatin1String("_scanffull")) scanfFormatter = ScanfFullFormatter; else if (prop == QLatin1String("_scanffullnomb")) scanfFormatter = ScanfFullNoMultibytesFormatter; else if (prop == QLatin1String("_scanflarge")) scanfFormatter = ScanfLargeFormatter; else if (prop == QLatin1String("_scanflargenomb")) scanfFormatter = ScanfLargeFormatter; else if (prop == QLatin1String("_scanfsmall")) scanfFormatter = ScanfSmallFormatter; else if (prop == QLatin1String("_scanfsmallnomb")) scanfFormatter = ScanfSmallNoMultibytesFormatter; } } } PrintfFormatter printfFormatter = PrintfAutoFormatter; ScanfFormatter scanfFormatter = ScanfAutoFormatter; }; // Stack/heap page options. struct StackHeapPageOptions final { explicit StackHeapPageOptions(const ProductData &qbsProduct) { const auto &qbsProps = qbsProduct.moduleProperties(); const QStringList flags = IarewUtils::cppModuleLinkerFlags(qbsProps); // Detect stack size. stackSize = IarewUtils::flagValue( flags, QStringLiteral("-D_STACK_SIZE")); if (stackSize.isEmpty()) stackSize = QLatin1String("A0"); // Detect data heap16 size. data16HeapSize = IarewUtils::flagValue( flags, QStringLiteral("-D_DATA16_HEAP_SIZE")); if (data16HeapSize.isEmpty()) stackSize = QLatin1String("A0"); // Detect data heap20 size. data20HeapSize = IarewUtils::flagValue( flags, QStringLiteral("-D_DATA20_HEAP_SIZE")); if (data20HeapSize.isEmpty()) stackSize = QLatin1String("50"); } QString stackSize; QString data16HeapSize; QString data20HeapSize; }; } // namespace //Msp430GeneralSettingsGroup Msp430GeneralSettingsGroup::Msp430GeneralSettingsGroup( const Project &qbsProject, const ProductData &qbsProduct, const std::vector &qbsProductDeps) { Q_UNUSED(qbsProductDeps) setName(QByteArrayLiteral("General")); setArchiveVersion(kGeneralArchiveVersion); setDataVersion(kGeneralDataVersion); setDataDebugInfo(gen::utils::debugInformation(qbsProduct)); const QString buildRootDirectory = gen::utils::buildRootPath(qbsProject); buildTargetPage(qbsProduct); buildOutputPage(buildRootDirectory, qbsProduct); buildLibraryConfigPage(buildRootDirectory, qbsProduct); buildLibraryOptionsPage(qbsProduct); buildStackHeapPage(qbsProduct); } void Msp430GeneralSettingsGroup::buildTargetPage( const ProductData &qbsProduct) { const TargetPageOptions opts(qbsProduct); // Add 'OGChipSelectMenu' item // (Device: xxx). addOptionsGroup(QByteArrayLiteral("OGChipSelectMenu"), {opts.deviceMenu}); // Add 'RadioCodeModelType' item // (Code model: small/large). addOptionsGroup(QByteArrayLiteral("RadioCodeModelType"), {opts.codeModel}); // Add 'RadioDataModelType' item // (Data model: small/medium/large). addOptionsGroup(QByteArrayLiteral("RadioDataModelType"), {opts.dataModel}); // Add 'OGDouble' item // (Floating point double size: 32/64 bits). addOptionsGroup(QByteArrayLiteral("OGDouble"), {opts.floatingPointDoubleSize}); // Add 'Hardware Multiplier' item // (Hardware multiplier). addOptionsGroup(QByteArrayLiteral("Hardware Multiplier"), {opts.enableHardwareMultiplier}); if (opts.enableHardwareMultiplier) { // Add 'RadioHardwareMultiplierType' item. addOptionsGroup(QByteArrayLiteral("Hardware RadioHardwareMultiplierType"), {opts.hardwareMultiplierType}); } // Add 'Ropi' item. // (Position independence: Code and read-only data). addOptionsGroup(QByteArrayLiteral("Ropi"), {opts.enableRopi}); // Add 'NoRwDynamicInit' item. // (Position independence: No dynamic read/write initialization). addOptionsGroup(QByteArrayLiteral("NoRwDynamicInit"), {opts.disableDynamicReadWriteInitialization}); } void Msp430GeneralSettingsGroup::buildOutputPage( const QString &baseDirectory, const ProductData &qbsProduct) { const OutputPageOptions opts(baseDirectory, qbsProduct); // Add 'GOutputBinary' item (Output file: executable/library). addOptionsGroup(QByteArrayLiteral("GOutputBinary"), {opts.binaryType}); // Add 'ExePath' item (Executable/binaries output directory). addOptionsGroup(QByteArrayLiteral("ExePath"), {opts.binaryDirectory}); // Add 'ObjPath' item (Object files output directory). addOptionsGroup(QByteArrayLiteral("ObjPath"), {opts.objectDirectory}); // Add 'ListPath' item (List files output directory). addOptionsGroup(QByteArrayLiteral("ListPath"), {opts.listingDirectory}); } void Msp430GeneralSettingsGroup::buildLibraryConfigPage( const QString &baseDirectory, const ProductData &qbsProduct) { const LibraryConfigPageOptions opts(baseDirectory, qbsProduct); // Add 'GRuntimeLibSelect' and 'GRuntimeLibSelectSlave' items // (Link with runtime: none/normal/full/custom). addOptionsGroup(QByteArrayLiteral("GRuntimeLibSelect"), {opts.libraryType}); addOptionsGroup(QByteArrayLiteral("GRuntimeLibSelectSlave"), {opts.libraryType}); // Add 'RTConfigPath' item (Runtime configuration file). addOptionsGroup(QByteArrayLiteral("RTConfigPath"), {opts.configPath}); // Add 'RTLibraryPath' item (Runtime library file). addOptionsGroup(QByteArrayLiteral("RTLibraryPath"), {opts.libraryPath}); } void Msp430GeneralSettingsGroup::buildLibraryOptionsPage( const ProductData &qbsProduct) { const LibraryOptionsPageOptions opts(qbsProduct); // Add 'Output variant' item (Printf formatter). addOptionsGroup(QByteArrayLiteral("Output variant"), {opts.printfFormatter}); // Add 'Input variant' item (Scanf formatter). addOptionsGroup(QByteArrayLiteral("Input variant"), {opts.scanfFormatter}); } void Msp430GeneralSettingsGroup::buildStackHeapPage( const ProductData &qbsProduct) { const StackHeapPageOptions opts(qbsProduct); // Add 'GStackHeapOverride' item (Override default). addOptionsGroup(QByteArrayLiteral("GStackHeapOverride"), {1}); // Add 'GStackSize2' item (Stack size). addOptionsGroup(QByteArrayLiteral("GStackSize2"), {opts.stackSize}); // Add 'GHeapSize2' item (Heap16 size). addOptionsGroup(QByteArrayLiteral("GHeapSize2"), {opts.data16HeapSize}); // Add 'GHeap20Size' item (Heap16 size). addOptionsGroup(QByteArrayLiteral("GHeap20Size"), {opts.data20HeapSize}); } } // namespace v7 } // namespace msp430 } // namespace iarew } // namespace qbs